Felixrobin antony
Felixrobin antony

Reputation: 11

Handling list of maps in for loop in terraform

I have the following locals file. I need to get the child and parent names separately in for each in terraform.

 locals:
  {
     l3_crm:
        [
          { parent: "crm", child: ["crm-sap", "crm-sf"] },
          { parent: "fin", child: ["fin-mon"] },
        ] 
  }

For the following ou creation code in aws, parent_id needs the parent name from the locals and ou_name needs the corresponding child name iterated.

module "l3_crm" {
  source = "./modules/ou"
  for_each   = { for idx, val in local.l3_crm : idx => val }
  ou_name    = [each.value.child]
  parent_id  = module.l2[each.key.parent].ou_ids[0]
  depends_on = [module.l2]
  ou_tags    = var.l2_ou_tags
}

I get the following error:

│ Error: Unsupported attribute
│
│   on main.tf line 30, in module "l3_rnd":
│   30:   parent_id  = module.l2[each.key.parent].ou_ids[0]
│     ├────────────────
│     │ each.key is a string, known only after apply
│
│ This value does not have any attributes.
╵

Let me know what I am doing wrong in for loop.

I tried this as well:

  module "l3_rnd" {
  source     = "./modules/ou"
  for_each   = { for parent, child in local.l3_crm : parent => child }
  ou_name    = [each.value]
  parent_id  = module.l2[each.key].ou_ids[0]
  depends_on = [module.l2]
  ou_tags    = var.l2_ou_tags
}

with the local.tf:

locals {

  l3_crm = [
    { "rnd" : ["crm-sap", "crm-sf"] },
    { "trade" : ["fin-mon"] }
  ]

}

I get these errors:

╷
│ Error: Invalid value for module argument
│
│   on main.tf line 28, in module "l3_crm":
│   28:   ou_name    = [each.value]
│
│ The given value is not suitable for child module variable "ou_name" defined
│ at modules\ou\variables.tf:1,1-19: element 0: string required.
╵
╷
│ Error: Invalid value for module argument
│
│   on main.tf line 28, in module "l3_crm":
│   28:   ou_name    = [each.value]
│
│ The given value is not suitable for child module variable "ou_name" defined
│ at modules\ou\variables.tf:1,1-19: element 0: string required.
╵
╷
│ Error: Invalid index
│
│   on main.tf line 29, in module "l3_crm":
│   29:   parent_id  = module.l2[each.key].ou_ids[0]
│     ├────────────────
│     │ each.key is "1"
│     │ module.l2 is object with 2 attributes
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│   on main.tf line 29, in module "l3_crm":
│   29:   parent_id  = module.l2[each.key].ou_ids[0]
│     ├────────────────
│     │ each.key is "0"
│     │ module.l2 is object with 2 attributes
│
│ The given key does not identify an element in this collection value.
╵
time=2022-11-11T13:24:15Z level=error msg=Hit multiple errors:
Hit multiple errors:
exit status 1

Upvotes: 0

Views: 850

Answers (1)

Matthew Schuchard
Matthew Schuchard

Reputation: 28739

With your current structure you can reconstruct the map in your meta-argument like:

for_each = { for l3_crm in local.l3_crm : l3_crm.parent => l3_crm.child }

to access the values of each key in the list element and reconstruct to a map of parent keys and child values.

You can also optimize the structure like:

l3_crm:
  [
    { "crm" = ["crm-sap", "crm-sf"] },
    { "fin" = ["fin-mon"] },
  ]

and then:

for_each = { for parent, child in local.l3_crm : parent => child }

where you cannot simply convert to a set type with toset because set(map) is not allowed as an argument value type.

Either way the references are updated fully accordingly:

ou_name   = [each.key]
parent_id = module.l2[each.value].ou_ids[0]

Upvotes: 1

Related Questions