diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index df737555b..1c61db81b 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -225,6 +225,7 @@ func Provider() terraform.ResourceProvider { "aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(), "aws_rds_cluster": resourceAwsRDSCluster(), "aws_rds_cluster_instance": resourceAwsRDSClusterInstance(), + "aws_rds_cluster_parameter_group": resourceAwsRDSClusterParameterGroup(), "aws_redshift_cluster": resourceAwsRedshiftCluster(), "aws_redshift_security_group": resourceAwsRedshiftSecurityGroup(), "aws_redshift_parameter_group": resourceAwsRedshiftParameterGroup(), diff --git a/builtin/providers/aws/resource_aws_rds_cluster.go b/builtin/providers/aws/resource_aws_rds_cluster.go index 2d2b0fdf4..06104082e 100644 --- a/builtin/providers/aws/resource_aws_rds_cluster.go +++ b/builtin/providers/aws/resource_aws_rds_cluster.go @@ -61,6 +61,12 @@ func resourceAwsRDSCluster() *schema.Resource { Computed: true, }, + "parameter_group_name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "endpoint": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -189,6 +195,10 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error createOpts.DBSubnetGroupName = aws.String(attr.(string)) } + if attr, ok := d.GetOk("parameter_group_name"); ok { + createOpts.DBClusterParameterGroupName = aws.String(attr.(string)) + } + if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { createOpts.VpcSecurityGroupIds = expandStringList(attr.List()) } @@ -280,6 +290,7 @@ func resourceAwsRDSClusterRead(d *schema.ResourceData, meta interface{}) error { } d.Set("db_subnet_group_name", dbc.DBSubnetGroup) + d.Set("parameter_group_name", dbc.DBClusterParameterGroup) d.Set("endpoint", dbc.Endpoint) d.Set("engine", dbc.Engine) d.Set("master_username", dbc.MasterUsername) @@ -340,6 +351,11 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error req.BackupRetentionPeriod = aws.Int64(int64(d.Get("backup_retention_period").(int))) } + if d.HasChange("parameter_group_name") { + d.SetPartial("parameter_group_name") + req.DBClusterParameterGroupName = aws.String(d.Get("parameter_group_name").(string)) + } + _, err := conn.ModifyDBCluster(req) if err != nil { return fmt.Errorf("[WARN] Error modifying RDS Cluster (%s): %s", d.Id(), err) diff --git a/builtin/providers/aws/resource_aws_rds_cluster_parameter_group.go b/builtin/providers/aws/resource_aws_rds_cluster_parameter_group.go new file mode 100644 index 000000000..aa193037a --- /dev/null +++ b/builtin/providers/aws/resource_aws_rds_cluster_parameter_group.go @@ -0,0 +1,274 @@ +package aws + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/iam" + "github.com/aws/aws-sdk-go/service/rds" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsRDSClusterParameterGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsRDSClusterParameterGroupCreate, + Read: resourceAwsRDSClusterParameterGroupRead, + Update: resourceAwsRDSClusterParameterGroupUpdate, + Delete: resourceAwsRDSClusterParameterGroupDelete, + Schema: map[string]*schema.Schema{ + "arn": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Required: true, + ValidateFunc: validateDbParamGroupName, + }, + "family": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "description": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "parameter": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + ForceNew: false, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "value": &schema.Schema{ + Type: schema.TypeString, + Required: true, + }, + "apply_method": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Default: "immediate", + // this parameter is not actually state, but a + // meta-parameter describing how the RDS API call + // to modify the parameter group should be made. + // Future reads of the resource from AWS don't tell + // us what we used for apply_method previously, so + // by squashing state to an empty string we avoid + // needing to do an update for every future run. + StateFunc: func(interface{}) string { return "" }, + }, + }, + }, + Set: resourceAwsDbParameterHash, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceAwsRDSClusterParameterGroupCreate(d *schema.ResourceData, meta interface{}) error { + rdsconn := meta.(*AWSClient).rdsconn + tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) + + createOpts := rds.CreateDBClusterParameterGroupInput{ + DBClusterParameterGroupName: aws.String(d.Get("name").(string)), + DBParameterGroupFamily: aws.String(d.Get("family").(string)), + Description: aws.String(d.Get("description").(string)), + Tags: tags, + } + + log.Printf("[DEBUG] Create DB Cluster Parameter Group: %#v", createOpts) + _, err := rdsconn.CreateDBClusterParameterGroup(&createOpts) + if err != nil { + return fmt.Errorf("Error creating DB Cluster Parameter Group: %s", err) + } + + d.SetId(*createOpts.DBClusterParameterGroupName) + log.Printf("[INFO] DB Cluster Parameter Group ID: %s", d.Id()) + + return resourceAwsRDSClusterParameterGroupUpdate(d, meta) +} + +func resourceAwsRDSClusterParameterGroupRead(d *schema.ResourceData, meta interface{}) error { + rdsconn := meta.(*AWSClient).rdsconn + + describeOpts := rds.DescribeDBClusterParameterGroupsInput{ + DBClusterParameterGroupName: aws.String(d.Id()), + } + + describeResp, err := rdsconn.DescribeDBClusterParameterGroups(&describeOpts) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "DBParameterGroupNotFound" { + log.Printf("[WARN] DB Cluster Parameter Group (%s) not found, error code (404)", d.Id()) + d.SetId("") + return nil + } + + return err + } + + if len(describeResp.DBClusterParameterGroups) != 1 || + *describeResp.DBClusterParameterGroups[0].DBClusterParameterGroupName != d.Id() { + return fmt.Errorf("Unable to find Cluster Parameter Group: %#v", describeResp.DBClusterParameterGroups) + } + + d.Set("name", describeResp.DBClusterParameterGroups[0].DBClusterParameterGroupName) + d.Set("family", describeResp.DBClusterParameterGroups[0].DBParameterGroupFamily) + d.Set("description", describeResp.DBClusterParameterGroups[0].Description) + + // Only include user customized parameters as there's hundreds of system/default ones + describeParametersOpts := rds.DescribeDBClusterParametersInput{ + DBClusterParameterGroupName: aws.String(d.Id()), + Source: aws.String("user"), + } + + describeParametersResp, err := rdsconn.DescribeDBClusterParameters(&describeParametersOpts) + if err != nil { + return err + } + + d.Set("parameter", flattenParameters(describeParametersResp.Parameters)) + + paramGroup := describeResp.DBClusterParameterGroups[0] + arn, err := buildRDSCPGARN(d, meta) + if err != nil { + name := "" + if paramGroup.DBClusterParameterGroupName != nil && *paramGroup.DBClusterParameterGroupName != "" { + name = *paramGroup.DBClusterParameterGroupName + } + log.Printf("[DEBUG] Error building ARN for DB Cluster Parameter Group, not setting Tags for Cluster Param Group %s", name) + } else { + d.Set("arn", arn) + resp, err := rdsconn.ListTagsForResource(&rds.ListTagsForResourceInput{ + ResourceName: aws.String(arn), + }) + + if err != nil { + log.Printf("[DEBUG] Error retrieving tags for ARN: %s", arn) + } + + var dt []*rds.Tag + if len(resp.TagList) > 0 { + dt = resp.TagList + } + d.Set("tags", tagsToMapRDS(dt)) + } + + return nil +} + +func resourceAwsRDSClusterParameterGroupUpdate(d *schema.ResourceData, meta interface{}) error { + rdsconn := meta.(*AWSClient).rdsconn + + d.Partial(true) + + if d.HasChange("parameter") { + o, n := d.GetChange("parameter") + if o == nil { + o = new(schema.Set) + } + if n == nil { + n = new(schema.Set) + } + + os := o.(*schema.Set) + ns := n.(*schema.Set) + + // Expand the "parameter" set to aws-sdk-go compat []rds.Parameter + parameters, err := expandParameters(ns.Difference(os).List()) + if err != nil { + return err + } + + if len(parameters) > 0 { + modifyOpts := rds.ModifyDBClusterParameterGroupInput{ + DBClusterParameterGroupName: aws.String(d.Get("name").(string)), + Parameters: parameters, + } + + log.Printf("[DEBUG] Modify DB Cluster Parameter Group: %s", modifyOpts) + _, err = rdsconn.ModifyDBClusterParameterGroup(&modifyOpts) + if err != nil { + return fmt.Errorf("Error modifying DB Cluster Parameter Group: %s", err) + } + } + d.SetPartial("parameter") + } + + if arn, err := buildRDSCPGARN(d, meta); err == nil { + if err := setTagsRDS(rdsconn, d, arn); err != nil { + return err + } else { + d.SetPartial("tags") + } + } + + d.Partial(false) + + return resourceAwsRDSClusterParameterGroupRead(d, meta) +} + +func resourceAwsRDSClusterParameterGroupDelete(d *schema.ResourceData, meta interface{}) error { + stateConf := &resource.StateChangeConf{ + Pending: []string{"pending"}, + Target: []string{"destroyed"}, + Refresh: resourceAwsRDSClusterParameterGroupDeleteRefreshFunc(d, meta), + Timeout: 3 * time.Minute, + MinTimeout: 1 * time.Second, + } + _, err := stateConf.WaitForState() + return err +} + +func resourceAwsRDSClusterParameterGroupDeleteRefreshFunc( + d *schema.ResourceData, + meta interface{}) resource.StateRefreshFunc { + rdsconn := meta.(*AWSClient).rdsconn + + return func() (interface{}, string, error) { + + deleteOpts := rds.DeleteDBClusterParameterGroupInput{ + DBClusterParameterGroupName: aws.String(d.Id()), + } + + if _, err := rdsconn.DeleteDBClusterParameterGroup(&deleteOpts); err != nil { + rdserr, ok := err.(awserr.Error) + if !ok { + return d, "error", err + } + + if rdserr.Code() != "DBParameterGroupNotFound" { + return d, "error", err + } + } + + return d, "destroyed", nil + } +} + +func buildRDSCPGARN(d *schema.ResourceData, meta interface{}) (string, error) { + iamconn := meta.(*AWSClient).iamconn + region := meta.(*AWSClient).region + // An zero value GetUserInput{} defers to the currently logged in user + resp, err := iamconn.GetUser(&iam.GetUserInput{}) + if err != nil { + return "", err + } + userARN := *resp.User.Arn + accountID := strings.Split(userARN, ":")[4] + arn := fmt.Sprintf("arn:aws:rds:%s:%s:cluster-pg:%s", region, accountID, d.Id()) + return arn, nil +} diff --git a/builtin/providers/aws/resource_aws_rds_cluster_parameter_group_test.go b/builtin/providers/aws/resource_aws_rds_cluster_parameter_group_test.go new file mode 100644 index 000000000..fbbd7347b --- /dev/null +++ b/builtin/providers/aws/resource_aws_rds_cluster_parameter_group_test.go @@ -0,0 +1,360 @@ +package aws + +import ( + "fmt" + "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/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSDBClusterParameterGroup_basic(t *testing.T) { + var v rds.DBClusterParameterGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDBClusterParameterGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSDBClusterParameterGroupConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.bar", &v), + testAccCheckAWSDBClusterParameterGroupAttributes(&v), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "name", "cluster-parameter-group-test-terraform"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "family", "aurora5.6"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "description", "Test cluster parameter group for terraform"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1708034931.name", "character_set_results"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1708034931.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2421266705.name", "character_set_server"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2421266705.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2478663599.name", "character_set_client"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2478663599.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "tags.#", "1"), + ), + }, + resource.TestStep{ + Config: testAccAWSDBClusterParameterGroupAddParametersConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.bar", &v), + testAccCheckAWSDBClusterParameterGroupAttributes(&v), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "name", "cluster-parameter-group-test-terraform"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "family", "aurora5.6"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "description", "Test cluster parameter group for terraform"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1706463059.name", "collation_connection"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1706463059.value", "utf8_unicode_ci"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1708034931.name", "character_set_results"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.1708034931.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2421266705.name", "character_set_server"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2421266705.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2475805061.name", "collation_server"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2475805061.value", "utf8_unicode_ci"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2478663599.name", "character_set_client"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "parameter.2478663599.value", "utf8"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "tags.#", "2"), + ), + }, + }, + }) +} + +func TestAccAWSDBClusterParameterGroup_disappears(t *testing.T) { + var v rds.DBClusterParameterGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDBClusterParameterGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSDBClusterParameterGroupConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.bar", &v), + testAccAWSDBClusterParameterGroupDisappears(&v), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSDBClusterParameterGroupOnly(t *testing.T) { + var v rds.DBClusterParameterGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDBClusterParameterGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSDBClusterParameterGroupOnlyConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSDBClusterParameterGroupExists("aws_rds_cluster_parameter_group.bar", &v), + testAccCheckAWSDBClusterParameterGroupAttributes(&v), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "name", "cluster-parameter-group-test-terraform"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "family", "aurora5.6"), + resource.TestCheckResourceAttr( + "aws_rds_cluster_parameter_group.bar", "description", "Test cluster parameter group for terraform"), + ), + }, + }, + }) +} + +func TestResourceAWSDBClusterParameterGroupName_validation(t *testing.T) { + cases := []struct { + Value string + ErrCount int + }{ + { + Value: "tEsting123", + ErrCount: 1, + }, + { + Value: "testing123!", + ErrCount: 1, + }, + { + Value: "1testing123", + ErrCount: 1, + }, + { + Value: "testing--123", + ErrCount: 1, + }, + { + Value: "testing123-", + ErrCount: 1, + }, + { + Value: randomString(256), + ErrCount: 1, + }, + } + + for _, tc := range cases { + _, errors := validateDbParamGroupName(tc.Value, "aws_rds_cluster_parameter_group_name") + + if len(errors) != tc.ErrCount { + t.Fatalf("Expected the DB Cluster Parameter Group Name to trigger a validation error") + } + } +} + +func testAccCheckAWSDBClusterParameterGroupDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).rdsconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_rds_cluster_parameter_group" { + continue + } + + // Try to find the Group + resp, err := conn.DescribeDBClusterParameterGroups( + &rds.DescribeDBClusterParameterGroupsInput{ + DBClusterParameterGroupName: aws.String(rs.Primary.ID), + }) + + if err == nil { + if len(resp.DBClusterParameterGroups) != 0 && + *resp.DBClusterParameterGroups[0].DBClusterParameterGroupName == rs.Primary.ID { + return fmt.Errorf("DB Cluster Parameter Group still exists") + } + } + + // Verify the error + newerr, ok := err.(awserr.Error) + if !ok { + return err + } + if newerr.Code() != "DBParameterGroupNotFound" { + return err + } + } + + return nil +} + +func testAccCheckAWSDBClusterParameterGroupAttributes(v *rds.DBClusterParameterGroup) resource.TestCheckFunc { + return func(s *terraform.State) error { + + if *v.DBClusterParameterGroupName != "cluster-parameter-group-test-terraform" { + return fmt.Errorf("bad name: %#v", v.DBClusterParameterGroupName) + } + + if *v.DBParameterGroupFamily != "aurora5.6" { + return fmt.Errorf("bad family: %#v", v.DBParameterGroupFamily) + } + + if *v.Description != "Test cluster parameter group for terraform" { + return fmt.Errorf("bad description: %#v", v.Description) + } + + return nil + } +} + +func testAccAWSDBClusterParameterGroupDisappears(v *rds.DBClusterParameterGroup) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).rdsconn + opts := &rds.DeleteDBClusterParameterGroupInput{ + DBClusterParameterGroupName: v.DBClusterParameterGroupName, + } + if _, err := conn.DeleteDBClusterParameterGroup(opts); err != nil { + return err + } + return resource.Retry(40*time.Minute, func() *resource.RetryError { + opts := &rds.DescribeDBClusterParameterGroupsInput{ + DBClusterParameterGroupName: v.DBClusterParameterGroupName, + } + _, err := conn.DescribeDBClusterParameterGroups(opts) + if err != nil { + dbparamgrouperr, ok := err.(awserr.Error) + if ok && dbparamgrouperr.Code() == "DBParameterGroupNotFound" { + return nil + } + return resource.NonRetryableError( + fmt.Errorf("Error retrieving DB Cluster Parameter Groups: %s", err)) + } + return resource.RetryableError(fmt.Errorf( + "Waiting for cluster parameter group to be deleted: %v", v.DBClusterParameterGroupName)) + }) + } +} + +func testAccCheckAWSDBClusterParameterGroupExists(n string, v *rds.DBClusterParameterGroup) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No DB Cluster Parameter Group ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).rdsconn + + opts := rds.DescribeDBClusterParameterGroupsInput{ + DBClusterParameterGroupName: aws.String(rs.Primary.ID), + } + + resp, err := conn.DescribeDBClusterParameterGroups(&opts) + + if err != nil { + return err + } + + if len(resp.DBClusterParameterGroups) != 1 || + *resp.DBClusterParameterGroups[0].DBClusterParameterGroupName != rs.Primary.ID { + return fmt.Errorf("DB Cluster Parameter Group not found") + } + + *v = *resp.DBClusterParameterGroups[0] + + return nil + } +} + +const testAccAWSDBClusterParameterGroupConfig = ` +resource "aws_rds_cluster_parameter_group" "bar" { + name = "cluster-parameter-group-test-terraform" + family = "aurora5.6" + description = "Test cluster parameter group for terraform" + + parameter { + name = "character_set_server" + value = "utf8" + } + + parameter { + name = "character_set_client" + value = "utf8" + } + + parameter { + name = "character_set_results" + value = "utf8" + } + + tags { + foo = "bar" + } +} +` + +const testAccAWSDBClusterParameterGroupAddParametersConfig = ` +resource "aws_rds_cluster_parameter_group" "bar" { + name = "cluster-parameter-group-test-terraform" + family = "aurora5.6" + description = "Test cluster parameter group for terraform" + + parameter { + name = "character_set_server" + value = "utf8" + } + + parameter { + name = "character_set_client" + value = "utf8" + } + + parameter { + name = "character_set_results" + value = "utf8" + } + + parameter { + name = "collation_server" + value = "utf8_unicode_ci" + } + + parameter { + name = "collation_connection" + value = "utf8_unicode_ci" + } + + tags { + foo = "bar" + baz = "foo" + } +} +` + +const testAccAWSDBClusterParameterGroupOnlyConfig = ` +resource "aws_rds_cluster_parameter_group" "bar" { + name = "cluster-parameter-group-test-terraform" + family = "aurora5.6" + description = "Test cluster parameter group for terraform" +} +` diff --git a/builtin/providers/aws/resource_aws_rds_cluster_test.go b/builtin/providers/aws/resource_aws_rds_cluster_test.go index 12349ce33..8ae460bca 100644 --- a/builtin/providers/aws/resource_aws_rds_cluster_test.go +++ b/builtin/providers/aws/resource_aws_rds_cluster_test.go @@ -27,6 +27,8 @@ func TestAccAWSRDSCluster_basic(t *testing.T) { testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), resource.TestCheckResourceAttr( "aws_rds_cluster.default", "storage_encrypted", "false"), + resource.TestCheckResourceAttr( + "aws_rds_cluster.default", "parameter_group_name", "default.aurora5.6"), ), }, }, @@ -47,6 +49,8 @@ func TestAccAWSRDSCluster_encrypted(t *testing.T) { testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), resource.TestCheckResourceAttr( "aws_rds_cluster.default", "storage_encrypted", "true"), + resource.TestCheckResourceAttr( + "aws_rds_cluster.default", "parameter_group_name", "default.aurora5.6"), ), }, }, @@ -164,6 +168,7 @@ resource "aws_rds_cluster" "default" { database_name = "mydb" master_username = "foo" master_password = "mustbeeightcharaters" + parameter_group_name = "default.aurora5.6" }`, n) } diff --git a/website/source/docs/providers/aws/r/rds_cluster.html.markdown b/website/source/docs/providers/aws/r/rds_cluster.html.markdown index c7e5e8b8d..14e2d7b6d 100644 --- a/website/source/docs/providers/aws/r/rds_cluster.html.markdown +++ b/website/source/docs/providers/aws/r/rds_cluster.html.markdown @@ -76,6 +76,7 @@ Default: A 30-minute window selected at random from an 8-hour block of time per are applied immediately, or during the next maintenance window. Default is `false`. See [Amazon RDS Documentation for more information.](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html) * `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. +* `parameter_group_name` - (Optional) A cluster parameter group to associate with the cluster. ## Attributes Reference diff --git a/website/source/docs/providers/aws/r/rds_cluster_parameter_group.markdown b/website/source/docs/providers/aws/r/rds_cluster_parameter_group.markdown new file mode 100644 index 000000000..617ec6f35 --- /dev/null +++ b/website/source/docs/providers/aws/r/rds_cluster_parameter_group.markdown @@ -0,0 +1,55 @@ +--- +layout: "aws" +page_title: "AWS: aws_rds_cluster_parameter_group" +sidebar_current: "docs-aws-resource-rds-cluster-parameter-group" +--- + +# aws\_rds\_cluster\_parameter\_group + +Provides an RDS DB cluster parameter group resource. + +## Example Usage + +``` +resource "aws_rds_cluster_parameter_group" "default" { + name = "rds-cluster-pg" + family = "aurora5.6" + description = "RDS default cluster parameter group" + + parameter { + name = "character_set_server" + value = "utf8" + } + + parameter { + name = "character_set_client" + value = "utf8" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the DB cluster parameter group. +* `family` - (Required) The family of the DB cluster parameter group. +* `description` - (Required) The description of the DB cluster parameter group. +* `parameter` - (Optional) A list of DB parameters to apply. +* `tags` - (Optional) A mapping of tags to assign to the resource. + +Parameter blocks support the following: + +* `name` - (Required) The name of the DB parameter. +* `value` - (Required) The value of the DB parameter. +* `apply_method` - (Optional) "immediate" (default), or "pending-reboot". Some + engines can't apply some parameters without a reboot, and you will need to + specify "pending-reboot" here. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The db cluster parameter group name. +* `arn` - The ARN of the db cluster parameter group. + diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index b274eea98..55d25ff7f 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -571,6 +571,10 @@ aws_rds_cluster_instance + > + aws_rds_cluster_parameter_group + +