terraform-provider-aws: aws_route53_record: plans that only change `set_identifier` do not apply correctly

Community Note

  • Please vote on this issue by adding a 👍 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave “+1” or “me too” comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment

Terraform Version

Terraform v0.11.11

  • provider.aws v2.2.0
  • provider.template v1.0.0

Affected Resource(s)

  • aws_route53_record

Terraform Configuration Files

“Before” config

resource "aws_route53_record" "main" {
  zone_id        = "${data.aws_route53_zone.domain_root.zone_id}"
  name           = "setidentifiertest"
  type           = "A"
  set_identifier = "example-foo" # <--- OLD_NAME

  alias {
    name                   = "${data.aws_lb.load_balancer.dns_name}"
    zone_id                = "${data.aws_lb.load_balancer.zone_id}"
    evaluate_target_health = true
  }

  weighted_routing_policy {
    weight = "100"
  }
}

“After” config

resource "aws_route53_record" "main" {
  zone_id        = "${data.aws_route53_zone.domain_root.zone_id}"
  name           = "setidentifiertest"
  type           = "A"
  set_identifier = "example-bar" # <--- NEW_NAME

  alias {
    ...
  }

  weighted_routing_policy {
    ...
  }
}

Plan Output

Error: Error applying plan:

1 error(s) occurred:

* aws_route53_record.main: 1 error(s) occurred:

* aws_route53_record.main: [ERR]: Error building changeset: InvalidInput: Invalid request: Expected exactly one of [Weight, Region, Failover, GeoLocation, or MultiValueAnswer], but found none in Change with [Action=DELETE, Name=setidentifiertest.the-root-domain.com, Type=A, SetIdentifier=example-foo]

Expected Behaviour

The terraform configuration should have been applied as stated in the plan, which suggests something such as

  ~ aws_route53_record.main
      set_identifier:                     "example-foo" => "example-bar"

Actual Behaviour

The plan aborts, and the particular Route 53 record set then appears to be REMOVED from the state. applying the same plan again will allow CREATION of a new route53 recordset with weighted set identifier example-bar, but the subsequent outcome is that a “dangling” example-foo recordset remains on Amazon’s infrastructure without being reflected in the state.

Steps to Reproduce

  • Create terraform similar to the “before” config above
    • a “weighted” route53 record with a set_identifier.
  • Apply the config.
  • Modify the terraform config similar to the “after” config above.
    • Don’t change anything except the set_identifier
  • terraform plan
    • Plan is shown as normal (see “Expected Behaviour” above)
  • terraform apply
    • Plan executes with the error specified in “Plan Output” above

Important Factoids

To summarise, my belief is that terraform is unable to apply changesets to aws_route53_record that don’t contain changes other than the set_identifier field. If this is attempted, Terraform appears to throw an error and silently remove the offending aws_route53_record from internal state.

To mitigate/workaround I had to apply the state twice (once for it to fail/“delete from state”, once for it to add the new identifier) and then manually remove the duplicate records using the AWS Web Console.

References

I am not 100% certain but I believe #7199 was trying to describe the same issue.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 67
  • Comments: 15 (6 by maintainers)

Most upvoted comments

I was trying to debug the issue and I’ve found out that the routing policy is not getting added to oldRec.

following is from cloud trail changeset if you update it using AWS console

"changeBatch": {
            "changes": [
                {
                    "action": "DELETE",
                    "resourceRecordSet": {
                        "name": "dsdatsme.test.com.",
                        "type": "A",
                        "setIdentifier": "testtest",
                        "geoLocation": {
                            "continentCode": "AF"
                        },
                        "tTL": 300,
                        "resourceRecords": [
                            {
                                "value": "8.8.8.8"
                            }
                        ]
                    }
                },
                {
                    "action": "CREATE",
                    "resourceRecordSet": {
                        "name": "dsdatsme.test.com",
                        "type": "A",
                        "setIdentifier": "testtest2222",
                        "geoLocation": {
                            "continentCode": "AF"
                        },
                        "tTL": 300,
                        "resourceRecords": [
                            {
                                "value": "8.8.8.8"
                            }
                        ]
                    }
                }
            ]
        }

whereas if you change setIdentifier using terraform this is the changeset

ChangeBatch: {
    Changes: [{
        Action: "DELETE",
        ResourceRecordSet: {
          Name: "dsdatsme.test.com",
          ResourceRecords: [{
              Value: "8.8.8.8"
            }],
          SetIdentifier: "testtest1",
          TTL: 300,
          Type: "A"
        }
      },{
        Action: "CREATE",
        ResourceRecordSet: {
          GeoLocation: {
            ContinentCode: "AF"
          },
          Name: "dsdatsme.test.com",
          ResourceRecords: [{
              Value: "8.8.8.8"
            }],
          SetIdentifier: "testtest2",
          TTL: 300,
          Type: "A"
        }
      }],
    Comment: "Managed by Terraform"
  }

So basically DELETE block in terraform has a routing policy missing(i.e. GeoLocation block). So the solution is to add condition to check if oldRec is a non-simple routing policy and add it to that variable. But I could not find a cleaner way to add routing policy to the variable.

an error by AWS SDK is

Error: [ERR]: Error building changeset: InvalidInput: Invalid request: Expected exactly one of [Weight, Region, Failover, GeoLocation, or MultiValueAnswer], but found none in Change with [Action=DELETE, Name=dsdatsme.test.com, Type=A, SetIdentifier=testtest1] 

@bflad can you guild me to solve this?

PR is in: https://github.com/hashicorp/terraform-provider-aws/pull/25620

People who are affected (or just want to see this closed after 3 years!) and want to help get this prioritized for review, please hop over to the PR and hit the thumbs up emoji on the top comment? Thank you!

PS @DSdatsme thanks for your comment above, the information above helped motivate me to realize I could fix this pretty quickly, definitely a help!

Still having this issue with provider registry.terraform.io/hashicorp/aws v3.27.0 It’s pretty terrible because it fails in a way such that the record remains in route53, but the entry is removed from state.