Search code examples
amazon-web-servicesterraformterraform-provider-aws

Terraform: Delete resource before creating another resource


OVERVIEW

I'd like to create a Route53 DNS record. Depending on a variable it will either be a CNAME record or an ALIAS record.

On the first run, this works OK because neither of the records exists.

However, when updating the variable var.route_53_redirection_type to change the record type the terraform apply fails because it attempts to create the new record before the old one is deleted.

Error: [ERR]: Error building changeset: InvalidChangeBatch: [RRSet of type A with DNS name redirect is not permitted because a conflicting RRSet of type CNAME with the same DNS name already exists in zone.]

When terraform apply is run again it works because the record had been deleted on the previous run.

Here is the code:

resource "aws_route53_record" "alias" {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
  count = var.route_53_redirection_type == "ALIAS" ? 1 : 0
  zone_id = data.aws_route53_zone.public.zone_id
  name    = "redirect"
  type    = "A"
  alias {
    name                   = module.alb.alb_dns_name
    zone_id                = module.alb.alb_zone_id
    evaluate_target_health = true
  }
  
}

resource "aws_route53_record" "cname" {
  count = var.route_53_redirection_type == "CNAME" ? 1 : 0
  zone_id = data.aws_route53_zone.public.zone_id
  name    = "redirect"
  type    = "CNAME"
  ttl     = "5"
  records        = ["www.google.com"]
}

QUESTIONS

  • Is it possible to ensure the deletion happens before the creation?
  • Is there a better approach entirely, which removes the dependency?

NOTES I've looked at lifecycle and depends_on but neither of these seem applicable in this case.

Thanks in advance!


Solution

  • I think it would be really hard to achieve what you want based on the requirements. I think that a better way of approaching this would be using dynamic block [1] and for_each [2] (still not sure that would work as expected). The code would then look like:

    resource "aws_route53_record" "record" {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
      zone_id = data.aws_route53_zone.public.zone_id
      name    = "redirect"
      type    = var.route_53_redirection_type == "ALIAS" ? "A" : "CNAME"
      ttl     = var.route_53_redirection_type == "ALIAS" ? null : 5
    
      dynamic "alias" {
        for_each = var.route_53_redirection_type == "ALIAS" ? [1] : []
        content {
          name                   = module.alb.alb_dns_name
          zone_id                = module.alb.alb_zone_id
          evaluate_target_health = true
        }
      }
    
    }
    

    [1] https://www.terraform.io/language/expressions/dynamic-blocks

    [2] https://www.terraform.io/language/meta-arguments/for_each