Search code examples
azureterraformtuplesterraform-provider-azure

How to output a specific attribute from a map within a map while having an attribute substring as conditional in terraform?


Objective:

Using Terraform 1.3.5 and the latest AzureRM provider version, assign a (dynamic) subnet ID to a VM NIC but only when the subnet's name = "all"

Main premise:

  • the subnet name is an attribute of a map within another map(object({})) variable (full output below)

This:

output "debug_all_subnet_id" {
  value = azurerm_virtual_network.vnet_workloads
}

produces this:

Changes to Outputs:
  + debug_all_subnet_id = {
      + customerA = {
          + address_space           = [
              + "10.200.17.128/28",
            ]
          + bgp_community           = null
          + ddos_protection_plan    = []
          + dns_servers             = (known after apply)
          + edge_zone               = null
          + encryption              = []
          + flow_timeout_in_minutes = null
          + guid                    = (known after apply)
          + id                      = (known after apply)
          + location                = "westeurope"
          + name                    = (known after apply)
          + resource_group_name     = (known after apply)
          + subnet                  = [
              + {
                  + address_prefix = "10.200.17.128/29"
                  + id             = (known after apply)
                  + name           = "base"
                  + security_group = ""
                },
              + {
                  + address_prefix = "10.200.17.136/29"
                  + id             = (known after apply)
                  + name           = "all"
                  + security_group = ""
                },
            ]
          + tags                    = null
          + timeouts                = null
        }
      + customerB = {
          + address_space           = [
              + "10.200.17.192/28",
            ]
          + bgp_community           = null
          + ddos_protection_plan    = []
          + dns_servers             = (known after apply)
          + edge_zone               = null
          + encryption              = []
          + flow_timeout_in_minutes = null
          + guid                    = (known after apply)
          + id                      = (known after apply)
          + location                = "eastus2"
          + name                    = (known after apply)
          + resource_group_name     = (known after apply)
          + subnet                  = [
              + {
                  + address_prefix = "10.200.17.192/29"
                  + id             = (known after apply)
                  + name           = "base"
                  + security_group = ""
                },
              + {
                  + address_prefix = "10.200.17.200/29"
                  + id             = (known after apply)
                  + name           = "all"
                  + security_group = ""
                },
            ]
          + tags                    = null
          + timeouts                = null
        }
      + hubA      = {
          + address_space           = [
              + "10.200.17.0/27",
            ]
          + bgp_community           = null
          + ddos_protection_plan    = []
          + dns_servers             = (known after apply)
          + edge_zone               = null
          + encryption              = []
          + flow_timeout_in_minutes = null
          + guid                    = (known after apply)
          + id                      = (known after apply)
          + location                = "westeurope"
          + name                    = (known after apply)
          + resource_group_name     = (known after apply)
          + subnet                  = [
              + {
                  + address_prefix = "10.200.17.0/28"
                  + id             = (known after apply)
                  + name           = "base"
                  + security_group = ""
                },
              + {
                  + address_prefix = "10.200.17.16/28"
                  + id             = (known after apply)
                  + name           = "all"
                  + security_group = ""
                },
            ]
          + tags                    = null
          + timeouts                = null
        }
      + hubB      = {
          + address_space           = [
              + "10.200.17.64/27",
            ]
          + bgp_community           = null
          + ddos_protection_plan    = []
          + dns_servers             = (known after apply)
          + edge_zone               = null
          + encryption              = []
          + flow_timeout_in_minutes = null
          + guid                    = (known after apply)
          + id                      = (known after apply)
          + location                = "eastus2"
          + name                    = (known after apply)
          + resource_group_name     = (known after apply)
          + subnet                  = [
              + {
                  + address_prefix = "10.200.17.64/28"
                  + id             = (known after apply)
                  + name           = "base"
                  + security_group = ""
                },
              + {
                  + address_prefix = "10.200.17.80/28"
                  + id             = (known after apply)
                  + name           = "all"
                  + security_group = ""
                },
            ]
          + tags                    = null
          + timeouts                = null
        }
    }

And I'm trying to do something like this, but have no idea how to achieve it with terraform:

output "debug_all_subnet_id" {

  if azurerm_virtual_network.vnet_workloads[*].subnet.name = "all"
   then
    value = azurerm_virtual_network.vnet_workloads[*].subnet.id
  else
   exit/null

}

Side note:

This:

output "debug_all_subnet_id" {
  value = azurerm_virtual_network.vnet_workloads["customerA"].subnet
}

