Skip to content

Commit

Permalink
Filter well known labels and annotations (#1253)
Browse files Browse the repository at this point in the history
Co-authored-by: John Houston <jrhouston@users.noreply.github.com>
  • Loading branch information
DrFaust92 and jrhouston authored May 17, 2021
1 parent 6eb06c1 commit e5b56a9
Show file tree
Hide file tree
Showing 38 changed files with 194 additions and 76 deletions.
45 changes: 45 additions & 0 deletions kubernetes/resource_kubernetes_pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,28 @@ func TestAccKubernetesPod_topologySpreadConstraint(t *testing.T) {
})
}

func TestAccKubernetesPod_filterAnnotations(t *testing.T) {
name := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "kubernetes_pod.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
CheckDestroy: testAccCheckKubernetesPodDestroy,
Steps: []resource.TestStep{
{
Config: testAccKubernetesPodConfigFilterAnnotations(name, busyboxImageVersion),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "metadata.0.annotations.%", "1"),
resource.TestCheckResourceAttr(resourceName, "metadata.0.annotations.kubernetes.io/ingress.class", "gce-multi-cluster"),
resource.TestCheckResourceAttr(resourceName, "metadata.0.labels.%", "1"),
resource.TestCheckResourceAttr(resourceName, "metadata.0.labels.kubernetes.io/ingress.class", "gce-multi-cluster"),
),
},
},
})
}

