Skip to content

Instantly share code, notes, and snippets.

@reegnz
Last active October 22, 2024 13:55
Show Gist options
  • Save reegnz/7de97f4dd70da6320e6bf86eb883cfdd to your computer and use it in GitHub Desktop.
Save reegnz/7de97f4dd70da6320e6bf86eb883cfdd to your computer and use it in GitHub Desktop.
The Terraform group_by you've been missing

The Terraform group_by you've been missing

I'm playing around a lot nowadays with Terraform 0.13 and I found a really interesting feature and that's the ... symbol (also called an ellipsis) to be used with for expressions.

The operator can be used for group_by operations.

Example

We have a list of entries. The list contains employee/manager/project triplets.

locals {
  input = [
    { employee = "Pete", manager = "Joe", project = "DEF" },
    { employee = "Paul", manager = "Joe", project = "ABC" },
    { employee = "Paul", manager = "Joe", project = "DEF" },
    { employee = "Pam", manager = "Jim", project = "ABC" },
  ]
}

The goal is to group the list by either one of the attributes.

First you'd try to go check terraform built-in function for group_by, but after an hour of groking the terraform documentation you realize that terraform doesn't have a built-in group-by function for a list of maps/objects. You start to give up.

BUT!!!

You CAN do group_by with terraform!

This is how you do a group by project to get employees of a project:

output project_employees {
  value = {
    for item in local.input :
    item.project => item.employee...
  }
}

And given the above input, you'd get this output:

{
  "ABC" = [
    "Paul",
    "Pam",
  ]
  "DEF" = [
    "Pete",
    "Paul",
  ]
}

The crucial part is the .... This feature is hidden deep in the documentation of the for expression with only a single example to grab onto:

Finally, if the result type is an object (using { and } delimiters) then the value result expression can be followed by the ... symbol to group together results that have a common key:

{for s in var.list : substr(s, 0, 1) => s... if s != ""}

There was also a blog post introducing TF 0.12 for and for_each that mentions this feature:

Finally, the map form of a for expression has a grouping mode where the map key is used to group items together into a list for each distinct key. This mode is activated by placing an ellipsis (...) after the value expression:

# Configuration for Terraform 0.12
output "instances_by_availability_zone" {
  # Result is a map from availability zone to instance ids, such as:
  #  {"us-east-1a": ["i-1234", "i-5678"]}
  value = {
    for instance in aws_instance.example:
    instance.availability_zone => instance.id...
  }
}

In the the example above we show that a resource with count set now also behaves as a list, allowing all of the instances of aws_instance.example to be iterated over to produce a grouping by availability zone.

And that's how you group_by in Terraform!

locals {
input = [
{ employee = "Pete", manager = "Joe", project = "DEF" },
{ employee = "Paul", manager = "Joe", project = "ABC" },
{ employee = "Paul", manager = "Joe", project = "DEF" },
{ employee = "Pam", manager = "Jim", project = "ABC" },
]
}
output project_employees {
value = {
for item in local.input :
item.project => item.employee...
}
}
output employee_projects {
value = {
for item in local.input :
item.employee => item.project...
}
}
output manager_employees {
value = {
for item in local.input :
item.manager => item.employee...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment