Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

merge two terraform maps, only if condition is true

Tags:

terraform

Introduction

I'd like to merge two terraform maps, only when a condition is true.

  • The merging can be done with the merge() function.
  • The condition is whether a key exists in a map. That can be checked with the lookup() function.
locals {
  # this merge is fine
  #
  workspace_default = "${
    merge(
      local.env["default"], 
      local.workspaces[terraform.workspace])}"

   # this merge fails with: "conditional operator cannot be used with list values"
   #
   # What I'd like for workspace is this conditional merge
   # based on wether local.env[terraform.workspace] exists. 
   #
    my_workspace = "${lookup(local.env, terraform.workspace, "") != "" ? 
      merge(local.workspace_default, local.env[terraform.workspace]) : 
      local.workspace_default}"

Background

You may skip reading this if you don't care why I'm doing a conditional merge.

Some background on why I'm doing these merge, as perhaps this isn't the best way to achieve that result in terraform.

I terraform the same project to multiple workspaces. The workspaces are different AWS accounts and regions. That list is defined in a central terraform file. That information is kept out of each project because:

  • many projects are terraformed to many workspaces,
  • a project's terraform files in source control shouldn't need to be edited, if I later want to terraform that project to a new workspace that didn't exist when the project's terraform files were written. I much prefer to add new workspaces to one central terraform file than to every project's terraform. A project's terraform files should be about what AWS resources are needed (lambdas, dynamo, roles, etc..), but not in what AWS account, the latter being managed outside the project.

The central terraform file looks like

locals {
  workspaces = {
    workspace_1 = {
       aws_region = us-east-1
       aws_account = [some account id]
    }
    workspace_2 = {
       aws_region = us-west-2
       aws_account = [some account id]
    }
    ...
    # a list of workspaces
  }
}

The workspace information (aws account, region) can be loaded via a simple merge() into workspace_default. So far so good.

Now each project may want to define a specific local map entry, perhaps that project needs a higher DynamoDB RCU in workspace_17. For e.g.

locals {
   env = {
     # stuff that is common to this project in any workspace
     default = {
         rcu = [the normal RCU value]
         ...
         # list of key value pairs
     }
     # stuff that must be defined for this project in workspace_17
     workspace_17 {
         rcu = [a higher RCU value]
     }
   }
}

I'm trying to find out how to merge that project's workspace overrides into my_workspace. And a project may not override anything, so locals.env[terraform.workspace] may not exist. Hence the use of the lookup() function.

Terraform Version

I use terraform version 1.11.13 and I cannot easily upgrade to 1.12, so any solution needs to work with 1.11.

like image 870
mipnw Avatar asked Jan 30 '26 10:01

mipnw


1 Answers

The following does a conditional merge

locals {
  workspace = "${
    merge(
      local.workspaces[terraform.workspace],
      merge(
        local.env["default"],
        local.env[contains(keys(local.env), terraform.workspace) ? terraform.workspace : "default"]))}"
}

like image 128
mipnw Avatar answered Feb 02 '26 10:02

mipnw