Context: This is continuation of below post which I raised Issue while creating multiple subnets using for_each in Terraform
Objective: How to use output value of one resource created and use that for creating another resource in same root module
What I tried:
resource "azurerm_virtual_network" "vnet" {
name = var.hub_vnet_name
location = azurerm_resource_group.rg[0].location
resource_group_name = azurerm_resource_group.rg[0].name
for_each = {for k,v in var.vnet_address_space: k=>v if k == "${var.env}"}
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
}
}
}
output "azurerm_vnets_names" {
value = values(azurerm_virtual_network.vnet)[*].name
}
Till above point its working and I see output of as
Outputs:
azurerm_vnets_names = [
"vnet-hub",
]
Now as next step I am trying to create Subnets in loop as below
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"]
}}
]
}
In 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 == "Dev"
}]...)
}
#Creating subnets
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_nework.vnet.name
resource_group_name = var.resource_group_name
}
Now below line is erroring out
virtual_network_name = azurerm_virtual_nework.vnet.name
saying " since I used for_each
in creating vnet I cannot use that above way
Now since I see output variable which I defined above which is azurerm_vnets_names
, I tried to refer that as below
virtual_network_name = azurerm_vnets_names
it didnt work
Then
I tried to add datasource
data "azurerm_virtual_network" "vnet" {
name = "vnet-hub"
resource_group_name = "hub"
}
then tried below:
virtual_network_name = data.azurerm_virtual_nework.vnet.name
Again error says that.. Its not declared.
I tried below one also, didnt work
virtual_network_name = azurerm_virtual_network.vnet[*].name
Please help me with identifying issue.
CodePudding user response:
This is erroring out because azurerm_virtual_nework.vnet
is a set, not a single value. You created azurerm_virtual_nework.vnet
with a for_each
, so Terraform thinks there can be more than one azurerm_virtual_nework.vnet
resource, and you aren't telling it which one to use. This should be clear if you look at the error message Terraform is giving you.
virtual_network_name = azurerm_virtual_nework.vnet.name
This is invalid Terraform syntax:
virtual_network_name = azurerm_vnets_names
Outputs are only to be referenced by parent modules. In the root module outputs are only used for outputting things to the output log of your terraform apply
run. You don't declare outputs to use in the same module that you declare them in.
The fix is to actually pull out the value you need from the azurerm_virtual_nework.vnet
set:
virtual_network_name = azurerm_virtual_nework.vnet[var.env].name
Although, I think you could clean up the code even more by not using a for_each
at all in your azurerm_virtual_nework.vnet
resource, and just lookup the value from your map instead of greatly overcomplicating everything by trying to loop over it your map with an if statement: var.vnet_address_space[var.env]
.