2
votes

I am creating an Azure VNet using terraform, and creating a couple subnets in it. Later on , I want to create a network interface, and want to put it in one of the subnets already created for VNet. I do not know how to reference that subnet.

I tried below but it is now working:

subnet_id = "${azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}"

resource "azurerm_virtual_network" "virtual-network" {
    name                = "${var.ClientShortName}-az-network"
    address_space       = ["${local.AzureInfraNetwork}"]
    location            = "${var.resource-location}"
    resource_group_name =  "${azurerm_resource_group.test-resource-group.name}"

subnet {
    name           = "ServersSubnet"
    address_prefix = "${local.ServersSubnet}"
}

subnet {
    name           = "GatewaySubnet"
    address_prefix = "${local.GatewaySubnet}"
} 
}

Error: Cannot index a set value

on main.tf line 120, in resource "azurerm_network_interface" "DCNIC": 120: subnet_id = "${azurerm_virtual_network.virtual-network.subnet.ServersSubnet.id}"

Block type "subnet" is represented by a set of objects, and set elements do not have addressable keys. To find elements matching specific criteria, use a "for" expression with an "if" clause.

4

4 Answers

2
votes

Below is the complete solution.

If the subnets are created as blocks, you can reference a given subnet's resource ID as follows:

resource "azurerm_resource_group" "main" {
  name     = "vnet-rg"
  location = "eastus"
}

resource "azurerm_virtual_network" "main" {
  name                = "my-vnet"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  address_space       = ["10.0.0.0/16"]

  subnet {
    name           = "subnet1"
    address_prefix = "10.0.1.0/24"
  }

  subnet {
    name           = "subnet2"
    address_prefix = "10.0.2.0/24"
  }

  subnet {
    name           = "subnet3"
    address_prefix = "10.0.3.0/24"
  }

}

output "subnet1_id" {
  value = azurerm_virtual_network.main.subnet.*.id[0]
}

output "subnet2_id" {
  value = azurerm_virtual_network.main.subnet.*.id[1]
}

output "subnet3_id" {
  value = azurerm_virtual_network.main.subnet.*.id[2]
}
1
votes

When creating subnets as blocks you must reference them using the list syntax, e.g.:

foo = azurerm_virtual_network.virtual-network.subnet[0].id
bar = azurerm_virtual_network.virtual-network.subnet[1].id

This is useful if the subnets form a pool of redundant resources and you don't care about referencing any subnet in particular.

I don't believe that's your case, so you might consider creating your subnets as separated resources, e.g:

resource "azurerm_virtual_network" "main" {
    name                = "${var.ClientShortName}-az-network"
    address_space       = [local.AzureInfraNetwork]
    location            = var.resource-location
    resource_group_name = azurerm_resource_group.test-resource-group.name
}

resource "azurerm_subnet" "server" {
    virtual_network_name  = azurerm_virtual_network.main.name
    name                  = "ServersSubnet"
    address_prefix        = local.ServersSubnet
}

resource "azurerm_subnet" "gateway" {
    virtual_network_name  = azurerm_virtual_network.main.name
    name                  = "GatewaySubnet"
    address_prefix        = local.ServersSubnet
}

Then you could reference one of your subnets using the regular object attribute syntax:

foo = azurerm_subnet.server.id

Also note that I'm using terraform => 0.12 syntax, so I can write foo.bar instead of "${foo.bar}" when I don't need string interpolation.

1
votes

If anyone else needs the answer to this use this:

"${element(azuread_application.events_backend.app_role[*].id,0)}"
0
votes

You can break this out into creating the virtual network and the subnet as separate resources. Advantage of this is that you can return your subnets as a map rather than a list, making it easier to retrieve by name later on, it also makes it stable if you need to add/remove subnets at a later stage.

locals {
  subnets = {
    Servers = "10.0.1.0/24",
    Gateway = "10.0.2.0/24"
  }
}

resource "azurerm_resource_group" "main" {
  name     = "vnet-rg"
  location = "eastus"
}

resource "azurerm_virtual_network" "main" {
  name                = "my-vnet"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  address_space       = [ local.AzureInfraNetwork ]    
}

resource "azurerm_subnet" "main" {
  for_each = var.subnets

  name                 = "${each.key}-subnet"
  resource_group_name  = azurerm_resource_group.main.name
  virtual_network_name = azurerm_virtual_network.main.name
  address_prefixes     = [ each.value ]
}

output "subnets" {
  value = azurerm_subnet.main
}