Looping with complex types - maps, objects, lists ... oh my```

TL;DR - want to iterate over a list that contains different types of data, looking for examples with for_each as well as conditional logic

I’m reorganizing and consolidating variable definitions. For example:

"subnets": [
    {
      "name": "inside",
      "prefix": "10.248.0.0/28",
      "route_table": true,
      "nsg": true,
      "security_group_rules": [
        {
          "name": "AllowAllInbound",
          "properties": {
            "priority": 100,
            "access": "Allow",
            "direction": "Inbound",
            "protocol": "*",
            "sourcePortRange": "*",
            "destinationPortRange": "*",
            "sourceAddressPrefix": "*",
            "destinationAddressPrefix": "*"
          }
        },
        {
          "name": "AllowAllOutbound",
          "properties": {
            "priority": 100,
            "access": "Allow",
            "direction": "Outbound",
            "protocol": "*",
            "sourcePortRange": "*",
            "destinationPortRange": "*",
            "sourceAddressPrefix": "*",
            "destinationAddressPrefix": "*"
          }
        }
      ]
    },

you can see that I have a subnet key that contains objects, lists, etc. I’d like to look through this subnet list and build the various items. First, run down the list and build the subnets, then loop over the same list and build the security groups. The issue is that Terraform seems to be having a hard time with all of the nesting of types. I figure I should be able to use a

resource "azurerm_subnets" "subnets" {
    for_each         = var.subnets 

    name             = each.value.name
    address_prefixes = [ each.value.prefix ]
}

etc… but I get an error of
argument must be a map, or set of strings, and you have provided a value of type tuple.

my variable definition is set with no type, just to see if TF could figure it out for me. I’ve tried:

variable "subnets" {
  type = list(object({
    name = string
    prefix = string
    nsg = bool
    security_group_rules = list(string)
  }))
}

but it just gets more complicate. I’m HOPING I can keep the tfvars.json format I have since it would be super functional. I know I could just format my .tfvars.json differently and make it work but that would end up being messy.

Thoughts?

I’m looking to do the same thing, did you have much luck with this? Thanks

The argument to for_each must be a map, or set of strings. In the example shown here, it is a tuple, as the error message says.

An appropriate approach to convert it would be:

  for_each = {for x in var.subnets: x.name => x}

Consult https://www.terraform.io/language/expressions/for for additional information.