diff --git a/.changelog/38476.txt b/.changelog/38476.txt new file mode 100644 index 00000000000..f3b573dc6e5 --- /dev/null +++ b/.changelog/38476.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_elasticache_replication_group: Fix `error marshaling prior state` when upgrading from v4.67.0 to v5.59.0 +``` \ No newline at end of file diff --git a/internal/service/elasticache/replication_group_migrate.go b/internal/service/elasticache/replication_group_migrate.go index f94db85fcc3..bf4b6526629 100644 --- a/internal/service/elasticache/replication_group_migrate.go +++ b/internal/service/elasticache/replication_group_migrate.go @@ -9,11 +9,9 @@ import ( awstypes "github.com/aws/aws-sdk-go-v2/service/elasticache/types" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" - "github.com/hashicorp/terraform-provider-aws/internal/enum" + tfmaps "github.com/hashicorp/terraform-provider-aws/internal/maps" "github.com/hashicorp/terraform-provider-aws/internal/sdkv2/types/nullable" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" - "github.com/hashicorp/terraform-provider-aws/internal/verify" "github.com/hashicorp/terraform-provider-aws/names" ) @@ -22,9 +20,20 @@ func replicationGroupStateUpgradeV1(ctx context.Context, rawState map[string]int rawState = map[string]interface{}{} } - // Set auth_token_update_strategy to new default value + // Set auth_token_update_strategy to new default value. rawState["auth_token_update_strategy"] = awstypes.AuthTokenUpdateStrategyTypeRotate + // The v4.67.0 schema contained block attribute named 'cluster_mode'. + // It was removed at v5.0.0. + // The v5.59.0 schema introduced a new string attribute named 'cluster_mode'. + // Remove any trace of the old cluster_mode block. + for _, k := range tfmaps.Keys(rawState) { + if strings.HasPrefix(k, "cluster_mode.") { + delete(rawState, k) + } + } + delete(rawState, "cluster_mode") + return rawState, nil } @@ -48,17 +57,14 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Computed: true, }, "auth_token": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - ValidateFunc: validReplicationGroupAuthToken, - ConflictsWith: []string{"user_group_ids"}, - }, - names.AttrAutoMinorVersionUpgrade: { - Type: nullable.TypeNullableBool, - Optional: true, - Computed: true, - ValidateFunc: nullable.ValidateTypeStringNullableBool, + Type: schema.TypeString, + Optional: true, + Sensitive: true, + }, + names.AttrAutoMinorVersionUpgrade: { // nosemgrep:ci.semgrep.types.valid-nullable-bool + Type: nullable.TypeNullableBool, + Optional: true, + Computed: true, }, "automatic_failover_enabled": { Type: schema.TypeBool, @@ -80,23 +86,20 @@ func resourceReplicationGroupConfigV1() *schema.Resource { ForceNew: true, }, names.AttrDescription: { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validation.StringIsNotEmpty, + Type: schema.TypeString, + Optional: true, + Computed: true, }, names.AttrEngine: { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: engineRedis, - ValidateFunc: validation.StringInSlice([]string{engineRedis}, true), + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: engineRedis, }, names.AttrEngineVersion: { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validRedisVersionString, + Type: schema.TypeString, + Optional: true, + Computed: true, }, "engine_version_actual": { Type: schema.TypeString, @@ -107,24 +110,11 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - ConflictsWith: []string{ - "num_node_groups", - names.AttrParameterGroupName, - names.AttrEngine, - names.AttrEngineVersion, - "node_type", - "security_group_names", - "transit_encryption_enabled", - "at_rest_encryption_enabled", - "snapshot_arns", - "snapshot_name", - }, }, "ip_discovery": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateDiagFunc: enum.Validate[awstypes.IpDiscovery](), + Type: schema.TypeString, + Optional: true, + Computed: true, }, "log_delivery_configuration": { Type: schema.TypeSet, @@ -133,23 +123,20 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "destination_type": { - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: enum.Validate[awstypes.DestinationType](), + Type: schema.TypeString, + Required: true, }, names.AttrDestination: { Type: schema.TypeString, Required: true, }, "log_format": { - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: enum.Validate[awstypes.LogFormat](), + Type: schema.TypeString, + Required: true, }, "log_type": { - Type: schema.TypeString, - Required: true, - ValidateDiagFunc: enum.Validate[awstypes.LogType](), + Type: schema.TypeString, + Required: true, }, }, }, @@ -158,17 +145,11 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - StateFunc: func(val interface{}) string { - // ElastiCache always changes the maintenance to lowercase - return strings.ToLower(val.(string)) - }, - ValidateFunc: verify.ValidOnceAWeekWindowFormat, }, "member_clusters": { Type: schema.TypeSet, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, "multi_az_enabled": { Type: schema.TypeBool, @@ -176,11 +157,10 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Default: false, }, "network_type": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - ValidateDiagFunc: enum.Validate[awstypes.NetworkType](), + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, }, "node_type": { Type: schema.TypeString, @@ -188,41 +168,28 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Computed: true, }, "notification_topic_arn": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: verify.ValidARN, + Type: schema.TypeString, + Optional: true, }, "num_cache_clusters": { - Type: schema.TypeInt, - Computed: true, - Optional: true, - ConflictsWith: []string{"num_node_groups"}, + Type: schema.TypeInt, + Computed: true, + Optional: true, }, "num_node_groups": { - Type: schema.TypeInt, - Optional: true, - Computed: true, - ConflictsWith: []string{"num_cache_clusters", "global_replication_group_id"}, + Type: schema.TypeInt, + Optional: true, + Computed: true, }, names.AttrParameterGroupName: { Type: schema.TypeString, Optional: true, Computed: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - return strings.HasPrefix(old, "global-datastore-") - }, }, names.AttrPort: { Type: schema.TypeInt, Optional: true, ForceNew: true, - DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { - // Suppress default Redis ports when not defined - if !d.IsNewResource() && new == "0" && old == defaultRedisPort { - return true - } - return false - }, }, "preferred_cache_cluster_azs": { Type: schema.TypeList, @@ -243,13 +210,9 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Computed: true, }, "replication_group_id": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validateReplicationGroupID, - StateFunc: func(val interface{}) string { - return strings.ToLower(val.(string)) - }, + Type: schema.TypeString, + Required: true, + ForceNew: true, }, "security_group_names": { Type: schema.TypeSet, @@ -257,14 +220,12 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Computed: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, names.AttrSecurityGroupIDs: { Type: schema.TypeSet, Optional: true, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, }, "snapshot_arns": { Type: schema.TypeSet, @@ -273,23 +234,16 @@ func resourceReplicationGroupConfigV1() *schema.Resource { // Note: Unlike aws_elasticache_cluster, this does not have a limit of 1 item. Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validation.All( - verify.ValidARN, - validation.StringDoesNotContainAny(","), - ), }, - Set: schema.HashString, }, "snapshot_retention_limit": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntAtMost(35), + Type: schema.TypeInt, + Optional: true, }, "snapshot_window": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: verify.ValidOnceADayWindowFormat, + Type: schema.TypeString, + Optional: true, + Computed: true, }, "snapshot_name": { Type: schema.TypeString, @@ -311,11 +265,9 @@ func resourceReplicationGroupConfigV1() *schema.Resource { Computed: true, }, "user_group_ids": { - Type: schema.TypeSet, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - ConflictsWith: []string{"auth_token"}, + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, names.AttrKMSKeyID: { Type: schema.TypeString, diff --git a/internal/service/elasticache/replication_group_test.go b/internal/service/elasticache/replication_group_test.go index a1d179e2fac..cb722360e0b 100644 --- a/internal/service/elasticache/replication_group_test.go +++ b/internal/service/elasticache/replication_group_test.go @@ -643,6 +643,45 @@ func TestAccElastiCacheReplicationGroup_stateUpgrade5270(t *testing.T) { }) } +// https://github.com/hashicorp/terraform-provider-aws/issues/38464. +func TestAccElastiCacheReplicationGroup_stateUpgrade5590(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var rg awstypes.ReplicationGroup + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elasticache_replication_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(ctx, t) }, + ErrorCheck: acctest.ErrorCheck(t, names.ElastiCacheServiceID), + CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "aws": { + Source: "hashicorp/aws", + VersionConstraint: "4.67.0", + }, + }, + Config: testAccReplicationGroupConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg), + ), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Config: testAccReplicationGroupConfig_basic(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg), + ), + }, + }, + }) +} + func TestAccElastiCacheReplicationGroup_vpc(t *testing.T) { ctx := acctest.Context(t) if testing.Short() {