I’m running into an issue when I attempt to reference a local variable as the for_each argument of a dynamic block inside of a parent for_each. The statement also attempts to reference the key from the parent for_each, which Terraform also errors on. When I comment out the dynamic block in question, Terraform is able to validate the code and generate a plan without issue.
The simplified resource creation code is below.
resource "azurerm_linux_web_app" "linux_webapps" {
for_each = var.linux_java_app_services
...
site_config {
...
dynamic "ip_restriction" {
iterator = "subnet_rule"
for_each = (local.app_service_network_restrictions[(each.key)].subnets)
content {
action = subnet_rule.value.action
name = subnet_rule.value.name
priority = subnet_rule.value.priority
virtual_network_subnet_id = subnet_rule.value.virtual_network_subnet_id
}
}
}
}
With the dynamic block included, Terraform errors with two “Unsupported attribute” errors. I have multiple dynamic blocks due to the required naming conventions; however, each block produces the same errors. I’ve commented out all the blocks and tested each one individually as well as modified the references to include or not include parenthesis around different portions of the argument.
Error on “local.app_service_network_restrictions”
for_each = (local.app_service_network_restrictions[(each.key)].subnets)
This object does not have an attribute named “app_service_network_restrictions”.Error on “each.key”
for_each = (local.app_service_network_restrictions[(each.key)].subnets)
This object does not have an attribute named “key”.
The variables and locals referenced are formatted as follows. Truncated to remove irrelevant items.
linux_java_app_services = {
"app1" = {
...
network_restrictions_azure_services = [{
action = "Allow"
is_frontend_rule = false
is_scm_rule = true
priority = 100
service = "AzureCloud"
}]
network_restrictions_vnet_subnets = [{
action = "Allow"
is_frontend_rule = true
is_scm_rule = false
priority = 100
subnet_key = "AzureAppGatewayFirewall"
vnet_key = "vn-001"
}]
}
}
locals {
app_service_network_restrictions = {for key, value in var.linux_java_app_services : key => {
scm_services = [for restriction in value.network_restrictions_azure_services : {
action = restriction.action
name = "${restriction.action} ${restriction.service}"
priority = restriction.priority
service_tag = restriction.service
} if restriction.is_scm_rule]
subnets = [for restriction in value.network_restrictions_vnet_subnets : {
action = restriction.action
name = "${restriction.action} ${restriction.subnet_key} on ${restriction.vnet_key}"
priority = restriction.priority
virtual_network_subnet_id = module.vnet.network[(restriction.vnet_key)].subnets[(restriction.subnet_key)].id
} if restriction.is_frontend_rule]
}
When I output my local.app_service_network_restrictions variable, it is formatted as I expect.
+ app_restrictions = {
+ app1 = {
+ ips = []
+ scm_ips = []
+ scm_services = [
+ {
+ action = "Allow"
+ name = "Allow AzureCloud"
+ priority = 100
+ service_tag = "AzureCloud"
},
]
+ scm_subnets = []
+ services = []
+ subnets = [
+ {
+ action = "Allow"
+ name = "Allow AzureAppGatewayFirewall on vn-001"
+ priority = 100
+ virtual_network_subnet_id = "/subscriptions/-removed ID-/resourceGroups/example001/providers/Microsoft.Network/virtualNetworks/vn-001/subnets/AzureAppGatewayFirewall"
},
]
}
}
I’m unsure of how to proceed, as my output statement
output "app_restrictions" {
value = local.app_service_network_restrictions
}
indicates that the attribute does exist, and “each.key” is used elsewhere without issue.
If anyone can shed some light on what I’m overlooking, I’d appreciate it.