I am using terraform via terragrunt. I have a folder with a single terragrunt.hcl file in it. The purpose of this file is to create multiple subnetworks in GCP.
To create a subnetwork, I have a module that takes several inputs.
I want to be able to create several subnetworks in my terragrunt.hcl file.
I think the best way would be to create a list with dictionaries (or maps as terraform call them) and then iterate over them.
I have some code that is not working
Here is some non-working code.
#terragrunt.hcl
include {
path = find_in_parent_folders()
}
inputs = {
# Common tags to be assigned to all resources
subnetworks = [
{
"subnetName": "subnet1-euw"
"subNetwork": "10.2.0.0/16"
"region": "europe-west1"
},
{
"subnetName": "subnet1-usc1"
"subNetwork": "10.3.0.0/16"
"region": "us-central1"
}
]
}
terraform {
module "subnetworks" {
source = "github.com/MyProject/infrastructure-modules.git//vpc/subnetwork"
vpc_name = "MyVPC"
vpc_subnetwork_name = [for network in subnetworks: network.subnetName]
vpc_subnetwork_cidr = [for network in subnetworks: network.subNetwork]
vpc_subnetwork_region = [for network in subnetworks: network.region]
}
}
Seems I cannot use "module" inside the "terraform" block. Hopefully the code at least show what I want to achieve.
For reference, the module I am calling looks like this
#main.tf
terraform {
# Intentionally empty. Will be filled by Terragrunt.
backend "gcs" {}
}
resource "google_compute_subnetwork" "vpc_subnetwork" {
name = var.vpc_subnetwork_name
ip_cidr_range = var.vpc_subnetwork_cidr
region = var.vpc_subnetwork_region
network = var.vpc_name
}
#variables.tf
variable "vpc_name" {
description = "Name of VPC"
type = string
}
variable "vpc_subnetwork_name" {
description = "Name of subnetwork"
type = string
}
variable "vpc_subnetwork_cidr" {
description = "Subnetwork CIDR"
type = string
}
variable "vpc_subnetwork_region" {
description = "Subnetwork region"
type = string
}
Terragrunt does not have a loop construct. In Terragrunt, you'd use a directory hierarchy to do what you want here. For example, to achieve your goals above, something like this:
└── live
├── empty.yaml
├── euw
│ ├── region.yaml
│ └── vpc
│ └── terragrunt.hcl
├── terragrunt.hcl
└── usc1
├── region.yaml
└── vpc
└── terragrunt.hcl
Within live/terragrunt.hcl
, you make the other yaml files available within the terragrunt configuration:
# live/terragrunt.hcl
inputs = merge(
# Configure Terragrunt to use common vars encoded as yaml to help you keep often-repeated variables (e.g., account ID)
# DRY. We use yamldecode to merge the maps into the inputs, as opposed to using varfiles due to a restriction in
# Terraform >=0.12 that all vars must be defined as variable blocks in modules. Terragrunt inputs are not affected by
# this restriction.
yamldecode(
file("${get_terragrunt_dir()}/${find_in_parent_folders("region.yaml", "${path_relative_from_include()}/empty.yaml")}"),
)
)
In the region.yaml
within each region, you simply state the region:
# live/euw/region.yaml
# These variables apply to this entire region. They are automatically pulled in using the extra_arguments
# setting in the root terraform.tfvars file's Terragrunt configuration.
region: "europe-west1"
# live/usc1/region.yaml
region: "us-central1"
Now you can refer to the region in your per-region terragrunt.hcl
files as a variable:
# live/euw/vpc/terragrunt.hcl
terraform {
source = "github.com/MyProject/infrastructure-modules.git//vpc/subnetwork"
}
include {
path = find_in_parent_folders()
}
inputs = {
vpc_subnetwork_name = "subnet1-${region}"
vpc_subnetwork_cidr = "10.2.0.0/16"
vpc_subnetwork_region = region
vpc_name = "MyVPC"
}
Also:
# live/usc1/vpc/terragrunt.hcl
terraform {
source = "github.com/MyProject/infrastructure-modules.git//vpc/subnetwork"
}
include {
path = find_in_parent_folders()
}
inputs = {
vpc_subnetwork_name = "subnet1-${region}"
vpc_subnetwork_cidr = "10.3.0.0/16"
vpc_subnetwork_region = region
vpc_name = "MyVPC"
}
You might find the example terragrunt repository from Gruntwork helpful.