0

I am using terraform with helm provider to deploy a helm chart, everything works with terraform, the problem is when the application is already running and I changed the image tag from the gitlab pipeline.

So the next time that I run terraform the image tag deployed from gitlab will be change to the previous one.

I tried to use lifecycle, this is my terraform code:

resource "helm_release" "app1" {
  name      = "app1"
  namespace = "money"
  chart     = "stable/perl"

  set {
    name  = "image.repository"
    value = "docker.registry.local/app1-api"
  }

  set {
    name  = "replicaCount"
    value = "2"
  }
  set {
    name  = "image.tag"
    value = "1.0.1"
  }

  set {
    name  = "image.pullPolicy"
    value = "Always"
  }

  set {
    name  = "service.type"
    value = "ClusterIP"
  }

  lifecycle {
    ignore_changes = [for s in set : s.name if s.name == "image.tag"]
  }
}

terraform apply:

A static list expression is required.
c4f4t0r
  • 5,149
  • 3
  • 28
  • 41
  • There must be a better way to set up that ignore_changes line. I haven't tested, but would something like `ignore_changes = [set["image.tag"]]` work? –  Apr 19 '20 at 16:56
  • @Kyle I tried your code, this is the result "Block type "set" is represented by a set of objects, and set elements do not have addressable keys. To find elements matching specific criteria, use a "for" expression with an "if" clause. " – c4f4t0r Apr 19 '20 at 22:02
  • What about getting rid of ignore_changes, and NOT specifying the value for `image.tag` at all here? Can you look up the value with a script, and create an external data resource using it? Something like `value = data.external.look_up_tag.result["image.tag"]` –  Apr 20 '20 at 04:13
  • @Kyle that's is goog soluction, what data provider do you use for the docker image? – c4f4t0r Apr 21 '20 at 08:25
  • That would be up to you, I don't know anything about your environment or where your images are stored. The "external" data source (see [here](https://www.terraform.io/docs/providers/external/data_source.html)) allows you to run an arbitrary script. The script needs to output in a particular way for terraform to consume it. If you go with this provider, you will need to make the script retrieve that image.tag value for you. –  Apr 21 '20 at 17:02

1 Answers1

0

Specifically for the Helm resource, you can trick Terraform into ignoring all objects of the same "type", meaning you can use one of the three objects (set, set_sensitive, set_string) inside the lifecycle and ignore them all.

Is this ideal? Of course not, but it does work. The root cause for the why objects are not addressable is here.

In your example, it would be something like this:

resource "helm_release" "app1" {
  set_string {
    name  = "image.tag"
    value = "1.0.1"
  }

  lifecycle {
    ignore_changes = [set_string]
  }
}

Edit: Please note that ignore_changes is quite literal, since any update will enforce the old value to replace whatever is currently configured in Helm.

Example: Terraform has the initial tag configured and the initial replicaCount == 2. Then the CI/CD system does its things and update the tag. Now, if you were to use Terraform to change replicaCount the initial tag would be re-applied since it's the one Terraform knows about...

  • I will try and I will let know :) – c4f4t0r Jun 17 '20 at 07:01
  • Just another side note regarding the "solution", I edited the answer after finding out Terraform ignore changes to the tag, but in case the resource is updated due to other parameter changes, the old tag will replace the current... – Davi S Evangelista Jun 26 '20 at 03:47