Suppose you get an assignment where you have to deploy the same resource multiple times (in one environment and as resource local network gateway in my context). How would you do it?
You could
- Create each resource manually;
- Create a module and refer to it multiple times;
- Use a count and loop through it.
The options above would show something like this (excluding count here):
# Done via creating resource manually or via Modules.
module "local-net-gw" {
source = "../../modules/local-net-gw"
name = var.name
resource_group_name = var.resource-group-name
location = var.location
gateway_address = var.gateway-address
address_space = var.address-space
}
module "local-net-gw2" {
source = "../../modules/local-net-gw"
name = var.name2
resource_group_name = var.resource-group-name2
location = var.location
gateway_address = var.gateway-address2
address_space = var.address-space2
}
While Terraform can deploy this successfully, you’ve created more duplicated code in your resource.tf file and defined more variables in your variables.tf & .tfvars’ files.
So what can we do to mitigate this kind of coding? We can make lists for this, but we need to have to define the unique parameters in it.
In this blog, we will discuss the solution for this with the use of for_each
.
For each
A for_each can be seen as a loop where it will accept a map or a set of strings.
A map
is a group of values that can be identified by labeling it (this can be seen in the Python language as a dictionary).
If we go back to the module code, we need to create a map in the input fields that this module needs to have in order to deploy:
Main.tf
Line 5 defines the for_each
function to loop it through var.local-net-gw which is in the variables.tf a map
type.
Line 7 – 11 shows the syntax to perform the each value for each variable.
module "local-net-gw" {
source = "../../modules/local-net-gw"
# Process Resource List
for_each = var.local-net-gw # Use for_each based on the variables below.
name = each.value.name
resource_group_name = each.value.resource-group-name
location = each.value.location
gateway_address = each.value.gateway-address
address_space = each.value.address-space
}
Variables.tf
# Local Network Gateway
variable "local-net-gw" {
description = "Variable Mapping for Configuration Local Network Gateway"
type = map(any)
}
Your unique parameters will be defined in the .tfvars file as usual but with a different format of syntax since we’re using maps:
dev.tfvars
# Local Network Gateway
local-net-gw = {
# VPN Connections (Site-to-Site)
"local-network-gateway1" = {
name = "local-network-gateway1"
resource-group-name = "rg-onemanitarmy"
location = "westeurope"
gateway-address = "100.100.100.1"
address-space = ["192.168.1.0/24"]
},
"local-network-gateway2" = {
name = "local-network-gateway2"
resource-group-name = "rg-onemanitarmy"
location = "westeurope"
gateway-address = "100.100.100.2"
address-space = ["192.168.2.0/24"]
}
}
And there you have it.
Personally, if someone asks me to create one resource, I would probably implement it via modules for future purposes and adjust the resource.tf to for_each
if multiple resources are needed to deploy.
More information (such as restrictions) can be found on the official webpage of Terraform.
Code can be found in the repository link here.