Skip to content

Commit

Permalink
service/rds: Prevent ordering differences with enabled_cloudwatch_log…
Browse files Browse the repository at this point in the history
…s_exports arguments (#15404)

* service/rds: Prevent ordering differences with enabled_cloudwatch_logs_exports arguments

Reference: #6799

Changes:

```
* resource/aws_db_instance: Prevent ordering differences with `enabled_cloudwatch_logs_exports` argument
* resource/aws_rds_cluster: Prevent ordering differences with `enabled_cloudwatch_logs_exports` argument
```

Output from acceptance testing:

```
--- PASS: TestAccAWSDBInstance_EnabledCloudwatchLogsExports_Postgresql (552.53s)
--- PASS: TestAccAWSDBInstance_EnabledCloudwatchLogsExports_MSSQL (742.59s)
--- PASS: TestAccAWSDBInstance_EnabledCloudwatchLogsExports_Oracle (805.86s)
--- PASS: TestAccAWSDBInstance_EnabledCloudwatchLogsExports_MySQL (828.42s)

--- PASS: TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_Postgresql (133.14s)
--- PASS: TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_MySQL (243.49s)
```

* docs/service/rds: List -> Set for enabled_cloudwatch_logs_exports arguments
  • Loading branch information
bflad committed Sep 30, 2020
1 parent a71d27a commit e903501
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 72 deletions.
40 changes: 18 additions & 22 deletions aws/resource_aws_db_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func resourceAwsDbInstance() *schema.Resource {
},

"enabled_cloudwatch_logs_exports": {
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -571,8 +571,8 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.DBSubnetGroupName = aws.String(attr.(string))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
opts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
opts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOk("iam_database_authentication_enabled"); ok {
Expand Down Expand Up @@ -905,8 +905,8 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.DomainIAMRoleName = aws.String(attr.(string))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
opts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
opts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOk("engine"); ok {
Expand Down Expand Up @@ -1116,8 +1116,8 @@ func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error
opts.DBSubnetGroupName = aws.String(attr.(string))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
opts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
opts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOk("iops"); ok {
Expand Down Expand Up @@ -1584,7 +1584,17 @@ func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error
}

if d.HasChange("enabled_cloudwatch_logs_exports") {
req.CloudwatchLogsExportConfiguration = buildCloudwatchLogsExportConfiguration(d)
oraw, nraw := d.GetChange("enabled_cloudwatch_logs_exports")
o := oraw.(*schema.Set)
n := nraw.(*schema.Set)

enable := n.Difference(o)
disable := o.Difference(n)

req.CloudwatchLogsExportConfiguration = &rds.CloudwatchLogsExportConfiguration{
EnableLogTypes: expandStringSet(enable),
DisableLogTypes: expandStringSet(disable),
}
requestUpdate = true
}

Expand Down Expand Up @@ -1738,20 +1748,6 @@ func resourceAwsDbInstanceStateRefreshFunc(id string, conn *rds.RDS) resource.St
}
}

func buildCloudwatchLogsExportConfiguration(d *schema.ResourceData) *rds.CloudwatchLogsExportConfiguration {

oraw, nraw := d.GetChange("enabled_cloudwatch_logs_exports")
o := oraw.([]interface{})
n := nraw.([]interface{})

create, disable := diffCloudwatchLogsExportConfiguration(o, n)

return &rds.CloudwatchLogsExportConfiguration{
EnableLogTypes: expandStringList(create),
DisableLogTypes: expandStringList(disable),
}
}

func diffCloudwatchLogsExportConfiguration(old, new []interface{}) ([]interface{}, []interface{}) {
create := make([]interface{}, 0)
disable := make([]interface{}, 0)
Expand Down
48 changes: 21 additions & 27 deletions aws/resource_aws_db_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"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/terraform"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfawsresource"
)

func init() {
Expand Down Expand Up @@ -2289,9 +2289,9 @@ func TestAccAWSDBInstance_cloudwatchLogsExportConfiguration(t *testing.T) {
})
}

func TestAccAWSDBInstance_cloudwatchLogsExportConfigurationUpdate(t *testing.T) {
func TestAccAWSDBInstance_EnabledCloudwatchLogsExports_MySQL(t *testing.T) {
var v rds.DBInstance

resourceName := "aws_db_instance.bar"
rInt := acctest.RandInt()

resource.ParallelTest(t, resource.TestCase{
Expand All @@ -2302,43 +2302,37 @@ func TestAccAWSDBInstance_cloudwatchLogsExportConfigurationUpdate(t *testing.T)
{
Config: testAccAWSDBInstanceConfig_CloudwatchLogsExportConfiguration(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.0", "audit"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.1", "error"),
testAccCheckAWSDBInstanceExists(resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "2"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "audit"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "error"),
),
},
{
Config: testAccAWSDBInstanceConfig_CloudwatchLogsExportConfigurationAdd(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.0", "audit"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.1", "error"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.2", "general"),
testAccCheckAWSDBInstanceExists(resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "3"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "audit"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "error"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "general"),
),
},
{
Config: testAccAWSDBInstanceConfig_CloudwatchLogsExportConfigurationModify(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.0", "audit"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.1", "general"),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.2", "slowquery"),
testAccCheckAWSDBInstanceExists(resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "3"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "audit"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "general"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "slowquery"),
),
},
{
Config: testAccAWSDBInstanceConfig_CloudwatchLogsExportConfigurationDelete(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSDBInstanceExists("aws_db_instance.bar", &v),
resource.TestCheckResourceAttr(
"aws_db_instance.bar", "enabled_cloudwatch_logs_exports.#", "0"),
testAccCheckAWSDBInstanceExists(resourceName, &v),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "0"),
),
},
},
Expand Down
26 changes: 18 additions & 8 deletions aws/resource_aws_rds_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ func resourceAwsRDSCluster() *schema.Resource {
},

"enabled_cloudwatch_logs_exports": {
Type: schema.TypeList,
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -490,8 +490,8 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error
opts.DBSubnetGroupName = aws.String(attr.(string))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
opts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
opts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOk("engine_version"); ok {
Expand Down Expand Up @@ -623,8 +623,8 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error
createOpts.EnableIAMDatabaseAuthentication = aws.Bool(attr.(bool))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
createOpts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
createOpts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOkExists("storage_encrypted"); ok {
Expand Down Expand Up @@ -752,8 +752,8 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error
createOpts.EnableIAMDatabaseAuthentication = aws.Bool(attr.(bool))
}

if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && len(attr.([]interface{})) > 0 {
createOpts.EnableCloudwatchLogsExports = expandStringList(attr.([]interface{}))
if attr, ok := d.GetOk("enabled_cloudwatch_logs_exports"); ok && attr.(*schema.Set).Len() > 0 {
createOpts.EnableCloudwatchLogsExports = expandStringSet(attr.(*schema.Set))
}

if attr, ok := d.GetOk("replication_source_identifier"); ok && createOpts.GlobalClusterIdentifier == nil {
Expand Down Expand Up @@ -1051,7 +1051,17 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error
}

if d.HasChange("enabled_cloudwatch_logs_exports") {
req.CloudwatchLogsExportConfiguration = buildCloudwatchLogsExportConfiguration(d)
oraw, nraw := d.GetChange("enabled_cloudwatch_logs_exports")
o := oraw.(*schema.Set)
n := nraw.(*schema.Set)

enable := n.Difference(o)
disable := o.Difference(n)

req.CloudwatchLogsExportConfiguration = &rds.CloudwatchLogsExportConfiguration{
EnableLogTypes: expandStringSet(enable),
DisableLogTypes: expandStringSet(disable),
}
requestUpdate = true
}

Expand Down
52 changes: 39 additions & 13 deletions aws/resource_aws_rds_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"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/terraform"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/tfawsresource"
)

func init() {
Expand Down Expand Up @@ -498,8 +498,8 @@ func TestAccAWSRDSCluster_Tags(t *testing.T) {
})
}

func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports(t *testing.T) {
var dbCluster1, dbCluster2, dbCluster3, dbCluster4 rds.DBCluster
func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_MySQL(t *testing.T) {
var dbCluster1, dbCluster2, dbCluster3 rds.DBCluster
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_rds_cluster.test"

Expand All @@ -513,7 +513,7 @@ func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists(resourceName, &dbCluster1),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.0", "audit"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "audit"),
),
},
{
Expand All @@ -529,30 +529,56 @@ func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports(t *testing.T) {
},
},
{
Config: testAccAWSClusterConfigEnabledCloudwatchLogsExports2(rName, "error", "slowquery"),
Config: testAccAWSClusterConfigEnabledCloudwatchLogsExports2(rName, "slowquery", "error"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists(resourceName, &dbCluster2),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "2"),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.0", "error"),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.1", "slowquery"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "error"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "slowquery"),
),
},
{
Config: testAccAWSClusterConfigEnabledCloudwatchLogsExports1(rName, "error"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists(resourceName, &dbCluster3),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.0", "error"),
tfawsresource.TestCheckTypeSetElemAttr(resourceName, "enabled_cloudwatch_logs_exports.*", "error"),
),
},
},
})
}

