HashiCorp Terraform is a great Infrastructure as Code (IaC) tool that allows you to easily manage many resources efficiently. While you can write Terraform code for each individual resource, Terraform supports for_each
loops and other programming constructs that enable more efficient resource management to be programmed within a Terraform project. This article will show you ow to use for_each
in Terraform to create / manage multiple instances of resources or Terraform modules with unique configurations more easily.
Let’s dive in!
Table of Contents
What is for_each
in Terraform?
In HashiCorp Terraform, the for_each
serves as a loop function in HCL (HashiCorp Configuration Language), empowering DevOps Engineers and Site Reliability Engineers (SREs) to manage multiple instances of the same resources with distinct individual configurations. Unlike count
, which generates identical resource instances, for_each
facilitates an easier ability to create resources with individualized configurations, enhancing precision and flexibility in infrastructure provisioning.
The syntax for utilizing for_each
in Terraform is as follows:
resource <PROVIDER_TYPE> "<NAME>" {
for_each = <COLLECTION>
# Resource configuration here
}
Within the resource configuration block, HashiCorp Terraform iterates over the collection provided to for_each
, accessing each item via the each
keyword, which is comprised of key-value pairs.
Using Terraform for_each
with a set
In Terraform, sets offer a means to define a collection of items for configuring multiple resource instances using for_each
. If working with a list, the toset()
function can be employed to convert it to a set, as lists are not directly supported by for_each
.
Let’s take a look at doing this with both a resource
block and Terraform Modules…
Use for_each
on a resource block
Consider the following example, where we define a list of Azure Resource Group names and employ for_each
to configure multiple resource groups:
resource azurerm_resource_group "resource_groups" {
for_each = toset([
"prod-b59-webapp1-rg",
"prod-b59-database1-rg"
])
name = each.key
location = "eastus"
}
This example will provision multiple Azure Resource Groups by iterating over the set of strings provided to for_each
via toset()
. The each.key
is utilized to access the string value for each of the items in the collection.
Use for_each
on a Terraform Module block
Similarly, when using Terraform Modules, for_each
can be employed to configure module
blocks too:
module "resource_groups" {
for_each = toset([
"b59-prod-eus-webapp",
"b59-prod-eus-database"
])
source = "./resource_groups_module"
name = "${each.key}-rg"
}
In this example, a set is defined to specify the instances of the module, and each.key
is used within expressions to customize the configurations accordingly.
What are Terraform Modules? Terraform Modules are a way to create blocks of Terraform HCL (HashiCorp Configuration Language) code that is reusable either within a single Terraform project, or even reusable across multiple Terraform projects.
Using Terraform for_each
with a map
Maps serve as a means to define collections of key-value pairs in Terraform. Consider the following example of using for_each
with a map of key-value pairs.
Here’s the key-value pair map definition:
locals {
resource_groups = {
"b59-prod-eus-webapp-rg" = "eastus"
"b59-prod-eus-database-rg" = "eastus"
}
}
Utilizing this map, we can configure Azure Resource Groups using for_each
as in the following examples:
resource azurerm_resource_group "resource_groups" {
for_each = local.resource_groups
name = each.key
location = each.value
}
In this example, for_each
iterates over the map, enabling the configuration of multiple Azure Resource Groups with the location
attribute set to the each.value
of the map.
Using Terraform for_each
with a map of Objects
Expanding on using for_each
with maps, you can utilize a map of Objects to define more complex configurations.
Here’s an example map of Objects:
locals {
virtual_machines = {
"b59-prod-eus-vm" = {
location = "eastus"
size = "Standard_B2s"
}
"b59-prod-wus-vm" = {
location = "westus"
size = "Standard_B4ms"
}
}
}
By using for_each
and passing it the map, you can configure multiple resources, such as Azure Virtual Machines in the following example:
resource azurerm_virtual_machine "vm" {
for_each = local.virtual_machines
name = each.key
location = each.value.location
vm_size = each.value.size
# Additional VM configurations here
}
Advantages of using for_each
in Terraform
Using for_each
in HashiCorp Terraform offers several advantages over other loop functions such as count
:
- Simplifies Resource Management – Manage multiple resources of the same type with a single block of code, reducing complexity, while enabling each instance to have individual configurations.
- Avoids Repetitive Code – Enhances code cleanliness by eliminating the need for repetitive resource or module blocks within the Terraform project for similarly configured resources.
- Increases Efficiency – Streamlines infrastructure provisioning, saving time and reducing errors when multiple similarly configured resources are managed.
Conclusion
The for_each
in HashiCorp Terraform is an important programming construct that makes the HCL (HashiCorp Configuration Language) for managing IaC projects more robust. By simplifying resource management using for_each
, you can reduce code duplication and boosting efficiency. The for_each
empowers DevOps Engineers and Site Reliability Engineers (SREs) to create scalable and more easily maintainable infrastructure configurations using HashiCorp Terraform.