Reputation: 3147
I get the following error when try out for_each (which is a type of list of objects) but the same thing works fine in a dynamic block.
Here is the error:
The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of strings, and you have provided a value of type list of object.
This is the module where I get the error
vpc_subnets = [
{name: "public_test_a", cidr_block: "10.0.0.0/28", map_public_ip_on_launch: true, availability_zone: "ap-south-1a"},
{name: "public_test_b", cidr_block: "10.0.0.16/28", map_public_ip_on_launch: true, availability_zone: "ap-south-1b"},
{name: "private_test_a", cidr_block: "10.0.0.32/28", map_public_ip_on_launch: false, availability_zone: "ap-south-1a"},
{name: "private_test_b", cidr_block: "10.0.0.48/28", map_public_ip_on_launch: false, availability_zone: "ap-south-1b"}
]
# Create Subnets
resource "aws_subnet" "subnets" {
for_each = var.vpc_subnets
vpc_id = aws_vpc.vpc.id
cidr_block = each.value.cidr_block
map_public_ip_on_launch = each.value.map_public_ip_on_launch
availability_zone = each.value.availability
tags = merge({
Name = each.value.name
}, var.subnet_tags)
}
But in another module, it works fine. The only difference is that its in a dynamic block.
ingress_rules = [
{description: "Port 3306", cidr_blocks: ["10.0.0.0/24", "10.0.4.0/24"], port: 3306, protocol: "tcp"},
{description: "Port 22", cidr_blocks: ["0.0.0.0/0"], port: 22, protocol: "tcp"},
{description: "port 80", cidr_blocks: ["0.0.0.0/0"], port: 80, protocol: "tcp"}
]
resource "aws_security_group" "security_group" {
name = var.name
dynamic "ingress" {
for_each = var.ingress_rules
content {
description = ingress.value.description
cidr_blocks = ingress.value.cidr_blocks
from_port = ingress.value.port
to_port = ingress.value.port
protocol = ingress.value.protocol
}
}
}
Upvotes: 0
Views: 8203
Reputation: 238259
It does not work, because for_each, when used to create resources, accepts only a map or a set of strings and you are passing a list of maps.
Thus, you have to modify it to use a map only:
# Create Subnets
resource "aws_subnet" "subnets" {
for_each = {for idx, subnet in var.vpc_subnets: idx => subnet}
vpc_id = aws_vpc.vpc.id
cidr_block = each.value.cidr_block
map_public_ip_on_launch = each.value.map_public_ip_on_launch
availability_zone = each.value.availability
tags = merge({
Name = each.value.name
}, var.subnet_tags)
}
for_each used in dynamic blocks does not have such limitations, so you can iterate over your list of maps.
Upvotes: 2