Skip to content

Commit

Permalink
add plan time validation to task_type, service_role_arn, `targets…
Browse files Browse the repository at this point in the history
….notification_arn`, `targets.service_role_arn`

add `cloudwatch_config` argument
  • Loading branch information
DrFaust92 committed Jan 27, 2020
1 parent 42d63b3 commit 979825f
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 11 deletions.
79 changes: 71 additions & 8 deletions aws/resource_aws_ssm_maintenance_window_task.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ import (
"sort"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/helper/validation"

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

func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
Expand Down Expand Up @@ -45,6 +44,12 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
ssm.MaintenanceWindowTaskTypeRunCommand,
ssm.MaintenanceWindowTaskTypeAutomation,
ssm.MaintenanceWindowTaskTypeStepFunctions,
ssm.MaintenanceWindowTaskTypeLambda,
}, false),
},

"task_arn": {
Expand All @@ -53,8 +58,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
},

"service_role_arn": {
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Required: true,
ValidateFunc: validateArn,
},

"targets": {
Expand Down Expand Up @@ -236,8 +242,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"notification_arn": {
Type: schema.TypeString,
Optional: true,
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},

"notification_events": {
Expand Down Expand Up @@ -288,14 +295,32 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource {
},

"service_role_arn": {
Type: schema.TypeString,
Optional: true,
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},

"timeout_seconds": {
Type: schema.TypeInt,
Optional: true,
},
"cloudwatch_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cloudwatch_log_group_name": {
Type: schema.TypeString,
Optional: true,
},
"cloudwatch_output_enabled": {
Type: schema.TypeBool,
Optional: true,
},
},
},
},
},
},
},
Expand Down Expand Up @@ -527,6 +552,10 @@ func expandAwsSsmTaskInvocationRunCommandParameters(config []interface{}) *ssm.M
if attr, ok := configParam["timeout_seconds"]; ok && attr.(int) != 0 {
params.TimeoutSeconds = aws.Int64(int64(attr.(int)))
}

if attr, ok := configParam["cloudwatch_config"]; ok && len(attr.([]interface{})) > 0 {
params.CloudWatchOutputConfig = expandAwsSsmTaskInvocationRunCommandParametersCloudWatchConfig(attr.([]interface{}))
}
return params
}

Expand Down Expand Up @@ -560,6 +589,9 @@ func flattenAwsSsmTaskInvocationRunCommandParameters(parameters *ssm.Maintenance
if parameters.TimeoutSeconds != nil {
result["timeout_seconds"] = aws.Int64Value(parameters.TimeoutSeconds)
}
if parameters.CloudWatchOutputConfig != nil {
result["cloudwatch_config"] = flattenAwsSsmTaskInvocationRunCommandParametersCloudWatchConfig(parameters.CloudWatchOutputConfig)
}

return []interface{}{result}
}
Expand Down Expand Up @@ -631,6 +663,37 @@ func flattenAwsSsmTaskInvocationRunCommandParametersNotificationConfig(config *s
return []interface{}{result}
}

func expandAwsSsmTaskInvocationRunCommandParametersCloudWatchConfig(config []interface{}) *ssm.CloudWatchOutputConfig {
if len(config) == 0 || config[0] == nil {
return nil
}

params := &ssm.CloudWatchOutputConfig{}
configParam := config[0].(map[string]interface{})

if attr, ok := configParam["cloudwatch_log_group_name"]; ok && len(attr.(string)) != 0 {
params.CloudWatchLogGroupName = aws.String(attr.(string))
}
if attr, ok := configParam["cloudwatch_output_enabled"]; ok {
params.CloudWatchOutputEnabled = aws.Bool(attr.(bool))
}

return params
}

func flattenAwsSsmTaskInvocationRunCommandParametersCloudWatchConfig(config *ssm.CloudWatchOutputConfig) []interface{} {
result := make(map[string]interface{})

if config.CloudWatchLogGroupName != nil {
result["cloudwatch_log_group_name"] = aws.StringValue(config.CloudWatchLogGroupName)
}
if config.CloudWatchOutputEnabled != nil {
result["cloudwatch_output_enabled"] = aws.BoolValue(config.CloudWatchOutputEnabled)
}

return []interface{}{result}
}

func expandAwsSsmTaskInvocationCommonParameters(config []interface{}) map[string][]*string {
if len(config) == 0 || config[0] == nil {
return nil
Expand Down
74 changes: 71 additions & 3 deletions aws/resource_aws_ssm_maintenance_window_task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"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-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
Expand Down Expand Up @@ -194,6 +193,38 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParameters(t *te
})
}

