In the modern world, organizations tend to use IaC (Infrastructure as Code) tools instead of traditional methods to provision and manage their IT infrastructure components.
The main disadvantage of using traditional methods is it can be complex to provision and manage many IT infrastructure components manually. So, there can be errors that take more time to troubleshoot and fix and consume more time.
As a solution, people use IaC tools such as Terraform, Ansible, AWS CloudFormation, etc., to automate this process. Terraform is known as one of the popular IaC tools used in the industry. In Terraform, there is a feature called ‘Locals’ which helps us to maintain our code.
Through this article, we will deeply discuss the definition of Terraform locals, the difference between locals and variables, and how to define and refer to them through some examples.
Firstly, let’s see what Terraform locals are.
Terraform Locals
Terraform locals are named values that can be assigned and used within our code. Locals assign names to values or expressions in our code. Then, we can refer to them multiple times whenever and wherever we need, as it helps us to reduce duplicates and keep our code clean. It also increases the code readability.
In programming languages, we have variables that can be changed or manipulated during any action or process. But in Terraform, locals do not modify the values during the Terraform workflow; terraform init, plan, apply.
Now, let’s see the differences between Terraform locals and variables.
Terraform locals vs Terraform Variables
Let’s do the comparison under four main characteristics.
- Scope: Terraform locals have a limited range as they can only be accessed within the defined block or module. But Terraform variables have a broader scope as they can be accessible anywhere from the configuration.
- Visibility: Locals are visible only in their defined module, where variables are visible in all the modules that import the module where the variables are declared.
- Mutability: Values of the locals cannot be changed or manipulated once assigned. However, variable values can be changed by the Terraform or the user during the Terraform plan and apply processes.
- Value: In Terraform locals, we can set the value of a local using an expression where the value can be calculated based on the values of the other variables or resources. However, the value of a Terraform variable can be set using an input or a variable.
Now we have a clear idea about what a Terraform local is and how it differs from variables in Terraform, we can learn the syntax and some examples of defining Terraform locals.
Syntax of a Terraform local
The general syntax of declaring a Terraform Local is as follows.
locals {
variable_name = <expression>
}
- locals: When we need to use locals in Terraform, this is the keyword we use to open a local block.
- variable_name: These are the names for the local variables defined by the users. When assigning the names, we must adhere to the Terraform naming conventions.
- expressions: These can be Terraform expressions, including string manipulations, function calls, arithmetic operations, etc.
Defining a Local in Terraform
Now we know the syntax of a Terraform local. Let’s see some simple examples of defining Terraform locals.
Example 1: Assigning a simple string as the value.
locals {
env = "development"
}
Here, we have used one local variable called ‘env’, which has the value ‘development’. So, we used a simple string as the value.
Example 2: Assigning an expression as the value.
locals {
rect_width = 10
rect_height = 5
rect_area = local.rect_width * local.rect_height
}
Here, we have defined three local variables: ‘rect_width’, ‘rect_height’ and ‘rect_area’, representing a rectangle’s width, height and area. Width and height have simple values, but for the area, we have assigned an expression to calculate the area with the relevant data.
Example 3: Assigning a map as the value
Instead of using expressions and other single values, we can assign a map as the value, which consists of key-value pairs.
locals {
env_tags = {
env = "development"
env_team = "development_team"
}
}
Here, we have assigned a map called ‘env_tags’, which has ‘env’ and ‘env_team’ keys with related values.
So, as in the above examples, we can declare and assign values in different ways. Let’s see how we can use/refer to these defined locals in our configuration.
Referring local values
Once we declare the local values, we can refer to them in expressions in a specific way.
local.<NAME>
Here, the ‘local’ keyword refers to the locals block and <NAME> is the variable name (env, rect_width, rect_height, etc.) we used in our locals block.
Note: We use ‘locals’ blocks to declare local values. But when referring to them, we use the ‘local’ keyword. So, we have to be careful when declaring and referring to the locals.
Now, let’s see some examples.
Example 1: Using a local in a single resource block
Let’s assume we want to provision an AWS S3 bucket. It must include a name for the S3 bucket, Access Control List (ACL) configurations and tags. As the tags, we will have the ‘Name’ and the ‘Environment’.
We can create a locals block to declare some values to use within the configuration. Look at the code below.
locals {
bucket_name = "newBucket"
env_name = "development"
}
resource "aws_s3_bucket" "sample_bucket" {
bucket = local.bucket_name
acl = "private"
tags = {
Name = local.bucket_name
Environment = local.env_name
}
}
Here, we have defined two locals, ‘bucket_name’ and ‘env_name’, with relevant values within the locals block. Then, have declared our resource block for the S3 bucket with ‘bucket’, ‘acl’ and ‘tags’ as the attributes.
As you can see, we have referred to the bucket, ‘Name’ and ‘Environment’ using the locals we defined.
bucket = local.bucket_name
Name = local.bucket_name
Environment = local.env_name
Example 2: Using locals across multiple resource blocks.
Let’s assume we have declared three resources: an AWS S3 bucket, an EC2 instance and a VPC. All of them contain the attribute called ‘tags’; inside this attribute, we have to define the environment; in our case, it is a ‘development’ environment.
locals {
env = "development"
}
resource "aws_s3_bucket" "sample_bucket" {
bucket = newBucket
acl = "private"
tags = {
Environment = local.env
}
}
resource "aws_vpc" "sample-vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Environment = local.env
}
}
resource "aws_instance" "sample_ec2" {
ami = "ami-0767046d1677be5a0"
instance_type = "t3.nano"
tags = {
Environment = local.env
}
}
Here, we have declared a local called ‘env’ with ‘development’ as the value. As needed, we have the ‘Environment’ attribute inside every ‘tags’ attribute and have referred to it using the locals we created.
This way, we can easily use our locals within our Terraform configuration.
Conclusion
In this article, we learned about the Terraform locals, some critical differences between Terraform locals and variables, and how to declare locals and use them within our Terraform configuration. As we discussed, Terraform locals are very beneficial as we can reduce the duplications in the code, which can lead to errors. It also helps us maintain the code and have it clean, increasing the code readability.
So, it is our responsibility to get the maximum out of these features to save time and costs and ease the process of automating the infrastructure management and provisioning.