3

I'm trying to create local variable for for_each loop in other resource, but can't make a local map as expected.

The following is what I tried. (Terraform 0.12)

Expected map to loop

temple_list = { "test2-role" = "test-test2-role", ... }

main.tf

locals {
  tmpl_list = flatten([ 
    for role in keys(var.roles) : {
      for tmpl_vars in values(var.roles[role].tmpl_vars) : 
        role => "test-${role}" if tmpl_vars == "SECRET"
    }
  ])
}

output "tmpl_list" {
  value = local.tmpl_list
}

variable "roles" {
    type = map(object({
        tmpl_vars = map(string)
        tags = map(string)
    }))
    
    default = {
        "test-role" = {
            tmpl_vars = {test = "y"}
            tags = { test = "xxx"}
        }
            "test2-role" = {
            tmpl_vars = { token = "SECRET" }
            tags = {}
        }
        "test3-role" = {
            tmpl_vars = {test = "x"}
            tags = {}
        }
    }
}

Error comes from merge

    | var.roles is map of object with 3 elements

Call to function "merge" failed: arguments must be maps or objects, got
"tuple".

Without merge

locals {
  tmpl_list = flatten([ 
    for role in keys(var.roles) : {
      for tmpl_vars in values(var.roles[role].tmpl_vars) : 
        role => "test-${role}" if tmpl_vars == "SECRET"
    }
  ])
}

output "tmpl_list" {
  value = local.tmpl_list
}

variable "roles" {
    type = map(object({
        tmpl_vars = map(string)
        tags = map(string)
    }))
    
    default = {
        "test-role" = {
            tmpl_vars = {test = "y"}
            tags = { test = "xxx"}
        }
            "test2-role" = {
            tmpl_vars = { token = "SECRET" }
            tags = {}
        }
        "test3-role" = {
            tmpl_vars = {test = "x"}
            tags = {}
        }
    }
}

Result of no merge

tmpl_list = [
  {},
  {
    "test2-role" = "test-test2-role"
  },
  {},
]

I tried other functions like tomap(), but it seems not working for me. (Also I'm not sure why empty ones are created.)

How can I convert this tuple to a map without empty ones?

1 Answer 1

7

You can do it in two steps:

  1. Convert it to the filtered list of objects:
locals {  
  result = flatten([
    for role, role_value in var.roles: [
      for tmpl_vars in role_value.tmpl_vars: {
        key = role
        value = "test-${role}"
      } if tmpl_vars == "SECRET"
    ]
  ])
}

local.result would have following value:

[
  {
    "key" = "test2-role"
    "value" = "test-test2-role"
  },
]
  1. Then it's easy to convert it into the map with for:
my_map = { for item in local.result: item.key => item.value }

which gives:

{
  "test2-role" = "test-test2-role"
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.