Managing Terraform locals efficiently is crucial for creating clean, maintainable, and reusable configurations. This guide will cover what Terraform locals are, how to implement them, and best practices for their use.
What are Terraform Locals?
All programming languages have mechanisms to store values within the context of a code block. In Terraform configurations, this functionality is provided through local values. Locals allow you to define temporary values and reference them elsewhere in your configuration.
Local values, often called “locals” or “Terraform local variables,” can be used to store expressions that will be referenced multiple times, perform data transformations, or hold static values. Locals are one of three types of Terraform variables, the other two being input variables and output values. This post will examine how to define local values, how they differ from input variables, and common use cases for locals.
How to Implement Terraform Locals?
Defining local values in Terraform is done using a locals block, with each local assigned a name and value in a key-value pair format. Here’s an example:
locals {
environment = "development"
}
Locals can be assigned any valid Terraform data type, such as strings, lists, maps, or objects. The actual values can come from input variables, resource attributes, or other local values defined in the configuration.
locals {
environment = "development"
server_list = ["web", "app", "db"]
subnet_map = {
web = var.web_subnet
app = var.app_subnet
db = var.db_subnet
}
}
A locals block is useful for composing expressions that will be used elsewhere in the configuration, including ternary, and for expressions. For example, setting a DNS value conditionally:
locals {
dns_entry = var.create_load_balancer ? azurerm_public_ip.lb.fqdn : azurerm_public_ip.vm.fqdn
}
Using a for expression to create local values for naming resources:
locals {
server_list = ["web", "app", "db"]
server_names = [ for svr in local.server_list : "${var.prefix}-${svr}" ]
}
You can have multiple locals blocks in a Terraform configuration, as long as each local value has a unique name. Some prefer to define all locals in a single locals block in a dedicated locals.tf file, while others place multiple locals blocks near the resources and data sources that reference them.
Referencing a local value is done with the local keyword followed by the local’s name. Here’s how to use the server_names and environment locals in an Azure VM resource:
resource "azurerm_linux_virtual_machine" "web" {
name = local.server_names[0]
#...
tags = {
environment = local.environment
}
}
Locals defined in a Terraform module are only available within that module. They follow the same scoping principles as input variables, resources, and data sources.
Terraform Locals vs. Input Variables
While Terraform input variables and local values are similar, there are key differences:
Input Variables
- Dynamic values defined at runtime
- Values cannot come from other configuration sources
- Default value can be overridden
Local Values
- Defined by an internal expression
- Can be assigned any valid Terraform expression
- Can be assigned static values
In most programming languages, input variables would be called “parameters,” and local values would be called “variables.” Use input variables for values that need to be dynamic and change at runtime. Use local values for reusable expressions or data transformations.
Examples of Terraform Locals
Reusing a Value
Locals allow you to define a value once and reuse it throughout the configuration. For instance, using a local value to define a set of common tags:
locals {
common_tags = {
environment = var.environment
project = var.project
billing = var.billingcode
}
}
resource "azurerm_resource_group" "main" {
...
tags = local.common_tags
}
Data Transformation
Locals can transform data before it is used in the configuration. For example, updating list values:
locals {
env_config_list = [ for item in var.config_list : "${local.environment}-${item}" ]
}
Even if the local value isn’t used multiple times, performing data transformation in a locals block can simplify other configuration blocks and make them easier to read.
Constant Values
Unlike input variables, locals don’t accept input values, making them ideal for setting static constants that can only be updated by altering the code. For example:
locals {
web_app_ports = ["8080", "8443"]
}
If you want to change the port list, you must update the code itself, rather than altering input variable values during a Terraform run. This approach helps maintain configuration values in one place and prevents unauthorized changes.
Conclusion
Locals in Terraform configuration files help construct reusable values to be referenced throughout a configuration. Values can be assigned to locals from input variables, resources, data sources, and other local values. Understanding and effectively using locals can lead to more organized and maintainable Terraform configurations.
If you’re new to Terraform and want to dive deeper, check out our post: Get Started with Terraform: Terraform Tutorial For Beginners.