Terraform-provider-kubernetes: Kubernetes label validation is invalid

Created on 1 Nov 2018  路  11Comments  路  Source: hashicorp/terraform-provider-kubernetes

Terraform Version

terraform -v
Terraform v0.11.8
+ provider.kubernetes v1.3.0

Your version of Terraform is out of date! The latest version
is 0.11.10. You can update by downloading from www.terraform.io/downloads.html

Affected Resource(s)

I noticed this with kubernetes_namespace but it might affect others too?

Terraform Configuration Files

resource "kubernetes_namespace" "foobar" {
  metadata {
    labels {
      name  = "foo/bar"
      value = ""
    }

    name = "foobar"
  }
}

Actual Behavior

In the above example terraform does not accept the label:

$ terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "kubernetes" (1.3.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.kubernetes: version = "~> 1.3"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
$ terraform plan

Error: kubernetes_namespace.foobar: metadata.0.labels ("foo/bar") a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character (e.g. 'MyValue',  or 'my_value',  or '12345', regex used for validation is '(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?')

Expected Behavior

It should apply cleanly.

The documentation states:

Valid label keys have two segments: an optional prefix and name, separated by a slash [...]

$ cat foo.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: foobar
  labels:
    foo/bar: ""
$ kubectl apply -f foo.yaml
namespace/foobar created
$ kubectl describe ns foobar
Name:         foobar
Labels:       foo/bar=
Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Namespace","metadata":{"annotations":{},"labels":{"foo/bar":""},"name":"foobar","namespace":""}}

Status:  Active

No resource quota.

No resource limits.

Steps to Reproduce

See above.

Most helpful comment

I am having the same issue . Terraform is applying the labels but at every run it sets them again

for example:

  ~ kubernetes_cluster_role.argocd-application-controller                                                                                      
      metadata.0.labels.%:                                        "0" => "3"                                                                
      metadata.0.labels.app.kubernetes.io/component:              "" => "application-controller"      
      metadata.0.labels.app.kubernetes.io/name:                   "" => "argocd-application-controller"                                   
      metadata.0.labels.app.kubernetes.io/part-of:                "" => "argocd"  

I can see that those labels where indeed set on the resource.

Is there a correct way to apply this kind of "complex" labels through the terraform kubernetes provider ?

All 11 comments

Try this:

resource "kubernetes_namespace" "foobar" {
  metadata {
    labels {
      "foo/bar" = ""
    }

    name = "foobar"
  }
}

@ctranstrum at first I thought your solution worked , because indeed works for the first time , but in the next apply is not able to process the '/' from the state and does not read the label correctly and at the end you have a perpetual diff.

'terraform show' does not display the label but I can see it with the kubetcl

I am having the same issue . Terraform is applying the labels but at every run it sets them again

for example:

  ~ kubernetes_cluster_role.argocd-application-controller                                                                                      
      metadata.0.labels.%:                                        "0" => "3"                                                                
      metadata.0.labels.app.kubernetes.io/component:              "" => "application-controller"      
      metadata.0.labels.app.kubernetes.io/name:                   "" => "argocd-application-controller"                                   
      metadata.0.labels.app.kubernetes.io/part-of:                "" => "argocd"  

I can see that those labels where indeed set on the resource.

Is there a correct way to apply this kind of "complex" labels through the terraform kubernetes provider ?

I'm also having this issue. I'm stuck with a perpetual diff when trying to use labels that have keys that are quoted and have a / in them. The labels are definitely applied, but they're not detected on subsequent apply operations.

Looks like this is caused by this fix for this previous bug, from when Terraform didn't allow label names to contain /. The solution was to filter out "internal" k8s labels that were being automatically applied.

Now that we're using the upstream k8s libraries to validate label names and can set labels with names containing /, we should revert the previous bugfix/workaround.

So is there a workaround?

bump having the same issues with kubernetes_service_account

Having same issue with kubernetes_config_map

The issue reported by the OP does not happen with recent versions.

For example, this works fine:

provider kubernetes {
  version = "1.7.0"
}

terraform {
  required_version = "0.12.2"
}

resource "kubernetes_namespace" "foobar" {
  metadata {
    labels = {
      "foo/bar" = ""
    }

    name = "foobar"
  }
}
# terraform init && terraform apply -auto-approve

Initializing the backend...

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
kubernetes_namespace.foobar: Creating...
kubernetes_namespace.foobar: Creation complete after 0s [id=foobar]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
# terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

kubernetes_namespace.foobar: Refreshing state... [id=foobar]

------------------------------------------------------------------------

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.



md5-1b51882555db148e5bee0dac249fc938



# kubectl get namespaces foobar -o yaml
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: "2019-06-19T11:16:55Z"
  labels:
    foo/bar: ""
  name: foobar
  resourceVersion: "39691"
  selfLink: /api/v1/namespaces/foobar
  uid: beff1b0f-9283-11e9-9dcb-e851f8def6f3
spec:
  finalizers:
  - kubernetes
status:
  phase: Active



md5-1b51882555db148e5bee0dac249fc938



# terraform state show kubernetes_namespace.foobar
# kubernetes_namespace.foobar: 
resource "kubernetes_namespace" "foobar" {
    id = "foobar"

    metadata {
        generation       = 0
        labels           = {
            "foo/bar" = ""
        }
        name             = "foobar"
        resource_version = "39691"
        self_link        = "/api/v1/namespaces/foobar"
        uid              = "beff1b0f-9283-11e9-9dcb-e851f8def6f3"
    }
}

I can confirm what @pdecat has demonstrated above. I am also not able to reproduce this issue anymore. It works correctly using these versions:

Terraform v0.12.2
+ provider.kubernetes v1.7.0

Here's the configuration I used:

terraform {
  required_version = "0.12.2"
}

resource "kubernetes_config_map" "foobar" {
  metadata {
    labels = {
      "foo/bar" = "some-data"
    }
    name = "foobar"
  }
}

I'm going to close this issue.
If anyone has configurations that can still reproduce the error, please reopen this and post your configuration.

Was this page helpful?
0 / 5 - 0 ratings