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.
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!