Mikesh
Mikesh

Reputation: 25

Terraform: Iterate over a list of strings in a nested JSON with terraform-provider-aci

I am having problems with this issue for to long. I am trying to set up some Infrastructure with Terraform and Cisco ACI. What I want to do now is to set up multiple epgs for one tenant. So with for_each iam iterating over my JSON. But I don't get it how I can iterate over the epg key (which contains a list of strings). It can't be that hard! But I don't get it.

First of all my .json

{
   "tenants": [
 {
   "id": 1,
   "name": "kde0815",
   "bd": "bd0815",
   "vRF": "vrf0815",
   "epg": [
      "epg1"
   ],
   "_fwdCtrl": "disabled",
   "_isAttrBasedEPg": "no",
   "_matchT": "no",
   "_prefGrMemb": "unenforced"
},
 {
   "id": 97,
   "name": "kde0816",
   "bd": [
      "bd0816"  
   ],
   "vRF": "vrf0816",
   "epg": [
      "epg1",
      "epg2,
      "epg3,
      "epg4" 
   ],
   "_fwdCtrl": "disabled",
   "_isAttrBasedEPg": "no",
   "_matchT": "no",
   "_prefGrMemb": "unenforced"
}
]
}

my resources.tf

locals {
  # get json 
  user_data = jsondecode(file("./data/aci-data_test.json"))

  # get all users
  all_users = [for tenants in local.user_data.tenants : tenants.name]

}

resource "aci_application_epg" "epgLocalName" {
  for_each               = { for inst in local.user_data.tenants : inst.id => inst }
  relation_fv_rs_bd      = aci_bridge_domain.bdLocalName[each.value.id].id
  application_profile_dn = aci_application_profile.apLocalName[each.value.id].id
  
  # dynamic "name" {
  #   for_each = each.value.epg 
  #   content {
  #     name = name.value
  #   }
  #}

}

of course this is not all of my code. I´ve created Tenants, Bridgedomains and so on already. I tried to use the dynamic block to go over the "epg" two errors occurred

Error: Missing required argument
│ The argument "name" is required, but no definition was found
Error: Unsupported block type
│ Blocks of type "name" are not expected here.

so I tired to use a second for_each loop

Error: Attribute redefined: The argument "for_each" was already set at resources.tf:54,3-11. Each argument may be set only once.

so far I understood you use for-loops only for modifying/filtering... strings. Is there a way just to use the for loop to pass the string to the variable "name" in the aci_applicaton_profile?

I am really stuck with Terraform here... never had problems with Python doing this. So if you have any idea I would really appreciate it.

Upvotes: 1

Views: 2486

Answers (1)

Marcin
Marcin

Reputation: 238209

You have to flatten your user_data. For example:

locals {
 
  flat_all_users = merge([ for id, inst in local.user_data.tenants:
          {
            for epg in inst.epg:
              "${id}-${epg}" => {
                    id = id
                    name = epg
              }
          }    
    ]...)
}

then

resource "aci_application_epg" "epgLocalName" {
  for_each               = localflat_all_users
  relation_fv_rs_bd      = aci_bridge_domain.bdLocalName[each.value.id].id
  application_profile_dn = aci_application_profile.apLocalName[each.value.id].id
  name                   = each.value.name
}

Upvotes: 1

Related Questions