From 67979a70684770695514cfd0d81c7342782bad54 Mon Sep 17 00:00:00 2001 From: Gregory DEPUILLE Date: Tue, 13 Apr 2021 16:00:58 +0200 Subject: [PATCH] Allow upgrade major version on RDS Aurora when use custom parameter groups --- .changelog/18820.txt | 7 ++ aws/resource_aws_rds_cluster.go | 11 ++ aws/resource_aws_rds_cluster_instance.go | 1 - aws/resource_aws_rds_cluster_test.go | 107 ++++++++++++++++++ website/docs/r/rds_cluster.html.markdown | 6 +- .../docs/r/rds_cluster_instance.html.markdown | 2 +- 6 files changed, 131 insertions(+), 3 deletions(-) create mode 100644 .changelog/18820.txt diff --git a/.changelog/18820.txt b/.changelog/18820.txt new file mode 100644 index 00000000000..0b5367f4533 --- /dev/null +++ b/.changelog/18820.txt @@ -0,0 +1,7 @@ +```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 when use custom parameter groups. +``` \ No newline at end of file diff --git a/aws/resource_aws_rds_cluster.go b/aws/resource_aws_rds_cluster.go index 5f8fa630356..85832a3e0c0 100644 --- a/aws/resource_aws_rds_cluster.go +++ b/aws/resource_aws_rds_cluster.go @@ -117,6 +117,12 @@ func resourceAwsRDSCluster() *schema.Resource { Computed: true, }, + "db_instance_parameter_group_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "deletion_protection": { Type: schema.TypeBool, Optional: true, @@ -1197,6 +1203,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("deletion_protection") { req.DeletionProtection = aws.Bool(d.Get("deletion_protection").(bool)) requestUpdate = true diff --git a/aws/resource_aws_rds_cluster_instance.go b/aws/resource_aws_rds_cluster_instance.go index 2d24257e537..67c0932f791 100644 --- a/aws/resource_aws_rds_cluster_instance.go +++ b/aws/resource_aws_rds_cluster_instance.go @@ -102,7 +102,6 @@ func resourceAwsRDSClusterInstance() *schema.Resource { "engine_version": { Type: schema.TypeString, Optional: true, - ForceNew: true, Computed: true, }, diff --git a/aws/resource_aws_rds_cluster_test.go b/aws/resource_aws_rds_cluster_test.go index b3c26ebb887..b4613aacc06 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" @@ -209,6 +210,58 @@ func TestAccAWSRDSCluster_AllowMajorVersionUpgrade(t *testing.T) { }) } +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 := "11.9" + engineVersion2 := "12.4" + + 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), + 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), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "allow_major_version_upgrade", + "apply_immediately", + "cluster_identifier_prefix", + "master_password", + "skip_final_snapshot", + "db_instance_parameter_group_name", + }, + }, + { + Config: testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName, true, engine, engineVersion2), + 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_OnlyMajorVersion(t *testing.T) { var dbCluster1 rds.DBCluster rName := acctest.RandomWithPrefix("tf-acc-test") @@ -2569,6 +2622,60 @@ resource "aws_rds_cluster_instance" "test" { `, allowMajorVersionUpgrade, rName, engine, engineVersion) } +func testAccAWSClusterConfig_AllowMajorVersionUpgradeWithCustomParameters(rName string, allowMajorVersionUpgrade bool, engine string, engineVersion string) string { + return fmt.Sprintf(` +resource "aws_rds_cluster" "test" { + allow_major_version_upgrade = %[1]t + apply_immediately = true + cluster_identifier = %[2]q + engine = %[3]q + engine_version = %[4]q + master_password = "mustbeeightcharaters" + master_username = "test" + db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.cluster_parameters.name + db_instance_parameter_group_name = aws_db_parameter_group.db_parameters.name + 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 = true + cluster_identifier = aws_rds_cluster.test.id + 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 + db_parameter_group_name = aws_db_parameter_group.db_parameters.name +} + +# Custom cluster parameter group +resource "aws_rds_cluster_parameter_group" "cluster_parameters" { + name_prefix = %[2]q + family = %[5]q + + lifecycle { + create_before_destroy = true + } +} + +# Custom instance parameter group +resource "aws_db_parameter_group" "db_parameters" { + name_prefix = %[2]q + family = %[5]q + + lifecycle { + create_before_destroy = true + } +} +`, allowMajorVersionUpgrade, rName, engine, engineVersion, 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" { diff --git a/website/docs/r/rds_cluster.html.markdown b/website/docs/r/rds_cluster.html.markdown index d30318a02a1..24cf9215a60 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) An instance parameter group to associate to all instances of the DB cluster. This 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`. diff --git a/website/docs/r/rds_cluster_instance.html.markdown b/website/docs/r/rds_cluster_instance.html.markdown index 77758ca777a..5a325f166a9 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.