diff --git a/aws/resource_aws_db_instance.go b/aws/resource_aws_db_instance.go index 1d4dee37a517..a90bfd175503 100644 --- a/aws/resource_aws_db_instance.go +++ b/aws/resource_aws_db_instance.go @@ -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, @@ -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 { @@ -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 { @@ -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 { @@ -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 } @@ -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) diff --git a/aws/resource_aws_db_instance_test.go b/aws/resource_aws_db_instance_test.go index e1571350fc2d..fa96a0a8e11e 100644 --- a/aws/resource_aws_db_instance_test.go +++ b/aws/resource_aws_db_instance_test.go @@ -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() { @@ -2292,9 +2292,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{ @@ -2305,43 +2305,37 @@ func TestAccAWSDBInstance_cloudwatchLogsExportConfigurationUpdate(t *testing.T) { Config: testAccAWSDBInstanceConfigCloudwatchLogsExportConfiguration(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: testAccAWSDBInstanceConfigCloudwatchLogsExportConfigurationAdd(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: testAccAWSDBInstanceConfigCloudwatchLogsExportConfigurationModify(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: testAccAWSDBInstanceConfigCloudwatchLogsExportConfigurationDelete(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"), ), }, }, diff --git a/aws/resource_aws_rds_cluster.go b/aws/resource_aws_rds_cluster.go index 7fb2db4b8af6..2deb18da6014 100644 --- a/aws/resource_aws_rds_cluster.go +++ b/aws/resource_aws_rds_cluster.go @@ -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, @@ -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 { @@ -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 { @@ -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 { @@ -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 } diff --git a/aws/resource_aws_rds_cluster_test.go b/aws/resource_aws_rds_cluster_test.go index 8e2ca72e1667..a5b435ede8c0 100644 --- a/aws/resource_aws_rds_cluster_test.go +++ b/aws/resource_aws_rds_cluster_test.go @@ -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() { @@ -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" @@ -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"), ), }, { @@ -529,12 +529,12 @@ 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"), ), }, { @@ -542,17 +542,43 @@ func TestAccAWSRDSCluster_EnabledCloudwatchLogsExports(t *testing.T) { 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", + }, + }, }, }) } diff --git a/website/docs/r/db_instance.html.markdown b/website/docs/r/db_instance.html.markdown index 0fab0c57ed88..9ea37c9d2dfa 100644 --- a/website/docs/r/db_instance.html.markdown +++ b/website/docs/r/db_instance.html.markdown @@ -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'. diff --git a/website/docs/r/rds_cluster.html.markdown b/website/docs/r/rds_cluster.html.markdown index 674e1b17d983..0064ccf50f64 100644 --- a/website/docs/r/rds_cluster.html.markdown +++ b/website/docs/r/rds_cluster.html.markdown @@ -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`