How to get subnet_id from terraform when subnets created with for_each

Problem Statement: Trying to get subnet id from subnets created with for_each in terraform
My terraform.tfvars.json:

"subnets" : {
        "Dev" :
        [  
        {"gw_snet":{
          "name"                 : "GatewaySubnet",
          "address_prefixes"     : ["10.1.1.0/24"]
        },
        "dns-snet" : {
          "name"                 : "InboundDNSSubnet",
          "address_prefixes"     : ["10.1.2.0/24"]
        },
        "common_snet" : {
          "name"                 : "Common",
          "address_prefixes"     : ["10.1.3.0/24"]
        },
        "clientdata_snet" : {
          "name"                 : "ClientDataSubnet",
          "address_prefixes"     : ["10.1.4.0/20"]
        }}
        ],
        "Stage" :
        [  
        {"gw_snet":{
          "name"                 : "GatewaySubnet",
          "address_prefixes"     : ["10.2.1.0/24"]
        },
        "dns-snet" : {
          "name"                 : "InboundDNSSubnet",
          "address_prefixes"     : ["10.2.2.0/24"]
        },
        "common_snet" : {
          "name"                 : "Common",
          "address_prefixes"     : ["10.2.3.0/24"]
        },
        "clientdata_snet" : {
          "name"                 : "ClientDataSubnet",
          "address_prefixes"     : ["10.2.4.0/20"]
        }}
        ],
        "Prod" :
        [  
        {"gw_snet":{
          "name"                 : "GatewaySubnet",
          "address_prefixes"     : ["10.3.1.0/24"]
        },
        "dns-snet" : {
          "name"                 : "InboundDNSSubnet",
          "address_prefixes"     : ["10.3.2.0/24"]
        },
        "common_snet" : {
          "name"                 : "Common",
          "address_prefixes"     : ["10.3.3.0/24"]
        },
        "clientdata_snet" : {
          "name"                 : "ClientDataSubnet",
          "address_prefixes"     : ["10.3.4.0/20"]
        }}
        ]
      }  

my Main.tf

locals {
   net_subnets = merge([
    for env, network in var.subnets : {
      for k, v in network[0] :
      "${k}-${v.name}" => {
        subnet_name      = v.name
        address_prefixes = v.address_prefixes
      } if env == "${var.env}"
  }]...)
}

resource "azurerm_virtual_network" "vnet" {
  for_each = {for k,v in var.vnet_address_space: k=>v if k == "${var.env}"}
  name                = var.hub_vnet_name
  location            = azurerm_resource_group.rg[0].location
  resource_group_name = azurerm_resource_group.rg[0].name
  address_space       = each.value
  dns_servers         = var.dns_servers
  tags     = {
    environment = "${var.env}"
    costcentre = "14500"
  }
  dynamic "ddos_protection_plan" {
    for_each = local.if_ddos_enabled

    content {
      id     = azurerm_network_ddos_protection_plan.ddos[0].id
      enable = false
    }
  }
}

resource "azurerm_subnet" "mysubnet" {
  for_each             = local.net_subnets
  name                 = each.value.subnet_name
  address_prefixes     = each.value.address_prefixes
  virtual_network_name = azurerm_virtual_network.vnet[var.env].name  
  resource_group_name  = var.resource_group_name
  service_endpoints    = var.service_endpoints
}

resource "azurerm_network_security_group" "nsg" {
  name                = "nsg-vnet-orpcb-hub-${var.env}-we-indoundDNS"
  location            = azurerm_resource_group.rg[0].location
  resource_group_name = azurerm_resource_group.rg[0].name
  tags     = {
    environment = "${var.env}"
    costcentre = "14500"
  }
}

resource "azurerm_subnet_network_security_group_association" "nsg-assoc" {
  subnet_id                 =   subnet_id = azurerm_subnet.mysubnet[local.net_subnets.clientdata_snet-ClientDataSubnet].id  

  network_security_group_id = azurerm_network_security_group.nsg.id
}

Error I get is:

β”‚ A reference to a resource type must be followed by at least one attribute access, specifying the resource name.

As I want to attach nsg only to specific subnet,how can I get subnet_id of that specific subnet which is created with for_each

Please help

Hi @onenessboy,

Can you share the entire error message, which will also indicate which part of your configuration the error relates to? Your configuration snippet is too large to quickly scan and find potential errors. Thanks!

1 Like

Hi
Thanks for reply…apologies

My use case is I created multiple subnets in one go by using for_each. Its getting successful. But there after I have many operation, which I need to create as part of one particular subnet for example, ClientdataSubnet in my example above. To explain this further, for example in my original post, I am trying to create a network security group, But want to associate it with only One particular subnet called ClientDataSubnet. i.e i dont want to use for_each while creating associationg of network security group, as I dont want to attach it to all subnets, rather I wanted to attach it only to specific subnet in my case which is ClientDataSubnet. Now I am facing challenges to get this specific subnet id for this ClientDataSubnet

Here the full error message

Error: Unsupported attribute
β”‚ 
β”‚   on main.tf line 121, in resource "azurerm_subnet_network_security_group_association" "nsg-assoc":
β”‚  121:   subnet_id = azurerm_subnet.mysubnet[local.net_subnets.clientdata_snet-ClientDataSubnet].id  
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ local.net_subnets is object with no attributes
β”‚ 
β”‚ This object does not have an attribute named "clientdata_snet-ClientDataSubnet".

I tried below also and resulted in

subnet_id = azurerm_subnet.mysubnet[local.net_subnets.ClientDataSubnet].id

β•·
β”‚ Error: Unsupported attribute
β”‚ 
β”‚   on main.tf line 121, in resource "azurerm_subnet_network_security_group_association" "nsg-assoc":
β”‚  121:   subnet_id = azurerm_subnet.mysubnet[local.net_subnets.ClientDataSubnet].id  
β”‚     β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚     β”‚ local.net_subnets is object with no attributes
β”‚ 
β”‚ This object does not have an attribute named "ClientDataSubnet".

Tried below as well

subnet_id = azurerm_subnet.mysubnet[ClientDataSubnet].id


β•·
β”‚ Error: Invalid reference
β”‚ 
β”‚   on main.tf line 120, in resource "azurerm_subnet_network_security_group_association" "nsg-assoc":
β”‚  120:   subnet_id                 = azurerm_subnet.mysubnet[ClientDataSubnet].id  
β”‚ 
β”‚ A reference to a resource type must be followed by at least one attribute access, specifying the resource name.
β•΅

Please let me know if information makes sense, or if you need more information I can share… thanks again

Hi @onenessboy,

In the first error message it mentions that local.net_subnets is object with no attributes, which suggests that the for expression building that mapping is filtering out all of the networks.

The if clause in there is testing whether the environment name is correct for the currently-selected environment in var.env. Can you confirm that var.env matches one of your environments?

1 Like

yes, it does match var.env variable