Terraform Tutorials: How to do Loop / Iterate in Terraform?

Resources
Resources are the most important element in the Terraform language. Each resource block describes one or more infrastructure objects, such as virtual networks, compute instances, or higher-level components such as DNS records supported by providers.

Resources type
Each resource is associated with a single resource type, which determines the kind of infrastructure object it manages and what arguments and other attributes the resource supports.

Provider
Each resource type in turn belongs to a provider, which is a plugin for Terraform that offers a collection of resource types. A provider usually provides resources to manage a single cloud or on-premises infrastructure platform.

Resource Behavior by Meta-Arguments
Resource Behavior by Meta-Arguments, which can be used with any resource type to change the behavior of resources:

  • depends_on, for specifying hidden dependencies
  • count, for creating multiple resource instances according to a count
  • for_each, to create multiple instances according to a map, or set of strings
  • provider, for selecting a non-default provider configuration
    lifecycle, for lifecycle customizations
  • provisioner and connection, for taking extra actions after resource creation

count: which allows Multiple Resource Instances By Count

Out of these, count: which allows Multiple Resource Instances By Count and this Meta-Arguments can be used to Multiply resources which can be used as an alternative to Looping and Interators in Terraform.


resource "aws_instance" "example" {
  ami = "ami-2d39803a"
  instance_type = "t2.micro"
}

###### WRONG WAY ###### 
for i = 0; i < 3; i++ {
  resource "aws_instance" "example" {
    ami = "ami-2d39803a"
    instance_type = "t2.micro"
  }  
}

###### RIGHT WAY ###### 
resource "aws_instance" "example" {
  count = 3
  ami = "ami-2d39803a"
  instance_type = "t2.micro"
}

for_each: Multiple Resource Instances Defined By a Map, or Set of Strings.

If your resource instances are almost identical, count is appropriate. If some of their arguments need distinct values that can’t be directly derived from an integer, it’s safer to use for_each.

Before for_each was available, it was common to derive count from the length of a list and use count.index to look up the original list value:


variable "subnet_ids" {
  type = list(string)
}

resource "aws_instance" "server" {
  # Create one instance for each subnet
  count = length(var.subnet_ids)

  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
  subnet_id     = var.subnet_ids[count.index]

  tags {
    Name = "Server ${count.index}"
  }
}

The for_each meta-argument accepts a map or a set of strings, and creates an instance for each item in that map or set. Each instance has a distinct infrastructure object associated with it (as described above in Resource Behavior), and each is separately created, updated, or destroyed when the configuration is applied.


resource "azurerm_resource_group" "rg" {
  for_each = {
    a_group = "eastus"
    another_group = "westus2"
  }
  name     = each.key
  location = each.value
}

More reading can be done here

https://www.terraform.io/docs/configuration/resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings

Rajesh Kumar
Follow me