I see some strange behaviour while creating multiple vnets / subnets in azure. In the below .tfvars i define a object.
network = {
vnet1 = {
name = "vnet-dev-westeurope-001"
location = "westeurope"
cidr = ["10.18.0.0/16"]
subnets = {
sn1 = {
name = "subnet-dev-westeurope-001"
location = "westeurope"
cidr = ["10.18.1.0/24"]
nsg = "nsg-dev-westeurope-001"
endpoints = []
}
}
},
vnet2 = {
name = "vnet-dev-eastus2-001"
location = "eastus2"
cidr = ["10.19.0.0/16"]
subnets = {
sn1 = {
name = "subnet-dev-eastus2-001"
location = "eastus2"
cidr = ["10.19.1.0/24"]
nsg = "nsg-dev-eastus2-001"
endpoints = []
}
}
},
vnet3 = {
name = "vnet-dev-southeastasia-001"
location = "southeastasia"
cidr = ["10.20.0.0/16"]
subnets = {
sn1 = {
name = "subnet-dev-southeastasia-001"
location = "southeastasia"
cidr = ["10.20.1.0/24"]
nsg = "nsg-dev-southeastasia-001"
endpoints = []
}
}
}
}
In the below code i iterate through the key network to create multiple vnets.
resource "azurerm_virtual_network" "vnets" {
for_each = can(var.network) ? var.network : null
name = each.value.name
resource_group_name = azurerm_resource_group.rg["network"].name
location = each.value.location
address_space = each.value.cidr
}
To be able to create multiple subnets on each vnet using the tfvars i create i local variable with the flatten function. The resource subnet iterates through this local variable using the below code.
locals {
network_subnets = flatten([
for network_key, network in var.network : [
for subnet_key, subnet in network.subnets : {
network_key = network_key
subnet_key = subnet_key
address_prefixes = subnet.cidr
subnet_name = subnet.name
nsg_name = subnet.nsg
location = subnet.location
endpoints = subnet.endpoints
virtual_network_name = azurerm_virtual_network.vnets[network_key].name
}
]
])
}
resource "azurerm_subnet" "subnets" {
for_each = {
for sn in local.network_subnets : "${sn.network_key}.${sn.subnet_key}" => sn
}
name = each.value.subnet_name
resource_group_name = azurerm_resource_group.rg["network"].name
virtual_network_name = each.value.virtual_network_name
address_prefixes = each.value.address_prefixes
service_endpoints = lookup(each.value, "endpoints", null)
}
The below output show the local.network_subnets list it produced:
Changes to Outputs:
+ network = [
+ {
+ address_prefixes = [
+ "10.18.1.0/24",
]
+ endpoints = []
+ location = "westeurope"
+ network_key = "vnet1"
+ nsg_name = "nsg-dev-westeurope-001"
+ subnet_key = "sn1"
+ subnet_name = "subnet-dev-westeurope-001"
+ virtual_network_name = "vnet-dev-westeurope-001"
},
+ {
+ address_prefixes = [
+ "10.19.1.0/24",
]
+ endpoints = []
+ location = "eastus2"
+ network_key = "vnet2"
+ nsg_name = "nsg-dev-eastus2-001"
+ subnet_key = "sn1"
+ subnet_name = "subnet-dev-eastus2-001"
+ virtual_network_name = "vnet-dev-eastus2-001"
},
+ {
+ address_prefixes = [
+ "10.20.1.0/24",
]
+ endpoints = []
+ location = "southeastasia"
+ network_key = "vnet3"
+ nsg_name = "nsg-dev-southeastasia-001"
+ subnet_key = "sn1"
+ subnet_name = "subnet-dev-southeastasia-001"
+ virtual_network_name = "vnet-dev-southeastasia-001"
},
Finally i also iterate through this local regarding the nsg’s and associations
resource "azurerm_network_security_group" "nsg" {
for_each = {
for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
}
name = each.value.nsg_name
resource_group_name = azurerm_resource_group.rg["network"].name
location = each.value.location
}
resource "azurerm_subnet_network_security_group_association" "nsg_as" {
for_each = {
for subnet in local.network_subnets : "${subnet.network_key}.${subnet.subnet_key}" => subnet
}
subnet_id = azurerm_subnet.subnets[each.key].id
network_security_group_id = azurerm_network_security_group.nsg[each.key].id
}
The code works… only the problem i am facing is that randomly not all subnets are created. Terraform says it is created, but the subnet is not existing on for example 1 of the 3 vnets.
However the subnets are always created when i add --parallelism=2 in my terraform apply command.
My question is:
Is my code properly constructed? Everything should be properly implicitly linked together. Is this the case or i am i missing something?
Or is this a limitation in the azure rest api?