provider/aws Add support for updating SSM documents (#13491)
* Add schema_version as computed ssm document attribute * Update the SSM document itself if the content has changed and it has a schema >= 2.0 * Add default_version as DocumentVersion in SSM doc update * Acceptance test for updating an SSM document * Better error handling in updating SSM documents * Add SSM document update documentation * Better names for SSM input params
This commit is contained in:
parent
113c06a81c
commit
6ad4b89b8a
|
@ -3,6 +3,7 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -14,6 +15,10 @@ import (
|
|||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
MINIMUM_VERSIONED_SCHEMA = 2.0
|
||||
)
|
||||
|
||||
func resourceAwsSsmDocument() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceAwsSsmDocumentCreate,
|
||||
|
@ -35,6 +40,10 @@ func resourceAwsSsmDocument() *schema.Resource {
|
|||
Required: true,
|
||||
ValidateFunc: validateAwsSSMDocumentType,
|
||||
},
|
||||
"schema_version": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
"created_date": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
|
@ -173,6 +182,7 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error
|
|||
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)
|
||||
|
@ -238,6 +248,23 @@ func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) erro
|
|||
log.Printf("[DEBUG] Not setting document permissions on %q", d.Id())
|
||||
}
|
||||
|
||||
if !d.HasChange("content") {
|
||||
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
|
||||
}
|
||||
|
||||
return resourceAwsSsmDocumentRead(d, meta)
|
||||
}
|
||||
|
||||
|
@ -381,6 +408,47 @@ func deleteDocumentPermissions(d *schema.ResourceData, meta interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func updateAwsSSMDocument(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[INFO] Updating SSM Document: %s", d.Id())
|
||||
|
||||
name := d.Get("name").(string)
|
||||
|
||||
updateDocInput := &ssm.UpdateDocumentInput{
|
||||
Name: aws.String(name),
|
||||
Content: aws.String(d.Get("content").(string)),
|
||||
DocumentVersion: aws.String(d.Get("default_version").(string)),
|
||||
}
|
||||
|
||||
newDefaultVersion := d.Get("default_version").(string)
|
||||
|
||||
ssmconn := meta.(*AWSClient).ssmconn
|
||||
updated, err := ssmconn.UpdateDocument(updateDocInput)
|
||||
|
||||
if isAWSErr(err, "DuplicateDocumentContent", "") {
|
||||
log.Printf("[DEBUG] Content is a duplicate of the latest version so update is not necessary: %s", d.Id())
|
||||
log.Printf("[INFO] Updating the default version to the latest version %s: %s", newDefaultVersion, d.Id())
|
||||
|
||||
newDefaultVersion = d.Get("latest_version").(string)
|
||||
} else if err != nil {
|
||||
return errwrap.Wrapf("Error updating SSM document: {{err}}", err)
|
||||
} else {
|
||||
log.Printf("[INFO] Updating the default version to the new version %s: %s", newDefaultVersion, d.Id())
|
||||
newDefaultVersion = *updated.DocumentDescription.DocumentVersion
|
||||
}
|
||||
|
||||
updateDefaultInput := &ssm.UpdateDocumentDefaultVersionInput{
|
||||
Name: aws.String(name),
|
||||
DocumentVersion: aws.String(newDefaultVersion),
|
||||
}
|
||||
|
||||
_, err = ssmconn.UpdateDocumentDefaultVersion(updateDefaultInput)
|
||||
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("Error updating the default document version to that of the updated document: {{err}}", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateAwsSSMDocumentType(v interface{}, k string) (ws []string, errors []error) {
|
||||
value := v.(string)
|
||||
types := map[string]bool{
|
||||
|
|
|
@ -29,6 +29,39 @@ func TestAccAWSSSMDocument_basic(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestAccAWSSSMDocument_update(t *testing.T) {
|
||||
name := acctest.RandString(10)
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSSSMDocumentDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSSSMDocument20Config(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_document.foo", "schema_version", "2.0"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_document.foo", "latest_version", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_document.foo", "default_version", "1"),
|
||||
),
|
||||
},
|
||||
resource.TestStep{
|
||||
Config: testAccAWSSSMDocument20UpdatedConfig(name),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckAWSSSMDocumentExists("aws_ssm_document.foo"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_document.foo", "latest_version", "2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_ssm_document.foo", "default_version", "2"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccAWSSSMDocument_permission(t *testing.T) {
|
||||
name := acctest.RandString(10)
|
||||
resource.Test(t, resource.TestCase{
|
||||
|
@ -186,6 +219,66 @@ DOC
|
|||
`, rName)
|
||||
}
|
||||
|
||||
func testAccAWSSSMDocument20Config(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_document" "foo" {
|
||||
name = "test_document-%s"
|
||||
document_type = "Command"
|
||||
|
||||
content = <<DOC
|
||||
{
|
||||
"schemaVersion": "2.0",
|
||||
"description": "Sample version 2.0 document v2",
|
||||
"parameters": {
|
||||
|
||||
},
|
||||
"mainSteps": [
|
||||
{
|
||||
"action": "aws:runPowerShellScript",
|
||||
"name": "runPowerShellScript",
|
||||
"inputs": {
|
||||
"runCommand": [
|
||||
"Get-Process"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
DOC
|
||||
}
|
||||
`, rName)
|
||||
}
|
||||
|
||||
func testAccAWSSSMDocument20UpdatedConfig(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_document" "foo" {
|
||||
name = "test_document-%s"
|
||||
document_type = "Command"
|
||||
|
||||
content = <<DOC
|
||||
{
|
||||
"schemaVersion": "2.0",
|
||||
"description": "Sample version 2.0 document v2",
|
||||
"parameters": {
|
||||
|
||||
},
|
||||
"mainSteps": [
|
||||
{
|
||||
"action": "aws:runPowerShellScript",
|
||||
"name": "runPowerShellScript",
|
||||
"inputs": {
|
||||
"runCommand": [
|
||||
"Get-Process -Verbose"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
DOC
|
||||
}
|
||||
`, rName)
|
||||
}
|
||||
|
||||
func testAccAWSSSMDocumentPermissionConfig(rName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "aws_ssm_document" "foo" {
|
||||
|
|
|
@ -10,6 +10,10 @@ description: |-
|
|||
|
||||
Provides an SSM Document resource
|
||||
|
||||
~> **NOTE on updating SSM documents:** Only documents with a schema version of 2.0
|
||||
or greater can update their content once created, see [SSM Schema Features][1]. To update a document with an older
|
||||
schema version you must recreate the resource.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
|
@ -56,6 +60,7 @@ The following attributes are exported:
|
|||
* `content` - The json content of the document.
|
||||
* `created_date` - The date the document was created.
|
||||
* `description` - The description of the document.
|
||||
* `schema_version` - The schema version of the document.
|
||||
* `document_type` - The type of document created.
|
||||
* `default_version` - The default version of the document.
|
||||
* `hash` - The sha1 or sha256 of the document content
|
||||
|
@ -67,6 +72,8 @@ The following attributes are exported:
|
|||
* `permissions` - The permissions of how this document should be shared.
|
||||
* `platform_types` - A list of OS platforms compatible with this SSM document, either "Windows" or "Linux".
|
||||
|
||||
[1]: http://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-ssm-docs.html#document-schemas-features
|
||||
|
||||
## Permissions
|
||||
|
||||
The permissions attribute specifies how you want to share the document. If you share a document privately,
|
||||
|
|
Loading…
Reference in New Issue