Sitemap

How to use for expression in Terraform ?

4 min readDec 15, 2024
Using Terraform for expression !

I come from background of C,C++, Java, C# and so on. In my initial days of using Terraform HCL , I felt quite restrictive when it comes to loops and building conditional logic and complex conditions. I then came across for expression and then I said this is quite handy.

This post focuses on some of the scenarios where I have used for expression !

Problem Statement

I have a list of instances (this is technically map of objects in terraform world) as outlined below.

# main.tf

locals {
instances = {
web_server = {
instance_type = "t3.micro"
os = "Linux"
description = "Web Server"
},
app_server = {
instance_type = "t3.micro"
os = "Linux"
description = "Application Server"
},
db_server = {
instance_type = "m5.lagre"
os = "Windows"
description = "DB Server"
}
}
}

output "instances" {

value = local.instances

}

Question ?

How should one get three different lists so as to get :

  • List of instances with os =Windows
  • List of instances with os =Linux
  • List of instances grouped based on instance_type (t3.micro , m5.large and so on.)

If you come from programming background of Java , C# then you may struggle to come with the logic as HCL follows a paradigm of Declarative Language.

Output of initial list

Let us look at how this could be achieved using for expression in Terraform.

Solution

If we look at the given configuration the given list is actually map of objects.

We would need mechanism to filter the instances based on os. This is where for expression comes in play.

Part I — Filter out the Linux instances

locals  {
linux_instances = {

for k, v in local.instances : k => v
if v.os == "Linux"
}
}

output "linux_instances" {

value = local.linux_instances
}
  • For each key (k) and value (v) in map (local.instances) — create another map with key (k) having value (v) object provided if v.os = ‘Linux
  • This skips all the objects with other os i.e. v.os = “Windows”

The terraform plan output shows the linux_instances as a separate output.

Filtered Linux instances list

Part — II — Filter out the Windows Instances

Same mechanism is used to filter Windows instances as well.


locals {

windows_instances = {
for k, v in local.instances : k => v
if v.os == "Windows"
}
}


output "windows_instances" {

value = local.windows_instances
}
Filtered Windows instances list

This is quite cool as one can dynamically build the local lists and manipulate the way we want. Here the trick is to use condition i.e. if condition with for expression. i.e. if v.os = = “Windows and if v.os == “Linuxto have a different list.

Part III — Create a group of instances based on instance_type

This one is quite interesting and it shows the flexibility provided by the conditional logic where one can group the items in the map based on key.

locals {

instance_list_with_types = {
// There could be more than one instances of different type
//so ellipsis (...) is required
for k, v in local.instances : v.instance_type => v...
}
}

output "instance_list_with_types" {

value = local.instance_list_with_types
}
instance list organised based on instance_type

The above list creates a group based on the instance_type ! All the instance types with m5.large and t3.micro are grouped accordingly.

Quite handy isn’t it !

Appendix : Complete Code Listing

# main.tf

locals {
instances = {
web_server = {
instance_type = "t3.micro"
os = "Linux"
description = "Web Server"
},
app_server = {
instance_type = "t3.micro"
os = "Linux"
description = "Application Server"
},
db_server = {
instance_type = "m5.lagre"
os = "Windows"
description = "DB Server"
}
}
}

output "instances" {

value = local.instances

}

locals {
linux_instances = {
for k, v in local.instances : k => v
if v.os == "Linux"
}
}

output "linux_instances" {

value = local.linux_instances
}

locals {

windows_instances = {
for k, v in local.instances : k => v
if v.os == "Windows"
}
}


output "windows_instances" {

value = local.windows_instances
}

locals {

instance_list_with_types = {

for k, v in local.instances : v.instance_type => v... // There could be more than one instances of different type so ... is required
}
}

output "instance_list_with_types" {

value = local.instance_list_with_types
}

That is all for this post !

--

--

Aamod Kadam
Aamod Kadam

Written by Aamod Kadam

AWS Community Builder | upGrad Course Author | 7 x AWS | Terraform Associate | Cloud Consulting | AWS | Azure | Docker | Kubernetes | Software Architecture

No responses yet