Create list of map keys to iterate over in Terraform

29 views Asked by At

I have the following Terragrunt unit that I'd like to prefix a given environment too.

envs:
  - dev
  - stg
tables:
  dynamo-db-table:
    hash_key: "key"
    attributes:
      - name: "key"
        type: "S"

working with the following module

module "dynamodb_table" {
  source       = "terraform-aws-modules/dynamodb-table/aws"
  version      = "3.3.0"
  for_each     = var.tables
  name         = each.key
  hash_key     = each.value.hash_key

  attributes = each.value.attributes
}

variable "tables" {
  description = "Dyanamodb tables"
  type = map(object({
    hash_key   = string
    attributes = list(map(string))
  }))

When I apply the above config, I'd like the output to ultimately create 2 dynamodb tables "dev-dynamo-db-table" and "stg-dynamo-db-table"

I suspect there is a way of concatenating the envs value onto the map key through a locals value but am not sure how, nor if there is a much simpler way of doing it?

1

There are 1 answers

0
Rui Jarimba On

Full working sample code:

# variables.tf

variable "envs" {
  description = "List of environments"
  type        = list(string)
  default = [
    "dev",
    "stg"
  ]
}

variable "tables" {
  description = "Dyanamodb tables"
  type = map(object({
    hash_key   = string
    attributes = list(map(string))
  }))
  default = {
    "dynamo-db-table" = {
      hash_key = "key"
      attributes = [
        {
          name = "key"
          type = "S"
        }
      ]
    }
  }
}
# main.tf

locals {
  # Create a map of environment to tables
  environment_tables = flatten([
    for enviroment in var.envs : [
      for table_key, table_value in var.tables : {
        table_name = "${enviroment}-${table_key}"
        hash_key   = table_value.hash_key
        attributes = table_value.attributes
      }
    ]
  ])
}

# dummy resource, for testing purposes only
resource "null_resource" "dynamodb_table" {
  for_each = {
    for table in local.environment_tables : table.table_name => table
  }

  triggers = {
    name       = each.key
    hash_key   = each.value.hash_key
    # no need to use jsonencode in real code
    attributes = jsonencode(each.value.attributes)
  }
}

Output of terraform plan:

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # null_resource.dynamodb_table["dev-dynamo-db-table"] will be created
  + resource "null_resource" "dynamodb_table" {
      + id       = (known after apply)
      + triggers = {
          + "attributes" = jsonencode(
                [
                  + {
                      + name = "key"
                      + type = "S"
                    },
                ]
            )
          + "hash_key"   = "key"
          + "name"       = "dev-dynamo-db-table"
        }
    }

  # null_resource.dynamodb_table["stg-dynamo-db-table"] will be created
  + resource "null_resource" "dynamodb_table" {
      + id       = (known after apply)
      + triggers = {
          + "attributes" = jsonencode(
                [
                  + {
                      + name = "key"
                      + type = "S"
                    },
                ]
            )
          + "hash_key"   = "key"
          + "name"       = "stg-dynamo-db-table"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.