1

I need to iterate more times on specific HCL Map key/value pairs which need to be based on the value of specific variables.

I've come to the idea of modifying the current map - so that certain keys/values will be iterated more times.

If we have this map - let's call it "map_domains":

key_1 = value_1
key_2 = value_2

And we've set these variables:

variable "domains" {
  type = "list"

  default = [
    "key_1",
    "key_2",
  ]
}

variable "domain_alt_names" {
  type = "map"

  default = {
    key_1    = "value_1, value_2"
    key_2    = "value_3, value_4, value_5"
  }
}

How can we modify the map "map_domains" to:

key_1 = value_1
key_1 = value_1
key_1 = value_1
key_2 = value_2
key_2 = value_2
key_2 = value_2
key_2 = value_2

I'm trying to validate a couple of AWS ACM certificates through the DNS Validation option - and each of the domains has a couple of Domain Alternative Names which also need DNS records in Route53 to be created in order the domain certificates to be validated properly.

This is the code which is used to achieve the overall goal - and the problem is with the Zone ID which needs to be the same for the first couple of iterations and then another one for the rest of the iterations.

This line:

  zone_id = "${lookup(local.hosted_zone_ids_zipmap, element(keys(local.hosted_zone_ids_zipmap), count.index))}"

The whole code:

#
# EKS Worker Nodes Resources
#  * Issuing ACM certificates
#

resource "aws_route53_zone" "zones" {
  count = "${length(var.domains)}"

  name = "${element(var.domains, count.index)}"
}

locals {
  hosted_zone_ids_zipmap = "${zipmap(var.domains, aws_route53_zone.zones.*.zone_id)}"
}

resource "aws_acm_certificate" "cert" {
  count = "${length(var.domains)}"

  domain_name = "${element(keys(local.hosted_zone_ids_zipmap), count.index)}"

  subject_alternative_names = ["${
  lookup(var.domain_alt_names,
  "${element(var.domains, count.index)}")
  }"]

  validation_method = "DNS"

  tags {
    Domain = "${element(keys(local.hosted_zone_ids_zipmap), count.index)}"
  }
}

locals {
  dvo           = "${flatten(aws_acm_certificate.cert.*.domain_validation_options)}"
}

resource "aws_route53_record" "cert_validation" {
  count = "${length(var.domain_alt_names) + length(var.domains)}"

  zone_id = "${lookup(local.hosted_zone_ids_zipmap, element(keys(local.hosted_zone_ids_zipmap), count.index))}"
  name    = "${lookup(local.dvo[count.index], "resource_record_name")}"
  type    = "${lookup(local.dvo[count.index], "resource_record_type")}"
  records = ["${lookup(local.dvo[count.index], "resource_record_value")}"]
  ttl     = 60

  depends_on = ["aws_acm_certificate.cert"]
}

resource "aws_acm_certificate_validation" "cert" {
  count = "${length(var.domains)}"

  certificate_arn         = "${aws_acm_certificate.cert.*.arn[count.index]}"
  validation_record_fqdns = ["${aws_route53_record.cert_validation.*.fqdn[count.index]}"]

  depends_on = ["aws_acm_certificate.cert", "aws_route53_record.cert_validation"]
}
Xtigyro
  • 391
  • 2
  • 5
  • 13
  • A map, by definition, maps from one key to one value. It seems unintuitive to try to do this mapping multiple times. Maybe, map the key to a value and an integer which represents the multiplicity? Furthermore, it seems you're trying to achieve an overall goal which is not stated in the question. Maybe you can describe your desired behaviour to discuss different ways to achieve that? – Markus Jul 19 '18 at 09:22
  • @Markus I've updated my description and added more code. Thanks for the help, Markus! – Xtigyro Jul 19 '18 at 09:31
  • That's a much more meaningful question. I have no complete solution, but since you are using counters to access your map, you could use `counter // length` (`//` is supposed to be integer division) to allow for an increase every other step. – Markus Jul 19 '18 at 09:41
  • @Markus Could you please give me an example of your idea? – Xtigyro Jul 19 '18 at 10:20

1 Answers1

2

I've figured it out:

(1) Added this variable:

variable "domain_names_index" {
  // A flat map that will act as nested map
  //// for the subdomains and the alternative domain names
  //// so that the Hosted Zone ID can be calculated in a reverse order
  //// during the creation of the DNS Validation Route53 records

  type = "map"

  default = {
    tftestingdatorama.io  = "2"
    tftestingdatorama.org = "2"
    tftestingdlite.co     = "1"
    tftestingdlite.org    = "1"
  }
}

(2) And then I've changed the code to:

resource "aws_route53_record" "cert_validation" {
  count = "${length(var.domain_alt_names) + length(var.domains)}"

  zone_id = "${
     lookup(local.hosted_zone_ids_zipmap,
     element(keys(local.hosted_zone_ids_zipmap),
     lookup(var.domain_names_index, "${lookup(local.dvo[count.index], "domain_name")
     }")))}"

  name    = "${lookup(local.dvo[count.index], "resource_record_name")}"
  type    = "${lookup(local.dvo[count.index], "resource_record_type")}"
  records = ["${lookup(local.dvo[count.index], "resource_record_value")}"]
  ttl     = 60

  depends_on = ["aws_acm_certificate.cert"]
}
Xtigyro
  • 391
  • 2
  • 5
  • 13