Terraform — flatten the collection type variable

--

Photo by Önder Örtel on Unsplash

Terraform let’s us manage our infrastructure with all the cloud providers. Recently I used terraform with GCP to deploy some complex infrastructure. While writing code I came across a complex collection type variable which I needed to loop through but it was not possible to do that in it’s existing form. Let’s examine the variable as mentioned below.

Connect me on LinkedIn

Important Points

variable.tf

variable "bucket_user_roles" {    
type = list(object({
bucket_name = string
roles = list(object({
role_name = string
members = list(string)
}))
}))
}

terraform.tfvars — The value of the variable

bucket_user_roles = [
{
bucket_name = "bucket-1"
roles = [
{
role_name = "roles/storage.admin"
members = ["abc@gmail.com","def@gmail.com"]
},
{
role_name = "roles/storage.legacyBucketReader"
members = ["abc@gmail.com","def@gmail.com"]
},
{
role_name = "roles/storage.legacyBucketWriter"
members = ["abc@gmail.com","def@gmail.com"]
},
]
},
{
bucket_name = "bucket-2"
roles = [
{
role_name = "roles/storage.admin"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
{
role_name = "roles/storage.legacyBucketReader"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
{
role_name = "roles/storage.legacyBucketWriter"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
]
}
]

The challenge is that we need to find a way to loop through the roles list. roles is a nested block declared under variable bucket_user_roles.

The loop on roles list(nested block) is not possible in current form using count or for-each.

In order to achieve it we need to flatten this nested block into a flat list which we should be able to loop over using count or for-each. We will use a terraform function called flatten in order to achieve that.

Let’s see how flatten function can help to achieve what we need.

We will create a local variable with transformation applied using flatten. This creates a flat list of object with combination of bucket_name , role_name and members which we can use to loop over using count.

// flatten the collection variable into a list of object which can be used with count
locals {
local_user_role = flatten([
for key ,value in var.bucket_user_roles : [
for index , val in value.role : {
bucket_name = value.bucket_name
role_name = val.role_name
members = val.members
}
]
])
}

With input provided as variable bucket_user_roles, it returns following output.

local_user_role = [
{
bucket_name = "bucket-1"
role_name = "roles/storage.admin"
members = ["abc@gmail.com","def@gmail.com"]
},
{
bucket_name = "bucket-1"
role_name = "roles/storage.legacyBucketReader"
members = ["abc@gmail.com","def@gmail.com"]
},
{
bucket_name = "bucket-1"
role_name = "roles/storage.legacyBucketWriter"
members = ["abc@gmail.com","def@gmail.com"]
},
{
bucket_name = "bucket-2"
role_name = "roles/storage.admin"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
{
bucket_name = "bucket-2"
role_name = "roles/storage.legacyBucketReader"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
{
bucket_name = "bucket-2"
role_name = "roles/storage.legacyBucketWriter"
members = ["ghi@gmail.com","jkl@gmail.com"]
},
]

Great. Now we have a local variable local_user_rolewhich is a flat list of objects. Let’s use this variable in terraform code to perform iam binding using count loop.

// using count on local variable to loop through it resource 
"google_storage_bucket_iam_binding" "binding" {
count = length(local.local_user_role)
bucket = local.local_user_role[count.index].bucket_name
role = local.local_user_role[count.index].role_name
members = local.local_user_role[count.index].members
}

Running terraform plan

We can see that it’s going through all the roles declared to create 6 resources for 6 roles.

terraform plan .............
Plan: 6 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------

Hurray! We have successfully looped through the roles nested block as was needed to complete our challenge.

Hope you find it useful.

Good Luck.

--

--

Amit Kumar Dube (अमित दुबे)
Amit Kumar Dube (अमित दुबे)

Written by Amit Kumar Dube (अमित दुबे)

@AmitDubeDev | Professional GCP Architect | Terraform ACE | Lead Infra Consultant | Hindi Speaker

No responses yet