for loop

Syntax

[for ITEM in ITERABLE : EXPRESSION_USING_ITEM]

Iterate over a map of keys and values:

[for k, v in var.map : length(k) + length(v)]

Iterate of a list, using an optiona index.

[for i, v in var.list : "${i} is ${v}"]

Convert a list into a map:

{for s in var.list : s => upper(s)}

Sample result:

{
  foo = "FOO"
  bar = "BAR"
  baz = "BAZ"
}

Examples

Get an attribute:

[for x in var.my_var : x.my_attribute]

Using a function:

[for x in var.my_var : chomp(x)]

Using a filter:

[for word in var.word_list : upper(word) if word != "coffee"]

Given an array:

[ 
  { name = "Foo"}, 
  { name = "Bar"} 
]

You could get all the names as:

[for o in var.people : x.name]

Or the more succint splat:

var.people[*].name

Result:

["Arthur", "Martha"]

for_each

Set for_each as an attribute on a resource or module.

Array

For an array, you can use each.index.

module "my_module" {
  for_each = var.subpaths
  message = "Problem reaching page: ${var.subpaths[each.index]}"
}

Map and set

If you have a map or set, then you can reference using each.key and each.value. You can use toset to convert an array to a set - though this will mean order is not guaranteed and that any duplicates will be removed.

Here using each.key and each.value to get keys and values of a map.

my_map = {
 foo = "bar",
 fizz = "buzz"
}
 
resource "test_resource" "abc" {
 for_each = var.my_map
 
 my_key = each.key      # e.g. "foo"
 my_value = each.value  # e.g. "bar"
}

Here, flattening some nested values. Based on article.

my_instances = {
 instance_1 = {
   ami   = "ami-00124569584abc",
   type  = "t2.micro"
 },
 instance_2 = {
   ami   = "ami-987654321xyzab",
   type  = "t2.large"
 },
}
 
resource "aws_instance" "test" {
 for_each = var.my_instances
 
 ami           = each.value["ami"]
 instance_type = each.value["type"]
}

For an array, you need to convert it to a set first with toset.

This has duplication of the URL value. And that canโ€™t be broken out as in variables or locals because for_each references must be inside a module or resource.

module "my_module" {
  for_each    = toset(var.subpaths)
  name        = local.organic_name
  message     = "Problem reaching page: ${local.url_prefix}${var.main_url}/${each.key}"
  url         = "${local.url_prefix}${var.main_url}/${each.key}"
}

So, to avoid duplication:

module "my_module" {
  for_each = toset([for subpath in var.subpaths : "${local.url_prefix}${var.main_url}/${subpath}"])

  message     = "Problem reaching page: ${each.value}"
  url    = each.value
}