Introduction
In Terraform, managing infrastructure often requires handling collections of resources. One common structure you’ll encounter is a map, an associative array containing key-value pairs. This guide will walk you through several methods to iterate over a map in Terraform, ranging from basic examples to more advanced use cases, demonstrating how Terraform’s loop constructs can be leveraged effectively.
Understanding Maps in Terraform
Before diving into iteration, it’s essential to understand what maps are in Terraform. A map is a data structure that matches keys to values, providing a way to group related data. In Terraform, you typically use maps to configure resources with similar settings that have slight variations.
variable "instance_details" {
type = map(object({
zone = string
size = string
}))
default = {
"instance1" = { zone = "us-west-1a", size = "t2.micro" },
"instance2" = { zone = "us-west-1b", size = "t2.small" }
}
}
This example defines a map of objects, where each key-value pair represents the details of a virtual machine.
Basic Iteration with count
One of the simplest ways to iterate over a map in Terraform is using the count
parameter within a resource declaration. This method is especially useful for creating multiple instances of a resource.
resource "aws_instance" "example" {
count = length(var.instance_details)
ami = "ami-123456"
instance_type = var.instance_details[keys(var.instance_details)[count.index]].size
availability_zone = var.instance_details[keys(var.instance_details)[count.index]].zone
}
This snippet creates AWS instances based on the map’s values, iterating through the map using a combination of length
, keys
, and the count.index
loop variable.
Advanced Iteration with for_each
Terraform 0.12 introduced the for_each
statement, a more powerful iteration tool that iterates directly over maps and collections. It’s particularly useful when you want to create resources for each element in a map and maintain a clear relationship between the created resources and the map’s keys.
resource "aws_instance" "example" {
for_each = var.instance_details
ami = "ami-123456"
instance_type = each.value.size
availability_zone = each.value.zone
tags = {
Name = each.key
}
}
This example uses for_each
to iterate over the map, creating a unique AWS instance for each key-value pair. The each.key
and each.value
constructs provide access to the current element’s key and value, respectively.
Combining Maps with Dynamic Blocks
Dynamic blocks are a feature in Terraform that allows for the dynamic creation of nested blocks based on a complex variable, such as a map or list. When used in conjunction with for_each
, dynamic blocks can efficiently configure resources that require repeated nested configurations.
resource "aws_security_group" "example" {
name = "example-group"
dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
This code snippet defines a security group in AWS, where the ingress rules are dynamically generated from a map of ingress configurations.
Conditional Iteration
There are scenarios where you might wish to iterate over a map conditionally. This can be achieved by combining for_each
with a filtering step using a splat
expression or compact
function.
locals {
filtered_instance_details = { for k, v in var.instance_details : k => v if v.zone == "us-west-1a" }
}
resource "aws_instance" "filtered_example" {
for_each = local.filtered_instance_details
ami = "ami-123456"
instance_type = each.value.size
availability_zone = each.value.zone
}
This demonstrates filtering a map to iterate only over items that meet specific conditions, in this case, instances in the “us-west-1a” zone.
Conclusion
In Terraform, iterating over maps is a foundational skill that enables scalable and flexible infrastructure configurations. Starting with basic techniques like using count
and advancing to for_each
and dynamic blocks, Terraform provides a range of tools for efficiently managing infrastructure with complex configurations. By mastering these techniques, you can streamline your Terraform code and embrace infrastructure as code principles more fully.