diff --git a/.changelog/23996.txt b/.changelog/23996.txt new file mode 100644 index 00000000000..72ca5ee78ce --- /dev/null +++ b/.changelog/23996.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_elasticache_cluster: Add `auto_minor_version_upgrade` argument +``` + +```release-note:bug +resource/aws_elasticache_replication_group: Allow disabling `auto_minor_version_upgrade` +``` diff --git a/internal/service/elasticache/cluster.go b/internal/service/elasticache/cluster.go index 3fabe093ac9..013f28f7b42 100644 --- a/internal/service/elasticache/cluster.go +++ b/internal/service/elasticache/cluster.go @@ -6,6 +6,7 @@ import ( "log" "regexp" "sort" + "strconv" "strings" "time" @@ -18,6 +19,7 @@ import ( "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/conns" + "github.com/hashicorp/terraform-provider-aws/internal/experimental/nullable" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -53,6 +55,12 @@ func ResourceCluster() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "auto_minor_version_upgrade": { + Type: nullable.TypeNullableBool, + Optional: true, + Default: "true", + ValidateFunc: nullable.ValidateTypeStringNullableBool, + }, "availability_zone": { Type: schema.TypeString, Optional: true, @@ -340,8 +348,15 @@ func resourceClusterCreate(d *schema.ResourceData, meta interface{}) error { req.Engine = aws.String(v.(string)) } - if v, ok := d.GetOk("engine_version"); ok { - req.EngineVersion = aws.String(v.(string)) + version := d.Get("engine_version").(string) + if version != "" { + req.EngineVersion = aws.String(version) + } + + if v, ok := d.GetOk("auto_minor_version_upgrade"); ok { + if v, null, _ := nullable.Bool(v.(string)).Value(); !null { + req.AutoMinorVersionUpgrade = aws.Bool(v) + } } if v, ok := d.GetOk("port"); ok { @@ -523,6 +538,7 @@ func setFromCacheCluster(d *schema.ResourceData, c *elasticache.CacheCluster) er if err := setEngineVersionFromCacheCluster(d, c); err != nil { return err } + d.Set("auto_minor_version_upgrade", strconv.FormatBool(aws.BoolValue(c.AutoMinorVersionUpgrade))) d.Set("subnet_group_name", c.CacheSubnetGroupName) if err := d.Set("security_group_names", flattenSecurityGroupNames(c.CacheSecurityGroups)); err != nil { @@ -594,7 +610,7 @@ func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error { previousLogDeliveryConfig := oldLogDeliveryConfig.(*schema.Set).List() for _, previous := range previousLogDeliveryConfig { logDeliveryConfigurationRequest := expandEmptyLogDeliveryConfigurations(previous.(map[string]interface{})) - //if something was removed, send an empty request + // if something was removed, send an empty request if !logTypesToSubmit[*logDeliveryConfigurationRequest.LogType] { req.LogDeliveryConfigurations = append(req.LogDeliveryConfigurations, &logDeliveryConfigurationRequest) } @@ -623,6 +639,14 @@ func resourceClusterUpdate(d *schema.ResourceData, meta interface{}) error { requestUpdate = true } + if d.HasChange("auto_minor_version_upgrade") { + v := d.Get("auto_minor_version_upgrade") + if v, null, _ := nullable.Bool(v.(string)).Value(); !null { + req.AutoMinorVersionUpgrade = aws.Bool(v) + } + requestUpdate = true + } + if d.HasChange("snapshot_window") { req.SnapshotWindow = aws.String(d.Get("snapshot_window").(string)) requestUpdate = true diff --git a/internal/service/elasticache/cluster_test.go b/internal/service/elasticache/cluster_test.go index 34b6aed5a9a..a90bb620fec 100644 --- a/internal/service/elasticache/cluster_test.go +++ b/internal/service/elasticache/cluster_test.go @@ -43,7 +43,7 @@ func TestAccElastiCacheCluster_Engine_memcached(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccClusterConfig_Engine_Memcached(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckClusterExists(resourceName, &ec), resource.TestCheckResourceAttr(resourceName, "cache_nodes.0.id", "0001"), resource.TestCheckResourceAttrSet(resourceName, "configuration_endpoint"), @@ -77,11 +77,46 @@ func TestAccElastiCacheCluster_Engine_redis(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccClusterConfig_Engine_Redis(rName), - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckClusterExists(resourceName, &ec), resource.TestCheckResourceAttr(resourceName, "cache_nodes.0.id", "0001"), resource.TestCheckResourceAttr(resourceName, "engine", "redis"), + resource.TestMatchResourceAttr(resourceName, "engine_version_actual", regexp.MustCompile(`^6\.[[:digit:]]+\.[[:digit:]]+$`)), resource.TestCheckResourceAttr(resourceName, "port", "6379"), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "apply_immediately", + }, + }, + }, + }) +} + +func TestAccElastiCacheCluster_Engine_redis_v5(t *testing.T) { + var ec elasticache.CacheCluster + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elasticache_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elasticache.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccClusterConfig_Engine_Redis_v5(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckClusterExists(resourceName, &ec), + resource.TestCheckResourceAttr(resourceName, "engine", "redis"), + resource.TestCheckResourceAttr(resourceName, "engine_version_actual", "5.0.6"), + // Even though it is ignored, the API returns `true` in this case + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), ), }, { @@ -763,6 +798,43 @@ func TestAccElastiCacheCluster_Redis_finalSnapshot(t *testing.T) { }) } +func TestAccElastiCacheCluster_Redis_autoMinorVersionUpgrade(t *testing.T) { + var cluster elasticache.CacheCluster + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elasticache_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elasticache.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccClusterConfig_Redis_AutoMinorVersionUpgrade(rName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckClusterExists(resourceName, &cluster), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "apply_immediately", + }, + }, + { + Config: testAccClusterConfig_Redis_AutoMinorVersionUpgrade(rName, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckClusterExists(resourceName, &cluster), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + }, + }) +} + func TestAccElastiCacheCluster_Engine_Redis_LogDeliveryConfigurations(t *testing.T) { var ec elasticache.CacheCluster rName := sdkacctest.RandomWithPrefix("tf-acc-test") @@ -1110,7 +1182,7 @@ func testAccCheckClusterEC2ClassicExists(n string, v *elasticache.CacheCluster) func testAccClusterConfig_Engine_Memcached(rName string) string { return fmt.Sprintf(` resource "aws_elasticache_cluster" "test" { - cluster_id = "%s" + cluster_id = "%[1]s" engine = "memcached" node_type = "cache.t3.small" num_cache_nodes = 1 @@ -1121,7 +1193,19 @@ resource "aws_elasticache_cluster" "test" { func testAccClusterConfig_Engine_Redis(rName string) string { return fmt.Sprintf(` resource "aws_elasticache_cluster" "test" { - cluster_id = "%s" + cluster_id = "%[1]s" + engine = "redis" + node_type = "cache.t3.small" + num_cache_nodes = 1 +} +`, rName) +} + +func testAccClusterConfig_Engine_Redis_v5(rName string) string { + return fmt.Sprintf(` +resource "aws_elasticache_cluster" "test" { + cluster_id = "%[1]s" + engine_version = "5.0.6" engine = "redis" node_type = "cache.t3.small" num_cache_nodes = 1 @@ -1132,7 +1216,7 @@ resource "aws_elasticache_cluster" "test" { func testAccClusterConfig_Engine_None(rName string) string { return fmt.Sprintf(` resource "aws_elasticache_cluster" "test" { - cluster_id = "%s" + cluster_id = "%[1]s" node_type = "cache.t3.small" num_cache_nodes = 1 } @@ -1619,6 +1703,20 @@ resource "aws_elasticache_cluster" "test" { `, rName) } +func testAccClusterConfig_Redis_AutoMinorVersionUpgrade(rName string, enable bool) string { + return fmt.Sprintf(` +resource "aws_elasticache_cluster" "test" { + cluster_id = %[1]q + engine = "redis" + engine_version = "6.x" + node_type = "cache.t3.small" + num_cache_nodes = 1 + + auto_minor_version_upgrade = %[2]t +} +`, rName, enable) +} + func testAccClusterConfig_Engine_Redis_LogDeliveryConfigurations(rName string, slowLogDeliveryEnabled bool, slowDeliveryDestination string, slowDeliveryFormat string, engineLogDeliveryEnabled bool, engineDeliveryDestination string, engineLogDeliveryFormat string) string { return fmt.Sprintf(` data "aws_iam_policy_document" "p" { diff --git a/internal/service/elasticache/replication_group.go b/internal/service/elasticache/replication_group.go index 82ab8256edf..295a04a73d7 100644 --- a/internal/service/elasticache/replication_group.go +++ b/internal/service/elasticache/replication_group.go @@ -18,6 +18,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/experimental/nullable" "github.com/hashicorp/terraform-provider-aws/internal/flex" tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" "github.com/hashicorp/terraform-provider-aws/internal/tfresource" @@ -59,9 +60,10 @@ func ResourceReplicationGroup() *schema.Resource { ConflictsWith: []string{"user_group_ids"}, }, "auto_minor_version_upgrade": { - Type: schema.TypeBool, - Optional: true, - Default: true, + Type: nullable.TypeNullableBool, + Optional: true, + Default: "true", + ValidateFunc: nullable.ValidateTypeStringNullableBool, }, "automatic_failover_enabled": { Type: schema.TypeBool, @@ -407,8 +409,7 @@ func resourceReplicationGroupCreate(d *schema.ResourceData, meta interface{}) er tags := defaultTagsConfig.MergeTags(tftags.New(d.Get("tags").(map[string]interface{}))) params := &elasticache.CreateReplicationGroupInput{ - ReplicationGroupId: aws.String(d.Get("replication_group_id").(string)), - AutoMinorVersionUpgrade: aws.Bool(d.Get("auto_minor_version_upgrade").(bool)), + ReplicationGroupId: aws.String(d.Get("replication_group_id").(string)), } if len(tags) > 0 { @@ -443,6 +444,12 @@ func resourceReplicationGroupCreate(d *schema.ResourceData, meta interface{}) er params.EngineVersion = aws.String(v.(string)) } + if v, ok := d.GetOk("auto_minor_version_upgrade"); ok { + if v, null, _ := nullable.Bool(v.(string)).Value(); !null { + params.AutoMinorVersionUpgrade = aws.Bool(v) + } + } + if preferredAZs, ok := d.GetOk("preferred_cache_cluster_azs"); ok { params.PreferredCacheClusterAZs = flex.ExpandStringList(preferredAZs.([]interface{})) } @@ -670,6 +677,21 @@ func resourceReplicationGroupRead(d *schema.ResourceData, meta interface{}) erro d.Set("arn", rgp.ARN) d.Set("data_tiering_enabled", aws.StringValue(rgp.DataTiering) == elasticache.DataTieringStatusEnabled) + d.Set("log_delivery_configuration", flattenLogDeliveryConfigurations(rgp.LogDeliveryConfigurations)) + d.Set("snapshot_window", rgp.SnapshotWindow) + d.Set("snapshot_retention_limit", rgp.SnapshotRetentionLimit) + + if rgp.ConfigurationEndpoint != nil { + d.Set("port", rgp.ConfigurationEndpoint.Port) + d.Set("configuration_endpoint_address", rgp.ConfigurationEndpoint.Address) + } else { + d.Set("port", rgp.NodeGroups[0].PrimaryEndpoint.Port) + d.Set("primary_endpoint_address", rgp.NodeGroups[0].PrimaryEndpoint.Address) + d.Set("reader_endpoint_address", rgp.NodeGroups[0].ReaderEndpoint.Address) + } + + d.Set("user_group_ids", rgp.UserGroupIds) + // Tags cannot be read when the replication group is not Available _, err = WaitReplicationGroupAvailable(conn, d.Id(), d.Timeout(schema.TimeoutUpdate)) if err != nil { @@ -700,12 +722,9 @@ func resourceReplicationGroupRead(d *schema.ResourceData, meta interface{}) erro } } - if rgp.NodeGroups != nil { - if len(rgp.NodeGroups[0].NodeGroupMembers) == 0 { - return nil - } - - cacheCluster := *rgp.NodeGroups[0].NodeGroupMembers[0] // nosemgrep: prefer-aws-go-sdk-pointer-conversion-assignment // false positive + // This section reads settings that require checking the underlying cache clusters + if rgp.NodeGroups != nil && len(rgp.NodeGroups[0].NodeGroupMembers) != 0 { + cacheCluster := rgp.NodeGroups[0].NodeGroupMembers[0] res, err := conn.DescribeCacheClusters(&elasticache.DescribeCacheClustersInput{ CacheClusterId: cacheCluster.CacheClusterId, @@ -725,23 +744,7 @@ func resourceReplicationGroupRead(d *schema.ResourceData, meta interface{}) erro return err } - d.Set("log_delivery_configuration", flattenLogDeliveryConfigurations(rgp.LogDeliveryConfigurations)) - d.Set("snapshot_window", rgp.SnapshotWindow) - d.Set("snapshot_retention_limit", rgp.SnapshotRetentionLimit) - - if rgp.ConfigurationEndpoint != nil { - d.Set("port", rgp.ConfigurationEndpoint.Port) - d.Set("configuration_endpoint_address", rgp.ConfigurationEndpoint.Address) - } else { - d.Set("port", rgp.NodeGroups[0].PrimaryEndpoint.Port) - d.Set("primary_endpoint_address", rgp.NodeGroups[0].PrimaryEndpoint.Address) - d.Set("reader_endpoint_address", rgp.NodeGroups[0].ReaderEndpoint.Address) - } - - d.Set("user_group_ids", rgp.UserGroupIds) - d.Set("at_rest_encryption_enabled", c.AtRestEncryptionEnabled) - d.Set("auto_minor_version_upgrade", c.AutoMinorVersionUpgrade) d.Set("transit_encryption_enabled", c.TransitEncryptionEnabled) if c.AuthTokenEnabled != nil && !aws.BoolValue(c.AuthTokenEnabled) { @@ -800,7 +803,10 @@ func resourceReplicationGroupUpdate(d *schema.ResourceData, meta interface{}) er } if d.HasChange("auto_minor_version_upgrade") { - params.AutoMinorVersionUpgrade = aws.Bool(d.Get("auto_minor_version_upgrade").(bool)) + v := d.Get("auto_minor_version_upgrade") + if v, null, _ := nullable.Bool(v.(string)).Value(); !null { + params.AutoMinorVersionUpgrade = aws.Bool(v) + } requestUpdate = true } diff --git a/internal/service/elasticache/replication_group_test.go b/internal/service/elasticache/replication_group_test.go index 7dfe4d1e312..24daf2bd835 100644 --- a/internal/service/elasticache/replication_group_test.go +++ b/internal/service/elasticache/replication_group_test.go @@ -46,7 +46,6 @@ func TestAccElastiCacheReplicationGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "multi_az_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "automatic_failover_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "member_clusters.#", "1"), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), resource.TestCheckResourceAttr(resourceName, "parameter_group_name", "default.redis6.x"), resource.TestCheckResourceAttr(resourceName, "cluster_mode.#", "1"), resource.TestCheckResourceAttr(resourceName, "cluster_mode.0.num_node_groups", "1"), @@ -54,6 +53,7 @@ func TestAccElastiCacheReplicationGroup_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "cluster_enabled", "false"), resource.TestCheckResourceAttr(resourceName, "engine_version", "6.x"), resource.TestMatchResourceAttr(resourceName, "engine_version_actual", regexp.MustCompile(`^6\.[[:digit:]]+\.[[:digit:]]+$`)), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), resource.TestCheckResourceAttr(resourceName, "data_tiering_enabled", "false"), ), }, @@ -67,6 +67,42 @@ func TestAccElastiCacheReplicationGroup_basic(t *testing.T) { }) } +func TestAccElastiCacheReplicationGroup_basic_v5(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var rg elasticache.ReplicationGroup + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elasticache_replication_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elasticache.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckReplicationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccReplicationGroupConfig_v5(rName), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(resourceName, &rg), + resource.TestCheckResourceAttr(resourceName, "engine", "redis"), + resource.TestCheckResourceAttr(resourceName, "engine_version", "5.0.6"), + resource.TestCheckResourceAttr(resourceName, "engine_version_actual", "5.0.6"), + // Even though it is ignored, the API returns `true` in this case + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"apply_immediately"}, //not in the API + }, + }, + }) +} + func TestAccElastiCacheReplicationGroup_uppercase(t *testing.T) { if testing.Short() { t.Skip("skipping long-running test in short mode") @@ -210,7 +246,6 @@ func TestAccElastiCacheReplicationGroup_updateDescription(t *testing.T) { testAccCheckReplicationGroupExists(resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "number_cache_clusters", "1"), resource.TestCheckResourceAttr(resourceName, "replication_group_description", "test description"), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), ), }, { @@ -225,7 +260,6 @@ func TestAccElastiCacheReplicationGroup_updateDescription(t *testing.T) { testAccCheckReplicationGroupExists(resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "number_cache_clusters", "1"), resource.TestCheckResourceAttr(resourceName, "replication_group_description", "updated description"), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), ), }, }, @@ -455,7 +489,6 @@ func TestAccElastiCacheReplicationGroup_vpc(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckReplicationGroupExists(resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "number_cache_clusters", "1"), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), resource.TestCheckResourceAttr(resourceName, "preferred_cache_cluster_azs.#", "1"), ), }, @@ -489,7 +522,6 @@ func TestAccElastiCacheReplicationGroup_depecatedAvailabilityZones_vpc(t *testin Check: resource.ComposeTestCheckFunc( testAccCheckReplicationGroupExists(resourceName, &rg), resource.TestCheckResourceAttr(resourceName, "number_cache_clusters", "1"), - resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), resource.TestCheckResourceAttr(resourceName, "availability_zones.#", "1"), ), }, @@ -1817,6 +1849,47 @@ func TestAccElastiCacheReplicationGroup_finalSnapshot(t *testing.T) { }) } +func TestAccElastiCacheReplicationGroup_autoMinorVersionUpgrade(t *testing.T) { + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var rg elasticache.ReplicationGroup + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_elasticache_replication_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, elasticache.EndpointsID), + Providers: acctest.Providers, + CheckDestroy: testAccCheckClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccReplicationGroup_AutoMinorVersionUpgrade(rName, false), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(resourceName, &rg), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "false"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "apply_immediately", + }, + }, + { + Config: testAccReplicationGroup_AutoMinorVersionUpgrade(rName, true), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckReplicationGroupExists(resourceName, &rg), + resource.TestCheckResourceAttr(resourceName, "auto_minor_version_upgrade", "true"), + ), + }, + }, + }) +} + func TestAccElastiCacheReplicationGroup_Validation_noNodeType(t *testing.T) { var providers []*schema.Provider rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) @@ -2419,13 +2492,23 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" } `, rName) } +func testAccReplicationGroupConfig_v5(rName string) string { + return fmt.Sprintf(` +resource "aws_elasticache_replication_group" "test" { + replication_group_id = %[1]q + replication_group_description = "test description" + node_type = "cache.t3.small" + engine_version = "5.0.6" +} +`, rName) +} + func testAccReplicationGroupConfig_Uppercase(rName string) string { return acctest.ConfigCompose( acctest.ConfigVpcWithSubnets(2), @@ -2472,7 +2555,6 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" snapshot_retention_limit = 2 @@ -2516,7 +2598,6 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = true } `, rName) } @@ -2529,7 +2610,6 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = true maintenance_window = "wed:03:00-wed:06:00" snapshot_window = "01:00-02:00" } @@ -2574,7 +2654,6 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" transit_encryption_enabled = true @@ -2597,7 +2676,6 @@ resource "aws_elasticache_replication_group" "test" { subnet_group_name = aws_elasticache_subnet_group.test.name security_group_ids = [aws_security_group.test.id] preferred_cache_cluster_azs = [data.aws_availability_zones.available.names[0]] - auto_minor_version_upgrade = false } resource "aws_elasticache_subnet_group" "test" { @@ -2634,7 +2712,6 @@ resource "aws_elasticache_replication_group" "test" { subnet_group_name = aws_elasticache_subnet_group.test.name security_group_ids = [aws_security_group.test.id] availability_zones = [data.aws_availability_zones.available.names[0]] - auto_minor_version_upgrade = false } resource "aws_elasticache_subnet_group" "test" { @@ -3115,7 +3192,6 @@ resource "aws_elasticache_replication_group" "test" { number_cache_clusters = %[2]d port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" @@ -3139,7 +3215,6 @@ resource "aws_elasticache_replication_group" "test" { number_cache_clusters = %[2]d port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" @@ -3196,6 +3271,18 @@ resource "aws_elasticache_replication_group" "test" { `, rName) } +func testAccReplicationGroup_AutoMinorVersionUpgrade(rName string, enable bool) string { + return fmt.Sprintf(` +resource "aws_elasticache_replication_group" "test" { + replication_group_id = %[1]q + replication_group_description = "test description" + node_type = "cache.t3.small" + + auto_minor_version_upgrade = %[2]t +} +`, rName, enable) +} + func testAccReplicationGroupConfig_Validation_NoNodeType(rName string) string { return fmt.Sprintf(` resource "aws_elasticache_replication_group" "test" { @@ -3455,7 +3542,6 @@ resource "aws_elasticache_replication_group" "test" { port = 6379 subnet_group_name = aws_elasticache_subnet_group.test.name security_group_ids = [aws_security_group.test.id] - auto_minor_version_upgrade = false } resource "aws_elasticache_subnet_group" "test" { @@ -3569,7 +3655,6 @@ resource "aws_elasticache_replication_group" "test" { node_type = "cache.t3.small" port = 6379 apply_immediately = true - auto_minor_version_upgrade = false maintenance_window = "tue:06:30-tue:07:30" snapshot_window = "01:00-02:00" parameter_group_name = tobool("%[2]t") ? "default.redis6.x.cluster.on" : "default.redis6.x" diff --git a/website/docs/r/elasticache_cluster.html.markdown b/website/docs/r/elasticache_cluster.html.markdown index 6872e4036f7..8ba4b9f758f 100644 --- a/website/docs/r/elasticache_cluster.html.markdown +++ b/website/docs/r/elasticache_cluster.html.markdown @@ -106,11 +106,15 @@ The following arguments are required: The following arguments are optional: * `apply_immediately` - (Optional) Whether any database modifications are applied immediately, or during the next maintenance window. Default is `false`. See [Amazon ElastiCache Documentation for more information.](https://docs.aws.amazon.com/AmazonElastiCache/latest/APIReference/API_ModifyCacheCluster.html). +* `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. + Only supported for engine type `"redis"` and if the engine version is 6 or higher. + Defaults to `true`. * `availability_zone` - (Optional) Availability Zone for the cache cluster. If you want to create cache nodes in multi-az, use `preferred_availability_zones` instead. Default: System chosen Availability Zone. Changing this value will re-create the resource. * `az_mode` - (Optional, Memcached only) Whether the nodes in this Memcached node group are created in a single Availability Zone or created across multiple Availability Zones in the cluster's region. Valid values for this parameter are `single-az` or `cross-az`, default is `single-az`. If you want to choose `cross-az`, `num_cache_nodes` must be greater than `1`. * `engine_version` – (Optional) Version number of the cache engine to be used. -See [Describe Cache Engine Versions](https://docs.aws.amazon.com/cli/latest/reference/elasticache/describe-cache-engine-versions.html) -in the AWS Documentation for supported versions. When `engine` is `redis` and the version is 6 or higher, only the major version can be set, e.g., `6.x`, otherwise, specify the full version desired, e.g., `5.0.6`. The actual engine version used is returned in the attribute `engine_version_actual`, [defined below](#engine_version_actual). + If not set, defaults to the latest version. + See [Describe Cache Engine Versions](https://docs.aws.amazon.com/cli/latest/reference/elasticache/describe-cache-engine-versions.html) + in the AWS Documentation for supported versions. When `engine` is `redis` and the version is 6 or higher, only the major version can be set, e.g., `6.x`, otherwise, specify the full version desired, e.g., `5.0.6`. The actual engine version used is returned in the attribute `engine_version_actual`, [defined below](#engine_version_actual). * `final_snapshot_identifier` - (Optional, Redis only) Name of your final cluster snapshot. If omitted, no final snapshot will be made. * `log_delivery_configuration` - (Optional, Redis only) Specifies the destination and format of Redis [SLOWLOG](https://redis.io/commands/slowlog) or Redis [Engine Log](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Log_Delivery.html#Log_contents-engine-log). See the documentation on [Amazon ElastiCache](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Log_Delivery.html). See [Log Delivery Configuration](#log-delivery-configuration) below for more details. * `maintenance_window` – (Optional) Specifies the weekly time range for when maintenance diff --git a/website/docs/r/elasticache_replication_group.html.markdown b/website/docs/r/elasticache_replication_group.html.markdown index 3aa1828256b..7e336b1f91a 100644 --- a/website/docs/r/elasticache_replication_group.html.markdown +++ b/website/docs/r/elasticache_replication_group.html.markdown @@ -175,7 +175,9 @@ 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. * `auth_token` - (Optional) Password used to access a password protected server. Can be specified only if `transit_encryption_enabled = true`. -* `auto_minor_version_upgrade` - (Optional) Specifies whether a minor engine upgrades will be applied automatically to the underlying Cache Cluster instances during the maintenance window. This parameter is currently not supported by the AWS API. Defaults to `true`. +* `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. + Only supported for engine type `"redis"` and if the engine version is 6 or higher. + Defaults to `true`. * `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, `number_cache_clusters` must be greater than 1. Must be enabled for Redis (cluster mode enabled) replication groups. Defaults to `false`. * `availability_zones` - (Optional, **Deprecated** use `preferred_cache_cluster_azs` instead) List of EC2 availability zones in which the replication group's cache clusters will be created. The order of the availability zones in the list is not considered. * `cluster_mode` - (Optional, **Deprecated** use root-level `num_node_groups` and `replicas_per_node_group` instead) Create a native Redis cluster. `automatic_failover_enabled` must be set to true. Cluster Mode documented below. Only 1 `cluster_mode` block is allowed. Note that configuring this block does not enable cluster mode, i.e., data sharding, this requires using a parameter group that has the parameter `cluster-enabled` set to true.