Filter azurerm_network_interface output

Hello. I am calling a module to create multiple VMs with a for_each. Module gets called twice and each creates a nic resource. One of the VMs in each module call (total of 2) get a second ip configuration. I want to filter the output and get the private ip of only the nic that got the second ip configuration.

module call:

module "paloAltoFW" {
  source = "../../modules/palo-alto-fw"
  for_each = var.palo_alto_FW

  global_settings         = var.global_settings
  paFW_key                = each.key
  name                    = module.palo_alto_FW_name[each.key].name
  location                = var.location_map[each.value.location_map_key]
  resource_group_name     = azurerm_resource_group.resource_group[each.value.resource_group_key].name
  resource_group_id       = azurerm_resource_group.resource_group[each.value.resource_group_key].id
  vm_size                 = each.value.vm_size
  admin_username          = each.value.admin_username
  admin_password          = each.value.admin_password
  pa_publisher            = each.value.pa_publisher
  pa_sku                  = each.value.pa_sku
  pa_offer                = each.value.pa_offer
  pa_version              = each.value.pa_version
  transit_hub_vnet_resource_group_id  = data.azurerm_resource_group.transit_hub_rg.id
  transit_hub_vnet_mgmt_subnet        = data.azurerm_subnet.mgmt.id
  transit_hub_vnet_untrust_subnet     = data.azurerm_subnet.untrust.id
  transit_hub_vnet_trustInt_subnet    = data.azurerm_subnet.trustInt.id
  transit_hub_vnet_trustExt_subnet    = data.azurerm_subnet.trustExt.id
  transit_hub_vnet_fwHA_subnet        = data.azurerm_subnet.fwHA.id
  log_analytics_workspace_id          = local.log_analytics_resource_id
  storage_account_diag_logs_id        = local.storage_account_diag_logs[each.value.location_map_key].id
  palo_altoFW_untrust_pip_id          = each.value.pip_key != "" ? module.palo_alto_pip[each.value.pip_key].id : null
  create_floating_ipconfig            = each.value.create_floating_ipconfig
  deployInAvailabilitySet             = each.value.deployInAvailabilitySet
  availability_zone                   = each.value.availability_zone
  availability_set                    = azurerm_availability_set.palo_alto_availability_set[each.value.availability_set_key].id
  palo_altoFW_role_definition_id      = azurerm_role_definition.palo_alto_active_passive_role_definition[each.value.role_defintion_key].role_definition_id
  tags                                = merge(lookup(each.value, "tags", {}), local.tags)
}

input map:

palo_alto_FW = {
  pa01 = {
    name = "pa01"
    location_map_key                = "primary"
    resource_group_key              = "rg_paloalto"
    vm_size                         = "Standard_DS4_v2"
    admin_username                  = "***********"
    admin_password                  = "***********"
    pa_publisher                    = "paloaltonetworks"
    pa_sku                          = "byol"
    pa_offer                        = "vmseries-flex"
    pa_version                      = "10.1.5"
    pip_key                         = "pa01_untrust_pip"
    create_floating_ipconfig        = true
    deployInAvailabilitySet         = true
    availability_zone               = 1
    availability_set_key            = "pa_as"
    role_defintion_key              = "pa_rd"
  }
  pa02 = {
    name = "pa02"
    location_map_key                = "primary"
    resource_group_key              = "rg_paloalto"
    vm_size                         = "Standard_DS4_v2"
    admin_username                  = "***********"
    admin_password                  = "***********"
    pa_publisher                    = "paloaltonetworks"
    pa_sku                          = "byol"
    pa_offer                        = "vmseries-flex"
    pa_version                      = "10.1.5"
    pip_key                         = ""
    create_floating_ipconfig        = false
    deployInAvailabilitySet         = true
    availability_zone               = 2
    availability_set_key            = "pa_as"
    role_defintion_key              = "pa_rd"
  }
}

module outputs.tf. The [*] is there because the output is contained in a module being called with for_each.

output "fwTrustInt_nic_floating_ip_config" {
    value = data.azurerm_network_interface.fwTrustInt_nic_floating_ip_config[*].ip_configuration
}

My root module output.tf.

output "fwTrustInt_nic_floating_ip_config" {
  value = values(module.paloAltoFW)[*].fwTrustInt_nic_floating_ip_config
}

The result is this:

