Skip to content

Using for_each in Terraform

The for_each meta-argument in Terraform allows you to create multiple resource instances based on a map or a set of strings. This is particularly useful when you need to create several similar resources with slight variations.

Basic for_each Usage

Here's a basic example of using for_each with a map:

variable "subnets" {
  type = map(object({
    cidr_block        = string
    availability_zone = string
  }))
  default = {
    "subnet1" = { cidr_block = "10.0.1.0/24", availability_zone = "us-west-2a" },
    "subnet2" = { cidr_block = "10.0.2.0/24", availability_zone = "us-west-2b" }
  }
}

resource "aws_subnet" "example" {
  for_each = var.subnets

  vpc_id            = aws_vpc.main.id
  cidr_block        = each.value.cidr_block
  availability_zone = each.value.availability_zone

  tags = {
    Name = each.key
  }
}

In this example, we're creating multiple subnets based on the subnets variable.

Using for_each with a Set of Strings

You can also use for_each with a set of strings:

variable "user_names" {
  type    = set(string)
  default = ["john", "jane", "doe"]
}

resource "aws_iam_user" "example" {
  for_each = var.user_names
  name     = each.value
}

This will create an IAM user for each name in the user_names set.

Environment-Specific Variables with for_each

You can combine for_each with environment-specific variables:

variable "environments" {
  type = map(object({
    instance_type = string
    instance_count = number
  }))
  default = {
    dev  = { instance_type = "t2.micro", instance_count = 1 }
    test = { instance_type = "t2.small", instance_count = 2 }
    prod = { instance_type = "t2.medium", instance_count = 3 }
  }
}

resource "aws_instance" "example" {
  for_each = var.environments[terraform.workspace].instance_count > 0 ? toset(range(var.environments[terraform.workspace].instance_count)) : []

  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = var.environments[terraform.workspace].instance_type

  tags = {
    Name = "instance-${each.key}"
  }
}

This example creates a different number of instances with different instance types based on the current Terraform workspace.

Accessing Resources Created with for_each

When you use for_each, you access the created resources using the map syntax:

output "subnet_ids" {
  value = values(aws_subnet.example)[*].id
}

output "first_instance_id" {
  value = aws_instance.example["0"].id
}

Remember, when using for_each, Terraform creates each resource instance as a separate object in the state, which can be more efficient and easier to manage than using count for complex scenarios.