diff --git a/aws/resource_aws_ssm_document.go b/aws/resource_aws_ssm_document.go index c28f6227cfe..7dfb359af77 100644 --- a/aws/resource_aws_ssm_document.go +++ b/aws/resource_aws_ssm_document.go @@ -39,6 +39,33 @@ func resourceAwsSsmDocument() *schema.Resource { Required: true, ValidateFunc: validateAwsSSMName, }, + "attachments_source": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + ssm.AttachmentsSourceKeyAttachmentReference, + ssm.AttachmentsSourceKeySourceUrl, + ssm.AttachmentsSourceKeyS3fileUrl, + }, false), + }, + "name": { + Type: schema.TypeString, + Optional: true, + }, + "values": { + Type: schema.TypeList, + MinItems: 1, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, "content": { Type: schema.TypeString, Required: true, @@ -60,6 +87,7 @@ func resourceAwsSsmDocument() *schema.Resource { ssm.DocumentTypePolicy, ssm.DocumentTypeAutomation, ssm.DocumentTypeSession, + ssm.DocumentTypePackage, }, false), }, "schema_version": { @@ -164,6 +192,10 @@ func resourceAwsSsmDocumentCreate(d *schema.ResourceData, meta interface{}) erro docInput.Tags = keyvaluetags.New(v.(map[string]interface{})).IgnoreAws().SsmTags() } + if v, ok := d.GetOk("attachments_source"); ok { + docInput.Attachments = expandSsmAttachmentsSources(v.([]interface{})) + } + log.Printf("[DEBUG] Waiting for SSM Document %q to be created", d.Get("name").(string)) var resp *ssm.CreateDocumentOutput err := resource.Retry(5*time.Minute, func() *resource.RetryError { @@ -384,6 +416,31 @@ func resourceAwsSsmDocumentDelete(d *schema.ResourceData, meta interface{}) erro return nil } +func expandSsmAttachmentsSources(a []interface{}) []*ssm.AttachmentsSource { + if len(a) == 0 { + return nil + } + + results := make([]*ssm.AttachmentsSource, 0) + for _, raw := range a { + at := raw.(map[string]interface{}) + s := &ssm.AttachmentsSource{} + if val, ok := at["key"]; ok { + s.Key = aws.String(val.(string)) + } + if val, ok := at["name"]; ok && val != "" { + s.Name = aws.String(val.(string)) + } + if val, ok := at["values"]; ok { + s.Values = expandStringList(val.([]interface{})) + } + + results = append(results, s) + } + return results + +} + func setDocumentPermissions(d *schema.ResourceData, meta interface{}) error { ssmconn := meta.(*AWSClient).ssmconn @@ -572,6 +629,10 @@ func updateAwsSSMDocument(d *schema.ResourceData, meta interface{}) error { DocumentVersion: aws.String(d.Get("default_version").(string)), } + if d.HasChange("attachments_source") { + updateDocInput.Attachments = expandSsmAttachmentsSources(d.Get("attachments_source").([]interface{})) + } + newDefaultVersion := d.Get("default_version").(string) ssmconn := meta.(*AWSClient).ssmconn diff --git a/aws/resource_aws_ssm_document_test.go b/aws/resource_aws_ssm_document_test.go index 790074dd936..49f32e3b3b1 100644 --- a/aws/resource_aws_ssm_document_test.go +++ b/aws/resource_aws_ssm_document_test.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "os" "testing" "github.com/aws/aws-sdk-go/aws" @@ -244,6 +245,45 @@ func TestAccAWSSSMDocument_automation(t *testing.T) { }) } +func TestAccAWSSSMDocument_package(t *testing.T) { + name := acctest.RandString(10) + rInt := acctest.RandInt() + rInt2 := acctest.RandInt() + + source := testAccAWSS3BucketObjectCreateTempFile(t, "{anything will do }") + defer os.Remove(source) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMDocumentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMDocumentTypePackageConfig(name, source, rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMDocumentExists("aws_ssm_document.test"), + resource.TestCheckResourceAttr( + "aws_ssm_document.test", "document_type", "Package"), + ), + }, + { + ResourceName: "aws_ssm_document.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"attachments_source"}, // This doesn't work because the API doesn't provide attachments info directly + }, + { + Config: testAccAWSSSMDocumentTypePackageConfig(name, source, rInt2), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMDocumentExists("aws_ssm_document.test"), + resource.TestCheckResourceAttr( + "aws_ssm_document.test", "document_type", "Package"), + ), + }, + }, + }) +} + func TestAccAWSSSMDocument_SchemaVersion_1(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_ssm_document.test" @@ -750,6 +790,91 @@ DOC `, rName, rName, rName) } +func testAccAWSSSMDocumentTypePackageConfig(rName, source string, rInt int) string { + return fmt.Sprintf(` +data "aws_ami" "ssm_ami" { + most_recent = true + owners = ["099720109477"] # Canonical + + filter { + name = "name" + values = ["*hvm-ssd/ubuntu-trusty-14.04*"] + } +} + +resource "aws_iam_instance_profile" "ssm_profile" { + name = "ssm_profile-%s" + role = "${aws_iam_role.ssm_role.name}" +} + +resource "aws_iam_role" "ssm_role" { + name = "ssm_role-%s" + path = "/" + + assume_role_policy = <