diff --git a/.changelog/17111.txt b/.changelog/17111.txt new file mode 100644 index 00000000000..bd28d3e27f6 --- /dev/null +++ b/.changelog/17111.txt @@ -0,0 +1,19 @@ +```release-notes:bug +resource/aws_rds_cluster_instance: Remove force new resource on the `engine_version` parameter to allow upgrade without remove instances +``` + +```release-notes:enhancement +resource/aws_rds_cluster: Add `db_instance_parameter_group_name` attribute to allow major version upgrade using custom parameter groups +``` + +```release-note:enhancement +resource/rds_cluster_instance: Add `performance_insights_retention_period` attribute +``` + +```release-notes:bug +resource/aws_rds_cluster: Add possible pending states for cluster update +``` + +```release-note:enhancement +resource/aws_rds_cluster: Add `enable_global_write_forwarding` attribute +``` \ No newline at end of file diff --git a/aws/resource_aws_rds_cluster.go b/aws/resource_aws_rds_cluster.go index 5f8fa630356..54362b53519 100644 --- a/aws/resource_aws_rds_cluster.go +++ b/aws/resource_aws_rds_cluster.go @@ -117,6 +117,11 @@ func resourceAwsRDSCluster() *schema.Resource { Computed: true, }, + "db_instance_parameter_group_name": { + Type: schema.TypeString, + Optional: true, + }, + "deletion_protection": { Type: schema.TypeBool, Optional: true, @@ -132,6 +137,12 @@ func resourceAwsRDSCluster() *schema.Resource { Optional: true, }, + "enable_global_write_forwarding": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "reader_endpoint": { Type: schema.TypeString, Computed: true, @@ -863,6 +874,10 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error createOpts.GlobalClusterIdentifier = aws.String(attr.(string)) } + if attr, ok := d.GetOk("enable_global_write_forwarding"); ok { + createOpts.EnableGlobalWriteForwarding = aws.Bool(attr.(bool)) + } + if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { createOpts.VpcSecurityGroupIds = expandStringSet(attr) } @@ -1153,6 +1168,11 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error requestUpdate = true } + if d.HasChange("db_instance_parameter_group_name") { + req.DBInstanceParameterGroupName = aws.String(d.Get("db_instance_parameter_group_name").(string)) + requestUpdate = true + } + if d.HasChange("master_password") { req.MasterUserPassword = aws.String(d.Get("master_password").(string)) requestUpdate = true @@ -1232,6 +1252,11 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error requestUpdate = true } + if d.HasChange("enable_global_write_forwarding") { + req.EnableGlobalWriteForwarding = aws.Bool(d.Get("enable_global_write_forwarding").(bool)) + requestUpdate = true + } + if requestUpdate { err := resource.Retry(5*time.Minute, func() *resource.RetryError { _, err := conn.ModifyDBCluster(req) @@ -1470,7 +1495,9 @@ var resourceAwsRdsClusterDeletePendingStates = []string{ var resourceAwsRdsClusterUpdatePendingStates = []string{ "backing-up", + "configuring-iam-database-auth", "modifying", + "renaming", "resetting-master-credentials", "upgrading", } diff --git a/aws/resource_aws_rds_cluster_instance.go b/aws/resource_aws_rds_cluster_instance.go index fd652bd036f..1c3089c6ddd 100644 --- a/aws/resource_aws_rds_cluster_instance.go +++ b/aws/resource_aws_rds_cluster_instance.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/aws-sdk-go-base/tfawserr" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" iamwaiter "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/iam/waiter" "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/rds/finder" @@ -106,7 +107,6 @@ func resourceAwsRDSClusterInstance() *schema.Resource { "engine_version": { Type: schema.TypeString, Optional: true, - ForceNew: true, Computed: true, }, @@ -210,6 +210,13 @@ func resourceAwsRDSClusterInstance() *schema.Resource { ValidateFunc: validateArn, }, + "performance_insights_retention_period": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ValidateFunc: validation.IntInSlice([]int{7, 731}), + }, + "copy_tags_to_snapshot": { Type: schema.TypeBool, Optional: true, @@ -283,6 +290,10 @@ func resourceAwsRDSClusterInstanceCreate(d *schema.ResourceData, meta interface{ createOpts.PerformanceInsightsKMSKeyId = aws.String(attr.(string)) } + if attr, ok := d.GetOk("performance_insights_retention_period"); ok { + createOpts.PerformanceInsightsRetentionPeriod = aws.Int64(int64(attr.(int))) + } + if attr, ok := d.GetOk("preferred_backup_window"); ok { createOpts.PreferredBackupWindow = aws.String(attr.(string)) } @@ -459,6 +470,7 @@ func resourceAwsRDSClusterInstanceRead(d *schema.ResourceData, meta interface{}) d.Set("monitoring_role_arn", db.MonitoringRoleArn) d.Set("performance_insights_enabled", db.PerformanceInsightsEnabled) d.Set("performance_insights_kms_key_id", db.PerformanceInsightsKMSKeyId) + d.Set("performance_insights_retention_period", db.PerformanceInsightsRetentionPeriod) d.Set("preferred_backup_window", db.PreferredBackupWindow) d.Set("preferred_maintenance_window", db.PreferredMaintenanceWindow) d.Set("promotion_tier", db.PromotionTier) @@ -514,13 +526,17 @@ func resourceAwsRDSClusterInstanceUpdate(d *schema.ResourceData, meta interface{ requestUpdate = true } - if d.HasChanges("performance_insights_enabled", "performance_insights_kms_key_id") { + if d.HasChanges("performance_insights_enabled", "performance_insights_kms_key_id", "performance_insights_retention_period") { req.EnablePerformanceInsights = aws.Bool(d.Get("performance_insights_enabled").(bool)) if v, ok := d.GetOk("performance_insights_kms_key_id"); ok { req.PerformanceInsightsKMSKeyId = aws.String(v.(string)) } + if v, ok := d.GetOk("performance_insights_retention_period"); ok { + req.PerformanceInsightsRetentionPeriod = aws.Int64(int64(v.(int))) + } + requestUpdate = true } diff --git a/aws/resource_aws_rds_cluster_instance_test.go b/aws/resource_aws_rds_cluster_instance_test.go index 557f0edd5a6..9c4b2fb20e0 100644 --- a/aws/resource_aws_rds_cluster_instance_test.go +++ b/aws/resource_aws_rds_cluster_instance_test.go @@ -731,6 +731,46 @@ func TestAccAWSRDSClusterInstance_PerformanceInsightsKmsKeyId_AuroraMysql2_Defau }) } +func TestAccAWSRDSClusterInstance_PerformanceInsightsRetentionPeriod(t *testing.T) { + var dbInstance rds.DBInstance + resourceName := "aws_rds_cluster_instance.test" + rName := acctest.RandomWithPrefix("tf-acc-test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccRDSPerformanceInsightsDefaultVersionPreCheck(t, "aurora") }, + ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSClusterInstanceConfigPerformanceInsightsRetentionPeriod(rName, 731), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterInstanceExists(resourceName, &dbInstance), + resource.TestCheckResourceAttr(resourceName, "performance_insights_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "performance_insights_retention_period", "731"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "apply_immediately", + "identifier_prefix", + }, + }, + { + Config: testAccAWSClusterInstanceConfigPerformanceInsightsRetentionPeriod(rName, 7), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterInstanceExists(resourceName, &dbInstance), + resource.TestCheckResourceAttr(resourceName, "performance_insights_enabled", "true"), + resource.TestCheckResourceAttr(resourceName, "performance_insights_retention_period", "7"), + ), + }, + }, + }) +} + func TestAccAWSRDSClusterInstance_PerformanceInsightsKmsKeyId_AuroraPostgresql(t *testing.T) { var dbInstance rds.DBInstance kmsKeyResourceName := "aws_kms_key.test" @@ -1596,6 +1636,35 @@ resource "aws_rds_cluster_instance" "test" { `, rName, engine) } +func testAccAWSClusterInstanceConfigPerformanceInsightsRetentionPeriod(rName string, performanceInsightsRetentionPeriod int) string { + return fmt.Sprintf(` +resource "aws_rds_cluster" "test" { + cluster_identifier = %[1]q + database_name = "mydb" + engine = "aurora" + master_password = "mustbeeightcharacters" + master_username = "foo" + skip_final_snapshot = true +} + +data "aws_rds_orderable_db_instance" "test" { + engine = aws_rds_cluster.test.engine + engine_version = aws_rds_cluster.test.engine_version + supports_performance_insights = true + preferred_instance_classes = ["db.t3.medium", "db.r5.large", "db.r4.large"] +} + +resource "aws_rds_cluster_instance" "test" { + cluster_identifier = aws_rds_cluster.test.id + engine = aws_rds_cluster.test.engine + identifier = %[1]q + instance_class = data.aws_rds_orderable_db_instance.test.instance_class + performance_insights_enabled = true + performance_insights_retention_period = %[2]d +} +`, rName, performanceInsightsRetentionPeriod) +} + func testAccAWSRDSClusterInstanceConfig_PubliclyAccessible(rName string, publiclyAccessible bool) string { return fmt.Sprintf(` resource "aws_rds_cluster" "test" { diff --git a/aws/resource_aws_rds_cluster_test.go b/aws/resource_aws_rds_cluster_test.go index b3c26ebb887..80705e4e28b 100644 --- a/aws/resource_aws_rds_cluster_test.go +++ b/aws/resource_aws_rds_cluster_test.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "regexp" + "strings" "testing" "time" @@ -147,11 +148,13 @@ func TestAccAWSRDSCluster_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{ + "allow_major_version_upgrade", "apply_immediately", "cluster_identifier_prefix", + "db_instance_parameter_group_name", + "enable_global_write_forwarding", "master_password", "skip_final_snapshot", - "snapshot_identifier", }, }, }, @@ -192,6 +195,8 @@ func TestAccAWSRDSCluster_AllowMajorVersionUpgrade(t *testing.T) { "allow_major_version_upgrade", "apply_immediately", "cluster_identifier_prefix", + "db_instance_parameter_group_name", + "enable_global_write_forwarding", "master_password", "skip_final_snapshot", }, @@ -209,15 +214,16 @@ func TestAccAWSRDSCluster_AllowMajorVersionUpgrade(t *testing.T) { }) } -func TestAccAWSRDSCluster_OnlyMajorVersion(t *testing.T) { - var dbCluster1 rds.DBCluster +func TestAccAWSRDSCluster_AllowMajorVersionUpgradeWithCustomParametersApplyImm(t *testing.T) { + var dbCluster1, dbCluster2 rds.DBCluster rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_rds_cluster.test" // If these hardcoded versions become a maintenance burden, use DescribeDBEngineVersions // either by having a new data source created or implementing the testing similar // to TestAccAWSDmsReplicationInstance_EngineVersion engine := "aurora-postgresql" - engineVersion1 := "11" + engineVersion1 := "11.9" + engineVersion2 := "12.4" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -226,9 +232,49 @@ func TestAccAWSRDSCluster_OnlyMajorVersion(t *testing.T) { CheckDestroy: testAccCheckAWSClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSClusterConfig_MajorVersionOnly(rName, false, engine, engineVersion1), + Config: testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName, true, engine, engineVersion1, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster1), + resource.TestCheckResourceAttr(resourceName, "allow_major_version_upgrade", "true"), + resource.TestCheckResourceAttr(resourceName, "engine", engine), + resource.TestCheckResourceAttr(resourceName, "engine_version", engineVersion1), + ), + }, + { + Config: testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName, true, engine, engineVersion2, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster2), + resource.TestCheckResourceAttr(resourceName, "allow_major_version_upgrade", "true"), + resource.TestCheckResourceAttr(resourceName, "engine", engine), + resource.TestCheckResourceAttr(resourceName, "engine_version", engineVersion2), + ), + }, + }, + }) +} + +func TestAccAWSRDSCluster_AllowMajorVersionUpgradeWithCustomParameters(t *testing.T) { + var dbCluster1, dbCluster2 rds.DBCluster + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_rds_cluster.test" + // If these hardcoded versions become a maintenance burden, use DescribeDBEngineVersions + // either by having a new data source created or implementing the testing similar + // to TestAccAWSDmsReplicationInstance_EngineVersion + engine := "aurora-postgresql" + engineVersion1 := "10.11" + engineVersion2 := "11.7" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName, true, engine, engineVersion1, false), Check: resource.ComposeTestCheckFunc( testAccCheckAWSClusterExists(resourceName, &dbCluster1), + resource.TestCheckResourceAttr(resourceName, "allow_major_version_upgrade", "true"), resource.TestCheckResourceAttr(resourceName, "engine", engine), resource.TestCheckResourceAttr(resourceName, "engine_version", engineVersion1), ), @@ -241,19 +287,34 @@ func TestAccAWSRDSCluster_OnlyMajorVersion(t *testing.T) { "allow_major_version_upgrade", "apply_immediately", "cluster_identifier_prefix", + "db_instance_parameter_group_name", + "enable_global_write_forwarding", "master_password", "skip_final_snapshot", - "engine_version", }, }, + { + Config: testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName, true, engine, engineVersion2, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster2), + resource.TestCheckResourceAttr(resourceName, "allow_major_version_upgrade", "true"), + resource.TestCheckResourceAttr(resourceName, "engine", engine), + resource.TestCheckResourceAttr(resourceName, "engine_version", engineVersion2), + ), + }, }, }) } -func TestAccAWSRDSCluster_AvailabilityZones(t *testing.T) { - var dbCluster rds.DBCluster +func TestAccAWSRDSCluster_OnlyMajorVersion(t *testing.T) { + var dbCluster1 rds.DBCluster rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_rds_cluster.test" + // If these hardcoded versions become a maintenance burden, use DescribeDBEngineVersions + // either by having a new data source created or implementing the testing similar + // to TestAccAWSDmsReplicationInstance_EngineVersion + engine := "aurora-postgresql" + engineVersion1 := "11" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -262,9 +323,11 @@ func TestAccAWSRDSCluster_AvailabilityZones(t *testing.T) { CheckDestroy: testAccCheckAWSClusterDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSClusterConfig_AvailabilityZones(rName), + Config: testAccAWSClusterConfig_MajorVersionOnly(rName, false, engine, engineVersion1), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSClusterExists(resourceName, &dbCluster), + testAccCheckAWSClusterExists(resourceName, &dbCluster1), + resource.TestCheckResourceAttr(resourceName, "engine", engine), + resource.TestCheckResourceAttr(resourceName, "engine_version", engineVersion1), ), }, { @@ -272,8 +335,12 @@ func TestAccAWSRDSCluster_AvailabilityZones(t *testing.T) { ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{ + "allow_major_version_upgrade", "apply_immediately", "cluster_identifier_prefix", + "db_instance_parameter_group_name", + "enable_global_write_forwarding", + "engine_version", "master_password", "skip_final_snapshot", }, @@ -282,6 +349,27 @@ func TestAccAWSRDSCluster_AvailabilityZones(t *testing.T) { }) } +func TestAccAWSRDSCluster_AvailabilityZones(t *testing.T) { + var dbCluster rds.DBCluster + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_rds_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSClusterConfig_AvailabilityZones(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster), + ), + }, + }, + }) +} + func TestAccAWSRDSCluster_BacktrackWindow(t *testing.T) { var dbCluster rds.DBCluster resourceName := "aws_rds_cluster.test" @@ -306,17 +394,6 @@ func TestAccAWSRDSCluster_BacktrackWindow(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "backtrack_window", "86400"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - }, - }, }, }) } @@ -339,18 +416,6 @@ func TestAccAWSRDSCluster_ClusterIdentifierPrefix(t *testing.T) { resourceName, "cluster_identifier", regexp.MustCompile("^tf-test-")), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -372,17 +437,6 @@ func TestAccAWSRDSCluster_DbSubnetGroupName(t *testing.T) { testAccCheckAWSClusterExists(resourceName, &dbCluster), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - }, - }, }, }) } @@ -407,18 +461,6 @@ func TestAccAWSRDSCluster_s3Restore(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "engine", "aurora"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -495,18 +537,6 @@ func TestAccAWSRDSCluster_generatedName(t *testing.T) { resourceName, "cluster_identifier", regexp.MustCompile("^tf-")), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -528,19 +558,6 @@ func TestAccAWSRDSCluster_takeFinalSnapshot(t *testing.T) { testAccCheckAWSClusterExists(resourceName, &v), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - "final_snapshot_identifier", - }, - }, }, }) } @@ -582,18 +599,6 @@ func TestAccAWSRDSCluster_Tags(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfigTags2(rName, "key1", "value1updated", "key2", "value2"), Check: resource.ComposeTestCheckFunc( @@ -634,18 +639,6 @@ func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_MySQL(t *testing.T) { resource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "audit"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfigEnabledCloudwatchLogsExports2(rName, "slowquery", "error"), Check: resource.ComposeTestCheckFunc( @@ -686,18 +679,6 @@ func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_Postgresql(t *testing.T) resource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "postgresql"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -719,18 +700,6 @@ func TestAccAWSRDSCluster_updateIamRoles(t *testing.T) { testAccCheckAWSClusterExists(resourceName, &v), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfigAddIamRoles(ri), Check: resource.ComposeTestCheckFunc( @@ -769,18 +738,6 @@ func TestAccAWSRDSCluster_kmsKey(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName, "arn"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -805,18 +762,6 @@ func TestAccAWSRDSCluster_encrypted(t *testing.T) { resourceName, "db_cluster_parameter_group_name", "default.aurora5.6"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -839,18 +784,6 @@ func TestAccAWSRDSCluster_copyTagsToSnapshot(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "copy_tags_to_snapshot", "true"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfigWithCopyTagsToSnapshot(rInt, false), Check: resource.ComposeTestCheckFunc( @@ -896,19 +829,6 @@ func TestAccAWSRDSCluster_ReplicationSourceIdentifier_KmsKeyId(t *testing.T) { testAccCheckAWSClusterExistsWithProvider(resourceName2, &replicaCluster, testAccAwsRegionProviderFunc(testAccGetAlternateRegion(), &providers)), ), }, - { - Config: testAccAWSClusterConfigReplicationSourceIdentifierKmsKeyId(rName), - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -936,18 +856,6 @@ func TestAccAWSRDSCluster_backupsUpdate(t *testing.T) { resourceName, "preferred_maintenance_window", "tue:04:00-tue:04:30"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfig_backupsUpdate(ri), Check: resource.ComposeTestCheckFunc( @@ -982,18 +890,6 @@ func TestAccAWSRDSCluster_iamAuth(t *testing.T) { resourceName, "iam_database_authentication_enabled", "true"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1016,18 +912,6 @@ func TestAccAWSRDSCluster_DeletionProtection(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "deletion_protection", "true"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSRDSClusterConfig_DeletionProtection(rName, false), Check: resource.ComposeTestCheckFunc( @@ -1059,18 +943,6 @@ func TestAccAWSRDSCluster_EngineMode(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "scaling_configuration.#", "1"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSRDSClusterConfig_EngineMode(rName, "provisioned"), Check: resource.ComposeTestCheckFunc( @@ -1080,18 +952,6 @@ func TestAccAWSRDSCluster_EngineMode(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "scaling_configuration.#", "0"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1115,18 +975,6 @@ func TestAccAWSRDSCluster_EngineMode_Global(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "engine_mode", "global"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1150,18 +998,6 @@ func TestAccAWSRDSCluster_EngineMode_Multimaster(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "engine_mode", "multimaster"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1185,18 +1021,6 @@ func TestAccAWSRDSCluster_EngineMode_ParallelQuery(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "engine_mode", "parallelquery"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1221,18 +1045,6 @@ func TestAccAWSRDSCluster_EngineVersion(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "engine_version", dataSourceName, "version"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfig_EngineVersion(true, rInt), ExpectError: regexp.MustCompile(`Cannot modify engine version without a healthy primary instance in DB cluster`), @@ -1262,18 +1074,6 @@ func TestAccAWSRDSCluster_EngineVersionWithPrimaryInstance(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "engine_version", dataSourceName, "version"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfig_EngineVersionWithPrimaryInstance(true, rInt), Check: resource.ComposeTestCheckFunc( @@ -1306,18 +1106,6 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_EngineMode_Global(t *testing.T resource.TestCheckResourceAttrPair(resourceName, "global_cluster_identifier", globalClusterResourceName, "id"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1341,18 +1129,6 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_EngineMode_Global_Add(t *testi resource.TestCheckResourceAttr(resourceName, "global_cluster_identifier", ""), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSRDSClusterConfig_GlobalClusterIdentifier_EngineMode_Global(rName), ExpectError: regexp.MustCompile(`Existing RDS Clusters cannot be added to an existing RDS Global Cluster`), @@ -1381,18 +1157,6 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_EngineMode_Global_Remove(t *te resource.TestCheckResourceAttrPair(resourceName, "global_cluster_identifier", globalClusterResourceName, "id"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSRDSClusterConfig_EngineMode_Global(rName), Check: resource.ComposeTestCheckFunc( @@ -1425,18 +1189,6 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_EngineMode_Global_Update(t *te resource.TestCheckResourceAttrPair(resourceName, "global_cluster_identifier", globalClusterResourceName1, "id"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSRDSClusterConfig_GlobalClusterIdentifier_EngineMode_Global_Update(rName, globalClusterResourceName2), ExpectError: regexp.MustCompile(`Existing RDS Clusters cannot be migrated between existing RDS Global Clusters`), @@ -1465,18 +1217,6 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_EngineMode_Provisioned(t *test resource.TestCheckResourceAttrPair(resourceName, "global_cluster_identifier", globalClusterResourceName, "id"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1544,6 +1284,40 @@ func TestAccAWSRDSCluster_GlobalClusterIdentifier_ReplicationSourceIdentifier(t }) } +// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/14457 +func TestAccAWSRDSCluster_GlobalClusterIdentifier_SecondaryClustersWriteForwarding(t *testing.T) { + var providers []*schema.Provider + var primaryDbCluster, secondaryDbCluster rds.DBCluster + + rNameGlobal := acctest.RandomWithPrefix("tf-acc-test-global") + rNamePrimary := acctest.RandomWithPrefix("tf-acc-test-primary") + rNameSecondary := acctest.RandomWithPrefix("tf-acc-test-secondary") + + resourceNamePrimary := "aws_rds_cluster.primary" + resourceNameSecondary := "aws_rds_cluster.secondary" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + testAccMultipleRegionPreCheck(t, 2) + testAccPreCheckAWSRdsGlobalCluster(t) + }, + ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), + ProviderFactories: testAccProviderFactoriesAlternate(&providers), + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRDSClusterConfig_GlobalClusterIdentifier_SecondaryClustersWriteForwarding(rNameGlobal, rNamePrimary, rNameSecondary), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExistsWithProvider(resourceNamePrimary, &primaryDbCluster, testAccAwsRegionProviderFunc(testAccGetRegion(), &providers)), + testAccCheckAWSClusterExistsWithProvider(resourceNameSecondary, &secondaryDbCluster, testAccAwsRegionProviderFunc(testAccGetAlternateRegion(), &providers)), + resource.TestCheckResourceAttr(resourceNameSecondary, "enable_global_write_forwarding", "true"), + ), + }, + }, + }) +} + func TestAccAWSRDSCluster_Port(t *testing.T) { var dbCluster1, dbCluster2 rds.DBCluster rInt := acctest.RandInt() @@ -1562,18 +1336,6 @@ func TestAccAWSRDSCluster_Port(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "port", "5432"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, { Config: testAccAWSClusterConfig_Port(rInt, 2345), Check: resource.ComposeTestCheckFunc( @@ -1621,18 +1383,6 @@ func TestAccAWSRDSCluster_ScalingConfiguration(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "scaling_configuration.0.timeout_action", "ForceApplyCapacityChange"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1662,18 +1412,6 @@ func TestAccAWSRDSCluster_ScalingConfiguration_DefaultMinCapacity(t *testing.T) resource.TestCheckResourceAttr(resourceName, "scaling_configuration.0.timeout_action", "RollbackCapacityChange"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1701,18 +1439,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier(t *testing.T) { testAccCheckAWSClusterExists(resourceName, &dbCluster), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1741,18 +1467,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_DeletionProtection(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "deletion_protection", "true"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, // Ensure we disable deletion protection before attempting to delete :) { Config: testAccAWSRDSClusterConfig_SnapshotIdentifier_DeletionProtection(rName, false), @@ -1791,18 +1505,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EngineMode_ParallelQuery(t *testing resource.TestCheckResourceAttr(resourceName, "engine_mode", "parallelquery"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1831,18 +1533,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EngineMode_Provisioned(t *testing.T resource.TestCheckResourceAttr(resourceName, "engine_mode", "provisioned"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1875,18 +1565,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EngineMode_Serverless(t *testing.T) resource.TestCheckResourceAttr(resourceName, "engine_mode", "serverless"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1917,18 +1595,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EngineVersion_Different(t *testing. resource.TestCheckResourceAttrPair(resourceName, "engine_version", dataSourceName, "version"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -1959,18 +1625,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EngineVersion_Equal(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "engine_version", dataSourceName, "version"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2000,18 +1654,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_KmsKeyId(t *testing.T) { resource.TestCheckResourceAttrPair(resourceName, "kms_key_id", kmsKeyResourceName, "arn"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2040,18 +1682,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_MasterPassword(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "master_password", "password1"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2073,26 +1703,14 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_MasterUsername(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAWSRDSClusterConfig_SnapshotIdentifier_MasterUsername(rName, "username1"), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSClusterExists(sourceDbResourceName, &sourceDbCluster), - testAccCheckDbClusterSnapshotExists(snapshotResourceName, &dbClusterSnapshot), - testAccCheckAWSClusterExists(resourceName, &dbCluster), - resource.TestCheckResourceAttr(resourceName, "master_username", "foo"), - ), - // It is not currently possible to update the master username in the RDS API - ExpectNonEmptyPlan: true, - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(sourceDbResourceName, &sourceDbCluster), + testAccCheckDbClusterSnapshotExists(snapshotResourceName, &dbClusterSnapshot), + testAccCheckAWSClusterExists(resourceName, &dbCluster), + resource.TestCheckResourceAttr(resourceName, "master_username", "foo"), + ), + // It is not currently possible to update the master username in the RDS API + ExpectNonEmptyPlan: true, }, }, }) @@ -2122,18 +1740,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_PreferredBackupWindow(t *testing.T) resource.TestCheckResourceAttr(resourceName, "preferred_backup_window", "00:00-08:00"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2162,18 +1768,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_PreferredMaintenanceWindow(t *testi resource.TestCheckResourceAttr(resourceName, "preferred_maintenance_window", "sun:01:00-sun:01:30"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2203,18 +1797,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_Tags(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2242,18 +1824,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_VpcSecurityGroupIds(t *testing.T) { testAccCheckAWSClusterExists(resourceName, &dbCluster), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2287,18 +1857,6 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_VpcSecurityGroupIds_Tags(t *testing resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), ), }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, }, }) } @@ -2329,17 +1887,35 @@ func TestAccAWSRDSCluster_SnapshotIdentifier_EncryptedRestore(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "storage_encrypted", "true"), ), }, + }, + }) +} + +func TestAccAWSRDSCluster_EnableHttpEndpoint(t *testing.T) { + var dbCluster rds.DBCluster + + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_rds_cluster.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSRDSClusterConfig_EnableHttpEndpoint(rName, true), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster), + resource.TestCheckResourceAttr(resourceName, "enable_http_endpoint", "true"), + ), + }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, + Config: testAccAWSRDSClusterConfig_EnableHttpEndpoint(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists(resourceName, &dbCluster), + resource.TestCheckResourceAttr(resourceName, "enable_http_endpoint", "false"), + ), }, }, }) @@ -2480,48 +2056,6 @@ func testAccCheckAWSClusterRecreated(i, j *rds.DBCluster) resource.TestCheckFunc } } -func TestAccAWSRDSCluster_EnableHttpEndpoint(t *testing.T) { - var dbCluster rds.DBCluster - - rName := acctest.RandomWithPrefix("tf-acc-test") - resourceName := "aws_rds_cluster.test" - - resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ErrorCheck: testAccErrorCheck(t, rds.EndpointsID), - Providers: testAccProviders, - CheckDestroy: testAccCheckAWSClusterDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAWSRDSClusterConfig_EnableHttpEndpoint(rName, true), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSClusterExists(resourceName, &dbCluster), - resource.TestCheckResourceAttr(resourceName, "enable_http_endpoint", "true"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "apply_immediately", - "cluster_identifier_prefix", - "master_password", - "skip_final_snapshot", - "snapshot_identifier", - }, - }, - { - Config: testAccAWSRDSClusterConfig_EnableHttpEndpoint(rName, false), - Check: resource.ComposeTestCheckFunc( - testAccCheckAWSClusterExists(resourceName, &dbCluster), - resource.TestCheckResourceAttr(resourceName, "enable_http_endpoint", "false"), - ), - }, - }, - }) -} - func testAccAWSClusterConfig(rName string) string { return fmt.Sprintf(` resource "aws_rds_cluster" "test" { @@ -2569,6 +2103,62 @@ resource "aws_rds_cluster_instance" "test" { `, allowMajorVersionUpgrade, rName, engine, engineVersion) } +func testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName string, allowMajorVersionUpgrade bool, engine string, engineVersion string, applyImmediate bool) string { + return fmt.Sprintf(` +resource "aws_rds_cluster" "test" { + allow_major_version_upgrade = %[1]t + apply_immediately = true + cluster_identifier = %[2]q + db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.test.name + db_instance_parameter_group_name = aws_db_parameter_group.test.name + engine = %[3]q + engine_version = %[4]q + master_password = "mustbeeightcharaters" + master_username = "test" + skip_final_snapshot = true +} + +data "aws_rds_orderable_db_instance" "test" { + engine = aws_rds_cluster.test.engine + engine_version = aws_rds_cluster.test.engine_version + preferred_instance_classes = ["db.t3.medium", "db.r5.large", "db.r6g.large"] +} + +# Upgrading requires a healthy primary instance +resource "aws_rds_cluster_instance" "test" { + apply_immediately = %[5]t + cluster_identifier = aws_rds_cluster.test.id + db_parameter_group_name = aws_db_parameter_group.test.name + engine = data.aws_rds_orderable_db_instance.test.engine + engine_version = data.aws_rds_orderable_db_instance.test.engine_version + identifier = %[2]q + instance_class = data.aws_rds_orderable_db_instance.test.instance_class + + lifecycle { + ignore_changes = [engine_version] + } +} + +resource "aws_rds_cluster_parameter_group" "test" { + name_prefix = %[2]q + family = %[6]q + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_db_parameter_group" "test" { + name_prefix = %[2]q + family = %[6]q + + lifecycle { + create_before_destroy = true + } +} +`, allowMajorVersionUpgrade, rName, engine, engineVersion, applyImmediate, engine+strings.Split(engineVersion, ".")[0]) +} + func testAccAWSClusterConfig_MajorVersionOnly(rName string, allowMajorVersionUpgrade bool, engine string, engineVersion string) string { return fmt.Sprintf(` resource "aws_rds_cluster" "test" { @@ -3783,6 +3373,104 @@ resource "aws_rds_cluster_instance" "secondary" { `, rNameGlobal, rNamePrimary, rNameSecondary)) } +func testAccAWSRDSClusterConfig_GlobalClusterIdentifier_SecondaryClustersWriteForwarding(rNameGlobal, rNamePrimary, rNameSecondary string) string { + return composeConfig( + testAccMultipleRegionProviderConfig(2), + fmt.Sprintf(` +data "aws_region" "current" {} + +data "aws_availability_zones" "alternate" { + provider = "awsalternate" + state = "available" + + filter { + name = "opt-in-status" + values = ["opt-in-not-required"] + } +} + +resource "aws_rds_global_cluster" "test" { + global_cluster_identifier = "%[1]s" + engine = "aurora-mysql" + engine_version = "5.7.mysql_aurora.2.08.1" +} + +resource "aws_rds_cluster" "primary" { + cluster_identifier = "%[2]s" + database_name = "mydb" + master_username = "foo" + master_password = "barbarbar" + skip_final_snapshot = true + global_cluster_identifier = aws_rds_global_cluster.test.id + engine = aws_rds_global_cluster.test.engine + engine_version = aws_rds_global_cluster.test.engine_version +} + +resource "aws_rds_cluster_instance" "primary" { + identifier = "%[2]s" + cluster_identifier = aws_rds_cluster.primary.id + instance_class = "db.r4.large" # only db.r4 or db.r5 are valid for Aurora global db + engine = aws_rds_cluster.primary.engine + engine_version = aws_rds_cluster.primary.engine_version +} + +resource "aws_vpc" "alternate" { + provider = "awsalternate" + cidr_block = "10.0.0.0/16" + + tags = { + Name = "%[3]s" + } +} + +resource "aws_subnet" "alternate" { + provider = "awsalternate" + count = 3 + vpc_id = aws_vpc.alternate.id + availability_zone = data.aws_availability_zones.alternate.names[count.index] + cidr_block = "10.0.${count.index}.0/24" + + tags = { + Name = "%[3]s" + } +} + +resource "aws_db_subnet_group" "alternate" { + provider = "awsalternate" + name = "%[3]s" + subnet_ids = aws_subnet.alternate[*].id +} + +resource "aws_rds_cluster" "secondary" { + provider = "awsalternate" + cluster_identifier = "%[3]s" + db_subnet_group_name = aws_db_subnet_group.alternate.name + skip_final_snapshot = true + source_region = data.aws_region.current.name + global_cluster_identifier = aws_rds_global_cluster.test.id + enable_global_write_forwarding = true + engine = aws_rds_global_cluster.test.engine + engine_version = aws_rds_global_cluster.test.engine_version + depends_on = [aws_rds_cluster_instance.primary] + + lifecycle { + ignore_changes = [ + replication_source_identifier, + ] + } +} + +resource "aws_rds_cluster_instance" "secondary" { + provider = "awsalternate" + identifier = "%[3]s" + cluster_identifier = aws_rds_cluster.secondary.id + instance_class = "db.r4.large" # only db.r4 or db.r5 are valid for Aurora global db + engine = aws_rds_cluster.secondary.engine + engine_version = aws_rds_cluster.secondary.engine_version +} +`, rNameGlobal, rNamePrimary, rNameSecondary)) +} + func testAccAWSRDSClusterConfig_GlobalClusterIdentifier_ReplicationSourceIdentifier(rName string) string { return composeConfig( testAccMultipleRegionProviderConfig(2), diff --git a/website/docs/r/rds_cluster.html.markdown b/website/docs/r/rds_cluster.html.markdown index d30318a02a1..09a8aafcee2 100644 --- a/website/docs/r/rds_cluster.html.markdown +++ b/website/docs/r/rds_cluster.html.markdown @@ -98,7 +98,10 @@ resource "aws_rds_cluster" "example" { ## Argument Reference For more detailed documentation about each argument, refer to -the [AWS official documentation](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-cluster.html). +the AWS official documentation : + +* [create-db-cluster](https://docs.aws.amazon.com/cli/latest/reference/rds/create-db-cluster.html). +* [modify-db-cluster](https://docs.aws.amazon.com/cli/latest/reference/rds/modify-db-cluster.html) The following arguments are supported: @@ -112,6 +115,7 @@ The following arguments are supported: * `copy_tags_to_snapshot` – (Optional, boolean) Copy all Cluster `tags` to snapshots. Default is `false`. * `database_name` - (Optional) Name for an automatically created database on cluster creation. There are different naming restrictions per database engine: [RDS Naming Constraints][5] * `db_cluster_parameter_group_name` - (Optional) A cluster parameter group to associate with the cluster. +* `db_instance_parameter_group_name` - (Optional) Instance parameter group to associate with all instances of the DB cluster. The `db_instance_parameter_group_name` parameter is only valid in combination with the `allow_major_version_upgrade` parameter. * `db_subnet_group_name` - (Optional) A DB subnet group to associate with this DB instance. **NOTE:** This must match the `db_subnet_group_name` specified on every [`aws_rds_cluster_instance`](/docs/providers/aws/r/rds_cluster_instance.html) in the cluster. * `deletion_protection` - (Optional) If the DB instance should have deletion protection enabled. The database can't be deleted when this value is set to `true`. The default is `false`. * `enable_http_endpoint` - (Optional) Enable HTTP endpoint (data API). Only valid when `engine_mode` is set to `serverless`. @@ -121,6 +125,7 @@ The following arguments are supported: * `engine_version` - (Optional) The database engine version. Updating this argument results in an outage. See the [Aurora MySQL](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.html) and [Aurora Postgres](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.html) documentation for your configured engine to determine this value. For example with Aurora MySQL 2, a potential value for this argument is `5.7.mysql_aurora.2.03.2`. The value can contain a partial version where supported by the API. The actual engine version used is returned in the attribute `engine_version_actual`, [defined below](#engine_version_actual). * `final_snapshot_identifier` - (Optional) The name of your final DB snapshot when this DB cluster is deleted. If omitted, no final snapshot will be made. * `global_cluster_identifier` - (Optional) The global cluster identifier specified on [`aws_rds_global_cluster`](/docs/providers/aws/r/rds_global_cluster.html). +* `enable_global_write_forwarding` - (Optional) Whether cluster should forward writes to an associated global cluster. Applied to secondary clusters to enable them to forward writes to an [`aws_rds_global_cluster`](/docs/providers/aws/r/rds_global_cluster.html)'s primary cluster. See the [Aurora Userguide documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database-write-forwarding.html) for more information. * `iam_database_authentication_enabled` - (Optional) Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled. Please see [AWS Documentation](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.IAMDBAuth.html) for availability and limitations. * `iam_roles` - (Optional) A List of ARNs for the IAM roles to associate to the RDS Cluster. * `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `storage_encrypted` needs to be set to true. diff --git a/website/docs/r/rds_cluster_instance.html.markdown b/website/docs/r/rds_cluster_instance.html.markdown index 77758ca777a..42d60242fcc 100644 --- a/website/docs/r/rds_cluster_instance.html.markdown +++ b/website/docs/r/rds_cluster_instance.html.markdown @@ -58,7 +58,7 @@ The following arguments are supported: For information on the difference between the available Aurora MySQL engines see [Comparison between Aurora MySQL 1 and Aurora MySQL 2](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/AuroraMySQL.Updates.20180206.html) in the Amazon RDS User Guide. -* `engine_version` - (Optional, Forces new resource) The database engine version. When managing the engine version in the cluster, it is recommended to add the [lifecycle `ignore_changes` configuration](https://www.terraform.io/docs/configuration/meta-arguments/lifecycle.html#ignore_changes) for this argument to prevent Terraform from proposing changes to the instance engine version directly. +* `engine_version` - (Optional) The database engine version. * `instance_class` - (Required) The instance class to use. For details on CPU and memory, see [Scaling Aurora DB Instances][4]. Aurora uses `db.*` instance classes/types. Please see [AWS Documentation][7] for currently available instance classes and complete details. * `publicly_accessible` - (Optional) Bool to control if instance is publicly accessible. @@ -80,7 +80,8 @@ what IAM permissions are needed to allow Enhanced Monitoring for RDS Instances. Syntax: "ddd:hh24:mi-ddd:hh24:mi". Eg: "Mon:00:00-Mon:03:00". * `auto_minor_version_upgrade` - (Optional) Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window. Default `true`. * `performance_insights_enabled` - (Optional) Specifies whether Performance Insights is enabled or not. -* `performance_insights_kms_key_id` - (Optional) The ARN for the KMS key to encrypt Performance Insights data. When specifying `performance_insights_kms_key_id`, `performance_insights_enabled` needs to be set to true. +* `performance_insights_kms_key_id` - (Optional) ARN for the KMS key to encrypt Performance Insights data. When specifying `performance_insights_kms_key_id`, `performance_insights_enabled` needs to be set to true. +* `performance_insights_retention_period` - (Optional) Amount of time in days to retain Performance Insights data. Either 7 (7 days) or 731 (2 years). When specifying `performance_insights_retention_period`, `performance_insights_enabled` needs to be set to true. Defaults to '7'. * `copy_tags_to_snapshot` – (Optional, boolean) Indicates whether to copy all of the user-defined tags from the DB instance to snapshots of the DB instance. Default `false`. * `ca_cert_identifier` - (Optional) The identifier of the CA certificate for the DB instance. * `tags` - (Optional) A map of tags to assign to the instance. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.