I'm trying to build an object in the locals tf file that take the values obtained from data.azurerm_subnet.vnet-subnets to be used down the line for a web app deployment. However, I cannot get the index function to work. The web app deployment needs to take a "priority" in the form of a number. Any help is greatly appreciated.
locals.tf
locals {
webapp_vnet_subnets = {
for key, val in data.azurerm_subnet.vnet-subnets :
key => { for subnet in val : subnet => {
name = subnet.name
subnet_id = subnet.id
priority = index(tolist(data.azurerm_subnet.vnet-subnets), subnet.name) + 100
}
}
}
}
data.tf
data "azurerm_virtual_network" "vnet" {
name = var.prod_vnet
resource_group_name = var.prod_vnet_rg
}
data "azurerm_subnet" "vnet-subnets" {
for_each = toset(data.azurerm_virtual_network.vnet.subnets)
name = each.value
virtual_network_name = data.azurerm_virtual_network.vnet.name
resource_group_name = data.azurerm_virtual_network.vnet.resource_group_name
}
main.tf
module "ncs-management-service" {
source = "app.terraform.io//windows-web-app/azurerm"
version = "1.0.0"
webapp_name = "web-app-p-001"
resource_group_name = data.azurerm_resource_group.paas-rg.name
location = data.azurerm_resource_group.paas-rg.location
app_service_plan_id = module.asp.id
tags = {
"Billing Project" = var.billing_tag
Environment = var.environment_tag
Component = "App Service Plan"
System = var.system_tag
Terraform = var.terraform_tag
}
settings = {
subnet_id = data.azurerm_subnet.vnet-subnets[var.prod_subnet].id
vnet_route_all_enabled = true
always_on = true
use_32_bit_worker = false
minimum_tls_version = 1.2
worker_count = 1
current_stack = "dotnet"
dotnet_version = "v8.0"
deployment_slot_enabled = true
ip_restriction_default_action = "Deny"
network_rulesets = {
ip_rule = []
virtual_network_rule = [local.webapp_vnet_subnets]
}
}
}
Error
│ Error: Unsupported attribute
│
│ on locals.tf line 7, in locals:
│ 7: priority = index(tolist(data.azurerm_subnet.vnet-subnets), subnet.name) + 100
│
│ Can't access attributes on a primitive-typed value (string).
I'm trying to build an object in the locals tf file that take the values obtained from data.azurerm_subnet.vnet-subnets to be used down the line for a web app deployment. However, I cannot get the index function to work. The web app deployment needs to take a "priority" in the form of a number. Any help is greatly appreciated.
locals.tf
locals {
webapp_vnet_subnets = {
for key, val in data.azurerm_subnet.vnet-subnets :
key => { for subnet in val : subnet => {
name = subnet.name
subnet_id = subnet.id
priority = index(tolist(data.azurerm_subnet.vnet-subnets), subnet.name) + 100
}
}
}
}
data.tf
data "azurerm_virtual_network" "vnet" {
name = var.prod_vnet
resource_group_name = var.prod_vnet_rg
}
data "azurerm_subnet" "vnet-subnets" {
for_each = toset(data.azurerm_virtual_network.vnet.subnets)
name = each.value
virtual_network_name = data.azurerm_virtual_network.vnet.name
resource_group_name = data.azurerm_virtual_network.vnet.resource_group_name
}
main.tf
module "ncs-management-service" {
source = "app.terraform.io//windows-web-app/azurerm"
version = "1.0.0"
webapp_name = "web-app-p-001"
resource_group_name = data.azurerm_resource_group.paas-rg.name
location = data.azurerm_resource_group.paas-rg.location
app_service_plan_id = module.asp.id
tags = {
"Billing Project" = var.billing_tag
Environment = var.environment_tag
Component = "App Service Plan"
System = var.system_tag
Terraform = var.terraform_tag
}
settings = {
subnet_id = data.azurerm_subnet.vnet-subnets[var.prod_subnet].id
vnet_route_all_enabled = true
always_on = true
use_32_bit_worker = false
minimum_tls_version = 1.2
worker_count = 1
current_stack = "dotnet"
dotnet_version = "v8.0"
deployment_slot_enabled = true
ip_restriction_default_action = "Deny"
network_rulesets = {
ip_rule = []
virtual_network_rule = [local.webapp_vnet_subnets]
}
}
}
Error
│ Error: Unsupported attribute
│
│ on locals.tf line 7, in locals:
│ 7: priority = index(tolist(data.azurerm_subnet.vnet-subnets), subnet.name) + 100
│
│ Can't access attributes on a primitive-typed value (string).
Share
Improve this question
edited Mar 13 at 5:56
Vinay B
2,8242 gold badges3 silver badges12 bronze badges
Recognized by Microsoft Azure Collective
asked Mar 12 at 22:15
NickPNickP
891 gold badge1 silver badge6 bronze badges
8
- how do i do that? i still get this error 'priority = 100 + index(keys(data.azurerm_subnet.vnet-subnets), subnet_name) │ A reference to a resource type must be followed by at least one attribute access, specifying the resource name' – NickP Commented Mar 13 at 12:44
- Try this priority = 100 + index(keys({ for k, v in data.azurerm_subnet.vnet-subnets : k => v }), subnet_name) This ensures keys() extracts subnet names correctly before using index() @NickP – Vinay B Commented Mar 13 at 13:20
- Error: priority = 100 + index(keys({ for k, v in data.azurerm_subnet.vnet-subnets : k => v }), subnet_name) │ │ A reference to a resource type must be followed by at least one attribute access, specifying the resource name. – NickP Commented Mar 13 at 13:51
- this fixed it locals { webapp_vnet_subnets = { for k, v in data.azurerm_subnet.vnet-subnets : k => { name = v.name subnet_id = v.id priority = 100 + index(keys({ for k, v in data.azurerm_subnet.vnet-subnets : k => v }), v.name) } } } – NickP Commented Mar 13 at 13:53
- this now gives me an output in the format, webapp_vnet_subnets = { "subnet1" = { name = "subnet1" subnet_id = "subnet1_id" priority = 100 } "subnet2" = { name = "subnet2" subnet_id = "subnet2_id" priority = 101 }} How can i omit the keys for the resource needs it in a list format like so: webapp_vnet_subnets = [ { name = "subnet1" subnet_id = "subnet1_id" priority = 100 }, { name = "subnet2" subnet_id = "subnet2_id" priority = 101 }] – NickP Commented Mar 13 at 14:01
1 Answer
Reset to default 1Build Terraform variable object based off data block or varaiable
Glad to know it works for you @NickP posting this approach as solution so that it will be helpful for the community.
You define local object, Terraform pulls subnet information dynamically using
data "azurerm_subnet" "vnet-subnets" {
for_each = toset(data.azurerm_virtual_network.vnet.subnets)
name = each.value
virtual_network_name = data.azurerm_virtual_network.vnet.name
resource_group_name = data.azurerm_virtual_network.vnet.resource_group_name
}
Here, the use of for each ensure that it fetch every dynamically & data source stores the subnet objects mapped by their names.
With this, we can assume keys are subnet name and values are objects of subnet.
Now as discussed in comments rewrite the locals in the given format below
webapp_vnet_subnets = {
for k, v in data.azurerm_subnet.vnet-subnets :
k => {
name = v.name
subnet_id = v.id
priority = 100 + index(keys({ for k, v in data.azurerm_subnet.vnet-subnets : k => v }), v.name)
}
}
This creates a valid list of subnet names as expected.
Alternatively, the suggestion you mentioned
filtered_list = values(local.webapp_vnet_subnets)
which in general helps to extract only the value local.webapp_vnet_subnet
Will return only the values in list format, removing the keys.
Refer:
https://dev.to/sre_panchanan/terraform-for-expressions-5hcc
https://developer.hashicorp/terraform/language/values/outputs