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/awserr"
events "github.com/aws/aws-sdk-go/service/cloudwatchevents"
"github.com/hashicorp/terraform/helper/validation"
)
func resourceAwsCloudWatchEventTarget() *schema.Resource {
@ -21,14 +22,14 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
Delete: resourceAwsCloudWatchEventTargetDelete,
Schema: map[string]*schema.Schema{
"rule": &schema.Schema{
"rule": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateCloudWatchEventRuleName,
},
"target_id": &schema.Schema{
"target_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -36,12 +37,12 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
ValidateFunc: validateCloudWatchEventTargetId,
},
"arn": &schema.Schema{
"arn": {
Type: schema.TypeString,
Required: true,
},
"input": &schema.Schema{
"input": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"input_path"},
@ -49,11 +50,36 @@ func resourceAwsCloudWatchEventTarget() *schema.Resource {
// but for built-in targets input may not be JSON
},
"input_path": &schema.Schema{
"input_path": {
Type: schema.TypeString,
Optional: true,
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)
log.Printf("[DEBUG] Creating CloudWatch Event Target: %s", input)
out, err := conn.PutTargets(input)
if err != nil {
@ -128,6 +155,13 @@ func resourceAwsCloudWatchEventTargetRead(d *schema.ResourceData, meta interface
d.Set("target_id", t.Id)
d.Set("input", t.Input)
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
}
@ -162,6 +196,7 @@ func resourceAwsCloudWatchEventTargetUpdate(d *schema.ResourceData, meta interfa
conn := meta.(*AWSClient).cloudwatcheventsconn
input := buildPutTargetInputStruct(d)
log.Printf("[DEBUG] Updating CloudWatch Event Target: %s", input)
_, err := conn.PutTargets(input)
if err != nil {
@ -203,6 +238,14 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
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{
Rule: aws.String(d.Get("rule").(string)),
Targets: []*events.Target{e},
@ -210,3 +253,39 @@ func buildPutTargetInputStruct(d *schema.ResourceData) *events.PutTargetsInput {
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,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -28,7 +28,7 @@ func TestAccAWSCloudWatchEventTarget_basic(t *testing.T) {
regexp.MustCompile(":tf-acc-moon$")),
),
},
resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfigModified,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -50,7 +50,7 @@ func TestAccAWSCloudWatchEventTarget_missingTargetId(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfigMissingTargetId,
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudWatchEventTargetExists("aws_cloudwatch_event_target.moobar", &target),
@ -71,7 +71,7 @@ func TestAccAWSCloudWatchEventTarget_full(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudWatchEventTargetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudWatchEventTargetConfig_full,
Check: resource.ComposeTestCheckFunc(
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 {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
@ -126,17 +144,6 @@ func testAccCheckAWSCloudWatchEventTargetDestroy(s *terraform.State) error {
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 = `
resource "aws_cloudwatch_event_rule" "foo" {
name = "tf-acc-cw-event-rule-basic"
@ -249,3 +256,95 @@ resource "aws_kinesis_stream" "test_stream" {
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,
Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Required: true,
@ -195,6 +199,9 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error
d.Set("name", doc.Name)
d.Set("owner", doc.Owner)
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)
@ -238,6 +245,12 @@ func resourceAwsSsmDocumentRead(d *schema.ResourceData, meta interface{}) error
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 {
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_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.
* `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.