-
Notifications
You must be signed in to change notification settings - Fork 9.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
provider/aws: add aws_ssm_association resource #8376
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ssm" | ||
"github.com/hashicorp/errwrap" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsSsmAssociation() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsSsmAssociationCreate, | ||
Read: resourceAwsSsmAssociationRead, | ||
Delete: resourceAwsSsmAssociationDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"instance_id": { | ||
Type: schema.TypeString, | ||
ForceNew: true, | ||
Required: true, | ||
}, | ||
"name": { | ||
Type: schema.TypeString, | ||
ForceNew: true, | ||
Required: true, | ||
}, | ||
"parameters": &schema.Schema{ | ||
Type: schema.TypeMap, | ||
Optional: true, | ||
ForceNew: true, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsSsmAssociationCreate(d *schema.ResourceData, meta interface{}) error { | ||
ssmconn := meta.(*AWSClient).ssmconn | ||
|
||
log.Printf("[DEBUG] SSM association create: %s", d.Id()) | ||
|
||
assosciationInput := &ssm.CreateAssociationInput{ | ||
Name: aws.String(d.Get("name").(string)), | ||
InstanceId: aws.String(d.Get("instance_id").(string)), | ||
} | ||
|
||
if v, ok := d.GetOk("parameters"); ok { | ||
assosciationInput.Parameters = expandDocumentParameters(v.(map[string]interface{})) | ||
} | ||
|
||
resp, err := ssmconn.CreateAssociation(assosciationInput) | ||
|
||
if err != nil { | ||
return errwrap.Wrapf("[ERROR] Error creating SSM association: {{err}}", err) | ||
} | ||
|
||
if resp.AssociationDescription != nil { | ||
d.SetId(*resp.AssociationDescription.Name) | ||
} else { | ||
return fmt.Errorf("[ERROR] AssociationDescription was nil") | ||
} | ||
|
||
return resourceAwsSsmAssociationRead(d, meta) | ||
} | ||
|
||
func resourceAwsSsmAssociationRead(d *schema.ResourceData, meta interface{}) error { | ||
ssmconn := meta.(*AWSClient).ssmconn | ||
|
||
log.Printf("[DEBUG] Reading SSM Assosciation: %s", d.Id()) | ||
|
||
params := &ssm.DescribeAssociationInput{ | ||
Name: aws.String(d.Get("name").(string)), | ||
InstanceId: aws.String(d.Get("instance_id").(string)), | ||
} | ||
|
||
resp, err := ssmconn.DescribeAssociation(params) | ||
|
||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a chance that someone will manually delete the association from the console? What will happen if so? |
||
return errwrap.Wrapf("[ERROR] Error reading SSM association: {{err}}", err) | ||
} | ||
|
||
if resp.AssociationDescription != nil { | ||
association := resp.AssociationDescription | ||
|
||
d.Set("instance_id", association.InstanceId) | ||
d.Set("name", association.Name) | ||
d.Set("parameters", association.Parameters) | ||
|
||
} else { | ||
return fmt.Errorf("[ERROR] AssociationDescription was nil") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsSsmAssociationDelete(d *schema.ResourceData, meta interface{}) error { | ||
ssmconn := meta.(*AWSClient).ssmconn | ||
|
||
log.Printf("[DEBUG] Deleting SSM Assosciation: %s", d.Id()) | ||
|
||
params := &ssm.DeleteAssociationInput{ | ||
Name: aws.String(d.Get("name").(string)), | ||
InstanceId: aws.String(d.Get("instance_id").(string)), | ||
} | ||
|
||
_, err := ssmconn.DeleteAssociation(params) | ||
|
||
if err != nil { | ||
return errwrap.Wrapf("[ERROR] Error deleting SSM association: {{err}}", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func expandDocumentParameters(params map[string]interface{}) map[string][]*string { | ||
var docParams = make(map[string][]*string) | ||
for k, v := range params { | ||
var values []*string | ||
values[0] = aws.String(v.(string)) | ||
docParams[k] = values | ||
} | ||
|
||
return docParams | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/ssm" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSSSMAssociation_basic(t *testing.T) { | ||
name := acctest.RandString(10) | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSSSMAssociationDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccAWSSSMAssociationBasicConfig(name), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSSSMAssociationExists("aws_ssm_association.foo"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSSSMAssociationExists(n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No SSM Assosciation ID is set") | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).ssmconn | ||
|
||
_, err := conn.DescribeAssociation(&ssm.DescribeAssociationInput{ | ||
Name: aws.String(rs.Primary.Attributes["name"]), | ||
InstanceId: aws.String(rs.Primary.Attributes["instance_id"]), | ||
}) | ||
|
||
if err != nil { | ||
return fmt.Errorf("Could not descripbe the assosciation - %s", err) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what do we want the test behaviour to be if there is an empty response for DescribeAssociation? |
||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSSSMAssociationDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).ssmconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_ssm_association" { | ||
continue | ||
} | ||
|
||
out, err := conn.DescribeAssociation(&ssm.DescribeAssociationInput{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is out is nil or has a nil Association? |
||
Name: aws.String(rs.Primary.Attributes["name"]), | ||
InstanceId: aws.String(rs.Primary.Attributes["instance_id"]), | ||
}) | ||
|
||
if err != nil { | ||
// InvalidDocument means it's gone, this is good | ||
if wserr, ok := err.(awserr.Error); ok && wserr.Code() == "InvalidDocument" { | ||
return nil | ||
} | ||
return err | ||
} | ||
|
||
if out != nil { | ||
return fmt.Errorf("Expected AWS SSM Assosciation to be gone, but was still found") | ||
} | ||
} | ||
|
||
return fmt.Errorf("Default error in SSM Assosciation Test") | ||
} | ||
|
||
func testAccAWSSSMAssociationBasicConfig(rName string) string { | ||
return fmt.Sprintf(` | ||
resource "aws_security_group" "tf_test_foo" { | ||
name = "tf_test_foo-%s" | ||
description = "foo" | ||
ingress { | ||
protocol = "icmp" | ||
from_port = -1 | ||
to_port = -1 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
} | ||
|
||
resource "aws_instance" "foo" { | ||
# eu-west-1 | ||
ami = "ami-f77ac884" | ||
availability_zone = "eu-west-1a" | ||
instance_type = "t2.small" | ||
security_groups = ["${aws_security_group.tf_test_foo.name}"] | ||
} | ||
|
||
resource "aws_ssm_document" "foo_document" { | ||
name = "test_document_association-%s", | ||
content = <<DOC | ||
{ | ||
"schemaVersion": "1.2", | ||
"description": "Check ip configuration of a Linux instance.", | ||
"parameters": { | ||
|
||
}, | ||
"runtimeConfig": { | ||
"aws:runShellScript": { | ||
"properties": [ | ||
{ | ||
"id": "0.aws:runShellScript", | ||
"runCommand": ["ifconfig"] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
DOC | ||
} | ||
|
||
resource "aws_ssm_association" "foo" { | ||
name = "test_document_association-%s", | ||
instance_id = "${aws_instance.foo.id}" | ||
} | ||
`, rName, rName, rName) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_ssm_association" | ||
sidebar_current: "docs-aws-resource-ssm-association" | ||
description: |- | ||
Assosciates an SSM Document to an instance. | ||
--- | ||
|
||
# aws\_ssm\_association | ||
|
||
Assosciates an SSM Document to an instance. | ||
|
||
## Example Usage | ||
|
||
``` | ||
resource "aws_security_group" "tf_test_foo" { | ||
name = "tf_test_foo" | ||
description = "foo" | ||
ingress { | ||
protocol = "icmp" | ||
from_port = -1 | ||
to_port = -1 | ||
cidr_blocks = ["0.0.0.0/0"] | ||
} | ||
} | ||
|
||
resource "aws_instance" "foo" { | ||
# eu-west-1 | ||
ami = "ami-f77ac884" | ||
availability_zone = "eu-west-1a" | ||
instance_type = "t2.small" | ||
security_groups = ["${aws_security_group.tf_test_foo.name}"] | ||
} | ||
|
||
resource "aws_ssm_document" "foo_document" { | ||
name = "test_document_association-%s", | ||
content = <<DOC | ||
{ | ||
"schemaVersion": "1.2", | ||
"description": "Check ip configuration of a Linux instance.", | ||
"parameters": { | ||
|
||
}, | ||
"runtimeConfig": { | ||
"aws:runShellScript": { | ||
"properties": [ | ||
{ | ||
"id": "0.aws:runShellScript", | ||
"runCommand": ["ifconfig"] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
DOC | ||
} | ||
|
||
resource "aws_ssm_association" "foo" { | ||
name = "test_document_association-%s", | ||
instance_id = "${aws_instance.foo.id}" | ||
} | ||
|
||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `name` - (Required) The name of the SSM document to apply. | ||
* `instance_id` - (Required) The instance id to apply an SSM document to. | ||
* `parameters` - (Optional) Additional parameters to pass to the SSM document. | ||
|
||
## Attributes Reference | ||
|
||
The following attributes are exported: | ||
|
||
* `name` - The name of the SSM document to apply. | ||
* `instance_ids` - The instance id that the SSM document was applied to. | ||
* `parameters` - Additional parameters passed to the SSM document. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this isn't updatable, then it should be marked as ForceNew: true,