fwTrustInt_nic_floating_ip_config = [
  [
    [
      {
        "application_gateway_backend_address_pools_ids" = []
        "application_security_group_ids" = []
        "gateway_load_balancer_frontend_ip_configuration_id" = ""
        "load_balancer_backend_address_pools_ids" = []
        "load_balancer_inbound_nat_rules_ids" = []
        "name" = "ipconfig1"
        "primary" = true
        "private_ip_address" = "10.121.0.38"
        "private_ip_address_allocation" = "Dynamic"
        "private_ip_address_version" = "IPv4"
        "public_ip_address_id" = ""
        "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
      },
{
        "application_gateway_backend_address_pools_ids" = []
        "application_security_group_ids" = []
        "gateway_load_balancer_frontend_ip_configuration_id" = ""
        "load_balancer_backend_address_pools_ids" = []
        "load_balancer_inbound_nat_rules_ids" = []
        "name" = "trustInt-floating"
        "primary" = false
        "private_ip_address" = "10.121.0.39"
        "private_ip_address_allocation" = "Dynamic"
        "private_ip_address_version" = "IPv4"
        "public_ip_address_id" = ""
        "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
      },
    ],
  ],
[
    [
      {
        "application_gateway_backend_address_pools_ids" = []
        "application_security_group_ids" = []
        "gateway_load_balancer_frontend_ip_configuration_id" = ""
        "load_balancer_backend_address_pools_ids" = []
        "load_balancer_inbound_nat_rules_ids" = []
        "name" = "ipconfig1"
        "primary" = true
        "private_ip_address" = "10.121.0.37"
        "private_ip_address_allocation" = "Dynamic"
        "private_ip_address_version" = "IPv4"
        "public_ip_address_id" = ""
        "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
      },
    ],
  ],
]

I would like to only get the “private_ip_address” = “10.121.0.39” as a string because it has the “name” = “trustInt-floating”. This ip will be used as a next hop in an Azure route table.

Any help would be appreciated.

Hi @adonerok,

It looks like you currently have lists of lists of objects as a result of using multiple levels of splat operator, so I think I’d start here by using the flatten function to simplify into a single list of objects.

From there you can use a for expression to project this into a map of objects instead, using the name strings as keys. Once you have a mapping from name to object you can then access the individual attributes you need from each object.

locals {
  interfaces = tomap({
    for o in flatten(values(module.paloAltoFW)[*].fwTrustInt_nic_floating_ip_config) :
    o.name => o
  })
}

I think then the specific value you wanted would be in local.interfaces["trustInt-floating"].private_ip_address, and of course you can use this data structure for other lookups of particular attributes of particular interfaces too, as needed.

Thanks for the quick reply. I had to make a couple of changes.

I was getting this error due to the duplicate keys in flatten/for.

│ Error: Duplicate object key
│
│   on main.tf line 179, in locals:
│  177:   interfaces = tomap({
│  178:     for o in flatten(var.fwTrustInt_nic_floating_ip_config) :
│  179:     o.name => o
│  180:   })
│     ├────────────────
│     │ o.name is "ipconfig1"
│
│ Two different items produced the key "ipconfig1" in this 'for' expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.

I added the ellipsis as follows which resulted in:

locals {
  interfaces = tomap({
    for o in flatten(var.fwTrustInt_nic_floating_ip_config) :
    o.name => o...
  })
}

fwTrustInt_nic_floating_ip_config = tomap({
  "ipconfig1" = tolist([
    {
      "application_gateway_backend_address_pools_ids" = []
      "application_security_group_ids" = []
      "gateway_load_balancer_frontend_ip_configuration_id" = ""
      "load_balancer_backend_address_pools_ids" = []
      "load_balancer_inbound_nat_rules_ids" = []
      "name" = "ipconfig1"
      "primary" = true
      "private_ip_address" = "10.121.0.38"
      "private_ip_address_allocation" = "Dynamic"
      "private_ip_address_version" = "IPv4"
      "public_ip_address_id" = ""
      "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
    },
    {
      "application_gateway_backend_address_pools_ids" = []
      "application_security_group_ids" = []
      "gateway_load_balancer_frontend_ip_configuration_id" = ""
      "load_balancer_backend_address_pools_ids" = []
      "load_balancer_inbound_nat_rules_ids" = []
      "name" = "ipconfig1"
      "primary" = true
      "private_ip_address" = "10.121.0.37"
      "private_ip_address_allocation" = "Dynamic"
      "private_ip_address_version" = "IPv4"
      "public_ip_address_id" = ""
      "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
    },
  ])
  "trustInt-floating" = tolist([
    {
      "application_gateway_backend_address_pools_ids" = []
      "application_security_group_ids" = []
      "gateway_load_balancer_frontend_ip_configuration_id" = ""
      "load_balancer_backend_address_pools_ids" = []
      "load_balancer_inbound_nat_rules_ids" = []
      "name" = "trustInt-floating"
      "primary" = false
      "private_ip_address" = "10.121.0.39"
      "private_ip_address_allocation" = "Dynamic"
      "private_ip_address_version" = "IPv4"
      "public_ip_address_id" = ""
      "subnet_id" = "/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.Network/virtualNetworks/xxx/subnets/xxx"
    },
  ])
})

I was not able to access the element using the key as it is a list. so I changed it to:

output "fwTrustInt_nic_floating_ip_config" {
  #value = local.interfaces
  value = local.interfaces["trustInt-floating"].*.private_ip_address
  #value = join("",local.interfaces["trustInt-floating"].*.private_ip_address)
}

and ultimately the join to get the ip address as a string.

Thanks for your help!!!