I’m trying to make subnets like the following way. I’m trying to loop over objects in the parent module:
variable "list_of_subnets" {
description = "list of vpc subnets"
type = list(object({
subnet_type = string
cidr_block = string
av_zone = string
}))
default = [
{
subnet_type = "public"
cidr_block = "10.0.101.0/24"
av_zone = "us-west-1a"
},
{
subnet_type = "public"
cidr_block = "10.0.102.0/24"
av_zone = "us-west-1b"
},
{
subnet_type = "private"
cidr_block = "10.0.1.0/24"
av_zone = "us-west-1a"
},
{
subnet_type = "private"
cidr_block = "10.0.2.0/24"
av_zone = "us-west-1b"
},
{
subnet_type = "database"
cidr_block = "10.0.151.0/24"
av_zone = "us-west-1a"
},
{
subnet_type = "database"
cidr_block = "10.0.152.0/24"
av_zone = "us-west-1b"
}
]
}
The above is my variable bloc through which I’m looping over to make multiple subnets:
module "subnets" {
source = "./modules/subnets"
for_each = {for i, v in var.list_of_subnets: i => v}
aws_vpc_id = module.VPC-Manual.vpc_id
sub_cidr = each.value.cidr_block
sub_av_zone = each.value.av_zone
subnet_type = each.value.subnet_type
}
"./modules/subnets:" Now, in the child module, simply passing those variables:
resource "aws_subnet" "aws_subnets" {
vpc_id = var.aws_vpc_id
cidr_block = var.sub_cidr
availability_zone = var.sub_av_zone
tags = {
subnet_type = var.subnet_type
}
}
In the child output block trying to retrieve the ids based on tags so that only public subnet ids can be retrieved:
output "public_subnet_ids" {
value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
}
parent output:
output "subnet_ids" {
value = module.subnets.public_subnet_ids
}
Terraform apply gives the following errors:
Changes to Outputs:
+ vpc_id = (known after apply)
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Attempt to get attribute from null value
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This value is null, so it does not have any attributes.
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Attempt to get attribute from null value
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This value is null, so it does not have any attributes.
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Attempt to get attribute from null value
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This value is null, so it does not have any attributes.
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (bool).
╵
╷
│ Error: Attempt to get attribute from null value
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This value is null, so it does not have any attributes.
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Unsupported attribute
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ Can't access attributes on a primitive-typed value (string).
╵
╷
│ Error: Missing map element
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This map does not have an element with the key "tags".
╵
╷
│ Error: Missing map element
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This map does not have an element with the key "tags".
╵
╷
│ Error: Attempt to get attribute from null value
│
│ on modules/subnets/output.tf line 3, in output "public_subnet_ids":
│ 3: value = [for subnet in aws_subnet.aws_subnets: subnet.tags["subnet_type"] == "public" ? "${subnet.id}" : null]
│
│ This value is null, so it does not have any attributes.
2
Answers
If I read your code correctly, you are trying to create a single subnet per subnet module. However, I believe your intention is to have a single module for all of your subnets, then you should not have a
for_each
loop in your module, rather passing thelist_of_subnets
inside the module itself where you apply thefor_each
loop onto theaws_subnet
resource.That being said to address your current issue/error, you don’t need to loop through subnet in aws_subnet.aws_subnets because it will only ever be a single subnet.
Here is how I would change your code…
In the module:
variable "data"
to pass an entire object instead of individual variablesCalling the module
data = each.value
module.subnets
and get what you need