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

Is there a way to exclude items inside of a for_each

I’m using a module to create a list of maps for me to iterate over:

module "regions" {
  source          = "hashicorp/subnets/cidr"
  base_cidr_block = "1.2.0.0/23"
  networks = [
    {
      name     = "in-use-us-east1"
      new_bits = 5
    },
    {
      name     = "in-use-us-west1"
      new_bits = 5
    },
    {
      name     = "in-use-us-west4"
      new_bits = 5
    },
    {
      name     = "in-use-us-central1"
      new_bits = 5
    },
    {
      name     = "not-in-use"
      new_bits = 1
    },
  ]
}

module.regions creates an object that looks like this:

  + regions         = {
      + base_cidr_block     = "1.2.0.0/23"
      + network_cidr_blocks = {
          + "not-in-use"                = "1.2.1.0/24"
          + "in-use-us-central1" = "1.2.0.32/28"
          + "in-use-us-east1"    = "1.2.0.48/28"
          + "in-use-us-west1"    = "1.2.0.0/28"
          + "in-use-us-west4"    = "1.2.0.16/28"
        }
      + networks            = [
          + {
              + cidr_block = "1.2.0.0/28"
              + name       = "in-use-us-west1"
              + new_bits   = 5
            },
          + {
              + cidr_block = "1.2.0.16/28"
              + name       = "in-use-us-west4"
              + new_bits   = 5
            },
          ... etc

I’m looping over the object like this:

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

resource "google_compute_global_address" "regions" {
  for_each      = {for subnet in module.regions.networks:  subnet.name => subnet}
  provider      = google-beta
  name          = each.value.name
  purpose       = "VPC_PEERING"
  address_type  = "INTERNAL"
  prefix_length = split("/", each.value.cidr_block)[1]
  address       = split("/", each.value.cidr_block)[0]
  project       = local.project_id
  network       = google_compute_subnetwork.my_vpc.network
}

All of this works great and does everything I want with one exception.

How do I exclude a key from the set?

I only want to loop over objects where subnet.name does not start with not-in-use.

Is this possible? I’m so close, I really don’t want to have to reshape the whole thing in a new var in globals when I’m 90% of the way there. This is also very readable too.

I tried the following:
for_each = {for subnet in module.regions.networks: subnet.name => subnet if regexall("^in-use", subnet.name)}

But that throws an error:

Error: Invalid 'for' condition
The 'if' clause value is invalid: bool required.

I also tried wrapping regexall() in length() and that returned the same error.

>Solution :

I am somewhat hesitant to answer this because you almost completely did it yourself, but I will supply the final piece. While it is possible to do this with the regex function (it returns a bool whereas regexall returns a list which led to your error message since a bool is required for a conditional logical return), it would be even easier in your situation to use the startswith function:

for_each = {for subnet in module.regions.networks: subnet.name => subnet if startswith(subnet.name, "in-use")}
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