Search code examples
terraformgoogle-cloud-runterraform-provider-gcp

Avoid duplication in lists of terraform variables (Google Cloud Run)


I have a list of environment variables I want to make available for Google Cloud Run instances (1 service, 4 jobs)

Environment variables are shared massively between these jobs and if I need to add/change/remove any of them I need to do it 5 times, obviously this creates opportunities for errors to creep in, and I'm repeating myself a lot.

I thought of having a variable that contained all of these values and then unpacked them into the containers section of the terraform declaration.

resource "google_cloud_run_v2_job" "example_cloud_run_job" {
  # project, location, name, dependency info in here
  template {
    # template info such as parallelism and task count here
    template {
      # more info in here
      containers {
        # image, networking info, resources in here, but also a lot of environment variables!
        env {
          name  = "foo"
          value = var.bar
        }
        env {
          name  = "baz"
          value = var.qux
        }
        env {
          name  = "quux"
          value = var.corge
        }
        env {
          name  = "grault"
          value = var.garply
        }
      }
    }
  }
}

I'm hoping there is something I can do to unpack these variables into the containers object, similarly to how we could do it in JavaScript/Typescript with the ... operator or with the * operator in Python. I can't find this in the documentation for Terraform and I am sure that I am not the first to come across this problem!

I have been reading through the documentation and playing around in the code a bit but not come across a solid approach for this.


Solution

  • What you could do is use for_each meta-argument in combination with dynamic. You would also need to create a variable which will be used to iterate over:

    variable "env_vars" {
      type        = map(string)
      description = "Map of environment variables."
    
      default = {
        foo    = "some value"
        baz    = "some value"
        quux   = "some value"
        grault = "some value"
      }
    }
    
    resource "google_cloud_run_v2_job" "example_cloud_run_job" {
      # project, location, name, dependency info in here
      template {
        # template info such as parallelism and task count here
        template {
          # more info in here
          containers {
            dynamic "env" {
              for_each = var.env_vars
              content {
                name  = env.key
                value = env.value
              }
            }
          }
        }
      }
    }