Terraform - Loop over a list using for_each

by
Jeremy Canfield |
Updated: September 19 2023
| Terraform articles
for_each can be used to:
- loop through the items is a list (this article)
- loop through the keys and values in a dictionary
Here is an example of how for_each can be used to loop through the items in a list.
resource "aws_vpc" "my-vpc" {
for_each = toset( ["foo", "bar"] )
cidr_block = "10.0.0.0/16"
tags = {
Name = "my-vpc-${each.key}"
}
}
You can have multiple values in a list, like this.
resource "aws_lb_listener" "listeners" {
for_each = {
"foo-listener" = [var.foo_port, aws_lb_target_group.foo-target-group.arn]
"bar-listener" = [var.bar_port, aws_lb_target_group.bar-target-group.arn]
}
load_balancer_arn = aws_lb.application-load-balancer.arn
port = each.value[0]
protocol = "HTTP"
default_action {
type = "forward"
target_group_arn = each.value[1]
}
tags = {
Name = each.key
}
}
Often, you will be looping through a list that in one of your terraform.tfstate files that was generated from a data block or resource block.
Also be aware that if the items in the list are wrapped in double quotes, they will be interpreted as strings. There may be a situtation like this where you must NOT wrap the items in double quotes.
resource "aws_lb_target_group_attachment" "register-target" {
for_each = toset([data.terraform_remote_state.ec2_instances.outputs.my_docker1_instance.id, data.terraform_remote_state.ec2_instances.outputs.my_docker2_instance.id])
target_group_arn = aws_lb_target_group.my-application-load-balancer-target-group.arn
target_id = each.key
port = 12345
}
Let's say you have resource or data item that contains tolist, like this.
subnets = {
"filter" = toset([
{
"name" = "vpc-id"
"values" = tolist([
"vpc-014d2fcfa335d3c01",
])
},
])
"id" = "us-east-1"
"ids" = tolist([
"subnet-03f11417780f6cdbc",
"subnet-09b70fa463fcd4a19",
"subnet-0f35c3586e5090314",
"subnet-03c64e403dc5bf18f",
"subnet-0316e4d9fcd4efccc",
"subnet-05727079637285f90",
])
"tags" = tomap(null) /* of string */
"timeouts" = null /* object */
}
Here is how you could loop over each item in a tolist.
resource "aws_efs_mount_target" "my-efs-mount-target" {
for_each = tolist(data.aws_subnets.subnets.ids)
subnet_id = each.value
}
Or like this.
resource "aws_efs_mount_target" "my-efs-mount-target" {
for_each = { for index, subnet in data.aws_subnets.subnets.ids: index => subnet }
subnet_id = each.value
}
Did you find this article helpful?
If so, consider buying me a coffee over at