In the ever-evolving landscape of Infrastructure as Code (IaC), Terraform stands tall as one of the leading tools for provisioning and managing cloud resources. Terraform’s flexibility and robustness are often attributed to its wide array of features and functions, and among them, Terraform Locals emerge as a valuable gem. In this comprehensive guide, we will delve deep into Terraform Locals, exploring what they are, how to use them effectively, and their seamless integration with variables. Furthermore, we’ll provide you with real-world code examples to solidify your understanding.

What are Terraform Locals?

Terraform Locals, often referred to as locals, are a powerful construct that allows you to declare and define values within your Terraform configuration files. Think of them as user-defined variables that are scoped to a particular resource, module, or even the entire configuration. These locally defined values can be utilized throughout your configuration, promoting code reusability, enhancing readability, and reducing redundancy.

Locals can store a variety of data types, including strings, numbers, lists, and maps, making them highly versatile. They serve as a dynamic bridge between static values and the more complex expressions you may need within your Terraform configuration.

How to use Terraform Locals?

Utilizing Terraform Locals is remarkably straightforward, but the benefits they bring to your IaC projects are immense. Here’s a step-by-step guide on how to leverage locals effectively:

1. Declaration

To create a local, you’ll first declare it within your Terraform configuration. Use the locals block to define your locals, specifying a name for each and assigning it a value. Let’s say you want to create a local that stores the name of a virtual machine:

locals {
  vm_name = "my-vm"
}

2. Reference

Once declared, you can reference the local variable anywhere in your configuration using the following syntax:

resource "azurerm_virtual_machine" "example" {
  name = local.vm_name
  # other VM configurations
}

This simple example showcases how you can replace the static string "my-vm" with the local variable local.vm_name, enhancing maintainability and reducing errors in your code.

3. Utilization

Locals shine when you need to reuse values across multiple resources or when dealing with complex expressions. For example, you might define a local to calculate the desired count of virtual machines based on some criteria:

locals {
  vm_count = var.environment == "production" ? 5 : 2
}

This local variable vm_count now holds the number of VMs you need, which can be used consistently across various resources in your configuration.

Combine Terraform Locals with Variables

Terraform Locals and variables are a formidable duo, enhancing the modularity and flexibility of your IaC code. While locals are best suited for defining values within your configuration, variables are ideal for parameterizing your Terraform modules and configurations.

To combine Terraform Locals with variables, follow these steps:

1. Declare Variables

Start by declaring your variables using the variable block:

variable "environment" {
  description = "The environment (e.g., 'production' or 'development')."
  type        = string
  default     = "development"
}

2. Use Variables in Locals

Next, use these variables within your locals to create dynamic values:

locals {
  vm_count = var.environment == "production" ? 5 : 2
}

Now, the local variable vm_count adapts to the value of the environment variable, providing a flexible way to adjust your infrastructure based on different environments.

Examples of using Terraform Locals

Let’s tie it all together with a practical code example. Imagine you’re provisioning virtual machines in Azure, and you want to set the number of VM instances based on the environment. Here’s a Terraform configuration that showcases the power of Terraform Locals and their integration with variables:

# Declare variables
variable "environment" {
  description = "The environment (e.g., 'production' or 'development')."
  type        = string
  default     = "development"
}

# Define locals
locals {
  vm_count = var.environment == "production" ? 5 : 2
  vm_name  = "my-vm"
}

# Create Azure Virtual Machine
resource "azurerm_virtual_machine" "example" {
  count         = local.vm_count
  name          = "${local.vm_name}-${count.index}"
  # other VM configurations
}

In this example, the number of virtual machines and their names are determined by the vm_count and vm_name local variables, which in turn rely on the environment variable.

Next, let’s take a look at a few specific usage examples of Terraform Locals for more specific scenarios:

Example: String Interpolation with Terraform Locals

# Declare a local variable for the resource name
locals {
  resource_name = "my-resource"
}

# Create an Azure Resource Group with a dynamically generated name
resource "azurerm_resource_group" "example" {
  name     = local.resource_name
  location = "East US"
}

In this example, we use string interpolation to dynamically set the name attribute of an Azure Resource Group. The ${local.resource_name} placeholder is replaced with the value of the resource_name local variable.

Example: Conditional Logic with Terraform Functions

# Declare a local variable for the environment
locals {
  environment = "production"
}

# Create an Azure Virtual Machine with a conditional OS image selection
resource "azurerm_virtual_machine" "example" {
  name                  = "my-vm"
  location              = "East US"
  resource_group_name   = "my-resource-group"
  vm_size               = local.environment == "production" ? "Standard_DS2_v2" : "Standard_B1s"
  delete_os_disk_on_termination = local.environment == "production" ? false : true
}

In this example, we use conditional logic with Terraform functions to select different VM sizes and set the delete_os_disk_on_termination attribute based on the value of the environment local variable.

Example: List Manipulation with Terraform Functions

# Declare a local list of subnet names
locals {
  subnet_names = ["subnet-a", "subnet-b", "subnet-c"]
}

# Create Azure Network Security Groups and associate them with subnets
resource "azurerm_network_security_group" "example" {
  count = length(local.subnet_names)
  name  = "nsg-${local.subnet_names[count.index]}"
  location = "East US"
}

resource "azurerm_subnet_network_security_group_association" "example" {
  count                   = length(local.subnet_names)
  subnet_id               = azurerm_subnet.example[count.index].id
  network_security_group_id = azurerm_network_security_group.example[count.index].id
}

In this example, we declare a local list of subnet names and use Terraform functions like length and count.index to create Azure Network Security Groups with dynamically generated names and associate them with subnets based on the list.

Example: Map usage with Terraform Locals

# Declare a local map of Azure regions and their corresponding virtual network address prefixes
locals {
  region_prefixes = {
    "East US"       = "10.0.0.0/16",
    "West Europe"   = "10.1.0.0/16",
    "Southeast Asia" = "10.2.0.0/16",
  }
}

# Create Azure Virtual Networks with address prefixes from the local map
resource "azurerm_virtual_network" "example" {
  for_each            = local.region_prefixes
  name                = "vnet-${each.key}"
  location            = each.key
  address_space       = [local.region_prefixes[each.key]]
  dns_servers         = ["8.8.8.8", "8.8.4.4"]
}

In this example, we declare a local map region_prefixes that associates Azure regions with their corresponding virtual network address prefixes. We then use the for_each iterator to create Azure Virtual Networks with dynamically generated names and address spaces based on the values in the map.

Conclusion

In conclusion, Terraform Locals are a valuable tool in your IaC arsenal, providing a means to create reusable, dynamic values within your configurations. When combined with variables, they enable you to build flexible and maintainable infrastructure code. Harness the power of Terraform Locals in your projects, and watch your IaC efficiency soar.

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
Microsoft MVP HashiCorp Ambassador

Discover more from Build5Nines

Subscribe now to keep reading and get access to the full archive.

Continue reading