Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Terraform: Copy specific elements from map where specified by list

I feel like this is really easy and obvious, but for the life of me I can’t figure out how I should be approaching it.

I have a list of environments I wish to build ["env1", "env2"…], and then I have a map that specifies the values used for a specific environment.

    "wanted_envs": ["env1", "env2"]
    "envs": {
        "env1": {
            "type": "prod",
            "backend": "cust-prod-backend-vpc",
            "backend_subnet": "192.168.0.0/22",
            "k8_pod_subnet": "192.168.35.16.0/20",
            "k8_service_subnet": "192.168.40.0/20",
            "gateway_subnet": "1.2.3.0/27",
            "dmz": "env1"
        },
        "env2": {
            "type": "prod",
            "backend": "cust-prod-backend-vpc",
            "backend_subnet": "192.168.0.0/22",
            "k8_pod_subnet": "192.168.35.16.0/20",
            "k8_service_subnet": "192.168.40.0/20",
            "gateway_subnet": "1.2.3.0/27",
            "dmz": "env2"
        },
        "env3": {
            "type": "prod",
            "backend": "cust-prod-backend-vpc",
            "backend_subnet": "192.168.0.0/22",
            "k8_pod_subnet": "192.168.35.16.0/20",
            "k8_service_subnet": "192.168.40.0/20",
            "gateway_subnet": "1.2.3.0/27",
            "dmz": "env3"
        },
        ......

I simply need to create a local variable, which contains the details of the environments I wish to build (listed in my list of strings) copied from the map in envs.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

In my locals definition I’ve tried various forms of for_each thinking I can get the value from the list of required envs, but I can’t quite figure it out without just getting errors from doing the ‘wrong’ thing with terraform.

I would end up with a map, containing only the values for the envs listed in wanted_envs.

Like so:

    "envs_to_build": {
        "env1": {
            "type": "prod",
            "backend": "cust-prod-backend-vpc",
            "backend_subnet": "192.168.0.0/22",
            "k8_pod_subnet": "192.168.35.16.0/20",
            "k8_service_subnet": "192.168.40.0/20",
            "gateway_subnet": "1.2.3.0/27",
            "dmz": "env1"
        },
        "env2": {
            "type": "prod",
            "backend": "cust-prod-backend-vpc",
            "backend_subnet": "192.168.0.0/22",
            "k8_pod_subnet": "192.168.35.16.0/20",
            "k8_service_subnet": "192.168.40.0/20",
            "gateway_subnet": "1.2.3.0/27",
            "dmz": "env2"
        }
}

>Solution :

Using a for expression can get you what you need. Consider the following shortened example.

locals {
  envs = {
    env1 = {
      prop = "foo"
    },
    env2 = {
      prop = "bar"
    },
    env3 = {
      prop = "baz"
    }
  }

  targets = ["env1", "env3"]
}

output "target_envs" {
  value = [for k, v in local.envs : v if contains(local.targets, k)]
}

This yields the output of:

Changes to Outputs:
  + target_envs = [
      + {
          + prop = "foo"
        },
      + {
          + prop = "baz"
        },
    ]

And if you want to maintain the keys, as in your edit, one can do it like so:

locals {
  envs = {
    env1 = {
      prop = "foo"
    },
    env2 = {
      prop = "bar"
    },
    env3 = {
      prop = "baz"
    }
  }

  targets = ["env1", "env3"]
}

output "target_envs" {
  value = { for k, v in local.envs : k => v if contains(local.targets, k) }
}

which yields:

Changes to Outputs:
  + target_envs = {
      + env1 = {
          + prop = "foo"
        }
      + env3 = {
          + prop = "baz"
        }
    }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading