Home > Software engineering >  Terraform for loop inside for_each argument
Terraform for loop inside for_each argument

Time:09-17

Can someone please explain what a for loop inside a for_each argument does in Terraform? I am trying to create an AWS SSL certificate. I've seen other code like the below but I don't understand it:

resource "aws_acm_certificate" "nonprod_cert" {
    domain_name       = var.phz_domain_name
    validation_method = "DNS"
}

resource "aws_route53_record" "nonprod_cert_record" {
  for_each = {
    for dvo in aws_acm_certificate.nonprod_cert.domain_validation_options : dvo.domain_name => {
        name   = dvo.resource_record_name
        record = dvo.resource_record_value
        type   = dvo.resource_record_type
    }
  }
  zone_id = var.phz_id
  name    = each.value.name
  type    = each.value.type
  records = [each.value.record]
  ttl     = 60
}

resource "aws_acm_certificate_validation" "nonprod_cert_validated" {
  certificate_arn         = aws_acm_certificate.nonprod_cert.arn
  validation_record_fqdns = [for record in aws_route53_record.nonprod_cert_record : record.fqdn]
  depends_on = [
    aws_acm_certificate.nonprod_cert,
    aws_route53_record.nonprod_cert_record
  ]
}

The specific line that I don't understand is the one in the route53 record. I get that a for_each argument can be used to create multiple resources from a single block, but I can't find anywhere that explains what this for loop is doing inside of it. If someone could explain that would be great!

CodePudding user response:

The inner for "loop" creates the data that the for_each then iterates over. Specifically the each.key will be the dvo.domain_name and the each.value will be the

{
    name   = dvo.resource_record_name
    record = dvo.resource_record_value
    type   = dvo.resource_record_type
}

You could simply move that into a locals block beforehand and not have it in a single line:

locals { 
    records = {
        for dvo in aws_acm_certificate.nonprod_cert.domain_validation_options : dvo.domain_name => {
            name   = dvo.resource_record_name
            record = dvo.resource_record_value
            type   = dvo.resource_record_type
        }
    }
}

resource "aws_route53_record" "nonprod_cert_record" {
    for_each = local.records
    zone_id = var.phz_id
    name    = each.value.name
    type    = each.value.type
    records = [each.value.record]
    ttl     = 60
}

That will have the exact same effect.

CodePudding user response:

First they are using a for expression to convert one type of object into another type. In this case they are converting the list of domain_validation_options into a list of objects that can be used for creating aws_route53_record resources.

Next they are using for_each to create a new aws_route53_record resource for each element of the list that was generated by the for expression.

The key things to be aware of here are:

  • for is used to convert a list of objects into a list of different objects.
  • for_each is used to create multiple resources from a list, set, or map of values.

I highly recommend spending the time to go through the Terraform learning site, or at least the Terraform documentation to learn the basic keywords and overall syntax.

  • Related