Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_rds_cluster: Wait for no pending modified values on Update if apply_immediately is true #38437

Merged
merged 4 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
83 changes: 48 additions & 35 deletions internal/service/rds/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
itypes "github.com/hashicorp/terraform-provider-aws/internal/types"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
"github.com/hashicorp/terraform-provider-aws/names"
)
Expand All @@ -40,7 +41,7 @@ const (
// @SDKResource("aws_rds_cluster", name="Cluster")
// @Tags(identifierAttribute="arn")
// @Testing(tagsTest=false)
func ResourceCluster() *schema.Resource {
func resourceCluster() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceClusterCreate,
ReadWithoutTimeout: resourceClusterRead,
Expand Down Expand Up @@ -1174,7 +1175,7 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
return sdkdiag.AppendErrorf(diags, "updating RDS Cluster (%s): %s", d.Id(), err)
}

if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutCreate)); err != nil {
if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), true, d.Timeout(schema.TimeoutCreate)); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for RDS Cluster (%s) update: %s", d.Id(), err)
}
}
Expand Down Expand Up @@ -1333,8 +1334,9 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta int
"replication_source_identifier",
"skip_final_snapshot",
names.AttrTags, names.AttrTagsAll) {
applyImmediately := d.Get(names.AttrApplyImmediately).(bool)
input := &rds.ModifyDBClusterInput{
ApplyImmediately: aws.Bool(d.Get(names.AttrApplyImmediately).(bool)),
ApplyImmediately: aws.Bool(applyImmediately),
DBClusterIdentifier: aws.String(d.Id()),
}

Expand Down Expand Up @@ -1509,7 +1511,7 @@ func resourceClusterUpdate(ctx context.Context, d *schema.ResourceData, meta int
return sdkdiag.AppendErrorf(diags, "updating RDS Cluster (%s): %s", d.Id(), err)
}

if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutUpdate)); err != nil {
if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), applyImmediately, d.Timeout(schema.TimeoutUpdate)); err != nil {
return sdkdiag.AppendErrorf(diags, "waiting for RDS Cluster (%s) update: %s", d.Id(), err)
}
}
Expand Down Expand Up @@ -1636,7 +1638,7 @@ func resourceClusterDelete(ctx context.Context, d *schema.ResourceData, meta int
return false, fmt.Errorf("modifying RDS Cluster (%s) DeletionProtection=false: %s", d.Id(), err)
}

if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), d.Timeout(schema.TimeoutDelete)); err != nil {
if _, err := waitDBClusterUpdated(ctx, conn, d.Id(), false, d.Timeout(schema.TimeoutDelete)); err != nil {
return false, fmt.Errorf("waiting for RDS Cluster (%s) update: %s", d.Id(), err)
}
}
Expand Down Expand Up @@ -1785,7 +1787,7 @@ func findDBClusters(ctx context.Context, conn *rds.RDS, input *rds.DescribeDBClu
return output, nil
}

func statusDBCluster(ctx context.Context, conn *rds.RDS, id string) retry.StateRefreshFunc {
func statusDBCluster(ctx context.Context, conn *rds.RDS, id string, waitNoPendingModifiedValues bool) retry.StateRefreshFunc {
return func() (interface{}, string, error) {
output, err := FindDBClusterByID(ctx, conn, id)

Expand All @@ -1797,23 +1799,29 @@ func statusDBCluster(ctx context.Context, conn *rds.RDS, id string) retry.StateR
return nil, "", err
}

return output, aws.StringValue(output.Status), nil
status := aws.StringValue(output.Status)

if status == clusterStatusAvailable && waitNoPendingModifiedValues && !itypes.IsZero(output.PendingModifiedValues) {
status = clusterStatusAvailableWithPendingModifiedValues
}
ewbankkit marked this conversation as resolved.
Show resolved Hide resolved

return output, status, nil
}
}

