provider/aws: Support run_command_parameters in aws_cloudwatch_event_target (#14067)

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSCloudWatchEventTarget_'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/04/29 11:00:09 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSCloudWatchEventTarget_ -timeout 120m
=== RUN   TestAccAWSCloudWatchEventTarget_basic
--- PASS: TestAccAWSCloudWatchEventTarget_basic (58.75s)
=== RUN   TestAccAWSCloudWatchEventTarget_missingTargetId
--- PASS: TestAccAWSCloudWatchEventTarget_missingTargetId (36.11s)
=== RUN   TestAccAWSCloudWatchEventTarget_full
--- PASS: TestAccAWSCloudWatchEventTarget_full (90.30s)
=== RUN   TestAccAWSCloudWatchEventTarget_ssmDocument
--- PASS: TestAccAWSCloudWatchEventTarget_ssmDocument (38.64s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	223.833s
```
This commit is contained in:
Paul Stack 2017-05-04 20:46:11 +03:00 committed by GitHub
parent 560a723c9e
commit 046bb0e1c3
4 changed files with 219 additions and 20 deletions

View File

@ -11,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/aws/awserr"
events "github.com/aws/aws-sdk-go/service/cloudwatchevents" events "github.com/aws/aws-sdk-go/service/cloudwatchevents"
"github.com/hashicorp/terraform/helper/validation"
) )
func resourceAwsCloudWatchEventTarget() *schema.Resource { func resourceAwsCloudWatchEventTarget() *schema.Resource {
@ -21,14 +22,14 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
Delete: resourceAwsCloudWatchEventTargetDelete, Delete: resourceAwsCloudWatchEventTargetDelete,
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"rule": &schema.Schema{ "rule": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
ValidateFunc: validateCloudWatchEventRuleName, ValidateFunc: validateCloudWatchEventRuleName,
}, },
"target_id": &schema.Schema{ "target_id": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
@ -36,12 +37,12 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
ValidateFunc: validateCloudWatchEventTargetId, ValidateFunc: validateCloudWatchEventTargetId,
}, },
"arn": &schema.Schema{ "arn": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
"input": &schema.Schema{ "input": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ConflictsWith: []string{"input_path"}, ConflictsWith: []string{"input_path"},
@ -49,11 +50,36 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
// but for built-in targets input may not be JSON // but for built-in targets input may not be JSON
}, },
"input_path": &schema.Schema{ "input_path": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ConflictsWith: []string{"input"}, ConflictsWith: []string{"input"},
}, },
"role_arn": {
Type: schema.TypeString,
Optional: true,
},
"run_command_targets": {
Type: schema.TypeList,
Optional: true,
MaxItems: 5,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(1, 128),
},
"values": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
}, },
} }
} }
@ -72,6 +98,7 @@ func resourceAwsCloudWatchEventTargetCreate(d *schema.ResourceData, meta interfa
} }
input := buildPutTargetInputStruct(d) input := buildPutTargetInputStruct(d)
log.Printf("[DEBUG] Creating CloudWatch Event Target: %s", input) log.Printf("[DEBUG] Creating CloudWatch Event Target: %s", input)
out, err := conn.PutTargets(input) out, err := conn.PutTargets(input)
if err != nil { if err != nil {
@ -128,6 +155,13 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface
d.Set("target_id", t.Id) d.Set("target_id", t.Id)
d.Set("input", t.Input) d.Set("input", t.Input)
d.Set("input_path", t.InputPath) d.Set("input_path", t.InputPath)
d.Set("role_arn", t.RoleArn)
if t.RunCommandParameters != nil {
if err := d.Set("run_command_targets", flattenAwsCloudWatchEventTargetRunParameters(t.RunCommandParameters)); err != nil {
return fmt.Errorf("[DEBUG] Error setting run_command_targets error: %#v", err)
}
}
return nil return nil
} }
@ -162,6 +196,7 @@ func resourceAwsCloudWatchEventTargetUpdate(d *schema.ResourceData, meta interfa
conn := meta.(*AWSClient).cloudwatcheventsconn conn := meta.(*AWSClient).cloudwatcheventsconn
input := buildPutTargetInputStruct(d) input := buildPutTargetInputStruct(d)
log.Printf("[DEBUG] Updating CloudWatch Event Target: %s", input) log.Printf("[DEBUG] Updating CloudWatch Event Target: %s", input)
_, err := conn.PutTargets(input) _, err := conn.PutTargets(input)
if err != nil { if err != nil {
@ -203,6 +238,14 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
e.InputPath = aws.String(v.(string)) e.InputPath = aws.String(v.(string))
} }
if v, ok := d.GetOk("role_arn"); ok {
e.RoleArn = aws.String(v.(string))
}
if v, ok := d.GetOk("run_command_targets"); ok {
e.RunCommandParameters = expandAwsCloudWatchEventTargetRunParameters(v.([]interface{}))
}
input := events.PutTargetsInput{ input := events.PutTargetsInput{
Rule: aws.String(d.Get("rule").(string)), Rule: aws.String(d.Get("rule").(string)),
Targets: []*events.Target{e}, Targets: []*events.Target{e},
@ -210,3 +253,39 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
return &input return &input
} }
func expandAwsCloudWatchEventTargetRunParameters(config []interface{}) *events.RunCommandParameters {
commands := make([]*events.RunCommandTarget, 0)
for _, c := range config {
param := c.(map[string]interface{})
command := &events.RunCommandTarget{
Key: aws.String(param["key"].(string)),
Values: expandStringList(param["values"].([]interface{})),
}
commands = append(commands, command)
}
command := &events.RunCommandParameters{
RunCommandTargets: commands,
}
return command
}
func flattenAwsCloudWatchEventTargetRunParameters(runCommand *events.RunCommandParameters) []map[string]interface{} {
result := make([]map[string]interface{}, 0)
for _, x := range runCommand.RunCommandTargets {
config := make(map[string]interface{})
config["key"] = *x.Key
config["values"] = flattenStringList(x.Values)
result = append(result, config)
}
return result
}

View File

@ -18,7 +18,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) {
Providers: testAccProviders, Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy, CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ {
Config: testAccAWSCloudWatchEventTargetConfig, Config: testAccAWSCloudWatchEventTargetConfig,
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target), testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -28,7 +28,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) {
regexp.MustCompile(":tf-acc-moon$")), regexp.MustCompile(":tf-acc-moon$")),
), ),
}, },
resource.TestStep{ {
Config: testAccAWSCloudWatchEventTargetConfigModified, Config: testAccAWSCloudWatchEventTargetConfigModified,
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target), testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -50,7 +50,7 @@ func TestAccAWSCloudWatchEventTarget_missingTargetId(t *testing.T) {
Providers: testAccProviders, Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy, CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ {
Config: testAccAWSCloudWatchEventTargetConfigMissingTargetId, Config: testAccAWSCloudWatchEventTargetConfigMissingTargetId,
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target), testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -71,7 +71,7 @@ func TestAccAWSCloudWatchEventTarget_full(t *testing.T) {
Providers: testAccProviders, Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy, CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ {
Config: testAccAWSCloudWatchEventTargetConfig_full, Config: testAccAWSCloudWatchEventTargetConfig_full,
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.foobar", &target), testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.foobar", &target),
@ -87,6 +87,24 @@ func TestAccAWSCloudWatchEventTarget_full(t *testing.T) {
}) })
} }
func TestAccAWSCloudWatchEventTarget_ssmDocument(t *testing.T) {
var target events.Target
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfigSsmDocument,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.test", &target),
),
},
},
})
}
func testAccCheckCloudWatchEventTargetExists(n string, rule *events.Target) resource.TestCheckFunc { func testAccCheckCloudWatchEventTargetExists(n string, rule *events.Target) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n] rs, ok := s.RootModule().Resources[n]
@ -126,17 +144,6 @@ func testAccCheckAWSCloudWatchEventTargetDestroy(s *terraform.State) error {
return nil return nil
} }
func testAccCheckTargetIdExists(targetId string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[targetId]
if !ok {
return fmt.Errorf("Not found: %s", targetId)
}
return nil
}
}
var testAccAWSCloudWatchEventTargetConfig = ` var testAccAWSCloudWatchEventTargetConfig = `
resource "aws_cloudwatch_event_rule" "foo" { resource "aws_cloudwatch_event_rule" "foo" {
name = "tf-acc-cw-event-rule-basic" name = "tf-acc-cw-event-rule-basic"
@ -249,3 +256,95 @@ resource "aws_kinesis_stream" "test_stream" {
shard_count = 1 shard_count = 1
} }
` `
var testAccAWSCloudWatchEventTargetConfigSsmDocument = `
resource "aws_ssm_document" "foo" {
name = "test_document-100"
document_type = "Command"
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_cloudwatch_event_rule" "console" {
name = "another_test"
description = "another_test"
event_pattern = <<PATTERN
{
"source": [
"aws.autoscaling"
]
}
PATTERN
}
resource "aws_cloudwatch_event_target" "test" {
arn = "${aws_ssm_document.foo.arn}"
rule = "${aws_cloudwatch_event_rule.console.id}"
role_arn = "${aws_iam_role.test_role.arn}"
run_command_targets {
key = "tag:Name"
values = ["acceptance_test"]
}
}
resource "aws_iam_role" "test_role" {
name = "test_role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "events.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy" "test_policy" {
name = "test_policy"
role = "${aws_iam_role.test_role.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "ssm:*",
"Effect": "Allow",
"Resource": [
"*"
]
}
]
}
EOF
}
`

View File

@ -27,6 +27,10 @@ func resourceAwsSsmDocument() *schema.Resource {
Delete: resourceAwsSsmDocumentDelete, Delete: resourceAwsSsmDocumentDelete,
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"name": { "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
@ -195,6 +199,9 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error
d.Set("name", doc.Name) d.Set("name", doc.Name)
d.Set("owner", doc.Owner) d.Set("owner", doc.Owner)
d.Set("platform_types", flattenStringList(doc.PlatformTypes)) d.Set("platform_types", flattenStringList(doc.PlatformTypes))
if err := d.Set("arn", flattenAwsSsmDocumentArn(meta, doc.Name)); err != nil {
return fmt.Errorf("[DEBUG] Error setting arn error: %#v", err)
}
d.Set("status", doc.Status) d.Set("status", doc.Status)
@ -238,6 +245,12 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error
return nil return nil
} }
func flattenAwsSsmDocumentArn(meta interface{}, docName *string) string {
region := meta.(*AWSClient).region
return fmt.Sprintf("arn:aws:ssm:%s::document/%s", region, *docName)
}
func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) error { func resourceAwsSsmDocumentUpdate(d *schema.ResourceData, meta interface{}) error {
if _, ok := d.GetOk("permissions"); ok { if _, ok := d.GetOk("permissions"); ok {

View File

@ -62,3 +62,11 @@ The following arguments are supported:
* `input` - (Optional) Valid JSON text passed to the target. * `input` - (Optional) Valid JSON text passed to the target.
* `input_path` - (Optional) The value of the [JSONPath](http://goessner.net/articles/JsonPath/) * `input_path` - (Optional) The value of the [JSONPath](http://goessner.net/articles/JsonPath/)
that is used for extracting part of the matched event when passing it to the target. that is used for extracting part of the matched event when passing it to the target.
* `role_arn` - (Optional) The Amazon Resource Name (ARN) of the IAM role to be used for this target when the rule is triggered.
* `run_command_targets` - (Optional) Parameters used when you are using the rule to invoke Amazon EC2 Run Command. Documented below. A maximum of 5 are allowed.
`run_command_parameters` support the following:
* `key` - (Required) Can be either `tag:tag-key` or `InstanceIds`.
* `values` - (Required) If Key is `tag:tag-key`, Values is a list of tag values. If Key is `InstanceIds`, Values is a list of Amazon EC2 instance IDs.