Home > database >  Nested for_each in terraform, attempting to self-merge map
Nested for_each in terraform, attempting to self-merge map

Time:10-29

i'm trying to account for an annoying case when creating my own private hosted zones where the kinesis-streams endpoint has several non-standard DNS records. I am aiming to create a custom map of objects for each endpoint with information that I need (below):

locals {
  endpoint_service_names = {
    ec2             = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ec2"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["ec2.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = false
    }
    "ecr.dkr"         = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ecr.dkr"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["dkr.ecr.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = true
    }
    "ecr.api"        = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ecr.api"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["api.ecr.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = false
    }
    kinesis-streams = {
      name         = "com.amazonaws.${data.aws_region.current.name}.kinesis-streams"
      type         = "Interface"
      private_dns  = false
      phz_names    = [
        "kinesis.${data.aws_region.current.name}.amazonaws.com",
        "data-kinesis.${data.aws_region.current.name}.amazonaws.com",
        "control-kinesis.${data.aws_region.current.name}.amazonaws.com"
      ]
      phz_wildcard = true
    }
  }

In order to use this in my impl, however, I would need to perform a nested for_each which Terraform does not directly allow, so I need to merge my map info into a new map with the service and DNS names in the one object. My problem is similar to: Looping in for_each nested resources with terraform

except I do not have a list in each map element, only on the phz_names. I can't figure out how to get the syntax right to produce something like this:

endpoint_service_dns_list = {
kinesis-streams = [
        "kinesis.${data.aws_region.current.name}.amazonaws.com",
        "data-kinesis.${data.aws_region.current.name}.amazonaws.com",
        "control-kinesis.${data.aws_region.current.name}.amazonaws.com"
      ]

[...]
}
}

My attempt:

  endpoint_service_dns_list = merge([
    for servicename, service in local.endpoint_service_names : {
  for phz_name in service[0].phz_names :
  "${servicename}-${phz_name}" => {
    service_name = servicename
    phz_name     = phz.phz_names
  }
  }
  ])

but the syntax highlighting/attempt to indexing obviously fails because I do not have a list for each service, but I am not sure what to replace it with.

CodePudding user response:

Maybe I have missed the point but based on your comments and your kind of expected result in the question you could have something like this. I have added a format that maps then service name to all its urls as a list. Or incase you wanted a mapping of each url to its service name I added an additional local var.

locals {
  endpoint_service_names    = {
    ec2             = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ec2"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["ec2.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = false
    }
    "ecr.dkr"       = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ecr.dkr"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["dkr.ecr.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = true
    }
    "ecr.api"       = {
      name         = "com.amazonaws.${data.aws_region.current.name}.ecr.api"
      type         = "Interface"
      private_dns  = false
      phz_names    = ["api.ecr.${data.aws_region.current.name}.amazonaws.com"]
      phz_wildcard = false
    }
    kinesis-streams = {
      name         = "com.amazonaws.${data.aws_region.current.name}.kinesis-streams"
      type         = "Interface"
      private_dns  = false
      phz_names    = [
        "kinesis.${data.aws_region.current.name}.amazonaws.com",
        "data-kinesis.${data.aws_region.current.name}.amazonaws.com",
        "control-kinesis.${data.aws_region.current.name}.amazonaws.com"
      ]
      phz_wildcard = true
    }
  }
  endpoint_service_dns_list = {for service, attrs in local.endpoint_service_names : service => attrs.phz_names}
  endpoint_dns_service_list = merge([for service, attrs in local.endpoint_service_names : {for url in attrs["phz_names"] : url => service}]...)


}

data "aws_region" "current" {}

output "endpoint_service_dns_list" {
  value = local.endpoint_service_dns_list
}

output "endpoint_dns_service_list" {
  value = local.endpoint_dns_service_list
}

This would map the phz_names with the service as seen in the output, or map each url to its service

endpoint_dns_service_list = {
  "api.ecr.eu-west-2.amazonaws.com" = "ecr.api"
  "control-kinesis.eu-west-2.amazonaws.com" = "kinesis-streams"
  "data-kinesis.eu-west-2.amazonaws.com" = "kinesis-streams"
  "dkr.ecr.eu-west-2.amazonaws.com" = "ecr.dkr"
  "ec2.eu-west-2.amazonaws.com" = "ec2"
  "kinesis.eu-west-2.amazonaws.com" = "kinesis-streams"
}

endpoint_service_dns_list = {
  "ec2" = [
    "ec2.eu-west-2.amazonaws.com",
  ]
  "ecr.api" = [
    "api.ecr.eu-west-2.amazonaws.com",
  ]
  "ecr.dkr" = [
    "dkr.ecr.eu-west-2.amazonaws.com",
  ]
  "kinesis-streams" = [
    "kinesis.eu-west-2.amazonaws.com",
    "data-kinesis.eu-west-2.amazonaws.com",
    "control-kinesis.eu-west-2.amazonaws.com",
  ]
}

Hopefully one of these is the kind of thing you were looking to do

  • Related