From 85ab94ddfe2cc9bc8951ef1d7c04b45a3c06c5b8 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Mohanty Date: Mon, 17 Dec 2018 23:23:43 +0200 Subject: [PATCH 1/2] add support for tags for rds snapshots --- aws/resource_aws_db_snapshot.go | 49 +++++++++++++++ aws/resource_aws_db_snapshot_test.go | 89 ++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/aws/resource_aws_db_snapshot.go b/aws/resource_aws_db_snapshot.go index 92001bdeca0..bcfd29fc478 100644 --- a/aws/resource_aws_db_snapshot.go +++ b/aws/resource_aws_db_snapshot.go @@ -16,6 +16,7 @@ func resourceAwsDbSnapshot() *schema.Resource { return &schema.Resource{ Create: resourceAwsDbSnapshotCreate, Read: resourceAwsDbSnapshotRead, + Update: resourceAwsDbSnapshotUpdate, Delete: resourceAwsDbSnapshotDelete, Timeouts: &schema.ResourceTimeout{ @@ -102,16 +103,19 @@ func resourceAwsDbSnapshot() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "tags": tagsSchema(), }, } } func resourceAwsDbSnapshotCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).rdsconn + tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) params := &rds.CreateDBSnapshotInput{ DBInstanceIdentifier: aws.String(d.Get("db_instance_identifier").(string)), DBSnapshotIdentifier: aws.String(d.Get("db_snapshot_identifier").(string)), + Tags: tags, } _, err := conn.CreateDBSnapshot(params) @@ -167,6 +171,9 @@ func resourceAwsDbSnapshotRead(d *schema.ResourceData, meta interface{}) error { d.Set("snapshot_type", snapshot.SnapshotType) d.Set("status", snapshot.Status) d.Set("vpc_id", snapshot.VpcId) + if err := saveTagsRDS(conn, d, aws.StringValue(snapshot.DBSnapshotArn)); err != nil { + log.Printf("[WARN] Failed to save tags for RDS Snapshot (%s): %s", d.Id(), err) + } return nil } @@ -185,6 +192,48 @@ func resourceAwsDbSnapshotDelete(d *schema.ResourceData, meta interface{}) error return nil } +func resourceAwsDbSnapshotUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).rdsconn + arn := d.Get("db_snapshot_arn").(string) + if d.HasChange("tags") { + oldTagsRaw, newTagsRaw := d.GetChange("tags") + oldTagsMap := oldTagsRaw.(map[string]interface{}) + newTagsMap := newTagsRaw.(map[string]interface{}) + createTags, removeTags := diffTagsRDS(tagsFromMapRDS(oldTagsMap), tagsFromMapRDS(newTagsMap)) + + if len(removeTags) > 0 { + removeTagKeys := make([]*string, len(removeTags)) + for i, removeTag := range removeTags { + removeTagKeys[i] = removeTag.Key + } + + input := &rds.RemoveTagsFromResourceInput{ + ResourceName: aws.String(arn), + TagKeys: removeTagKeys, + } + + log.Printf("[DEBUG] Untagging RDS Cluster: %s", input) + if _, err := conn.RemoveTagsFromResource(input); err != nil { + return fmt.Errorf("error untagging RDS Cluster (%s): %s", d.Id(), err) + } + } + + if len(createTags) > 0 { + input := &rds.AddTagsToResourceInput{ + ResourceName: aws.String(arn), + Tags: createTags, + } + + log.Printf("[DEBUG] Tagging RDS Cluster: %s", input) + if _, err := conn.AddTagsToResource(input); err != nil { + return fmt.Errorf("error tagging RDS Cluster (%s): %s", d.Id(), err) + } + } + } + + return nil +} + func resourceAwsDbSnapshotStateRefreshFunc( d *schema.ResourceData, meta interface{}) resource.StateRefreshFunc { return func() (interface{}, string, error) { diff --git a/aws/resource_aws_db_snapshot_test.go b/aws/resource_aws_db_snapshot_test.go index e7b0d62c77e..0c5a1706218 100644 --- a/aws/resource_aws_db_snapshot_test.go +++ b/aws/resource_aws_db_snapshot_test.go @@ -28,6 +28,34 @@ func TestAccAWSDBSnapshot_basic(t *testing.T) { }) } +func TestAccAWSDBSnapshot_tags(t *testing.T) { + var v rds.DBSnapshot + rInt := acctest.RandInt() + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccAwsDbSnapshotConfigTags1(rInt, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDbSnapshotExists("aws_db_snapshot.test", &v), + resource.TestCheckResourceAttr("aws_db_snapshot.test", "tags.%", "1"), + resource.TestCheckResourceAttr("aws_db_snapshot.test", "tags.key1", "value1"), + ), + }, + { + Config: testAccAwsDbSnapshotConfigTags2(rInt, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckDbSnapshotExists("aws_db_snapshot.test", &v), + resource.TestCheckResourceAttr("aws_db_snapshot.test", "tags.%", "2"), + resource.TestCheckResourceAttr("aws_db_snapshot.test", "tags.key1", "value1updated"), + resource.TestCheckResourceAttr("aws_db_snapshot.test", "tags.key2", "value2"), + ), + }, + }, + }) +} + func testAccCheckDbSnapshotExists(n string, v *rds.DBSnapshot) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -81,3 +109,64 @@ resource "aws_db_snapshot" "test" { db_snapshot_identifier = "testsnapshot%d" }`, rInt) } + +func testAccAwsDbSnapshotConfigTags1(rInt int, tag1Key, tag1Value string) string { + return fmt.Sprintf(` +resource "aws_db_instance" "bar" { + allocated_storage = 10 + engine = "MySQL" + engine_version = "5.6.35" + instance_class = "db.t2.micro" + name = "baz" + password = "barbarbarbar" + username = "foo" + + maintenance_window = "Fri:09:00-Fri:09:30" + + backup_retention_period = 0 + + parameter_group_name = "default.mysql5.6" + + skip_final_snapshot = true +} + +resource "aws_db_snapshot" "test" { + db_instance_identifier = "${aws_db_instance.bar.id}" + db_snapshot_identifier = "testsnapshot%d" + + tags = { + %q = %q + } + }`, rInt, tag1Key, tag1Value) +} + +func testAccAwsDbSnapshotConfigTags2(rInt int, tag1Key, tag1Value, tag2Key, tag2Value string) string { + return fmt.Sprintf(` +resource "aws_db_instance" "bar" { + allocated_storage = 10 + engine = "MySQL" + engine_version = "5.6.35" + instance_class = "db.t2.micro" + name = "baz" + password = "barbarbarbar" + username = "foo" + + maintenance_window = "Fri:09:00-Fri:09:30" + + backup_retention_period = 0 + + parameter_group_name = "default.mysql5.6" + + skip_final_snapshot = true +} + +resource "aws_db_snapshot" "test" { + db_instance_identifier = "${aws_db_instance.bar.id}" + db_snapshot_identifier = "testsnapshot%d" + + tags = { + %q = %q + %q = %q + } + }`, rInt, tag1Key, tag1Value, tag2Key, tag2Value) +} From f491b9782ecd64f6b0af5f9b8182ebb174768bf8 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Mohanty Date: Mon, 17 Dec 2018 23:24:13 +0200 Subject: [PATCH 2/2] update documentation --- website/docs/r/db_snapshot.html.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/website/docs/r/db_snapshot.html.markdown b/website/docs/r/db_snapshot.html.markdown index 0539270579b..b520b2028ce 100644 --- a/website/docs/r/db_snapshot.html.markdown +++ b/website/docs/r/db_snapshot.html.markdown @@ -39,6 +39,7 @@ The following arguments are supported: * `db_instance_identifier` - (Required) The DB Instance Identifier from which to take the snapshot. * `db_snapshot_identifier` - (Required) The Identifier for the snapshot. +* `tags` - (Optional) Key-value mapping of resource tags ## Attributes Reference