I’m trying to create virtual network peering resources by passing in existing resource data to a child module. Our Azure network will be a typical hub/spoke design, so I’m using two resource blocks to define the different peering configurations (one creates the peering between the spokes and the hub, one creates the peering between the hub and the spokes). I actually have the first one working already, but the second is giving me trouble.
From main.tf in our networking module (parent module)
resource "azurerm_virtual_network" "vnets" {
for_each = var.vnets
name = each.key
location = each.value.location
resource_group_name = each.value.resource_group_name
address_space = each.value.address_space
dns_servers = each.value.dns_servers
depends_on = [
azurerm_resource_group.rg-network
]
}
module "firewall" {
source = "./modules/Fortigate/Active-Active-ELB-ILB"
vnet_hub_id = azurerm_virtual_network.vnets["${var.hub_vnet}"].id
vnet_hub_name = var.vnet_hub_name
subnets = var.subnets
vnets = var.vnets
subnet_associations = {for name,id in azurerm_subnet.subnets: name => id}
rg_network_name = azurerm_resource_group.rg-network.name
rg_network_location = azurerm_resource_group.rg-network.location
rg_keyvault_name = var.rg_keyvault_name
}
The two peering resource blocks from main.tf in firewall module (child module)
resource "azurerm_virtual_network_peering" "peer-spoke-hub-eastus" {
for_each = {
for k,v in var.vnets : k => v
if v.hub != true
}
name = "peer-${each.key}-to-hub"
resource_group_name = var.rg_network_name
virtual_network_name = each.key
remote_virtual_network_id = var.vnet_hub_id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = false
depends_on = [
var.vnets,
var.subnets,
azurerm_subnet_route_table_association.subnet_associations,
]
}
resource "azurerm_virtual_network_peering" "peer-hub-spoke-eastus" {
for_each = {
for k,v in data.azurerm_virtual_network.vnet_spoke : k => v
}
name = "peer-hub-to-${each.key}"
resource_group_name = var.rg_network_name
virtual_network_name = var.vnet_hub_name
remote_virtual_network_id = each.value.id
allow_virtual_network_access = true
allow_forwarded_traffic = true
allow_gateway_transit = false
depends_on = [
var.vnets,
var.subnets,
azurerm_subnet_route_table_association.subnet_associations,
]
}
The first block was relatively easy. I’m not sure if this is the best way to do it, but I was able to just loop through all my vnet input objects using the original var.vnets variable. Then I’m using an attribute that I added to that variable to define which vnet is the hub and excluding it. This works fine.
For the second resource block I need to provide names and ids of the spoke networks. I can generate that easily enough using similar code to subnet_associatons but I haven’t figured out how to filter the hub network out.
The first thing I tried was some sort of for statement in an input variable in the firewall module block. I don’t have my code for that attempt, but something like
vnet_spoke_ids = for k,v in azurerm_virtual_network.vnets : k => v if v.hub != true
The second was trying to figure out if it might be possible to merge the ID into var.vnets. I… really struggle with some of the typing and data manipulation in Terraform. I didn’t get very far there.
Finally I’ve been trying to see if I could somehow bring in all the vnets from the data source azurerm_virtual_networks, but again I haven’t found a way to filter out the hub network. It would be nice if there were a way to filter out results based on name for example. Something like
filter {
name != var.vnet_hub
}
The only thing I have thought of but haven’t tried yet would be to tag the virtual networks as either hubs or spokes, and then filter on tag = spoke.
What would be the best way to accomplish what I’m trying to do?