Search code examples
terraformhcl

Terraform: How to use each.value as variable name


Here is a resource block that uses for_each on a set of string names. Each resource ends up being an environment variable for this provider, including a key and value:

resource "environments_variables_v1" "api_env_var" {
  service_sid     = local.api_sid
  environment_sid = local.api_env_sid
  for_each = {
    for k, v in var.api_env_var_names : k => v
    if var.feature_flag
  }
  key   = upper(each.value)
  value = var.each.value
}

The output should be a key (name changed to uppercase) and a value. The value is coming from secrets in the environment. I have a variable declared for it:

variable "api_env_var_name_1" {
  default     = ""
  type        = string
  description = "1st environment secret."
  sensitive   = true
  nullable    = false
}

My problem is I don't see a way to take an each.value and use it as the key name for a variable. var.each.value above is not the right syntax but I don't see an alternative.


Solution

  • In Terraform each input variable is entirely independent, so there is no way to select one dynamically based on a value as you are attempting here.

    If you need to look up values by keys, the most appropriate data structure for that is a map, which is a collection of elements where each element has a key and a value, and you can provide a single key to obtain the corresponding value.

    It seems from your example that var.api_env_var_names is already declared as having a map type, though you didn't include its declaration in your question so I'll write out what I'm guessing it looks like:

    variable "api_env_var_names" {
      type = map(string)
    }
    

    It seems that this variable is a map from something to the name of an environment variable. From what you've described, it seems like you then need a separate variable which maps from input variable names to their values, like this:

    variable "api_env_var_values" {
      type = map(string)
    }
    

    The above isn't particularly clear about what the keys and values in these variables represent, so here are some example definitions of these variables to show how I'm imagining them being used:

      api_env_var_names = {
        something      = "SOMETHING_NAME"
        something_else = "SOMETHING_ELSE_NAME"
      }
      api_env_var_values = {
        SOMETHING_NAME = "foo"
        SOMETHING_ELSE_NAME = "bar"
      }
    

    Now you can use the values from the first one as keys for the second one, like this:

    resource "environments_variables_v1" "api_env_var" {
      for_each = {
        for k, v in var.api_env_var_names : k => v
        if var.feature_flag
      }
    
      service_sid     = local.api_sid
      environment_sid = local.api_env_sid
      key             = upper(each.value)
      value           = var.api_env_var_values[each.value]
    }