Skip to content

Commit

Permalink
Merge pull request #9313 from terraform-providers/b-aws_ssm_document-…
Browse files Browse the repository at this point in the history
…schema_version-1-forcenew

resource/aws_ssm_document: Ensure content attribute is refreshed and support resource import
  • Loading branch information
bflad authored Jul 11, 2019
2 parents 47a5a31 + 56cc5f5 commit c7d1f77
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 27 deletions.
65 changes: 38 additions & 27 deletions aws/resource_aws_ssm_document.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@ package aws
import (
"fmt"
"log"
"strconv"
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ssm"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

const (
MINIMUM_VERSIONED_SCHEMA = 2.0
SSM_DOCUMENT_PERMISSIONS_BATCH_LIMIT = 20
)

Expand All @@ -27,6 +24,9 @@ func resourceAwsSsmDocument() *schema.Resource {
Read: resourceAwsSsmDocumentRead,
Update: resourceAwsSsmDocumentUpdate,
Delete: resourceAwsSsmDocumentDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"arn": {
Expand Down Expand Up @@ -204,31 +204,51 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error

log.Printf("[DEBUG] Reading SSM Document: %s", d.Id())

docInput := &ssm.DescribeDocumentInput{
Name: aws.String(d.Get("name").(string)),
describeDocumentInput := &ssm.DescribeDocumentInput{
Name: aws.String(d.Id()),
}

describeDocumentOutput, err := ssmconn.DescribeDocument(describeDocumentInput)

if isAWSErr(err, ssm.ErrCodeInvalidDocument, "") {
log.Printf("[WARN] SSM Document not found so removing from state")
d.SetId("")
return nil
}

resp, err := ssmconn.DescribeDocument(docInput)
if err != nil {
if ssmErr, ok := err.(awserr.Error); ok && ssmErr.Code() == "InvalidDocument" {
log.Printf("[WARN] SSM Document not found so removing from state")
d.SetId("")
return nil
}
return fmt.Errorf("Error describing SSM document: %s", err)
return fmt.Errorf("error describing SSM Document (%s): %s", d.Id(), err)
}

if describeDocumentOutput == nil || describeDocumentOutput.Document == nil {
return fmt.Errorf("error describing SSM Document (%s): empty result", d.Id())
}

getDocumentInput := &ssm.GetDocumentInput{
DocumentFormat: describeDocumentOutput.Document.DocumentFormat,
DocumentVersion: aws.String("$LATEST"),
Name: describeDocumentOutput.Document.Name,
}

getDocumentOutput, err := ssmconn.GetDocument(getDocumentInput)

if err != nil {
return fmt.Errorf("error getting SSM Document (%s): %s", d.Id(), err)
}

doc := resp.Document
if getDocumentOutput == nil {
return fmt.Errorf("error getting SSM Document (%s): empty result", d.Id())
}

doc := describeDocumentOutput.Document

d.Set("content", getDocumentOutput.Content)
d.Set("created_date", doc.CreatedDate)
d.Set("default_version", doc.DefaultVersion)
d.Set("description", doc.Description)
d.Set("schema_version", doc.SchemaVersion)

if _, ok := d.GetOk("document_type"); ok {
d.Set("document_type", doc.DocumentType)
}

d.Set("document_format", doc.DocumentFormat)
d.Set("document_type", doc.DocumentType)
d.Set("document_version", doc.DocumentVersion)
d.Set("hash", doc.Hash)
d.Set("hash_type", doc.HashType)
Expand Down Expand Up @@ -319,15 +339,6 @@ func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) erro
return nil
}

if schemaVersion, ok := d.GetOk("schemaVersion"); ok {
schemaNumber, _ := strconv.ParseFloat(schemaVersion.(string), 64)

if schemaNumber < MINIMUM_VERSIONED_SCHEMA {
log.Printf("[DEBUG] Skipping document update because document version is not 2.0 %q", d.Id())
return nil
}
}

if err := updateAwsSSMDocument(d, meta); err != nil {
return err
}
Expand Down
135 changes: 135 additions & 0 deletions aws/resource_aws_ssm_document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ func TestAccAWSSSMDocument_basic(t *testing.T) {
"aws_ssm_document.foo", "tags.Name", "My Document"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand All @@ -55,6 +60,11 @@ func TestAccAWSSSMDocument_update(t *testing.T) {
"aws_ssm_document.foo", "default_version", "1"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSSSMDocument20UpdatedConfig(name),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -86,6 +96,11 @@ func TestAccAWSSSMDocument_permission_public(t *testing.T) {
"aws_ssm_document.foo", "permissions.account_ids", "all"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand All @@ -106,6 +121,11 @@ func TestAccAWSSSMDocument_permission_private(t *testing.T) {
"aws_ssm_document.foo", "permissions.type", "Share"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand All @@ -126,6 +146,11 @@ func TestAccAWSSSMDocument_permission_batching(t *testing.T) {
"aws_ssm_document.foo", "permissions.type", "Share"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand All @@ -149,6 +174,11 @@ func TestAccAWSSSMDocument_permission_change(t *testing.T) {
resource.TestCheckResourceAttr("aws_ssm_document.foo", "permissions.account_ids", idsInitial),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSSSMDocumentPrivatePermissionConfig(name, idsRemove),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -196,6 +226,11 @@ func TestAccAWSSSMDocument_params(t *testing.T) {
"aws_ssm_document.foo", "parameter.2.type", "String"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand All @@ -215,6 +250,43 @@ func TestAccAWSSSMDocument_automation(t *testing.T) {
"aws_ssm_document.foo", "document_type", "Automation"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSSSMDocument_SchemaVersion_1(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_ssm_document.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSSMDocumentDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSSSMDocumentConfigSchemaVersion1(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSSMDocumentExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "schema_version", "1.0"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSSSMDocumentConfigSchemaVersion1Update(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSSMDocumentExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "schema_version", "1.0"),
),
},
},
})
}
Expand All @@ -234,6 +306,11 @@ func TestAccAWSSSMDocument_session(t *testing.T) {
"aws_ssm_document.foo", "document_type", "Session"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
Expand Down Expand Up @@ -275,6 +352,11 @@ mainSteps:
resource.TestCheckResourceAttr("aws_ssm_document.foo", "document_format", "YAML"),
),
},
{
ResourceName: "aws_ssm_document.foo",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSSSMDocumentConfig_DocumentFormat_YAML(name, content2),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -304,6 +386,11 @@ func TestAccAWSSSMDocument_Tags(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAWSSSMDocumentConfig_Tags_Multiple(rName, "key1", "value1updated", "key2", "value2"),
Check: resource.ComposeTestCheckFunc(
Expand Down Expand Up @@ -719,6 +806,54 @@ DOC
`, rName, content)
}

func testAccAWSSSMDocumentConfigSchemaVersion1(rName string) string {
return fmt.Sprintf(`
resource "aws_ssm_document" "test" {
name = %[1]q
document_type = "Session"
content = <<DOC
{
"schemaVersion": "1.0",
"description": "Document to hold regional settings for Session Manager",
"sessionType": "Standard_Stream",
"inputs": {
"s3BucketName": "test",
"s3KeyPrefix": "test",
"s3EncryptionEnabled": true,
"cloudWatchLogGroupName": "/logs/sessions",
"cloudWatchEncryptionEnabled": false
}
}
DOC
}
`, rName)
}

func testAccAWSSSMDocumentConfigSchemaVersion1Update(rName string) string {
return fmt.Sprintf(`
resource "aws_ssm_document" "test" {
name = %[1]q
document_type = "Session"
content = <<DOC
{
"schemaVersion": "1.0",
"description": "Document to hold regional settings for Session Manager",
"sessionType": "Standard_Stream",
"inputs": {
"s3BucketName": "test",
"s3KeyPrefix": "test",
"s3EncryptionEnabled": true,
"cloudWatchLogGroupName": "/logs/sessions-updated",
"cloudWatchEncryptionEnabled": false
}
}
DOC
}
`, rName)
}

func testAccAWSSSMDocumentConfig_Tags_Single(rName, key1, value1 string) string {
return fmt.Sprintf(`
resource "aws_ssm_document" "foo" {
Expand Down
8 changes: 8 additions & 0 deletions website/docs/r/ssm_document.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,11 @@ The permissions mapping supports the following:

* `type` - The permission type for the document. The permission type can be `Share`.
* `account_ids` - The AWS user accounts that should have access to the document. The account IDs can either be a group of account IDs or `All`.

## Import

SSM Documents can be imported using the name, e.g.

```
$ terraform import aws_ssm_document.example example
```

0 comments on commit c7d1f77

Please sign in to comment.