diff --git a/.changelog/45457.txt b/.changelog/45457.txt new file mode 100644 index 000000000000..c54cf4de5dd8 --- /dev/null +++ b/.changelog/45457.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_route53_zone: Operations to enable accelerated recovery are enforced to run serially when multiple hosted zones are configured +``` diff --git a/internal/service/route53/zone.go b/internal/service/route53/zone.go index 36375f2900ad..4fb2cd774a39 100644 --- a/internal/service/route53/zone.go +++ b/internal/service/route53/zone.go @@ -332,6 +332,11 @@ func resourceZoneDelete(ctx context.Context, d *schema.ResourceData, meta any) d } func updateEnableAcceleratedRecovery(ctx context.Context, conn *route53.Client, zoneID string, enabled bool, timeout time.Duration) error { + const zoneMutexKey = "aws_route53_zone_accelerated_recovery" + + conns.GlobalMutexKV.Lock(zoneMutexKey) + defer conns.GlobalMutexKV.Unlock(zoneMutexKey) + input := route53.UpdateHostedZoneFeaturesInput{ HostedZoneId: aws.String(zoneID), EnableAcceleratedRecovery: aws.Bool(enabled), diff --git a/internal/service/route53/zone_test.go b/internal/service/route53/zone_test.go index 295fe9869e40..72841165bedf 100644 --- a/internal/service/route53/zone_test.go +++ b/internal/service/route53/zone_test.go @@ -545,9 +545,11 @@ func TestAccRoute53Zone_escapedSpace(t *testing.T) { func TestAccRoute53Zone_enableAcceleratedRecovery(t *testing.T) { ctx := acctest.Context(t) - var zone route53.GetHostedZoneOutput - resourceName := "aws_route53_zone.test" - zoneName := acctest.RandomDomainName() + var zone1, zone2 route53.GetHostedZoneOutput + resourceName1 := "aws_route53_zone.test1" + resourceName2 := "aws_route53_zone.test2" + zoneName1 := acctest.RandomDomainName() + zoneName2 := acctest.RandomDomainName() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest.PreCheck(ctx, t) }, @@ -556,51 +558,39 @@ func TestAccRoute53Zone_enableAcceleratedRecovery(t *testing.T) { CheckDestroy: testAccCheckZoneDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName, true), + Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName1, zoneName2, true), Check: resource.ComposeTestCheckFunc( - testAccCheckZoneExists(ctx, resourceName, &zone), - acctest.MatchResourceAttrGlobalARNNoAccount(resourceName, names.AttrARN, "route53", regexache.MustCompile("hostedzone/.+")), - resource.TestCheckResourceAttr(resourceName, names.AttrName, zoneName), - resource.TestCheckResourceAttr(resourceName, "name_servers.#", "4"), - resource.TestCheckResourceAttrSet(resourceName, "primary_name_server"), - resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), - resource.TestCheckResourceAttr(resourceName, "vpc.#", "0"), - resource.TestCheckResourceAttr(resourceName, "enable_accelerated_recovery", acctest.CtTrue), + testAccCheckZoneExists(ctx, resourceName1, &zone1), + testAccCheckZoneExists(ctx, resourceName2, &zone2), + resource.TestCheckResourceAttr(resourceName1, "enable_accelerated_recovery", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName2, "enable_accelerated_recovery", acctest.CtTrue), ), }, { - ResourceName: resourceName, + ResourceName: resourceName1, ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{names.AttrForceDestroy}, }, { // Disable accelerated recovery - Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName, false), + Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName1, zoneName2, false), Check: resource.ComposeTestCheckFunc( - testAccCheckZoneExists(ctx, resourceName, &zone), - acctest.MatchResourceAttrGlobalARNNoAccount(resourceName, names.AttrARN, "route53", regexache.MustCompile("hostedzone/.+")), - resource.TestCheckResourceAttr(resourceName, names.AttrName, zoneName), - resource.TestCheckResourceAttr(resourceName, "name_servers.#", "4"), - resource.TestCheckResourceAttrSet(resourceName, "primary_name_server"), - resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), - resource.TestCheckResourceAttr(resourceName, "vpc.#", "0"), - resource.TestCheckResourceAttr(resourceName, "enable_accelerated_recovery", acctest.CtFalse), + testAccCheckZoneExists(ctx, resourceName1, &zone1), + testAccCheckZoneExists(ctx, resourceName2, &zone2), + resource.TestCheckResourceAttr(resourceName1, "enable_accelerated_recovery", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName2, "enable_accelerated_recovery", acctest.CtFalse), ), }, { // Re-enable accelerated recovery // Check a resource can be destroyed with it enabled - Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName, true), + Config: testAccZoneConfig_enableAcceleratedRecovery(zoneName1, zoneName2, true), Check: resource.ComposeTestCheckFunc( - testAccCheckZoneExists(ctx, resourceName, &zone), - acctest.MatchResourceAttrGlobalARNNoAccount(resourceName, names.AttrARN, "route53", regexache.MustCompile("hostedzone/.+")), - resource.TestCheckResourceAttr(resourceName, names.AttrName, zoneName), - resource.TestCheckResourceAttr(resourceName, "name_servers.#", "4"), - resource.TestCheckResourceAttrSet(resourceName, "primary_name_server"), - resource.TestCheckResourceAttr(resourceName, acctest.CtTagsPercent, "0"), - resource.TestCheckResourceAttr(resourceName, "vpc.#", "0"), - resource.TestCheckResourceAttr(resourceName, "enable_accelerated_recovery", acctest.CtTrue), + testAccCheckZoneExists(ctx, resourceName1, &zone1), + testAccCheckZoneExists(ctx, resourceName2, &zone2), + resource.TestCheckResourceAttr(resourceName1, "enable_accelerated_recovery", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName2, "enable_accelerated_recovery", acctest.CtTrue), ), }, }, @@ -885,12 +875,17 @@ resource "aws_route53_zone" "test" { `, rName, zoneName) } -func testAccZoneConfig_enableAcceleratedRecovery(zoneName string, enableAcceleratedRecovery bool) string { +func testAccZoneConfig_enableAcceleratedRecovery(zoneName1, zoneName2 string, enableAcceleratedRecovery bool) string { return fmt.Sprintf(` -resource "aws_route53_zone" "test" { +resource "aws_route53_zone" "test1" { name = "%[1]s." - enable_accelerated_recovery = %[2]t + enable_accelerated_recovery = %[3]t +} +resource "aws_route53_zone" "test2" { + name = "%[2]s." + + enable_accelerated_recovery = %[3]t } -`, zoneName, enableAcceleratedRecovery) +`, zoneName1, zoneName2, enableAcceleratedRecovery) }