func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParametersCloudWatch(t *testing.T) {
var task ssm.MaintenanceWindowTask
resourceName := "aws_ssm_maintenance_window_task.test"
serviceRoleResourceName := "aws_iam_role.test"
cwResourceName := "aws_cloudwatch_log_group.test"

name := acctest.RandString(10)
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(name),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task),
resource.TestCheckResourceAttrPair(resourceName, "service_role_arn", serviceRoleResourceName, "arn"),
resource.TestCheckResourceAttrPair(resourceName, "task_invocation_parameters.0.run_command_parameters.0.service_role_arn", serviceRoleResourceName, "arn"),
resource.TestCheckResourceAttrPair(resourceName, "task_invocation_parameters.0.run_command_parameters.0.cloudwatch_config.0.cloudwatch_log_group_name", cwResourceName, "name"),
resource.TestCheckResourceAttr(resourceName, "task_invocation_parameters.0.run_command_parameters.0.cloudwatch_config.0.cloudwatch_output_enabled", "true"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateIdFunc: testAccAWSSSMMaintenanceWindowTaskImportStateIdFunc(resourceName),
ImportStateVerify: true,
},
},
})
}

func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationStepFunctionParameters(t *testing.T) {
var task ssm.MaintenanceWindowTask
resourceName := "aws_ssm_maintenance_window_task.test"
Expand Down Expand Up @@ -322,7 +353,7 @@ func testAccCheckAWSSSMMaintenanceWindowTaskDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ssmconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_ssm_maintenance_window_target" {
if rs.Type != "aws_ssm_maintenance_window_task" {
continue
}

Expand All @@ -332,7 +363,7 @@ func testAccCheckAWSSSMMaintenanceWindowTaskDestroy(s *terraform.State) error {

if err != nil {
// Verify the error is what we want
if ae, ok := err.(awserr.Error); ok && ae.Code() == "DoesNotExistException" {
if isAWSErr(err, ssm.ErrCodeDoesNotExistException, "") {
continue
}
return err
Expand Down Expand Up @@ -737,6 +768,43 @@ resource "aws_ssm_maintenance_window_task" "test" {
`, rName, comment, timeoutSeconds)
}

func testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(rName string) string {
return fmt.Sprintf(testAccAWSSSMMaintenanceWindowTaskConfigBase(rName)+`
resource "aws_cloudwatch_log_group" "test" {
name = %[1]q
}
resource "aws_ssm_maintenance_window_task" "test" {
window_id = "${aws_ssm_maintenance_window.test.id}"
task_type = "RUN_COMMAND"
task_arn = "AWS-RunShellScript"
priority = 1
service_role_arn = "${aws_iam_role.test.arn}"
max_concurrency = "2"
max_errors = "1"
targets {
key = "WindowTargetIds"
values = ["${aws_ssm_maintenance_window_target.test.id}"]
}
task_invocation_parameters {
run_command_parameters {
document_hash = "${sha256("COMMAND")}"
document_hash_type = "Sha256"
service_role_arn = "${aws_iam_role.test.arn}"
parameter {
name = "commands"
values = ["date"]
}
cloudwatch_config {
cloudwatch_log_group_name = "${aws_cloudwatch_log_group.test.name}"
cloudwatch_output_enabled = true
}
}
}
}
`, rName)
}

func testAccAWSSSMMaintenanceWindowTaskStepFunctionConfig(rName string) string {
return testAccAWSSSMMaintenanceWindowTaskConfigBase(rName) + fmt.Sprintf(`
resource "aws_sfn_activity" "test" {
Expand Down
6 changes: 6 additions & 0 deletions website/docs/r/ssm_maintenance_window_task.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ The following arguments are supported:
* `parameter` - (Optional) The parameters for the RUN_COMMAND task execution. Documented below.
* `service_role_arn` - (Optional) The IAM service role to assume during task execution.
* `timeout_seconds` - (Optional) If this time is reached and the command has not already started executing, it doesn't run.
* `cloudwatch_config` - (Optional) Configuration options for sending command output to CloudWatch Logs. Documented below.

`step_functions_parameters` supports the following:

Expand All @@ -203,6 +204,11 @@ The following arguments are supported:
* `notification_events` - (Optional) The different events for which you can receive notifications. Valid values: `All`, `InProgress`, `Success`, `TimedOut`, `Cancelled`, and `Failed`
* `notification_type` - (Optional) When specified with `Command`, receive notification when the status of a command changes. When specified with `Invocation`, for commands sent to multiple instances, receive notification on a per-instance basis when the status of a command changes. Valid values: `Command` and `Invocation`

`cloudwatch_config` supports the following:

* `cloudwatch_log_group_name` - (Optional) The name of the CloudWatch log group where you want to send command output. If you don't specify a group name, Systems Manager automatically creates a log group for you. The log group uses the following naming format: aws/ssm/SystemsManagerDocumentName.
* `cloudwatch_output_enabled` - (Optional) Enables Systems Manager to send command output to CloudWatch Logs.

`parameter` supports the following:

* `name` - (Required) The parameter name.
Expand Down

0 comments on commit 979825f

Please sign in to comment.