diff --git a/aws/resource_aws_ssm_document.go b/aws/resource_aws_ssm_document.go index 2bb17929040..73ea866f130 100644 --- a/aws/resource_aws_ssm_document.go +++ b/aws/resource_aws_ssm_document.go @@ -141,6 +141,7 @@ func resourceAwsSsmDocument() *schema.Resource { }, }, }, + "tags": tagsSchema(), }, } } @@ -181,6 +182,10 @@ func resourceAwsSsmDocumentCreate(d *schema.ResourceData, meta interface{}) erro log.Printf("[DEBUG] Not setting permissions for %q", d.Id()) } + if err := setTagsSSM(ssmconn, d, d.Id(), ssm.ResourceTypeForTaggingDocument); err != nil { + return fmt.Errorf("error setting SSM Document tags: %s", err) + } + return resourceAwsSsmDocumentRead(d, meta) } @@ -271,10 +276,26 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error return err } + tagList, err := ssmconn.ListTagsForResource(&ssm.ListTagsForResourceInput{ + ResourceId: aws.String(d.Id()), + ResourceType: aws.String(ssm.ResourceTypeForTaggingDocument), + }) + if err != nil { + return fmt.Errorf("error listing SSM Document tags for %s: %s", d.Id(), err) + } + d.Set("tags", tagsToMapSSM(tagList.TagList)) + return nil } func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) error { + ssmconn := meta.(*AWSClient).ssmconn + + if d.HasChange("tags") { + if err := setTagsSSM(ssmconn, d, d.Id(), ssm.ResourceTypeForTaggingDocument); err != nil { + return fmt.Errorf("error setting SSM Document tags: %s", err) + } + } if _, ok := d.GetOk("permissions"); ok { if err := setDocumentPermissions(d, meta); err != nil { diff --git a/aws/resource_aws_ssm_document_test.go b/aws/resource_aws_ssm_document_test.go index 685158d78dc..5794b62dbd5 100644 --- a/aws/resource_aws_ssm_document_test.go +++ b/aws/resource_aws_ssm_document_test.go @@ -27,6 +27,7 @@ func TestAccAWSSSMDocument_basic(t *testing.T) { resource.TestCheckResourceAttr("aws_ssm_document.foo", "document_format", "JSON"), resource.TestMatchResourceAttr("aws_ssm_document.foo", "arn", regexp.MustCompile(`^arn:aws:ssm:[a-z]{2}-[a-z]+-\d{1}:\d{12}:document/.*$`)), + resource.TestCheckResourceAttr("aws_ssm_document.foo", "tags.%", "0"), ), }, }, @@ -184,6 +185,44 @@ mainSteps: }) } +func TestAccAWSSSMDocument_Tags(t *testing.T) { + rName := acctest.RandString(10) + resourceName := "aws_ssm_document.foo" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMDocumentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMDocumentConfig_Tags_Single(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMDocumentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + Config: testAccAWSSSMDocumentConfig_Tags_Multiple(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMDocumentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSSSMDocumentConfig_Tags_Single(rName, "key2", "value2updated"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMDocumentExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2updated"), + ), + }, + }, + }) +} + func testAccCheckAWSSSMDocumentExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -518,3 +557,70 @@ DOC } `, rName, content) } + +func testAccAWSSSMDocumentConfig_Tags_Single(rName, key1, value1 string) string { + return fmt.Sprintf(` +resource "aws_ssm_document" "foo" { + document_type = "Command" + name = "test_document-%s" + + content = <