Terraform script destroying previously created kubernetes namespace before creating a new one

I created this script:

provider "kubernetes" {
  host = "https://${var.cluster_url}:8443"
  client_certificate     = file("./admin.crt")
  client_key             = file(".admin.key")
  cluster_ca_certificate = file("./ca.crt")
}
resource "kubernetes_namespace" "resource" {
  metadata {
    annotations = {
      name = "exampleannotation"
    }

    labels = {
      mylabel = "labelvalue"
    }

    name = "${var.namespace_name}"
  }
}

If I run it twice, before running the second time, it removes the previous resource (see below).

I understand that, under the hood, terraform is tracking the resources it's created previously for that script in a state file. However I was wondering if there is any way to avoid the removal?

FIRST RUN:

 terraform apply  -var="namespace_name=pippo" -var="cluster_url=xxx.yyyy.zzz"

kubernetes_namespace.resource: Creating...
kubernetes_namespace.resource: Creation complete after 0s [id=pippo]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

SECOND RUN:

terraform apply  -var="namespace_name=pluto" -var="cluster_url=xxx.yyyy.zzz"

kubernetes_namespace.resource: Destroying... [id=pippo]
kubernetes_namespace.resource: Destruction complete after 6s
kubernetes_namespace.resource: Creating...
kubernetes_namespace.resource: Creation complete after 0s [id=pluto]


Apply complete! Resources: 1 added, 0 changed, 1 destroyed.

Upvotes: 1

Views: 311

Answers (2)

Chris Manzi
Chris Manzi

Reputation: 106

Terraform is behaving as expected here. It is meant to be stateful and deterministic, so if you change the input, the affected resources will change.

Terraform isn't designed to do what you are talking about doing. As the top comment points out, to create multiple namespaces, you can either create multiple separate 'namespace' resources, or use the for_each syntax. With for_each, you can then pass in a list of namespace names as an argument to control how many are created.

Upvotes: 1

Blokje5
Blokje5

Reputation: 5003

In this case you already had the right intuition: The Terraform resource (called "resource" in your example) had a name change. Given that a name uniquely identifies a namespace in Kubernetes the only way to change a name is by removing the old namespace and creating a new one.

If you want to keep two namespaces, you need two resources in Terraform. E.g.:

resource "kubernetes_namespace" "resource" {
  for_each = toset(["pippo", "pluto"])
  metadata {
    annotations = {
      name = "exampleannotation"
    }

    labels = {
      mylabel = "labelvalue"
    }

    name = each.key
  }
}

Note that for_each is only available after Terraform 0.12.

Upvotes: 2

Related Questions