gives me this, which leaves me a little bit closer to the desired output, but not close enough since in the main code I need to retrieve the ID of a specific subnet name ("all"/"snet-all") amongst different vnets and subnets:

Changes to Outputs:
  + debug_all_subnet_id = [
      + {
          + address_prefix = "10.200.17.128/29"
          + id             = (known after apply)
          + name           = "base"
          + security_group = ""
        },
      + {
          + address_prefix = "10.200.17.136/29"
          + id             = (known after apply)
          + name           = "all"
          + security_group = ""
        },
    ]

Any ideas?


Solution

  • I will try to give an answer, but keep in mind this was done moving the output you have shown to the local variables, so you might try to adjust that to your need:

    locals {
      debug_all_subnet_id = {
        customerA = {
          address_space = [
            "10.200.17.128/28",
          ]
          bgp_community           = null
          ddos_protection_plan    = []
          dns_servers             = ""
          edge_zone               = null
          encryption              = []
          flow_timeout_in_minutes = null
          guid                    = ""
          id                      = ""
          location                = "westeurope"
          name                    = ""
          resource_group_name     = ""
          subnet = [
            {
              address_prefix = "10.200.17.128/29"
              id             = ""
              name           = "base"
              security_group = ""
            },
            {
              address_prefix = "10.200.17.136/29"
              id             = ""
              name           = "all"
              security_group = ""
            },
          ]
          tags     = null
          timeouts = null
        }
        customerB = {
          address_space = [
            "10.200.17.192/28",
          ]
          bgp_community           = null
          ddos_protection_plan    = []
          dns_servers             = ""
          edge_zone               = null
          encryption              = []
          flow_timeout_in_minutes = null
          guid                    = ""
          id                      = ""
          location                = "eastus2"
          name                    = ""
          resource_group_name     = ""
          subnet = [
            {
              address_prefix = "10.200.17.192/29"
              id             = ""
              name           = "base"
              security_group = ""
            },
            {
              address_prefix = "10.200.17.200/29"
              id             = ""
              name           = "all"
              security_group = ""
            },
          ]
          tags     = null
          timeouts = null
        }
        hubA = {
          address_space = [
            "10.200.17.0/27",
          ]
          bgp_community           = null
          ddos_protection_plan    = []
          dns_servers             = ""
          edge_zone               = null
          encryption              = []
          flow_timeout_in_minutes = null
          guid                    = ""
          id                      = ""
          location                = "westeurope"
          name                    = ""
          resource_group_name     = ""
          subnet = [
            {
              address_prefix = "10.200.17.0/28"
              id             = ""
              name           = "base"
              security_group = ""
            },
            {
              address_prefix = "10.200.17.16/28"
              id             = ""
              name           = "all"
              security_group = ""
            },
          ]
          tags     = null
          timeouts = null
        }
        hubB = {
          address_space = [
            "10.200.17.64/27",
          ]
          bgp_community           = null
          ddos_protection_plan    = []
          dns_servers             = ""
          edge_zone               = null
          encryption              = []
          flow_timeout_in_minutes = null
          guid                    = ""
          id                      = ""
          location                = "eastus2"
          name                    = ""
          resource_group_name     = ""
          subnet = [
            {
              address_prefix = "10.200.17.64/28"
              id             = ""
              name           = "base"
              security_group = ""
            },
            {
              address_prefix = "10.200.17.80/28"
              id             = ""
              name           = "all"
              security_group = ""
            },
          ]
          tags     = null
          timeouts = null
        }
    }
    
    output "debug_all_subnet_id" {
      value = flatten([for i in values(local.debug_all_subnet_id)[*].subnet: [ for s in i: s if s.name == "all" ]])
    }
    

    This will result in:

    > flatten([for i in values(local.debug_all_subnet_id)[*].subnet: [ for s in i: s if s.name == "all" ]])
    [
      {
        "address_prefix" = "10.200.17.136/29"
        "id" = ""
        "name" = "all"
        "security_group" = ""
      },
      {
        "address_prefix" = "10.200.17.200/29"
        "id" = ""
        "name" = "all"
        "security_group" = ""
      },
      {
        "address_prefix" = "10.200.17.16/28"
        "id" = ""
        "name" = "all"
        "security_group" = ""
      },
      {
        "address_prefix" = "10.200.17.80/28"
        "id" = ""
        "name" = "all"
        "security_group" = ""
      },
    ]