func waitDBClusterCreated(ctx context.Context, conn *rds.RDS, id string, timeout time.Duration) (*rds.DBCluster, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{
ClusterStatusBackingUp,
ClusterStatusCreating,
ClusterStatusMigrating,
ClusterStatusModifying,
ClusterStatusPreparingDataMigration,
ClusterStatusRebooting,
ClusterStatusResettingMasterCredentials,
clusterStatusBackingUp,
clusterStatusCreating,
clusterStatusMigrating,
clusterStatusModifying,
clusterStatusPreparingDataMigration,
clusterStatusRebooting,
clusterStatusResettingMasterCredentials,
},
Target: []string{ClusterStatusAvailable},
Refresh: statusDBCluster(ctx, conn, id),
Target: []string{clusterStatusAvailable},
Refresh: statusDBCluster(ctx, conn, id, false),
Timeout: timeout,
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second,
Expand All @@ -1828,19 +1836,24 @@ func waitDBClusterCreated(ctx context.Context, conn *rds.RDS, id string, timeout
return nil, err
}

func waitDBClusterUpdated(ctx context.Context, conn *rds.RDS, id string, timeout time.Duration) (*rds.DBCluster, error) { //nolint:unparam
func waitDBClusterUpdated(ctx context.Context, conn *rds.RDS, id string, waitNoPendingModifiedValues bool, timeout time.Duration) (*rds.DBCluster, error) { //nolint:unparam
pendingStatuses := []string{
clusterStatusBackingUp,
clusterStatusConfiguringIAMDatabaseAuth,
clusterStatusModifying,
clusterStatusRenaming,
clusterStatusResettingMasterCredentials,
clusterStatusScalingCompute,
clusterStatusUpgrading,
}
if waitNoPendingModifiedValues {
pendingStatuses = append(pendingStatuses, clusterStatusAvailableWithPendingModifiedValues)
}

stateConf := &retry.StateChangeConf{
Pending: []string{
ClusterStatusBackingUp,
ClusterStatusConfiguringIAMDatabaseAuth,
ClusterStatusModifying,
ClusterStatusRenaming,
ClusterStatusResettingMasterCredentials,
ClusterStatusScalingCompute,
ClusterStatusUpgrading,
},
Target: []string{ClusterStatusAvailable},
Refresh: statusDBCluster(ctx, conn, id),
Pending: pendingStatuses,
Target: []string{clusterStatusAvailable},
Refresh: statusDBCluster(ctx, conn, id, waitNoPendingModifiedValues),
Timeout: timeout,
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second,
Expand All @@ -1858,15 +1871,15 @@ func waitDBClusterUpdated(ctx context.Context, conn *rds.RDS, id string, timeout
func waitDBClusterDeleted(ctx context.Context, conn *rds.RDS, id string, timeout time.Duration) (*rds.DBCluster, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{
ClusterStatusAvailable,
ClusterStatusBackingUp,
ClusterStatusDeleting,
ClusterStatusModifying,
ClusterStatusPromoting,
ClusterStatusScalingCompute,
clusterStatusAvailable,
clusterStatusBackingUp,
clusterStatusDeleting,
clusterStatusModifying,
clusterStatusPromoting,
clusterStatusScalingCompute,
},
Target: []string{},
Refresh: statusDBCluster(ctx, conn, id),
Refresh: statusDBCluster(ctx, conn, id, false),
Timeout: timeout,
MinTimeout: 10 * time.Second,
Delay: 30 * time.Second,
Expand Down
4 changes: 2 additions & 2 deletions internal/service/rds/cluster_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ func statusDBClusterSnapshot(ctx context.Context, conn *rds.RDS, id string) retr

func waitDBClusterSnapshotCreated(ctx context.Context, conn *rds.RDS, id string, timeout time.Duration) (*rds.DBClusterSnapshot, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{ClusterSnapshotStatusCreating},
Target: []string{ClusterSnapshotStatusAvailable},
Pending: []string{clusterSnapshotStatusCreating},
Target: []string{clusterSnapshotStatusAvailable},
Refresh: statusDBClusterSnapshot(ctx, conn, id),
Timeout: timeout,
MinTimeout: 10 * time.Second,
Expand Down
41 changes: 22 additions & 19 deletions internal/service/rds/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,34 @@ import (
)

const (
ClusterRoleStatusActive = "ACTIVE"
ClusterRoleStatusDeleted = "DELETED"
ClusterRoleStatusPending = "PENDING"
clusterRoleStatusActive = "ACTIVE"
clusterRoleStatusDeleted = "DELETED"
clusterRoleStatusPending = "PENDING"
)

const (
ClusterStatusAvailable = "available"
ClusterStatusBackingUp = "backing-up"
ClusterStatusConfiguringIAMDatabaseAuth = "configuring-iam-database-auth"
ClusterStatusCreating = "creating"
ClusterStatusDeleting = "deleting"
ClusterStatusMigrating = "migrating"
ClusterStatusModifying = "modifying"
ClusterStatusPreparingDataMigration = "preparing-data-migration"
ClusterStatusPromoting = "promoting"
ClusterStatusRebooting = "rebooting"
ClusterStatusRenaming = "renaming"
ClusterStatusResettingMasterCredentials = "resetting-master-credentials"
ClusterStatusScalingCompute = "scaling-compute"
ClusterStatusUpgrading = "upgrading"
clusterStatusAvailable = "available"
clusterStatusBackingUp = "backing-up"
clusterStatusConfiguringIAMDatabaseAuth = "configuring-iam-database-auth"
clusterStatusCreating = "creating"
clusterStatusDeleting = "deleting"
clusterStatusMigrating = "migrating"
clusterStatusModifying = "modifying"
clusterStatusPreparingDataMigration = "preparing-data-migration"
clusterStatusPromoting = "promoting"
clusterStatusRebooting = "rebooting"
clusterStatusRenaming = "renaming"
clusterStatusResettingMasterCredentials = "resetting-master-credentials"
clusterStatusScalingCompute = "scaling-compute"
clusterStatusUpgrading = "upgrading"

// Non-standard status values.
clusterStatusAvailableWithPendingModifiedValues = "tf-available-with-pending-modified-values"
)

const (
ClusterSnapshotStatusAvailable = "available"
ClusterSnapshotStatusCreating = "creating"
clusterSnapshotStatusAvailable = "available"
clusterSnapshotStatusCreating = "creating"
)

const (
Expand Down
1 change: 1 addition & 0 deletions internal/service/rds/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package rds
// Exports for use in tests only.
var (
ResourceCertificate = resourceCertificate
ResourceCluster = resourceCluster
ResourceEventSubscription = resourceEventSubscription
ResourceProxy = resourceProxy
ResourceProxyDefaultTargetGroup = resourceProxyDefaultTargetGroup
Expand Down
2 changes: 1 addition & 1 deletion internal/service/rds/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func FindDBClusterRoleByDBClusterIDAndRoleARN(ctx context.Context, conn *rds.RDS

for _, associatedRole := range dbCluster.AssociatedRoles {
if aws.StringValue(associatedRole.RoleArn) == roleARN {
if status := aws.StringValue(associatedRole.Status); status == ClusterRoleStatusDeleted {
if status := aws.StringValue(associatedRole.Status); status == clusterRoleStatusDeleted {
return nil, &retry.NotFoundError{
Message: status,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/service/rds/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/service/rds/sweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func sweepClusters(region string) error {
for _, v := range page.DBClusters {
arn := aws.StringValue(v.DBClusterArn)
id := aws.StringValue(v.DBClusterIdentifier)
r := ResourceCluster()
r := resourceCluster()
d := r.Data(nil)
d.SetId(id)
d.Set(names.AttrApplyImmediately, true)
Expand Down
6 changes: 3 additions & 3 deletions internal/service/rds/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (

func waitDBClusterRoleAssociationCreated(ctx context.Context, conn *rds.RDS, dbClusterID, roleARN string, timeout time.Duration) (*rds.DBClusterRole, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{ClusterRoleStatusPending},
Target: []string{ClusterRoleStatusActive},
Pending: []string{clusterRoleStatusPending},
Target: []string{clusterRoleStatusActive},
Refresh: statusDBClusterRole(ctx, conn, dbClusterID, roleARN),
Timeout: timeout,
MinTimeout: 10 * time.Second,
Expand All @@ -32,7 +32,7 @@ func waitDBClusterRoleAssociationCreated(ctx context.Context, conn *rds.RDS, dbC

func waitDBClusterRoleAssociationDeleted(ctx context.Context, conn *rds.RDS, dbClusterID, roleARN string, timeout time.Duration) (*rds.DBClusterRole, error) {
stateConf := &retry.StateChangeConf{
Pending: []string{ClusterRoleStatusActive, ClusterRoleStatusPending},
Pending: []string{clusterRoleStatusActive, clusterRoleStatusPending},
Target: []string{},
Refresh: statusDBClusterRole(ctx, conn, dbClusterID, roleARN),
Timeout: timeout,
Expand Down
Loading