func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports_Postgresql(t *testing.T) {
var dbCluster1 rds.DBCluster
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_rds_cluster.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSClusterConfigEnabledCloudwatchLogsExportsPostgres1(rName, "postgresql"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists(resourceName, &dbCluster4),
testAccCheckAWSClusterExists(resourceName, &dbCluster1),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.#", "1"),
resource.TestCheckResourceAttr(resourceName, "enabled_cloudwatch_logs_exports.0", "postgresql"),
tfawsresource.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",
},
},
},
})
}
Expand Down
2 changes: 1 addition & 1 deletion website/docs/r/db_instance.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ for additional read replica contraints.
* `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`.
* `domain` - (Optional) The ID of the Directory Service Active Directory domain to create the instance in.
* `domain_iam_role_name` - (Optional, but required if domain is provided) The name of the IAM role to be used when making API calls to the Directory Service.
* `enabled_cloudwatch_logs_exports` - (Optional) List of log types to enable for exporting to CloudWatch logs. If omitted, no logs will be exported. Valid values (depending on `engine`). MySQL and MariaDB: `audit`, `error`, `general`, `slowquery`. PostgreSQL: `postgresql`, `upgrade`. MSSQL: `agent` , `error`. Oracle: `alert`, `audit`, `listener`, `trace`.
* `enabled_cloudwatch_logs_exports` - (Optional) Set of log types to enable for exporting to CloudWatch logs. If omitted, no logs will be exported. Valid values (depending on `engine`). MySQL and MariaDB: `audit`, `error`, `general`, `slowquery`. PostgreSQL: `postgresql`, `upgrade`. MSSQL: `agent` , `error`. Oracle: `alert`, `audit`, `listener`, `trace`.
* `engine` - (Required unless a `snapshot_identifier` or `replicate_source_db`
is provided) The database engine to use. For supported values, see the Engine parameter in [API action CreateDBInstance](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBInstance.html).
Note that for Amazon Aurora instances the engine must match the [DB cluster](/docs/providers/aws/r/rds_cluster.html)'s engine'.
Expand Down
2 changes: 1 addition & 1 deletion website/docs/r/rds_cluster.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The following arguments are supported:
* `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`.
* `enabled_cloudwatch_logs_exports` - (Optional) List of log types to export to cloudwatch. If omitted, no logs will be exported. The following log types are supported: `audit`, `error`, `general`, `slowquery`, `postgresql` (PostgreSQL).
* `enabled_cloudwatch_logs_exports` - (Optional) Set of log types to export to cloudwatch. If omitted, no logs will be exported. The following log types are supported: `audit`, `error`, `general`, `slowquery`, `postgresql` (PostgreSQL).
* `engine_mode` - (Optional) The database engine mode. Valid values: `global`, `multimaster`, `parallelquery`, `provisioned`, `serverless`. Defaults to: `provisioned`. See the [RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/aurora-serverless.html) for limitations when using `serverless`.
* `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`.
* `engine` - (Optional) The name of the database engine to be used for this DB cluster. Defaults to `aurora`. Valid Values: `aurora`, `aurora-mysql`, `aurora-postgresql`
Expand Down

0 comments on commit e903501

Please sign in to comment.