skip to Main Content

I am trying to create Azure virtual network ( azurerm_virtual_network ) and Subnets based on the input json local block.

locals {
  networks = {
    hub-vnet = {
      address_space = ["10.0.0.0/9"]
      subnets = {
        app = {
          address_prefix    = ["10.1.0.0./16"]
          enable_netgateway = false
        },
        db = {
          address_prefix    = ["10.2.0.0./16"]
          enable_netgateway = true
        }
      }
    }
  }
}

locals {
  vnet_details = flatten([
    for k, v in local.networks : {
      // Nested for loop to read the map in values
      for snet_k, snet_val in v.subnets :
      snet_k => merge(
        {
          vnetName         = k
          vnet_addresspace = v.address_space
          subnetName       = snet_k
        }, snet_val
      )
      // Filtering 
      if(snet_val.enable_netgateway == true)
    }
  ])
}




resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
  for_each = { for item in local.vnet_details : item.subnetName => item }

  name                = each.value.vnetName
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  address_space       = each.value.vnet_addresspace
}

resource "azurerm_subnet" "example" {
  for_each = { for item in local.vnet_details : item.subnetName => item }

  name                 = each.value.subnetName
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example[each.key].name
  address_prefixes     = each.value.address_prefix
}

Expectation is create app subnet but I am getting below error. Could someone help me what is missing the foreach loop in azurerm_virtual_network resource ?

│ Error: Unsupported attribute
│
│   on forloop.tf line 89, in resource "azurerm_virtual_network" "example":
│   89:   for_each = { for item in local.vnet_details : item.subnetName => item }
│
│ This object does not have an attribute named "subnetName".

2

Answers


  1. The trailing dots on these lines could be the problem:

    address_prefix = ["10.1.0.0./16"]

    address_prefix = ["10.2.0.0./16"]

    Login or Signup to reply.
  2. Verifying Azure Virtual Network and Subnet Configurations in the Azure Portal

    The reason for the error is that your for_each expression in the azurerm_virtual_network resource is not structured properly. In particular, the local.vnet_details list that you’re looping over does not have a subnetName attribute for each element, since the vnet_details list that you’ve created has a flattened structure that does not correspond to what the for_each expects.

    The main focus of my configuration will be to create a configuration that correctly defines and uses local.vnet_details for creating virtual networks and local.subnet_details for creating subnets.

    My configuration:

    provider "azurerm" {
      features {}
    }
    
    locals {
      networks = {
        "hub-vnet" = {
          address_space = ["10.0.0.0/9"],
          subnets = {
            app = {
              address_prefixes = ["10.1.0.0/16"], // Ensure this is a list
              enable_netgateway = false
            },
            db = {
              address_prefixes = ["10.2.0.0/16"], // Ensure this is a list
              enable_netgateway = true
            }
          }
        }
      }
    }
    
    locals {
      vnet_details = { for vnet_name, vnet_config in local.networks :
                       vnet_name => {
                         address_space = vnet_config.address_space,
                         subnets = vnet_config.subnets
                       }
                     }
    }
    
    resource "azurerm_resource_group" "example" {
      name     = "testvkrg-resources"
      location = "West Europe"
    }
    
    resource "azurerm_virtual_network" "example" {
      for_each = local.vnet_details
    
      name                = each.key
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      address_space       = each.value.address_space
    }
    
    
    locals {
      // Flatten subnets into a structure suitable for iteration in resource blocks
      subnet_details = merge([
        for vnet_name, vnet_config in local.networks : {
          for subnet_name, subnet_config in vnet_config.subnets : "${vnet_name}-${subnet_name}" => {
            vnet_name      = vnet_name,
            subnet_name    = subnet_name,
            address_prefixes = subnet_config.address_prefixes // Ensure this matches the structure
          }
        }
      ]...)
    }
    
    resource "azurerm_subnet" "example" {
      for_each             = local.subnet_details
      name                 = each.value.subnet_name
      resource_group_name  = azurerm_resource_group.example.name
      virtual_network_name = each.value.vnet_name
      address_prefixes     = each.value.address_prefixes
    
      # Explicitly declare the dependency on the virtual network
      depends_on = [azurerm_virtual_network.example]
    }
    

    Deployment Succeded:

    enter image description here

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search