Terraform: How to create a map from two lists (keys and values)

Updated: February 3, 2024 By: Guest Contributor Post a comment

Introduction

When managing infrastructure as code with Terraform, you often need to organize data in a way that supports dynamic configurations. This can include converting two related lists — one of keys and another of values — into a map. Such a transformation can streamline variable management, data lookup, and resource configuration. In this tutorial, we’ll cover how to achieve this in Terraform, progressing from basic to advanced examples.

Let’s start by understanding the basic structure and syntax in Terraform for list and map creation before diving into how to effectively combine both.

Basics of Lists and Maps in Terraform

Lists are ordered collections of values that can be of the same type, accessed by their index. Maps, on the other hand, are collections of key-value pairs that provide a more descriptive way to organize and access data. Here’s how simple lists and maps look in Terraform:

variable "example_list" {
  type    = list(string)
  default = ["item1", "item2", "item3"]
}

variable "example_map" {
  type    = map(string)
  default = {"key1" : "value1", "key2": "value2", "key3": "value3"}
}

Creating a Map from Two Lists

Now, we’re ready to proceed to our main topic: creating a map from two lists. The most straightforward approach in Terraform 0.12 and later versions is using the zipmap function.

locals {
  keys   = ["key1", "key2", "key3"]
  values = ["value1", "value2", "value3"]
  result_map = zipmap(local.keys, local.values)
}

output "result_map" {
  value = local.result_map
}

This code produces the following output when applied:

{
  "key1" = "value1"
  "key2" = "value2"
  "key3" = "value3"
}

Handling Lists of Different Lengths

What happens if our lists of keys and values are of different lengths? By default, zipmap will error out. To handle this gracefully, we can use a combination of the count parameter and conditional expressions to ensure our lists are the same length or to fill in missing values.

Here’s an advanced example, adjusting for potentially unmatched list lengths:

locals {
  keys   = ["key1", "key2", "key3", "key4"]
  values = ["value1", "value2", "value3"]
  padded_values = length(local.keys) > length(local.values) ? concat(local.values, repeat("default", length(local.keys) - length(local.values))) : local.values
  result_map = zipmap(local.keys, local.padded_values)
}

output "result_map" {
  value = local.result_map
}

This example demonstrates how to ensure every key in our map gets a value, even if our original value list is too short. The output would adjust as needed, padding with “default” for any keys beyond the original list’s length.

Dynamic Map Creation with For Loops

In scenarios where zipmap might not offer the flexibility needed, Terraform’s for loop syntax can be used to dynamically create maps from two lists, allowing for more complex transformations or conditions as needed.

Here’s how to accomplish this with a for loop:

locals {
  keys   = ["alpha", "beta", "gamma"]
  values = [1, 2, 3]
  dynamic_map = { for i, k in local.keys : k => local.values[i] if local.values[i] > 1 }
}

output "dynamic_map" {
  value = local.dynamic_map
}

This creates a map just like before but filters the entries to only include those where the value is greater than 1. The result would include only “beta” and “gamma” keys with their respective values.

Conclusion

Creating a map from two lists of keys and values in Terraform enables more dynamic and readable configurations. From the straightforward zipmap function to more complex mapping with conditional logic, Terraform provides the tools to efficiently organize and leverage your data. By understanding and applying these techniques, you can enhance your Terraform configurations to be more flexible and maintainable.