Terraform : The "each" object does not support this operation

I'm trying to create "Parent" and "Child" resources with Terraform, from a variable like this:

variable "tags" {
  default = {
    parent1 = ["child1", "child2"]
    parent2 = ["child2", "child4", "child5"]
  }
}

For each key in my variable I want to create a Parent resource, which I do and works fine:

resource "google_tags_tag_key" "parent" {
    for_each = toset(keys(var.tags))
    parent = "organizations/1234567890"
    short_name = each.key
    description = ""
}

My problem is regarding child resources ... For each item in a list, I want to create a child resource. But I can't seem to do a nested loop on the "for_each" argument. So I tried to use the "setproduct" function to flatten my variable. as follows.

locals {
  helper_list = [for k, v in var.tags:
            setproduct(list(k), v)
      ]
}

This is a workaround, but despite everything, I still cannot resolve my problem by trying in the following way.

resource "google_tags_tag_value" "child" {
    for_each = local.helper_list
    parent = "tagKeys/${google_tags_tag_key.parent[each.0]}"
    short_name = each.1
    description = ""
}

This returns the folling error: The "each" object does not support this operation. How can I solve my problem by going through a helper_list or without?

1 answer

  • answered 2021-06-18 09:01 Marcin

    I would do this as follows:

    variable "tags" {
      default = {
        parent1 = ["child1", "child2"]
        parent2 = ["child2", "child4", "child5"]
      }
    }
    
    locals {
    
     # construct flat map
     helper_map = merge([
                   for parent, children in var.tags:
                    {
                      for child in children:
                      "${parent}-${child}" => {
                          "parent" = parent
                          "child" = child                      
                       }
                    }
               ]...)
    
     
    }
    
    output "helper_map" {
      value = local.helper_map
    }
    

    which gives:

    helper_map = {                                                                                                                                                                             
      "parent1-child1" = {                                                                                                                                                                     
        "child" = "child1"                                                                                                                                                                     
        "parent" = "parent1"                                                                                                                                                                   
      }                                                                                                                                                                                        
      "parent1-child2" = {                                                                                                                                                                     
        "child" = "child2"  
        "parent" = "parent1"
      }                    
      "parent2-child2" = {  
        "child" = "child2"  
        "parent" = "parent2"
      }                    
      "parent2-child4" = { 
        "child" = "child4"  
        "parent" = "parent2"
      }                   
      "parent2-child5" = {
        "child" = "child5"  
        "parent" = "parent2"
      }
    }  
    

    Then you can do, assuming I understand your desired outcome:

    resource "google_tags_tag_value" "child" {
        for_each = local.helper_map
        parent = "tagKeys/${google_tags_tag_key.parent[each.value.parent]}"
        short_name = each.value.child
        description = ""
    }