TIL

Using for_each to loop lists in terraform

02.02.2024

In terraform it is quite common to have lists of things that should result in a list of resources. It is also common to use count to loop over those lists to create the similar resources. It would look something like this the code below if we wanted to create a few cloud storage buckets with the same config. Not the most likely thing to do, but a resource that will give a concise example.

locals {
buckets = ["bucket-one", "bucket-two"]
}
resource "google_storage_bucket" "generic-buckets" {
count = length(local.buckets)
name = local.buckets[count.index]
location = "EU"
}

This will generate two buckets with these state labels in terraform:

  • resource.google_storage_bucket.generic-buckets[0]
  • resource.google_storage_bucket.generic-buckets[1]

The problem with this is that if bucket-one is no longer needed and we remove it from the list then terraform will destroy both buckets and recreate bucket-two. That problem will disappear if for_each is used instead of count.

locals {
buckets = ["bucket-one", "bucket-two"]
}
resource "google_storage_bucket" "generic-buckets" {
for_each = { for i, k in toset(local.buckets) : k => i }
name = each.key
location = "EU"
}

The code above creates the same buckets, but the state labels will now be using the value as the index:

  • resource.google_storage_bucket.generic-buckets[”bucket-one”]
  • resource.google_storage_bucket.generic-buckets[”bucket-two”]

This makes it possible to both remove items from the list and reorder them without destroying and recreating the buckets that has not been removed from the list.