Terraform

How to Use Terraform Merge Function – Examples

How to Use Terraform Merge Function - Examples

In Terraform, a “function” refers to a built-in or user-defined operation that can be performed on input values to produce an output value. Functions in Terraform allow you to manipulate data, perform calculations, and create more dynamic configurations. They are an essential part of the Terraform language and can be used within expressions to achieve various tasks.

In this article, we will take a look at what the Terraform merge function is and how to use it, with a few useful practical examples showing how to merge lists of maps, lists of objects, and apply merged lists of tags to cloud resources.

  1. What is merge in Terraform?
  2. How to use Terraform merge

What is merge in Terraform?

Terraform merge is a built-in function. The merge function takes an arbitrary number of maps or objects and returns a single map or object that contains a merged set of elements from all arguments.

Keep in mind that the merge function is available in Terraform versions 0.12 and later. If you are using an earlier version of Terraform, you might need to use alternative methods like the concat function or the for expression to achieve similar merging behavior.

How to use Terraform merge

Let’s explore how to practically use terraform merge with a few examples.

Example 1: Terraform merge maps

In Terraform, we define a map of objects within {}.

We can use the merge function by defining the maps we want to merge:

merge(map1, map2, ...)

Consider we have two maps of objects we want to merge together defined in our Terraform locals declaration:

locals {
  map1 = {
    luke  = "jedi"
    yoda  = "jedi"
    darth = "sith"
  },
  map2 = {
    quigon     = "jedi"
    palpantine = "sith"
    hansolo    = "chancer"
  }
}

We can use the merge function like so:

merged_map = merge(local.map1, local.map2)

Which would produce the following value for merged_map:

merged_map = {
  luke       = "jedi"
  yoda       = "jedi"
  darth      = "sith"
  quigon     = "jedi"
  palpantine = "sith"
  hansolo    = "chancer"
}

Note that when merging maps, if there are duplicate keys between the input maps, the value from the last map provided as an argument will take precedence.

In other words, if there are conflicting keys in the input maps, the value from the rightmost map will be used in the merged map.

For example, in our example above, if we defined the value as jedi for the key darth again in map2 (controversial!) — then the resulting output would be darth = "jedi".

Example 2: Terraform merge lists of objects

Terraform does not have a built-in function to directly merge lists of objects. However, there are a few techniques you can use to achieve this behavior. Which way you choose will depend on the structure of your data (i.e., how you have defined your lists).

One way is to use the concat function to take two or more lists and combine them into a single list.

locals {
  list1 = [
    { key = "luke", value = "jedi" },
    { key = "yoda", value = "jedi" }
  ]

  list2 = [
    { key = "darth", value = "sith" },
    { key = "palpatine", value = "sith" }
  ]

  merged_list = merge({ for elem in concat(local.list1, local.list2) : elem.key => elem })
}

merged_list will result in the following output:

[
  { key = "luke", value = "jedi" },
  { key = "yoda", value = "jedi" },
  { key = "darth", value = "sith" },
  { key = "palpatine", value = "sith" }
]

You could also use the for expression, which will result in the same output for merged_list:

locals {
  list1 = [
    { key = "luke", value = "jedi" },
    { key = "yoda", value = "jedi" }
  ]

  list2 = [
    { key = "darth", value = "sith" },
    { key = "palpatine", value = "sith" }
  ]

  merged_list = { for elem in concat(local.list1, local.list2) : elem.key => elem.value }}
}

Another way to achieve the same output is to use the flatten function:

locals {
  list_of_lists = [
    [
      { key = "luke", value = "jedi" },
      { key = "yoda", value = "jedi" }
    ],
    [
      { key = "darth", value = "sith" },
      { key = "palpatine", value = "sith" }
    ]
  ]

  merged_list = flatten(local.list_of_lists)
}

Example 3: Terraform merge lists of maps

You can also merge lists of maps.

The following will again result in the same output:

locals {
  list1 = [
    { key = "luke", value = "jedi" },
    { key = "yoda", value = "jedi" }
  ]

  list2 = [
    { key = "darth", value = "sith" },
    { key = "palpatine", value = "sith" }
  ]

  merged_list = { for elem in concat(local.list1, local.list2) : elem.key => elem.value }}
}

Here, merged_list will result in the following output:

[
  { key = "luke", value = "jedi" },
  { key = "yoda", value = "jedi" },
  { key = "darth", value = "sith" },
  { key = "palpatine", value = "sith" }
]

Example 4: Terraform merge tags

One common use case for using the merge function is to merge together lists of tags applied to cloud resources.

locals {
  default_tags = {
    Environment = "Production"
    Project     = "MyProject"
  }

  additional_tags = {
    CostCenter = "12345"
    Department = "Engineering"
  }

  merged_tags = merge(local.default_tags, local.additional_tags)
}

This will result in merged_tags containing the combined list which can then be applied to the resource as needed.

{
  Environment = "Production"
  Project     = "MyProject"
  CostCenter  = "12345"
  Department  = "Engineering"
}

The examples below show the list of merged_tags applied to the example AWS EC2 instance example1, where instance example2 will only have the default_tags applied.

resource "aws_instance" "example1" {
  ami           = "ami-0c55b159cbfafe1f0" # Replace with the AMI ID of your desired instance
  instance_type = "t2.micro"               # Replace with your desired instance type
  subnet_id     = "subnet-12345678"        # Replace with the subnet ID where you want to launch the instance

  tags = local.merged_tags
}

resource "aws_instance" "example2" {
  ami           = "ami-0c55b159cbfafe1f0" # Replace with the AMI ID of your desired instance
  instance_type = "t2.micro"               # Replace with your desired instance type
  subnet_id     = "subnet-12345678"        # Replace with the subnet ID where you want to launch the instance

  tags = local.default_tags
}

Key points

In this post, we covered another Terraform functionmerge, and learned what it is and how to use it. We went through examples showing how to merge lists of maps, lists of objects and apply merged lists of tags to cloud resources.

For easier Terraform management, you can also check out Spacelift – a sophisticated and compliant infrastructure delivery platform. Spacelift can help you with building more complex workflows based on Terraform, and has the flexibility to integrate with any third party tool you want.. You can test drive it for free by going here and creating a trial account.

Note: New versions of Terraform will be placed under the BUSL license, but everything created before version 1.5.x stays open-source. OpenTofu is an open-source version of Terraform that will expand on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6. OpenTofu retained all the features and functionalities that had made Terraform popular among developers while also introducing improvements and enhancements. OpenTofu works with your existing Terraform state file, so you won’t have any issues when you are migrating to it.

Manage Terraform Better with Spacelift

Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization, and many more.

Start free trial