From a94ef62f00cc7efe2b62bd0602cbaddeb30914ef Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Mon, 27 Jan 2020 18:55:47 +0200 Subject: [PATCH 01/10] add plan time validation to `task_type`, `service_role_arn`, `targets.notification_arn`, `targets.service_role_arn` add `cloudwatch_config` argument --- ...esource_aws_ssm_maintenance_window_task.go | 76 +++++++++++++++++-- ...ce_aws_ssm_maintenance_window_task_test.go | 74 +++++++++++++++++- .../ssm_maintenance_window_task.html.markdown | 6 ++ 3 files changed, 147 insertions(+), 9 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index c4631d0f87b..c67277f43c0 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -44,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": { @@ -52,8 +58,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "service_role_arn": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validateArn, }, "targets": { @@ -190,8 +197,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": { @@ -242,14 +250,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, + }, + }, + }, + }, }, }, }, @@ -425,6 +451,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 } @@ -458,6 +488,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} } @@ -529,6 +562,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 diff --git a/aws/resource_aws_ssm_maintenance_window_task_test.go b/aws/resource_aws_ssm_maintenance_window_task_test.go index 989a119c636..4d02ceeef4b 100644 --- a/aws/resource_aws_ssm_maintenance_window_task_test.go +++ b/aws/resource_aws_ssm_maintenance_window_task_test.go @@ -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/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -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" @@ -296,7 +327,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 } @@ -306,7 +337,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 @@ -743,6 +774,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" { diff --git a/website/docs/r/ssm_maintenance_window_task.html.markdown b/website/docs/r/ssm_maintenance_window_task.html.markdown index 4978332f6e9..e521c0a1a55 100644 --- a/website/docs/r/ssm_maintenance_window_task.html.markdown +++ b/website/docs/r/ssm_maintenance_window_task.html.markdown @@ -178,6 +178,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: @@ -190,6 +191,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. From 4dbdd5689b41e5cf453eec44e8de172a35a9927e Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Fri, 3 Jul 2020 00:59:33 +0300 Subject: [PATCH 02/10] add disappears and test disabling logging --- ...esource_aws_ssm_maintenance_window_task.go | 16 +++--- ...ce_aws_ssm_maintenance_window_task_test.go | 51 +++++++++++++++++-- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index c67277f43c0..b6fbd8cedd8 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -633,7 +633,7 @@ func flattenAwsSsmTaskInvocationCommonParameters(parameters map[string][]*string } func resourceAwsSsmMaintenanceWindowTaskCreate(d *schema.ResourceData, meta interface{}) error { - ssmconn := meta.(*AWSClient).ssmconn + conn := meta.(*AWSClient).ssmconn log.Printf("[INFO] Registering SSM Maintenance Window Task") @@ -663,7 +663,7 @@ func resourceAwsSsmMaintenanceWindowTaskCreate(d *schema.ResourceData, meta inte params.TaskInvocationParameters = expandAwsSsmTaskInvocationParameters(v.([]interface{})) } - resp, err := ssmconn.RegisterTaskWithMaintenanceWindow(params) + resp, err := conn.RegisterTaskWithMaintenanceWindow(params) if err != nil { return err } @@ -674,14 +674,14 @@ func resourceAwsSsmMaintenanceWindowTaskCreate(d *schema.ResourceData, meta inte } func resourceAwsSsmMaintenanceWindowTaskRead(d *schema.ResourceData, meta interface{}) error { - ssmconn := meta.(*AWSClient).ssmconn + conn := meta.(*AWSClient).ssmconn windowID := d.Get("window_id").(string) params := &ssm.GetMaintenanceWindowTaskInput{ WindowId: aws.String(windowID), WindowTaskId: aws.String(d.Id()), } - resp, err := ssmconn.GetMaintenanceWindowTask(params) + resp, err := conn.GetMaintenanceWindowTask(params) if isAWSErr(err, ssm.ErrCodeDoesNotExistException, "") { log.Printf("[WARN] Maintenance Window (%s) Task (%s) not found, removing from state", windowID, d.Id()) d.SetId("") @@ -715,7 +715,7 @@ func resourceAwsSsmMaintenanceWindowTaskRead(d *schema.ResourceData, meta interf } func resourceAwsSsmMaintenanceWindowTaskUpdate(d *schema.ResourceData, meta interface{}) error { - ssmconn := meta.(*AWSClient).ssmconn + conn := meta.(*AWSClient).ssmconn windowID := d.Get("window_id").(string) params := &ssm.UpdateMaintenanceWindowTaskInput{ @@ -745,7 +745,7 @@ func resourceAwsSsmMaintenanceWindowTaskUpdate(d *schema.ResourceData, meta inte params.TaskInvocationParameters = expandAwsSsmTaskInvocationParameters(v.([]interface{})) } - _, err := ssmconn.UpdateMaintenanceWindowTask(params) + _, err := conn.UpdateMaintenanceWindowTask(params) if isAWSErr(err, ssm.ErrCodeDoesNotExistException, "") { log.Printf("[WARN] Maintenance Window (%s) Task (%s) not found, removing from state", windowID, d.Id()) d.SetId("") @@ -760,7 +760,7 @@ func resourceAwsSsmMaintenanceWindowTaskUpdate(d *schema.ResourceData, meta inte } func resourceAwsSsmMaintenanceWindowTaskDelete(d *schema.ResourceData, meta interface{}) error { - ssmconn := meta.(*AWSClient).ssmconn + conn := meta.(*AWSClient).ssmconn log.Printf("[INFO] Deregistering SSM Maintenance Window Task: %s", d.Id()) @@ -769,7 +769,7 @@ func resourceAwsSsmMaintenanceWindowTaskDelete(d *schema.ResourceData, meta inte WindowTaskId: aws.String(d.Id()), } - _, err := ssmconn.DeregisterTaskFromMaintenanceWindow(params) + _, err := conn.DeregisterTaskFromMaintenanceWindow(params) if isAWSErr(err, ssm.ErrCodeDoesNotExistException, "") { return nil } diff --git a/aws/resource_aws_ssm_maintenance_window_task_test.go b/aws/resource_aws_ssm_maintenance_window_task_test.go index 4d02ceeef4b..fb98987bba1 100644 --- a/aws/resource_aws_ssm_maintenance_window_task_test.go +++ b/aws/resource_aws_ssm_maintenance_window_task_test.go @@ -206,7 +206,7 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParametersCloudW CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(name), + Config: testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(name, true), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task), resource.TestCheckResourceAttrPair(resourceName, "service_role_arn", serviceRoleResourceName, "arn"), @@ -221,6 +221,25 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParametersCloudW ImportStateIdFunc: testAccAWSSSMMaintenanceWindowTaskImportStateIdFunc(resourceName), ImportStateVerify: true, }, + { + Config: testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(name, false), + 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.TestCheckResourceAttr(resourceName, "task_invocation_parameters.0.run_command_parameters.0.cloudwatch_config.0.cloudwatch_output_enabled", "false"), + ), + }, + { + Config: testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(name, true), + 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"), + ), + }, }, }) } @@ -272,6 +291,28 @@ func TestAccAWSSSMMaintenanceWindowTask_emptyNotificationConfig(t *testing.T) { }) } +func TestAccAWSSSMMaintenanceWindowTask_disappears(t *testing.T) { + var before ssm.MaintenanceWindowTask + resourceName := "aws_ssm_maintenance_window_task.test" + + name := acctest.RandString(10) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &before), + testAccCheckResourceDisappears(testAccProvider, resourceAwsSsmMaintenanceWindowTask(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + func testAccCheckAwsSsmWindowsTaskNotRecreated(t *testing.T, before, after *ssm.MaintenanceWindowTask) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -313,7 +354,7 @@ func testAccCheckAWSSSMMaintenanceWindowTaskExists(n string, task *ssm.Maintenan } for _, i := range resp.Tasks { - if *i.WindowTaskId == rs.Primary.ID { + if aws.StringValue(i.WindowTaskId) == rs.Primary.ID { *task = *i return nil } @@ -774,7 +815,7 @@ resource "aws_ssm_maintenance_window_task" "test" { `, rName, comment, timeoutSeconds) } -func testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(rName string) string { +func testAccAWSSSMMaintenanceWindowTaskRunCommandCloudWatchConfig(rName string, enabled bool) string { return fmt.Sprintf(testAccAWSSSMMaintenanceWindowTaskConfigBase(rName)+` resource "aws_cloudwatch_log_group" "test" { name = %[1]q @@ -803,12 +844,12 @@ resource "aws_ssm_maintenance_window_task" "test" { } cloudwatch_config { cloudwatch_log_group_name = "${aws_cloudwatch_log_group.test.name}" - cloudwatch_output_enabled = true + cloudwatch_output_enabled = %[2]t } } } } -`, rName) +`, rName, enabled) } func testAccAWSSSMMaintenanceWindowTaskStepFunctionConfig(rName string) string { From 67c2ca999178fe66b41715ce1076ecf862d8864b Mon Sep 17 00:00:00 2001 From: DrFaust92 Date: Fri, 3 Jul 2020 01:15:40 +0300 Subject: [PATCH 03/10] add computed to cloudwatch --- aws/resource_aws_ssm_maintenance_window_task.go | 1 + 1 file changed, 1 insertion(+) diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index b6fbd8cedd8..a230e2b1ab0 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -268,6 +268,7 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "cloudwatch_log_group_name": { Type: schema.TypeString, Optional: true, + Computed: true, }, "cloudwatch_output_enabled": { Type: schema.TypeBool, From de9f7f67b70b3ef1ab7559215f99c5d08b091073 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Wed, 30 Sep 2020 15:46:31 +0300 Subject: [PATCH 04/10] use enum slices --- ...esource_aws_ssm_maintenance_window_task.go | 38 +++++++------------ aws/validators.go | 13 ------- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index a230e2b1ab0..0ca8e8cdab4 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -41,15 +41,10 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "task_type": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - ssm.MaintenanceWindowTaskTypeRunCommand, - ssm.MaintenanceWindowTaskTypeAutomation, - ssm.MaintenanceWindowTaskTypeStepFunctions, - ssm.MaintenanceWindowTaskTypeLambda, - }, false), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(ssm.MaintenanceWindowTaskType_Values(), false), }, "task_arn": { @@ -82,9 +77,10 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "name": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateAwsSSMMaintenanceWindowTaskName, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9_\-.]{3,128}$`), + "Only alphanumeric characters, hyphens, dots & underscores allowed."), }, "description": { @@ -182,12 +178,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "document_hash_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - ssm.DocumentHashTypeSha256, - ssm.DocumentHashTypeSha1, - }, false), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(ssm.DocumentHashType_Values(), false), }, "notification_config": { @@ -209,12 +202,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "notification_type": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{ - ssm.NotificationTypeCommand, - ssm.NotificationTypeInvocation, - }, false), + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(ssm.NotificationType_Values(), false), }, }, }, diff --git a/aws/validators.go b/aws/validators.go index 14f80bb226b..61cd136d114 100644 --- a/aws/validators.go +++ b/aws/validators.go @@ -1915,19 +1915,6 @@ func validateAwsSSMName(v interface{}, k string) (ws []string, errors []error) { return } -func validateAwsSSMMaintenanceWindowTaskName(v interface{}, k string) (ws []string, errors []error) { - // https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_RegisterTaskWithMaintenanceWindow.html#systemsmanager-RegisterTaskWithMaintenanceWindow-request-Name - value := v.(string) - - if !regexp.MustCompile(`^[a-zA-Z0-9_\-.]{3,128}$`).MatchString(value) { - errors = append(errors, fmt.Errorf( - "Only alphanumeric characters, hyphens, dots & underscores allowed in %q: %q (Must satisfy regular expression pattern: ^[a-zA-Z0-9_\\-.]{3,128}$)", - k, value)) - } - - return -} - func validateBatchName(v interface{}, k string) (ws []string, errors []error) { value := v.(string) if !regexp.MustCompile(`^[0-9a-zA-Z]{1}[0-9a-zA-Z_\-]{0,127}$`).MatchString(value) { From 5e7f14ccad693e362bed3a18adb64b9bec6f47aa Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Wed, 30 Sep 2020 15:52:15 +0300 Subject: [PATCH 05/10] fmt test --- ...ce_aws_ssm_maintenance_window_task_test.go | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task_test.go b/aws/resource_aws_ssm_maintenance_window_task_test.go index fb98987bba1..e722ee9b346 100644 --- a/aws/resource_aws_ssm_maintenance_window_task_test.go +++ b/aws/resource_aws_ssm_maintenance_window_task_test.go @@ -822,28 +822,32 @@ resource "aws_cloudwatch_log_group" "test" { } 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" + 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}"] + values = [aws_ssm_maintenance_window_target.test.id] } + task_invocation_parameters { run_command_parameters { - document_hash = "${sha256("COMMAND")}" + document_hash = sha256("COMMAND") document_hash_type = "Sha256" - service_role_arn = "${aws_iam_role.test.arn}" + service_role_arn = aws_iam_role.test.arn + parameter { - name = "commands" + name = "commands" values = ["date"] } + cloudwatch_config { - cloudwatch_log_group_name = "${aws_cloudwatch_log_group.test.name}" + cloudwatch_log_group_name = aws_cloudwatch_log_group.test.name cloudwatch_output_enabled = %[2]t } } From 85f37b0e41ddbd31271389efd622e18be76526bf Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Wed, 30 Sep 2020 16:38:18 +0300 Subject: [PATCH 06/10] fmt test --- aws/resource_aws_ssm_maintenance_window_task_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task_test.go b/aws/resource_aws_ssm_maintenance_window_task_test.go index e722ee9b346..28ebc7c6f08 100644 --- a/aws/resource_aws_ssm_maintenance_window_task_test.go +++ b/aws/resource_aws_ssm_maintenance_window_task_test.go @@ -837,9 +837,9 @@ resource "aws_ssm_maintenance_window_task" "test" { task_invocation_parameters { run_command_parameters { - document_hash = sha256("COMMAND") - document_hash_type = "Sha256" - service_role_arn = aws_iam_role.test.arn + document_hash = sha256("COMMAND") + document_hash_type = "Sha256" + service_role_arn = aws_iam_role.test.arn parameter { name = "commands" @@ -847,8 +847,8 @@ resource "aws_ssm_maintenance_window_task" "test" { } cloudwatch_config { - cloudwatch_log_group_name = aws_cloudwatch_log_group.test.name - cloudwatch_output_enabled = %[2]t + cloudwatch_log_group_name = aws_cloudwatch_log_group.test.name + cloudwatch_output_enabled = %[2]t } } } From f38dcc29bbe9f192d3a0253333afd6a32ed12abb Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Thu, 11 Feb 2021 22:25:29 +0200 Subject: [PATCH 07/10] changelog --- .changelog/11774.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/11774.txt diff --git a/.changelog/11774.txt b/.changelog/11774.txt new file mode 100644 index 00000000000..f01b6726a74 --- /dev/null +++ b/.changelog/11774.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_ssm_maintenance_window_task: Add `cloudwatch_config` argument +``` + +```release-note:enhancement +resource/aws_ssm_maintenance_window_task: Add plan time validation to `task_type`, `service_role_arn`, `targets.notification_arn`, `targets.service_role_arn` +``` \ No newline at end of file From b61fab5ef3c0226059d14f4a5143cae5c3570be3 Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Thu, 11 Feb 2021 22:50:39 +0200 Subject: [PATCH 08/10] changelog + validations --- .changelog/11774.txt | 7 ++- ...esource_aws_ssm_maintenance_window_task.go | 62 ++++++++++++++----- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/.changelog/11774.txt b/.changelog/11774.txt index f01b6726a74..30fd624d326 100644 --- a/.changelog/11774.txt +++ b/.changelog/11774.txt @@ -3,5 +3,10 @@ resource/aws_ssm_maintenance_window_task: Add `cloudwatch_config` argument ``` ```release-note:enhancement -resource/aws_ssm_maintenance_window_task: Add plan time validation to `task_type`, `service_role_arn`, `targets.notification_arn`, `targets.service_role_arn` +resource/aws_ssm_maintenance_window_task: Add `document_version` argument +``` + +```release-note:enhancement +resource/aws_ssm_maintenance_window_task: Add plan time validation to `task_type`, `service_role_arn`, `targets.notification_arn`, `targets.service_role_arn`, `max_concurrency`, `max_errors`, `targets`, `priority`, +`task_invocation_parameters.run_command_parameters.comment`, `task_invocation_parameters.run_command_parameters.document_hash`, `task_invocation_parameters.run_command_parameters.timeout_seconds`, `task_invocation_parameters.run_command_parameters.notification_config.notification_events` ``` \ No newline at end of file diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index 0ca8e8cdab4..331d20e7013 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -31,13 +31,15 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "max_concurrency": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), ""), }, "max_errors": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`), ""), }, "task_type": { @@ -60,7 +62,8 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "targets": { Type: schema.TypeList, - Required: true, + Optional: true, + MaxItems: 5, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "key": { @@ -70,6 +73,7 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "values": { Type: schema.TypeList, Required: true, + MaxItems: 50, Elem: &schema.Schema{Type: schema.TypeString}, }, }, @@ -90,8 +94,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "priority": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(0), }, "task_invocation_parameters": { @@ -168,13 +173,15 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "comment": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 100), }, "document_hash": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 256), }, "document_hash_type": { @@ -182,6 +189,11 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { Optional: true, ValidateFunc: validation.StringInSlice(ssm.DocumentHashType_Values(), false), }, + "document_version": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`([$]LATEST|[$]DEFAULT|^[1-9][0-9]*$)`), ""), + }, "notification_config": { Type: schema.TypeList, @@ -198,7 +210,17 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "notification_events": { Type: schema.TypeList, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "All", + "InProgress", + "Success", + "TimedOut", + "Cancelled", + "Failed", + }, false), + }, }, "notification_type": { @@ -246,8 +268,9 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { }, "timeout_seconds": { - Type: schema.TypeInt, - Optional: true, + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(30, 2592000), }, "cloudwatch_config": { Type: schema.TypeList, @@ -424,6 +447,9 @@ func expandAwsSsmTaskInvocationRunCommandParameters(config []interface{}) *ssm.M if attr, ok := configParam["document_hash_type"]; ok && len(attr.(string)) != 0 { params.DocumentHashType = aws.String(attr.(string)) } + if attr, ok := configParam["document_version"]; ok && len(attr.(string)) != 0 { + params.DocumentVersion = aws.String(attr.(string)) + } if attr, ok := configParam["notification_config"]; ok && len(attr.([]interface{})) > 0 { params.NotificationConfig = expandAwsSsmTaskInvocationRunCommandParametersNotificationConfig(attr.([]interface{})) } @@ -461,6 +487,9 @@ func flattenAwsSsmTaskInvocationRunCommandParameters(parameters *ssm.Maintenance if parameters.DocumentHashType != nil { result["document_hash_type"] = aws.StringValue(parameters.DocumentHashType) } + if parameters.DocumentVersion != nil { + result["document_version"] = aws.StringValue(parameters.DocumentVersion) + } if parameters.NotificationConfig != nil { result["notification_config"] = flattenAwsSsmTaskInvocationRunCommandParametersNotificationConfig(parameters.NotificationConfig) } @@ -635,7 +664,10 @@ func resourceAwsSsmMaintenanceWindowTaskCreate(d *schema.ResourceData, meta inte TaskType: aws.String(d.Get("task_type").(string)), ServiceRoleArn: aws.String(d.Get("service_role_arn").(string)), TaskArn: aws.String(d.Get("task_arn").(string)), - Targets: expandAwsSsmTargets(d.Get("targets").([]interface{})), + } + + if v, ok := d.GetOk("targets"); ok { + params.Targets = expandAwsSsmTargets(v.([]interface{})) } if v, ok := d.GetOk("name"); ok { From b5b7f45bfc1754132277c823b9d8fa71f86a54dc Mon Sep 17 00:00:00 2001 From: drfaust92 Date: Thu, 11 Feb 2021 23:01:03 +0200 Subject: [PATCH 09/10] tests --- ...ce_aws_ssm_maintenance_window_task_test.go | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/aws/resource_aws_ssm_maintenance_window_task_test.go b/aws/resource_aws_ssm_maintenance_window_task_test.go index 28ebc7c6f08..c28ece1aa32 100644 --- a/aws/resource_aws_ssm_maintenance_window_task_test.go +++ b/aws/resource_aws_ssm_maintenance_window_task_test.go @@ -15,23 +15,23 @@ func TestAccAWSSSMMaintenanceWindowTask_basic(t *testing.T) { var before, after ssm.MaintenanceWindowTask resourceName := "aws_ssm_maintenance_window_task.test" - name := acctest.RandString(10) + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name), + Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &before), ), }, { - Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdate(name, "test description", "RUN_COMMAND", "AWS-InstallPowerShellModule", 3, 3, 2), + Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdate(rName, "test description", "RUN_COMMAND", "AWS-InstallPowerShellModule", 3, 3, 2), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &after), - resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("maintenance-window-task-%s", name)), + resource.TestCheckResourceAttr(resourceName, "name", fmt.Sprintf("maintenance-window-task-%s", rName)), resource.TestCheckResourceAttr(resourceName, "description", "test description"), resource.TestCheckResourceAttr(resourceName, "task_type", "RUN_COMMAND"), resource.TestCheckResourceAttr(resourceName, "task_arn", "AWS-InstallPowerShellModule"), @@ -53,7 +53,7 @@ func TestAccAWSSSMMaintenanceWindowTask_basic(t *testing.T) { func TestAccAWSSSMMaintenanceWindowTask_updateForcesNewResource(t *testing.T) { var before, after ssm.MaintenanceWindowTask - name := acctest.RandString(10) + rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_ssm_maintenance_window_task.test" resource.ParallelTest(t, resource.TestCase{ @@ -62,13 +62,13 @@ func TestAccAWSSSMMaintenanceWindowTask_updateForcesNewResource(t *testing.T) { CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(name), + Config: testAccAWSSSMMaintenanceWindowTaskBasicConfig(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &before), ), }, { - Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(name), + Config: testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdated(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &after), resource.TestCheckResourceAttr(resourceName, "name", "TestMaintenanceWindowTask"), @@ -90,21 +90,21 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationAutomationParameters(t *te var task ssm.MaintenanceWindowTask resourceName := "aws_ssm_maintenance_window_task.test" - name := acctest.RandString(10) + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMMaintenanceWindowTaskAutomationConfig(name, "$DEFAULT"), + Config: testAccAWSSSMMaintenanceWindowTaskAutomationConfig(rName, "$DEFAULT"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task), resource.TestCheckResourceAttr(resourceName, "task_invocation_parameters.0.automation_parameters.0.document_version", "$DEFAULT"), ), }, { - Config: testAccAWSSSMMaintenanceWindowTaskAutomationConfigUpdate(name, "$LATEST"), + Config: testAccAWSSSMMaintenanceWindowTaskAutomationConfigUpdate(rName, "$LATEST"), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task), resource.TestCheckResourceAttr(resourceName, "task_invocation_parameters.0.automation_parameters.0.document_version", "$LATEST"), @@ -156,16 +156,16 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParameters(t *te var task ssm.MaintenanceWindowTask resourceName := "aws_ssm_maintenance_window_task.test" serviceRoleResourceName := "aws_iam_role.test" - s3BucketResourceName := "aws_s3_bucket.foo" + s3BucketResourceName := "aws_s3_bucket.test" - name := acctest.RandString(10) + rName := acctest.RandomWithPrefix("tf-acc-test") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckAWSSSMMaintenanceWindowTaskDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSSSMMaintenanceWindowTaskRunCommandConfig(name, "test comment", 30), + Config: testAccAWSSSMMaintenanceWindowTaskRunCommandConfig(rName, "test comment", 30), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task), resource.TestCheckResourceAttrPair(resourceName, "service_role_arn", serviceRoleResourceName, "arn"), @@ -175,7 +175,7 @@ func TestAccAWSSSMMaintenanceWindowTask_TaskInvocationRunCommandParameters(t *te ), }, { - Config: testAccAWSSSMMaintenanceWindowTaskRunCommandConfigUpdate(name, "test comment update", 60), + Config: testAccAWSSSMMaintenanceWindowTaskRunCommandConfigUpdate(rName, "test comment update", 60), Check: resource.ComposeTestCheckFunc( testAccCheckAWSSSMMaintenanceWindowTaskExists(resourceName, &task), resource.TestCheckResourceAttr(resourceName, "task_invocation_parameters.0.run_command_parameters.0.comment", "test comment update"), @@ -499,10 +499,10 @@ func testAccAWSSSMMaintenanceWindowTaskBasicConfigUpdate(rName, description, tas resource "aws_ssm_maintenance_window_task" "test" { window_id = aws_ssm_maintenance_window.test.id - task_type = "%[2]s" - task_arn = "%[3]s" + task_type = %[2]q + task_arn = %[3]q name = "maintenance-window-task-%[1]s" - description = "%[4]s" + description = %[4]q priority = %[5]d service_role_arn = aws_iam_role.ssm_role_update.arn max_concurrency = %[6]d @@ -646,7 +646,7 @@ resource "aws_ssm_maintenance_window_task" "test" { task_invocation_parameters { automation_parameters { - document_version = "%[2]s" + document_version = %[2]q parameter { name = "InstanceId" @@ -665,8 +665,8 @@ resource "aws_ssm_maintenance_window_task" "test" { func testAccAWSSSMMaintenanceWindowTaskAutomationConfigUpdate(rName, version string) string { return fmt.Sprintf(testAccAWSSSMMaintenanceWindowTaskConfigBase(rName)+` -resource "aws_s3_bucket" "foo" { - bucket = "tf-s3-%[1]s" +resource "aws_s3_bucket" "test" { + bucket = %[1]q acl = "private" force_destroy = true } @@ -687,7 +687,7 @@ resource "aws_ssm_maintenance_window_task" "test" { task_invocation_parameters { automation_parameters { - document_version = "%[2]s" + document_version = %[2]q parameter { name = "InstanceId" @@ -757,7 +757,7 @@ resource "aws_ssm_maintenance_window_task" "test" { task_invocation_parameters { run_command_parameters { - comment = "%[2]s" + comment = %[2]q document_hash = sha256("COMMAND") document_hash_type = "Sha256" service_role_arn = aws_iam_role.test.arn @@ -775,8 +775,8 @@ resource "aws_ssm_maintenance_window_task" "test" { func testAccAWSSSMMaintenanceWindowTaskRunCommandConfigUpdate(rName, comment string, timeoutSeconds int) string { return fmt.Sprintf(testAccAWSSSMMaintenanceWindowTaskConfigBase(rName)+` -resource "aws_s3_bucket" "foo" { - bucket = "tf-s3-%[1]s" +resource "aws_s3_bucket" "test" { + bucket = %[1]q acl = "private" force_destroy = true } @@ -797,12 +797,12 @@ resource "aws_ssm_maintenance_window_task" "test" { task_invocation_parameters { run_command_parameters { - comment = "%[2]s" + comment = %[2]q document_hash = sha256("COMMAND") document_hash_type = "Sha256" service_role_arn = aws_iam_role.test.arn timeout_seconds = %[3]d - output_s3_bucket = aws_s3_bucket.foo.id + output_s3_bucket = aws_s3_bucket.test.id output_s3_key_prefix = "foo" parameter { From 4abf9d232251ffa20052de5bc55aaf4a563457af Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Thu, 11 Feb 2021 18:56:03 -0500 Subject: [PATCH 10/10] Apply suggestions from code review --- .changelog/11774.txt | 9 ++------- aws/resource_aws_ssm_maintenance_window_task.go | 17 +++++------------ 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/.changelog/11774.txt b/.changelog/11774.txt index 30fd624d326..82746db52db 100644 --- a/.changelog/11774.txt +++ b/.changelog/11774.txt @@ -1,12 +1,7 @@ ```release-note:enhancement -resource/aws_ssm_maintenance_window_task: Add `cloudwatch_config` argument +resource/aws_ssm_maintenance_window_task: Add `task_invocation_parameters` `run_command_parameters` block `cloudwatch_config` and `document_version` arguments ``` ```release-note:enhancement -resource/aws_ssm_maintenance_window_task: Add `document_version` argument +resource/aws_ssm_maintenance_window_task: Add plan time validation to `max_concurrency`, `max_errors`, `priority`, `service_role_arn`, `targets`, `targets.notification_arn`, `targets.service_role_arn`, `task_type`, `task_invocation_parameters.run_command_parameters.comment`, `task_invocation_parameters.run_command_parameters.document_hash`, `task_invocation_parameters.run_command_parameters.timeout_seconds`, and `task_invocation_parameters.run_command_parameters.notification_config.notification_events` arguments ``` - -```release-note:enhancement -resource/aws_ssm_maintenance_window_task: Add plan time validation to `task_type`, `service_role_arn`, `targets.notification_arn`, `targets.service_role_arn`, `max_concurrency`, `max_errors`, `targets`, `priority`, -`task_invocation_parameters.run_command_parameters.comment`, `task_invocation_parameters.run_command_parameters.document_hash`, `task_invocation_parameters.run_command_parameters.timeout_seconds`, `task_invocation_parameters.run_command_parameters.notification_config.notification_events` -``` \ No newline at end of file diff --git a/aws/resource_aws_ssm_maintenance_window_task.go b/aws/resource_aws_ssm_maintenance_window_task.go index 331d20e7013..e79b9d3df86 100644 --- a/aws/resource_aws_ssm_maintenance_window_task.go +++ b/aws/resource_aws_ssm_maintenance_window_task.go @@ -33,13 +33,13 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "max_concurrency": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), ""), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), "must be a number without leading zeros or a percentage between 1% and 100% without leading zeros and ending with the percentage symbol"), }, "max_errors": { Type: schema.TypeString, Required: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`), ""), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`), "must be zero, a number without leading zeros, or a percentage between 1% and 100% without leading zeros and ending with the percentage symbol"), }, "task_type": { @@ -192,7 +192,7 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { "document_version": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`([$]LATEST|[$]DEFAULT|^[1-9][0-9]*$)`), ""), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`([$]LATEST|[$]DEFAULT|^[1-9][0-9]*$)`), "must be $DEFAULT, $LATEST, or a version number"), }, "notification_config": { @@ -211,15 +211,8 @@ func resourceAwsSsmMaintenanceWindowTask() *schema.Resource { Type: schema.TypeList, Optional: true, Elem: &schema.Schema{ - Type: schema.TypeString, - ValidateFunc: validation.StringInSlice([]string{ - "All", - "InProgress", - "Success", - "TimedOut", - "Cancelled", - "Failed", - }, false), + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice(ssm.NotificationEvent_Values(), false), }, },