diff --git a/.changelog/40514.txt b/.changelog/40514.txt new file mode 100644 index 00000000000..a7f8b8e3ca3 --- /dev/null +++ b/.changelog/40514.txt @@ -0,0 +1,3 @@ +```release-note:bug +resource/aws_elasticache_replication_group: Prevent perpetual diff which triggers resource replacement on `at_rest_encryption_enabled` when `engine` is `valkey`. +``` diff --git a/internal/service/elasticache/replication_group.go b/internal/service/elasticache/replication_group.go index 10cbf9d4903..7e40c1ed8ca 100644 --- a/internal/service/elasticache/replication_group.go +++ b/internal/service/elasticache/replication_group.go @@ -9,6 +9,7 @@ import ( "fmt" "log" "slices" + "strconv" "strings" "time" @@ -67,10 +68,11 @@ func resourceReplicationGroup() *schema.Resource { Computed: true, }, "at_rest_encryption_enabled": { - Type: schema.TypeBool, - Optional: true, - ForceNew: true, - Computed: true, + Type: nullable.TypeNullableBool, + Optional: true, + ForceNew: true, + Computed: true, + ValidateFunc: nullable.ValidateTypeStringNullableBool, }, "auth_token": { Type: schema.TypeString, @@ -434,8 +436,10 @@ func resourceReplicationGroupCreate(ctx context.Context, d *schema.ResourceData, Tags: getTagsIn(ctx), } - if _, ok := d.GetOk("at_rest_encryption_enabled"); ok { - input.AtRestEncryptionEnabled = aws.Bool(d.Get("at_rest_encryption_enabled").(bool)) + if v, ok := d.GetOk("at_rest_encryption_enabled"); ok { + if v, null, _ := nullable.Bool(v.(string)).ValueBool(); !null { + input.AtRestEncryptionEnabled = aws.Bool(v) + } } if v, ok := d.GetOk("auth_token"); ok { @@ -764,7 +768,7 @@ func resourceReplicationGroupRead(ctx context.Context, d *schema.ResourceData, m return sdkdiag.AppendErrorf(diags, "reading ElastiCache Replication Group (%s): reading Cache Cluster (%s): %s", d.Id(), aws.ToString(cacheCluster.CacheClusterId), err) } - d.Set("at_rest_encryption_enabled", c.AtRestEncryptionEnabled) + d.Set("at_rest_encryption_enabled", strconv.FormatBool(aws.ToBool(c.AtRestEncryptionEnabled))) // `aws_elasticache_cluster` resource doesn't define `security_group_names`, but `aws_elasticache_replication_group` does. // The value for that comes from []CacheSecurityGroupMembership which is part of CacheCluster object in AWS API. // We need to set it here, as it is not set in setFromCacheCluster, and we cannot add it to that function diff --git a/internal/service/elasticache/replication_group_test.go b/internal/service/elasticache/replication_group_test.go index e0a4b3a3e03..e646aabd126 100644 --- a/internal/service/elasticache/replication_group_test.go +++ b/internal/service/elasticache/replication_group_test.go @@ -63,6 +63,9 @@ func TestAccElastiCacheReplicationGroup_Redis_basic(t *testing.T) { testCheckEngineStuffRedisDefault(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, names.AttrAutoMinorVersionUpgrade, acctest.CtTrue), resource.TestCheckResourceAttr(resourceName, "data_tiering_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, { @@ -100,6 +103,9 @@ func TestAccElastiCacheReplicationGroup_Redis_basic_v5(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "engine_version_actual", "5.0.6"), // Even though it is ignored, the API returns `true` in this case resource.TestCheckResourceAttr(resourceName, names.AttrAutoMinorVersionUpgrade, acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, { @@ -144,6 +150,9 @@ func TestAccElastiCacheReplicationGroup_Valkey_basic(t *testing.T) { testCheckEngineStuffValkeyDefault(ctx, resourceName), resource.TestCheckResourceAttr(resourceName, names.AttrAutoMinorVersionUpgrade, acctest.CtTrue), resource.TestCheckResourceAttr(resourceName, "data_tiering_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, { @@ -363,6 +372,7 @@ func TestAccElastiCacheReplicationGroup_Engine_RedisToValkey(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( testAccCheckReplicationGroupExists(ctx, resourceName, &v1), resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "redis"), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtFalse), ), }, { @@ -375,6 +385,7 @@ func TestAccElastiCacheReplicationGroup_Engine_RedisToValkey(t *testing.T) { testAccCheckReplicationGroupExists(ctx, resourceName, &v2), testAccCheckReplicationGroupNotRecreated(&v1, &v2), resource.TestCheckResourceAttr(resourceName, names.AttrEngine, "valkey"), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtFalse), ), }, }, @@ -1612,7 +1623,7 @@ func TestAccElastiCacheReplicationGroup_transitEncryptionWithAuthToken(t *testin testAccCheckReplicationGroupExists(ctx, resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "auth_token", authToken), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), - resource.TestCheckResourceAttrSet(resourceName, "transit_encryption_mode"), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), ), }, { @@ -1646,7 +1657,7 @@ func TestAccElastiCacheReplicationGroup_transitEncryption5x(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( testAccCheckReplicationGroupExists(ctx, resourceName, &rg1), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), - resource.TestCheckResourceAttrSet(resourceName, "transit_encryption_mode"), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), ), }, { @@ -1663,19 +1674,20 @@ func TestAccElastiCacheReplicationGroup_transitEncryption5x(t *testing.T) { testAccCheckReplicationGroupExists(ctx, resourceName, &rg2), testAccCheckReplicationGroupRecreated(&rg1, &rg2), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, }, }) } -func TestAccElastiCacheReplicationGroup_transitEncryption7x(t *testing.T) { +func TestAccElastiCacheReplicationGroup_transitEncryption7x_basic(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { t.Skip("skipping long-running test in short mode") } - var rg1, rg2, rg3, rg4 awstypes.ReplicationGroup + var rg awstypes.ReplicationGroup rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) resourceName := "aws_elasticache_replication_group.test" @@ -1686,11 +1698,45 @@ func TestAccElastiCacheReplicationGroup_transitEncryption7x(t *testing.T) { CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModePreferred)), + Config: testAccReplicationGroupConfig_transitEncryption7x(rName, true), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckReplicationGroupExists(ctx, resourceName, &rg1), + testAccCheckReplicationGroupExists(ctx, resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), - resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModePreferred)), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, + }, + }) +} + +func TestAccElastiCacheReplicationGroup_transitEncryption7x_Enable(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var rg1, rg2, rg3 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), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccReplicationGroupConfig_transitEncryptionDisabled7x(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg1), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, { @@ -1700,39 +1746,108 @@ func TestAccElastiCacheReplicationGroup_transitEncryption7x(t *testing.T) { ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, }, { - // With Redis engine versions >= 7.0.5, transit_encryption_mode can be modified in-place. - Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModeRequired)), + // Before enabling transit encryption, mode must be set to "preferred" first. + Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModePreferred)), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckReplicationGroupExists(ctx, resourceName, &rg2), testAccCheckReplicationGroupNotRecreated(&rg1, &rg2), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), - resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModePreferred)), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, { // Before disabling transit encryption, mode must be transitioned back to "preferred" first. - Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModePreferred)), + Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModeRequired)), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckReplicationGroupExists(ctx, resourceName, &rg3), testAccCheckReplicationGroupNotRecreated(&rg2, &rg3), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, + }, + }) +} + +func TestAccElastiCacheReplicationGroup_transitEncryption7x_Disable(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var rg1, rg2, rg3 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), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModeRequired)), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg1), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModeRequired)), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, + { + // With Redis engine versions >= 7.0.5, transit_encryption_mode can be modified in-place. + Config: testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, string(awstypes.TransitEncryptionModePreferred)), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg2), + testAccCheckReplicationGroupNotRecreated(&rg1, &rg2), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtTrue), resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", string(awstypes.TransitEncryptionModePreferred)), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, { // With Redis engine versions >= 7.0.5, transit_encryption_enabled can be modified in-place. Config: testAccReplicationGroupConfig_transitEncryptionDisabled7x(rName), Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckReplicationGroupExists(ctx, resourceName, &rg4), - testAccCheckReplicationGroupNotRecreated(&rg3, &rg4), + testAccCheckReplicationGroupExists(ctx, resourceName, &rg3), + testAccCheckReplicationGroupNotRecreated(&rg2, &rg3), resource.TestCheckResourceAttr(resourceName, "transit_encryption_enabled", acctest.CtFalse), + resource.TestCheckResourceAttr(resourceName, "transit_encryption_mode", ""), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token", "auth_token_update_strategy", "preferred_cache_cluster_azs"}, + }, }, }) } -func TestAccElastiCacheReplicationGroup_enableAtRestEncryption(t *testing.T) { +func TestAccElastiCacheReplicationGroup_Redis_enableAtRestEncryption(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { t.Skip("skipping long-running test in short mode") @@ -1749,7 +1864,7 @@ func TestAccElastiCacheReplicationGroup_enableAtRestEncryption(t *testing.T) { CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), Steps: []resource.TestStep{ { - Config: testAccReplicationGroupConfig_enableAtRestEncryption(rName), + Config: testAccReplicationGroupConfig_Redis_enableAtRestEncryption(rName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckReplicationGroupExists(ctx, resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtTrue), @@ -1765,6 +1880,39 @@ func TestAccElastiCacheReplicationGroup_enableAtRestEncryption(t *testing.T) { }) } +func TestAccElastiCacheReplicationGroup_Valkey_disableAtRestEncryption(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), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckReplicationGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccReplicationGroupConfig_Valkey_disableAtRestEncryption(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(ctx, resourceName, &rg), + resource.TestCheckResourceAttr(resourceName, "at_rest_encryption_enabled", acctest.CtFalse), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{names.AttrApplyImmediately, "auth_token_update_strategy"}, + }, + }, + }) +} + func TestAccElastiCacheReplicationGroup_useCMKKMSKeyID(t *testing.T) { ctx := acctest.Context(t) if testing.Short() { @@ -3916,37 +4064,33 @@ resource "aws_kms_key" "test" { ) } -func testAccReplicationGroupConfig_enableAtRestEncryption(rName string) string { +func testAccReplicationGroupConfig_Redis_enableAtRestEncryption(rName string) string { return acctest.ConfigCompose( - acctest.ConfigVPCWithSubnets(rName, 1), fmt.Sprintf(` resource "aws_elasticache_replication_group" "test" { + engine = "redis" replication_group_id = %[1]q description = "test description" - node_type = "cache.t2.micro" + node_type = "cache.t4g.small" num_cache_clusters = "1" port = 6379 - subnet_group_name = aws_elasticache_subnet_group.test.name - security_group_ids = [aws_security_group.test.id] at_rest_encryption_enabled = true } - -resource "aws_elasticache_subnet_group" "test" { - name = %[1]q - subnet_ids = aws_subnet.test[*].id +`, rName), + ) } -resource "aws_security_group" "test" { - name = %[1]q - description = "tf-test-security-group-descr" - vpc_id = aws_vpc.test.id - - ingress { - from_port = -1 - to_port = -1 - protocol = "icmp" - cidr_blocks = ["0.0.0.0/0"] - } +func testAccReplicationGroupConfig_Valkey_disableAtRestEncryption(rName string) string { + return acctest.ConfigCompose( + fmt.Sprintf(` +resource "aws_elasticache_replication_group" "test" { + engine = "valkey" + replication_group_id = %[1]q + description = "test description" + node_type = "cache.t4g.small" + num_cache_clusters = "1" + port = 6379 + at_rest_encryption_enabled = false } `, rName), ) @@ -4042,23 +4186,48 @@ resource "aws_elasticache_replication_group" "test" { ) } +func testAccReplicationGroupConfig_transitEncryption7x(rName string, enabled bool) string { + return acctest.ConfigCompose( + testAccReplicationGroupConfig_transitEncryptionBase(rName), + fmt.Sprintf(` +resource "aws_elasticache_replication_group" "test" { + replication_group_id = %[1]q + description = "test description" + node_type = "cache.t2.micro" + num_cache_clusters = "1" + port = 6379 + subnet_group_name = aws_elasticache_subnet_group.test.name + security_group_ids = [aws_security_group.test.id] + parameter_group_name = "default.redis7" + engine_version = "7.0" + + transit_encryption_enabled = %[2]t + + apply_immediately = true +} +`, rName, enabled), + ) +} + func testAccReplicationGroupConfig_transitEncryptionEnabled7x(rName, transitEncryptionMode string) string { return acctest.ConfigCompose( testAccReplicationGroupConfig_transitEncryptionBase(rName), fmt.Sprintf(` resource "aws_elasticache_replication_group" "test" { - replication_group_id = %[1]q - description = "test description" - node_type = "cache.t2.micro" - num_cache_clusters = "1" - port = 6379 - subnet_group_name = aws_elasticache_subnet_group.test.name - security_group_ids = [aws_security_group.test.id] - parameter_group_name = "default.redis7" - engine_version = "7.0" + replication_group_id = %[1]q + description = "test description" + node_type = "cache.t2.micro" + num_cache_clusters = "1" + port = 6379 + subnet_group_name = aws_elasticache_subnet_group.test.name + security_group_ids = [aws_security_group.test.id] + parameter_group_name = "default.redis7" + engine_version = "7.0" + transit_encryption_enabled = true transit_encryption_mode = %[2]q - apply_immediately = true + + apply_immediately = true } `, rName, transitEncryptionMode), ) @@ -4069,17 +4238,19 @@ func testAccReplicationGroupConfig_transitEncryptionDisabled7x(rName string) str testAccReplicationGroupConfig_transitEncryptionBase(rName), fmt.Sprintf(` resource "aws_elasticache_replication_group" "test" { - replication_group_id = %[1]q - description = "test description" - node_type = "cache.t2.micro" - num_cache_clusters = "1" - port = 6379 - subnet_group_name = aws_elasticache_subnet_group.test.name - security_group_ids = [aws_security_group.test.id] - parameter_group_name = "default.redis7" - engine_version = "7.0" + replication_group_id = %[1]q + description = "test description" + node_type = "cache.t2.micro" + num_cache_clusters = "1" + port = 6379 + subnet_group_name = aws_elasticache_subnet_group.test.name + security_group_ids = [aws_security_group.test.id] + parameter_group_name = "default.redis7" + engine_version = "7.0" + transit_encryption_enabled = false - apply_immediately = true + + apply_immediately = true } `, rName), ) diff --git a/website/docs/r/elasticache_replication_group.html.markdown b/website/docs/r/elasticache_replication_group.html.markdown index f67217a5cfc..2b7c66b7945 100644 --- a/website/docs/r/elasticache_replication_group.html.markdown +++ b/website/docs/r/elasticache_replication_group.html.markdown @@ -195,6 +195,8 @@ The following arguments are optional: * `apply_immediately` - (Optional) Specifies whether any modifications are applied immediately, or during the next maintenance window. Default is `false`. * `at_rest_encryption_enabled` - (Optional) Whether to enable encryption at rest. + When `engine` is `redis`, default is `false`. + When `engine` is `valkey`, default is `true`. * `auth_token` - (Optional) Password used to access a password protected server. Can be specified only if `transit_encryption_enabled = true`. * `auth_token_update_strategy` - (Optional) Strategy to use when updating the `auth_token`. Valid values are `SET`, `ROTATE`, and `DELETE`. Defaults to `ROTATE`. * `auto_minor_version_upgrade` - (Optional) Specifies whether minor version engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window. @@ -203,7 +205,9 @@ The following arguments are optional: * `automatic_failover_enabled` - (Optional) Specifies whether a read-only replica will be automatically promoted to read/write primary if the existing primary fails. If enabled, `num_cache_clusters` must be greater than 1. Must be enabled for Redis (cluster mode enabled) replication groups. Defaults to `false`. * `cluster_mode` - (Optional) Specifies whether cluster mode is enabled or disabled. Valid values are `enabled` or `disabled` or `compatible` * `data_tiering_enabled` - (Optional) Enables data tiering. Data tiering is only supported for replication groups using the r6gd node type. This parameter must be set to `true` when using r6gd nodes. -* `engine` - (Optional) Name of the cache engine to be used for the clusters in this replication group. Valid values are `redis` or `valkey`. +* `engine` - (Optional) Name of the cache engine to be used for the clusters in this replication group. + Valid values are `redis` or `valkey`. + Default is `redis`. * `engine_version` - (Optional) Version number of the cache engine to be used for the cache clusters in this replication group. If the version is 7 or higher, the major and minor version should be set, e.g., `7.2`. If the version is 6, the major and minor version can be set, e.g., `6.2`,