Terraform

Terraform For Loop – Expression Overview with Examples

Terraform for loop

You will learn the following:

  1. Looping Constructs in Terraform
  2. Count, for_each, for comparison
  3. Using Terraform count
  4. Using Terraform for_each
  5. Using the for expression
  6. The for expression with if clause
  7. The for_each expression with if clause

Looping Constructs in Terraform

Count, For_each and For Comparison

Below you can find the table comparison of Terraform count, for_each and for.

Construct    Type Description Use Case
Count Meta-Argument Based on a count value Resources you are provisioning are identical
For_each Meta-Argument Based on a set of input values Resources change between the different instances
For Expression Based on a set of input values Transform a value

Using Terraform Count

variable "storage_account_names" {
  type    = list(string)
  default = ["jackuksstr001", "jackuksstr002", "jackuksstr003"]
}

resource "azurerm_resource_group" "example" {
  name     = "storage-rg"
  location = "UK South"
}

resource "azurerm_storage_account" "my_storage" {
  count                    = length(var.storage_account_names)
  name                     = var.storage_account_names[count.index]
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "GRS"
}

Using Terraform For_each

The example below uses a for_each loop to iterate through a list of the same storage account names and create a storage account with the name specified for each. The rest of the arguments are the same for each storage account.

The result will be the same as the example using count above.

variable "storage_account_names" {
  type    = list(string)
  default = ["jackuksstr001", "jackuksstr002", "jackuksstr003"]
}

resource "azurerm_resource_group" "example" {
  name     = "storage-rg"
  location = "UK South"
}

resource "azurerm_storage_account" "my_storage" {
  for_each                 = toset(var.storage_account_names)
  name                     = each.value
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "GRS"
}

Using the For Expression

The example below builds on the previous one and shows how to output a list of storage account IDs from the given list. The for expression is used to iterate over the storage_account_names list and retrieve the ID for each storage account instance with the corresponding name.

variable "storage_account_names" {
  type    = list(string)
  default = ["jackuksstr001", "jackuksstr002", "jackuksstr003"]
}

resource "azurerm_resource_group" "example" {
  name     = "storage-rg"
  location = "UK South"
}

resource "azurerm_storage_account" "my_storage" {
  for_each                 = toset(var.storage_account_names)
  name                     = each.value
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "GRS"
}

output "storage_account_names" {
  value = [
    for storage in var.storage_account_names:
    azurerm_storage_account.my_storage.example[storage].id
  ]
}

The For Expression With If Clause

for expression can also include an if clause to filter elements from the source variable, producing a value with fewer elements than the source value, and is commonly used to split lists based on a condition.

The syntax looks like the below:

[for VAR in COLLECTION: IF CONDITION_EXPRESSION: VAR]
variable "storage_account_names" {
  type    = list(string)
  default = ["jackuksstr001", "jackuksstr002", "jackuksstr003"]
}

resource "azurerm_resource_group" "example" {
  name     = "storage-rg"
  location = "UK South"
}

resource "azurerm_storage_account" "my_storage" {
  count                    = length(var.storage_account_names)
  name                     = var.storage_account_names[count.index]
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "GRS"
}

locals {
  grs_storage_accounts = [for sa in azurerm_storage_account.my_storage: sa if sa.account_replication_type == "GRS"]
}

output "grs_storage_account_names" {
  value = [for sa in local.grs_storage_accounts: sa.name]
}

The For_each Expression With If Clause

The if clause can be used to conditionally include or exclude certain expressions based on a boolean condition.

The syntax for using the if clause in an expression is as follows:

${condition ? true_value : false_value}

In the example below, we use the if condition to set the account_replication_type to GRS if the environment variable is set to prod , if it is not, then the account_replication_type will be set to LRS .

Because the default value for the environment variable is set to prod in the below example, the three storage accounts created using the for_each loop will all have their account_replication_typeset to GRS.

variable "storage_account_names" {
  type    = list(string)
  default = ["jackuksstr001", "jackuksstr002", "jackuksstr003"]
}

variable "environment" {
  default = "prod"
}

resource "azurerm_resource_group" "example" {
  name     = "storage-rg"
  location = "UK South"
}

resource "azurerm_storage_account" "my_storage" {
  for_each                 = toset(var.storage_account_names)
  name                     = each.value
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "${var.environment == "prod" ? "GRS" : "LRS"}"
}

Key Points

We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. You can check it for free, by creating a trial account.

Note: New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6. OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu works with your existing Terraform state file, so you won’t have any issues when you are migrating to it.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.

Start free trial
Terraform Loops and Conditionals Cheatsheet

Grab our ultimate cheat sheet PDF to keep your workflows DRY.

Share your data and download the cheatsheet