[November 20 Webinar] Detecting & Correcting Infrastructure Drift

➡️ Register Now

Terraform

Terraform Lookup Function – Syntax & Examples

Terraform lookup function

Terraform allows IaC developers to automate the provisioning and management of several cloud resources. It leverages a declarative syntax to describe the deployment state and then applies it to the target environment.

Terraform developers use various types of variables to store and process values. One such variable is the map variable that stores the values in pairs, called key-value pairs.

What does the lookup function do in Terraform? The Terraform lookup function is a built-in function that retrieves the values from a map variable or a list of objects. It considers the map variable’s name to retrieve the key and default values. It returns the key value only when a matching key is found. Otherwise, it returns the default value.

In this post, we dive deep into the lookup function and see its usage and applicability while writing IaC.

You will learn:

  1. The basic syntax of the lookup function
  2. How to use lookup with a map variable
  3. How to use lookup on Terraform resources/datasources
  4. How to use lookup with a list of objects

Basic Syntax of the Lookup Function

lookup(map name, key, default_value)

Based on the above syntax, the lookup function has three primary arguments.

  1. Map name: A map variable that contains the key-value pairs. Read more about the Terraform map variable.
  2. Key: A key value that we want to retrieve from the map
  3. Default value: A default value that we intend to return if the map doesn’t contain the key.

It is optional to specify the default value. However, the best practice is to add a unique default value in the lookup function to avoid function call errors or lookup failures.

Using Lookup With a Map Variable

Here is a sample Terraform configuration file to define a map variable “my_map”:

variable "my_map" {
 type = map(string)
 default = {
   "key1" = "value1"
   "key2" = "value2"
 }
}

To retrieve the value of a particular key from the above map – for example, in a local variable – use a lookup function as shown below:

locals {
 my_value = lookup(var.my_map, "key1", "")
}

To demonstrate the same, I have created an output variable that displays the intended value when executing plan or apply commands.

output "my_value_output" {
 value = local.my_value
}

As we can see in the output of the plan command below, it correctly displays the value of “key1”.

terraform plan

Changes to Outputs:
  + my_value_output = "value1"

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

Note that when the key does not exist in the lookup function, it returns an empty string as the default value.

Using Lookup on Terraform Resources/Datasources

The Terraform configuration below defines a security group resource. It also implements a local variable to look up the value of the security group ID when created. The lookup function is implemented similarly, as it is explained in the previous section.

We also define an output variable to print the value in the terminal.

resource "aws_security_group" "web" {
 name        = "web"
 description = "Security group for web servers"
 ingress {
   from_port   = 80
   to_port     = 80
   protocol    = "tcp"
   cidr_blocks = ["0.0.0.0/0"]
 }
 ingress {
   from_port   = 443
   to_port     = 443
   protocol    = "tcp"
   cidr_blocks = ["0.0.0.0/0"]
 }
 tags = {
   Name = "web"
 }
}

locals {
 web_sg_id = lookup(aws_security_group.web, "id", "")
}

output "my_value_output" {
 value = local.web_sg_id
}

Note that this value will be available in the output once the resource is created using the terraform apply command.

The output below confirms the same.

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + my_value_output = (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_security_group.web: Creating...
aws_security_group.web: Creation complete after 2s [id=sg-05bdcc469ccd7ddb4]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Outputs:

my_value_output = "sg-05bdcc469ccd7ddb4"

Alternatively, it is possible to perform a similar lookup operation on data sources included in the Terraform configuration.

Using Lookup With a List of Objects

The Terraform configuration below defines a variable named “Security_Groups” to hold a list of security group objects. Each of the security group objects has these properties – name, description, and ingress configuration object.

In the default values, we have provided configurations for a couple of security groups named “SecurityGroup-Web” and “SecurityGroup-App”.

Our intention here is to retrieve the description of “SecurityGroup-App” using the lookup function.

variable "Security_Groups" {
 type = list(object(
   {
     name        = string
     description = string
     ingress = optional(list(object({
       from_port   = number
       to_port     = number
       protocol    = string
       cidr_blocks = list(string)
     })), [
       {
         from_port   = 8080
         to_port     = 8080
         protocol    = "tcp"
         cidr_blocks = ["10.0.0.0/8"]
     }])
 }))
 default = [
   {
     name        = "SecurityGroups-Web"
     description = "Security group for web servers"
     ingress = [
       {
         from_port   = 80
         to_port     = 80
         protocol    = "tcp"
         cidr_blocks = ["0.0.0.0/0"]
       },
       {
         from_port   = 443
         to_port     = 443
         protocol    = "tcp"
         cidr_blocks = ["0.0.0.0/0"]
       }
     ]
   },
   {
     name        = "SecurityGroups-App"
     description = "Security group for application servers"
     ingress = [
       {
         from_port   = 8081
         to_port     = 8081
         protocol    = "tcp"
         cidr_blocks = ["10.0.0.0/8"]
     }]
 }]
}

Let us define the local and output variables, as shown below.

The lookup function is implemented in the local variable “SecurityGroups_description”. The first argument implements a for loop with a conditional expression to filter the desired security group from the list.

This operation provides us with a single object from the list, which is what the first argument for the lookup function is supposed to be.

locals {
 SecurityGroups_description = lookup(
   [for sg in var.Security_Groups : sg if sg.name == "SecurityGroups-App"][0],
   "description",
 "")
}

output "my_value_output" {
 value = local.SecurityGroups_description
}

Running terraform plan on this correctly shows the description of “SecurityGroups-App”.

terraform plan

Changes to Outputs:
  + my_value_output = "Security group for application servers"

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

Notice how the ingress attribute is initialized with an “optional” modifier. In Terraform, the optional modifier declares the attribute as optionally required. If the dependent module fails to provide the value for the “ingress” attribute, Terraform automatically uses the default value provided in this optional modifier.

The default value in the optional modifier is optional. If the default value is not provided, and the dependent module also does not provide the value, then a corresponding type’s null value is automatically assigned.

Key Points

Terraform lookup function simplifies data management and retrieves values from a map variable or a list of objects. The function has three arguments, including map, key, and default value. We can use the function to retrieve the value of a specific key or from a list of objects.

The lookup function also handles the key-value pairs efficiently. In conclusion, you can use the lookup function in different scenarios to simplify the infrastructure configurations defined using Terraform HCL.

We encourage you also to explore how Spacelift makes it easy to work with Terraform. If you need any help managing your Terraform infrastructure, building more complex workflows based on Terraform, and managing AWS credentials per run, instead of using a static pair on your local machine, Spacelift is a fantastic tool for this. It supports Git workflows, policy as code, programmatic configuration, context sharing, drift detection, and many more great features right out of the box. You can check it for free by creating a trial account.

Note: New versions of Terraform are 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 expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.

Automate Terraform Deployments with Spacelift

Automate your infrastructure provisioning, and 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

The Practitioner’s Guide to Scaling Infrastructure as Code

Transform your IaC management to scale

securely, efficiently, and productively

into the future.

ebook global banner
Share your data and download the guide