Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/45242.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
resource/aws_route53_zone: Fix InvalidChangeBatch error during ForceNew operations when zone name changes
```
12 changes: 10 additions & 2 deletions internal/service/route53/zone.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ func resourceZoneDelete(ctx context.Context, d *schema.ResourceData, meta any) d
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).Route53Client(ctx)

if err := deleteHostedZone(ctx, conn, d.Id(), d.Get(names.AttrName).(string), d.Get(names.AttrForceDestroy).(bool), d.Timeout(schema.TimeoutDelete)); err != nil {
if err := deleteHostedZone(ctx, conn, d.Id(), d.Get(names.AttrForceDestroy).(bool), d.Timeout(schema.TimeoutDelete)); err != nil {
return sdkdiag.AppendFromErr(diags, err)
}

Expand Down Expand Up @@ -319,8 +319,16 @@ func findHostedZoneByID(ctx context.Context, conn *route53.Client, id string) (*
return output, nil
}

func deleteHostedZone(ctx context.Context, conn *route53.Client, hostedZoneID, hostedZoneName string, force bool, timeout time.Duration) error {
func deleteHostedZone(ctx context.Context, conn *route53.Client, hostedZoneID string, force bool, timeout time.Duration) error {
if force {
// Get the actual zone name from AWS instead of relying on the Terraform state
// which might contain the new zone name during a ForceNew operation
zoneOutput, err := findHostedZoneByID(ctx, conn, hostedZoneID)
if err != nil {
return fmt.Errorf("reading Route 53 Hosted Zone (%s) for deletion: %w", hostedZoneID, err)
}

hostedZoneName := aws.ToString(zoneOutput.HostedZone.Name)
if err := deleteAllResourceRecordsFromHostedZone(ctx, conn, hostedZoneID, hostedZoneName, timeout); err != nil {
return err
}
Expand Down
47 changes: 47 additions & 0 deletions internal/service/route53/zone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,39 @@ func TestAccRoute53Zone_escapedSpace(t *testing.T) {
})
}

func TestAccRoute53Zone_nameUpdate(t *testing.T) {
ctx := acctest.Context(t)
var zone1, zone2 route53.GetHostedZoneOutput
resourceName := "aws_route53_zone.test"
zoneName1 := acctest.RandomDomainName()
zoneName2 := acctest.RandomDomainName()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.Route53ServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckZoneDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccZoneConfig_basic(zoneName1),
Check: resource.ComposeTestCheckFunc(
testAccCheckZoneExists(ctx, resourceName, &zone1),
resource.TestCheckResourceAttr(resourceName, names.AttrName, zoneName1),
),
},
{
Config: testAccZoneConfig_basic(zoneName2),
Check: resource.ComposeTestCheckFunc(
testAccCheckZoneExists(ctx, resourceName, &zone2),
resource.TestCheckResourceAttr(resourceName, names.AttrName, zoneName2),
// Verify that a new zone was created (different zone ID)
testAccCheckZoneRecreated(&zone1, &zone2),
),
},
},
})
}

func testAccCheckZoneDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).Route53Client(ctx)
Expand Down Expand Up @@ -666,6 +699,20 @@ func testAccCheckDomainName(zone *route53.GetHostedZoneOutput, domain string) re
}
}

func testAccCheckZoneRecreated(before, after *route53.GetHostedZoneOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {
if before.HostedZone.Id == nil || after.HostedZone.Id == nil {
return fmt.Errorf("Missing hosted zone ID")
}

if aws.ToString(before.HostedZone.Id) == aws.ToString(after.HostedZone.Id) {
return fmt.Errorf("Expected zone to be recreated, but zone ID remained the same: %s", aws.ToString(before.HostedZone.Id))
}

return nil
}
}

func testAccZoneConfig_basic(zoneName string) string {
return fmt.Sprintf(`
resource "aws_route53_zone" "test" {
Expand Down
2 changes: 1 addition & 1 deletion internal/service/route53domains/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ func (r *domainResource) Delete(ctx context.Context, request resource.DeleteRequ

// Delete the associated Route 53 hosted zone.
if hostedZoneID := fwflex.StringValueFromFramework(ctx, data.HostedZoneID); hostedZoneID != "" {
if err := tfroute53.DeleteHostedZone(ctx, r.Meta().Route53Client(ctx), hostedZoneID, domainName, true, timeout); err != nil {
if err := tfroute53.DeleteHostedZone(ctx, r.Meta().Route53Client(ctx), hostedZoneID, true, timeout); err != nil {
response.Diagnostics.AddError(fmt.Sprintf("deleting Route 53 Hosted Zone (%s)", hostedZoneID), err.Error())

return
Expand Down
Loading