func testAccCheckKubernetesPodDestroy(s *terraform.State) error {
conn, err := testAccProvider.Meta().(KubeClientsets).MainClientset()

Expand Down Expand Up @@ -2417,3 +2439,26 @@ func testAccKubernetesPodTopologySpreadConstraintConfig(podName, imageName strin
}
`, podName, imageName)
}

func testAccKubernetesPodConfigFilterAnnotations(name, imageName string) string {
return fmt.Sprintf(`resource "kubernetes_pod" "test" {
metadata {
name = "%s"
labels = {
"kubernetes.io/ingress.class" = "gce-multi-cluster"
}
annotations = {
"kubernetes.io/ingress.class" = "gce-multi-cluster"
}
}
spec {
container {
image = "%s"
name = "containername"
}
}
}
`, name, imageName)
}
76 changes: 73 additions & 3 deletions kubernetes/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,86 @@ package kubernetes
import (
"encoding/base64"
"fmt"
"net/url"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
apps "k8s.io/api/apps/v1beta1"
cert "k8s.io/api/certificates/v1beta1"
api "k8s.io/api/core/v1"
discovery "k8s.io/api/discovery/v1beta1"
networking "k8s.io/api/networking/v1beta1"
rbac "k8s.io/api/rbac/v1beta1"

"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// https://kubernetes.io/docs/reference/labels-annotations-taints
var builtInLabels = map[string]string{
//Core Api
api.LabelHostname: "",
api.LabelZoneFailureDomain: "",
api.LabelZoneRegion: "",
api.LabelZoneFailureDomainStable: "",
api.LabelZoneRegionStable: "",
api.LabelInstanceType: "",
api.LabelInstanceTypeStable: "",
api.LabelOSStable: "",
api.LabelArchStable: "",
api.LabelWindowsBuild: "",
api.LabelNamespaceSuffixKubelet: "",
api.LabelNamespaceSuffixNode: "",
api.LabelNamespaceNodeRestriction: "",
api.IsHeadlessService: "",
api.BetaStorageClassAnnotation: "",
api.MountOptionAnnotation: "",
api.ResourceDefaultNamespacePrefix: "",
api.ServiceAccountNameKey: "",
api.ServiceAccountUIDKey: "",
api.PodPresetOptOutAnnotationKey: "",
api.MirrorPodAnnotationKey: "",
api.TolerationsAnnotationKey: "",
api.TaintsAnnotationKey: "",
api.SeccompPodAnnotationKey: "",
api.SeccompContainerAnnotationKeyPrefix: "",
api.AppArmorBetaContainerAnnotationKeyPrefix: "",
api.AppArmorBetaDefaultProfileAnnotationKey: "",
api.AppArmorBetaAllowedProfilesAnnotationKey: "",
api.PreferAvoidPodsAnnotationKey: "",
api.NonConvertibleAnnotationPrefix: "",
api.AnnotationLoadBalancerSourceRangesKey: "",
api.EndpointsLastChangeTriggerTime: "",
api.MigratedPluginsAnnotationKey: "",
api.TaintNodeNotReady: "",
api.TaintNodeUnreachable: "",
api.TaintNodeUnschedulable: "",
api.TaintNodeMemoryPressure: "",
api.TaintNodeDiskPressure: "",
api.TaintNodeNetworkUnavailable: "",
api.TaintNodePIDPressure: "",

//Networking
networking.AnnotationIsDefaultIngressClass: "",
networking.AnnotationIngressClass: "",

//Discovery
discovery.LabelServiceName: "",
discovery.LabelManagedBy: "",
discovery.LabelSkipMirror: "",

//Certificate
cert.KubeAPIServerClientSignerName: "",
cert.KubeAPIServerClientKubeletSignerName: "",
cert.KubeletServingSignerName: "",
cert.LegacyUnknownSignerName: "",

//Apps
apps.StatefulSetPodNameLabel: "",

//RBAC
rbac.AutoUpdateAnnotationKey: "",
}

func idParts(id string) (string, string, error) {
parts := strings.Split(id, "/")
if len(parts) != 2 {
Expand Down Expand Up @@ -156,8 +227,7 @@ func isKeyInMap(key string, d map[string]interface{}) bool {
}

func isInternalKey(annotationKey string) bool {
u, err := url.Parse("//" + annotationKey)
if err == nil && strings.HasSuffix(u.Hostname(), "kubernetes.io") {
if _, ok := builtInLabels[annotationKey]; ok {
return true
}

Expand Down
9 changes: 6 additions & 3 deletions kubernetes/structures_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@ func TestIsInternalKey(t *testing.T) {
{"anyKey", false},
{"any.hostname.io", false},
{"any.hostname.com/with/path", false},
{"any.kubernetes.io", true},
{"kubernetes.io", true},
{"pv.kubernetes.io/any/path", true},
{"any.kubernetes.io", false},
{"kubernetes.io", false},
{"pv.kubernetes.io/any/path", false},
{"pv.kubernetes.io/any/path", false},
{"kubernetes.io/hostname", true},
{"statefulset.kubernetes.io/pod-name", true},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions website/docs/d/namespace.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ The following arguments are supported:

* `annotations` - (Optional) An unstructured key value map stored with the namespace that may be used to store arbitrary metadata.

~> By default, the provider ignores any annotations whose key names end with *kubernetes.io*. This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)
~> By default, the provider ignores any annotations whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)

* `generation` - A sequence number representing a specific generation of the desired state.
* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) namespaces. May match selectors of replication controllers and services.

~> By default, the provider ignores any labels whose key names end with *kubernetes.io*. This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)
~> By default, the provider ignores any labels whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)

* `resource_version` - An opaque value that represents the internal version of this namespace that can be used by clients to determine when namespaces have changed. Read more about [concurrency control and consistency](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency).
* `uid` - The unique in time and space value for this namespace. For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/identifiers#uids)
Expand Down
4 changes: 2 additions & 2 deletions website/docs/r/api_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ The following arguments are supported:

* `annotations` - (Optional) An unstructured key value map stored with the API service that may be used to store arbitrary metadata.

~> By default, the provider ignores any annotations whose key names end with *kubernetes.io*. This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)
~> By default, the provider ignores any annotations whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)

* `generate_name` - (Optional) Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. For more info see [Kubernetes reference](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#idempotency)
* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) the API service.

~> By default, the provider ignores any labels whose key names end with *kubernetes.io*. This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)
~> By default, the provider ignores any labels whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)

* `name` - (Optional) Name of the API service, must be unique. Cannot be updated. For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/identifiers#names)

Expand Down
4 changes: 2 additions & 2 deletions website/docs/r/certificate_signing_request.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ The following arguments are supported:

* `annotations` - (Optional) An unstructured key value map stored with the certificate signing request that may be used to store arbitrary metadata.

~> By default, the provider ignores any annotations whose key names end with *kubernetes.io*. This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)
~> By default, the provider ignores any annotations whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)

* `generate_name` - (Optional) Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. For more info see [Kubernetes reference](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#idempotency)
* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) the certificate signing request. May match selectors of replication controllers and services.

~> By default, the provider ignores any labels whose key names end with *kubernetes.io*. This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)
~> By default, the provider ignores any labels whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)

* `name` - (Optional) Name of the certificate signing request, must be unique. Cannot be updated. For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/identifiers#names)

Expand Down
4 changes: 2 additions & 2 deletions website/docs/r/cluster_role.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ The following arguments are supported:

* `annotations` - (Optional) An unstructured key value map stored with the cluster role binding that may be used to store arbitrary metadata.

~> By default, the provider ignores any annotations whose key names end with *kubernetes.io*. This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)
~> By default, the provider ignores any annotations whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such annotations can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such annotations in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/annotations)

* `generate_name` - (Optional) Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. For more info see [Kubernetes reference](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#idempotency)
* `labels` - (Optional) Map of string keys and values that can be used to organize and categorize (scope and select) the cluster role binding.

~> By default, the provider ignores any labels whose key names end with *kubernetes.io*. This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)
~> By default, the provider ignores any labels whose key names are in the [Well-Known Labels, Annotations and Taints](https://kubernetes.io/docs/reference/labels-annotations-taints). This is necessary because such labels can be mutated by server-side components and consequently cause a perpetual diff in the Terraform plan output. If you explicitly specify any such labels in the configuration template then Terraform will consider these as normal resource attributes and manage them as expected (while still avoiding the perpetual diff problem). For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/labels)

* `name` - (Optional) Name of the cluster role binding, must be unique. Cannot be updated. For more info see [Kubernetes reference](http://kubernetes.io/docs/user-guide/identifiers#names)

Expand Down
Loading

0 comments on commit e5b56a9

Please sign in to comment.