Today I Learned

Dynamic blocks with for_each in Terraform

We have a module with AWS CodePipeline:

module "codepipeline" {
  source = "../modules/codepipeline"
...

this module configures multiple apps deployments in a single AWS Region. We use this module for staging and production environment.

For AWS CodeBuild we need to provide bunch of ENVs for docker build aka. build args.

resource "aws_codebuild_project" "portal" {
  # ...
  environment {
    environment_variable {
        name  = "MIX_ENV"
        value = var.environment
    }
    environment_variable {
      name  = "REPOSITORY_URI"
      value = var.repo_uri
    }
   # ...
  }

Since Terraform 0.12.x we can refactor that into dynamic block:

environment {
    dynamic "environment_variable" {
      for_each = var.build_args

      content {
        name  = environment_variable.value.name
        value = environment_variable.value.value
      }
    }
}

so we can provide args to the module as a variable:

module "codepipeline" {
  source = "../modules/codepipeline"

  build_args = [
    {
      name = "MIX_ENV"
      value = "prod"
     },
    {
      name = "REPOSITORY_URI"
      value = module.ecr.repo_uri
    }
  ]
...

This gives us better flexibility and safe separation from production and staging because we can introduce changes independently.

More info here: here