How to use "for_each" to iterate over a list in Terraform

In Terraform, the for_each expression allows you to iterate over a list or map and create multiple instances of a resource or module based on the elements of that list or map. This is useful when you want to manage multiple similar resources or configurations in a more dynamic way.

The for_each value must be a map or a set of strings, which creates an instance for each item in that map or set. Each instance has a distinct infrastructure object associated with it, and each is separately created, updated, or destroyed when the configuration is applied.

Using for_each on a list of strings:

provider "null" {}

variable "user_names" {
  type    = list(string)
  default = ["user1", "user2", "user3"]
}

resource "null_resource" "users" {
  for_each = toset(var.user_names)

  triggers = {
    name = each.value
  }
}

output "user_names_output" {
  value = [for user in null_resource.users : user.triggers.name]
}

Code explanation

Line 1:

  • This line defines a Terraform provider named null. The null provider is a built-in provider that does nothing but can be useful in certain scenarios, like generating data or for testing purposes.

Line 3–6:

  • This block defines a variable named user_names.

  • The variable has a type of list(string), meaning it is a list of strings.

  • The default value of the variable is set to ["user1", "user2", "user3"], so if no value is provided when running Terraform, this default list will be used.

Line 8–14:

  • This block defines a null_resource named users.

  • The for_each argument is set to toset(var.user_names), which means that this resource will be created for each unique value in the user_names list variable.

  • Inside the triggers block, a trigger is set for each instance of the null_resource using the name from each value in the user_names list.

Line 16–18:

  • This block defines an output named user_names_output.

  • The value of the output is set using a list comprehension ([for … : …]) to loop over each instance of the null_resource resource and extract the name trigger value from each one.

Using for_each on a list of strings:

provider "null" {}

variable "users" {
  type = list(object({
    name = string
    age  = number
  }))
  default = [
    { name = "user1", age = 30 },
    { name = "user2", age = 25 },
    { name = "user3", age = 40 },
  ]
}

resource "null_resource" "users" {
  for_each = { for u in var.users : u.name => u }

  triggers = {
    name = each.key
    age  = each.value.age
  }
}

output "users_with_tags" {
  value = { for user in null_resource.users : user.triggers.name => user.triggers.age }
}

Code explanation

Line 3–13:

  • This block declares a variable named users.

  • The variable has a type of list(object({ name = string, age = number })), meaning it is a list of objects with name as a string and age as a number.

  • The default value of the variable is set to a list of three objects, each containing a name and an age field for three users.

Line 15–22:

  • This block defines a null_resource named users.

  • The for_each argument uses a for-loop with the for expression to create a map, where the keys are the name fields from the objects in the users list and the values are the full objects.

  • Inside the triggers block, a trigger is set for each instance of the null_resource using the name and age fields from each corresponding object.

Line 24–26:

  • This block defines an output named users_with_tags.

  • The value of the output is set using a map comprehension ({ for … : … }) to loop over each instance of the null_resource resource and extract the name as the key and age as the value from each trigger.

Copyright ©2024 Educative, Inc. All rights reserved