From 5cd1b6624a9a1f64c563ef5adc9300ac866c03e2 Mon Sep 17 00:00:00 2001 From: Paul Stack Date: Wed, 20 Jul 2016 19:37:26 +0100 Subject: [PATCH] provider/aws: Support Tags on `aws_rds_cluster` (#7695) Fixes #7692 ``` % make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSRDSCluster_' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSRDSCluster_ -timeout 120m === RUN TestAccAWSRDSCluster_basic --- PASS: TestAccAWSRDSCluster_basic (160.77s) === RUN TestAccAWSRDSCluster_updateTags --- PASS: TestAccAWSRDSCluster_updateTags (329.20s) === RUN TestAccAWSRDSCluster_encrypted --- PASS: TestAccAWSRDSCluster_encrypted (227.29s) === RUN TestAccAWSRDSCluster_backupsUpdate --- PASS: TestAccAWSRDSCluster_backupsUpdate (196.92s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 914.199s ``` --- .../providers/aws/resource_aws_rds_cluster.go | 49 +++++++++++++++++-- .../aws/resource_aws_rds_cluster_test.go | 48 ++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/builtin/providers/aws/resource_aws_rds_cluster.go b/builtin/providers/aws/resource_aws_rds_cluster.go index 481ef11dd..6cb76a7bb 100644 --- a/builtin/providers/aws/resource_aws_rds_cluster.go +++ b/builtin/providers/aws/resource_aws_rds_cluster.go @@ -192,18 +192,22 @@ func resourceAwsRDSCluster() *schema.Resource { return }, }, + + "tags": tagsSchema(), }, } } func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).rdsconn + tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) if _, ok := d.GetOk("snapshot_identifier"); ok { opts := rds.RestoreDBClusterFromSnapshotInput{ DBClusterIdentifier: aws.String(d.Get("cluster_identifier").(string)), SnapshotIdentifier: aws.String(d.Get("snapshot_identifier").(string)), Engine: aws.String("aurora"), + Tags: tags, } if attr := d.Get("availability_zones").(*schema.Set); attr.Len() > 0 { @@ -282,6 +286,7 @@ func resourceAwsRDSClusterCreate(d *schema.ResourceData, meta interface{}) error MasterUserPassword: aws.String(d.Get("master_password").(string)), MasterUsername: aws.String(d.Get("master_username").(string)), StorageEncrypted: aws.Bool(d.Get("storage_encrypted").(bool)), + Tags: tags, } if v := d.Get("database_name"); v.(string) != "" { @@ -430,11 +435,22 @@ func resourceAwsRDSClusterRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("[DEBUG] Error saving RDS Cluster Members to state for RDS Cluster (%s): %s", d.Id(), err) } + // Fetch and save tags + arn, err := buildRDSClusterARN(d.Id(), meta.(*AWSClient).accountid, meta.(*AWSClient).region) + if err != nil { + log.Printf("[DEBUG] Error building ARN for RDS Cluster (%s), not setting Tags", *dbc.DBClusterIdentifier) + } else { + if err := saveTagsRDS(conn, d, arn); err != nil { + log.Printf("[WARN] Failed to save tags for RDS Cluster (%s): %s", *dbc.DBClusterIdentifier, err) + } + } + return nil } func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).rdsconn + requestUpdate := false req := &rds.ModifyDBClusterInput{ ApplyImmediately: aws.Bool(d.Get("apply_immediately").(bool)), @@ -443,6 +459,7 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error if d.HasChange("master_password") { req.MasterUserPassword = aws.String(d.Get("master_password").(string)) + requestUpdate = true } if d.HasChange("vpc_security_group_ids") { @@ -451,33 +468,49 @@ func resourceAwsRDSClusterUpdate(d *schema.ResourceData, meta interface{}) error } else { req.VpcSecurityGroupIds = []*string{} } + requestUpdate = true } if d.HasChange("preferred_backup_window") { req.PreferredBackupWindow = aws.String(d.Get("preferred_backup_window").(string)) + requestUpdate = true } if d.HasChange("preferred_maintenance_window") { req.PreferredMaintenanceWindow = aws.String(d.Get("preferred_maintenance_window").(string)) + requestUpdate = true } if d.HasChange("backup_retention_period") { req.BackupRetentionPeriod = aws.Int64(int64(d.Get("backup_retention_period").(int))) + requestUpdate = true } if d.HasChange("parameter_group_name") { d.SetPartial("parameter_group_name") req.DBClusterParameterGroupName = aws.String(d.Get("parameter_group_name").(string)) + requestUpdate = true } if d.HasChange("db_cluster_parameter_group_name") { d.SetPartial("db_cluster_parameter_group_name") req.DBClusterParameterGroupName = aws.String(d.Get("db_cluster_parameter_group_name").(string)) + requestUpdate = true } - _, err := conn.ModifyDBCluster(req) - if err != nil { - return fmt.Errorf("[WARN] Error modifying RDS Cluster (%s): %s", d.Id(), err) + if requestUpdate { + _, err := conn.ModifyDBCluster(req) + if err != nil { + return fmt.Errorf("[WARN] Error modifying RDS Cluster (%s): %s", d.Id(), err) + } + } + + if arn, err := buildRDSClusterARN(d.Id(), meta.(*AWSClient).accountid, meta.(*AWSClient).region); err == nil { + if err := setTagsRDS(conn, d, arn); err != nil { + return err + } else { + d.SetPartial("tags") + } } return resourceAwsRDSClusterRead(d, meta) @@ -560,3 +593,13 @@ func resourceAwsRDSClusterStateRefreshFunc( return dbc, *dbc.Status, nil } } + +func buildRDSClusterARN(identifier, accountid, region string) (string, error) { + if accountid == "" { + return "", fmt.Errorf("Unable to construct RDS Cluster ARN because of missing AWS Account ID") + } + + arn := fmt.Sprintf("arn:aws:rds:%s:%s:cluster:%s", region, accountid, identifier) + return arn, nil + +} diff --git a/builtin/providers/aws/resource_aws_rds_cluster_test.go b/builtin/providers/aws/resource_aws_rds_cluster_test.go index ec59f44fe..b3eb1c790 100644 --- a/builtin/providers/aws/resource_aws_rds_cluster_test.go +++ b/builtin/providers/aws/resource_aws_rds_cluster_test.go @@ -35,6 +35,35 @@ func TestAccAWSRDSCluster_basic(t *testing.T) { }) } +func TestAccAWSRDSCluster_updateTags(t *testing.T) { + var v rds.DBCluster + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSClusterDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSClusterConfig(ri), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), + resource.TestCheckResourceAttr( + "aws_rds_cluster.default", "tags.%", "1"), + ), + }, + resource.TestStep{ + Config: testAccAWSClusterConfigUpdatedTags(ri), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSClusterExists("aws_rds_cluster.default", &v), + resource.TestCheckResourceAttr( + "aws_rds_cluster.default", "tags.%", "2"), + ), + }, + }, + }) +} + func TestAccAWSRDSCluster_encrypted(t *testing.T) { var v rds.DBCluster @@ -169,6 +198,25 @@ resource "aws_rds_cluster" "default" { master_username = "foo" master_password = "mustbeeightcharaters" db_cluster_parameter_group_name = "default.aurora5.6" + tags { + Environment = "production" + } +}`, n) +} + +func testAccAWSClusterConfigUpdatedTags(n int) string { + return fmt.Sprintf(` +resource "aws_rds_cluster" "default" { + cluster_identifier = "tf-aurora-cluster-%d" + availability_zones = ["us-west-2a","us-west-2b","us-west-2c"] + database_name = "mydb" + master_username = "foo" + master_password = "mustbeeightcharaters" + db_cluster_parameter_group_name = "default.aurora5.6" + tags { + Environment = "production" + AnotherTag = "test" + } }`, n) }