Johnathan
Johnathan

Reputation: 877

Create multiple objects from one Terraform module using Terragrunt

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
}

Upvotes: 4

Views: 7661

Answers (1)

Ben Whaley
Ben Whaley

Reputation: 34416

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.

Upvotes: 2

Related Questions