diff --git a/aws/resource_aws_ssm_maintenance_window.go b/aws/resource_aws_ssm_maintenance_window.go index aca2cad64e5..419768c0cbf 100644 --- a/aws/resource_aws_ssm_maintenance_window.go +++ b/aws/resource_aws_ssm_maintenance_window.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ssm" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) @@ -63,6 +64,12 @@ func resourceAwsSsmMaintenanceWindow() *schema.Resource { Optional: true, }, + "schedule_offset": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(1, 6), + }, + "start_date": { Type: schema.TypeString, Optional: true, @@ -100,6 +107,10 @@ func resourceAwsSsmMaintenanceWindowCreate(d *schema.ResourceData, meta interfac params.ScheduleTimezone = aws.String(v.(string)) } + if v, ok := d.GetOk("schedule_offset"); ok { + params.ScheduleOffset = aws.Int64(int64(v.(int))) + } + if v, ok := d.GetOk("start_date"); ok { params.StartDate = aws.String(v.(string)) } @@ -154,6 +165,10 @@ func resourceAwsSsmMaintenanceWindowUpdate(d *schema.ResourceData, meta interfac params.ScheduleTimezone = aws.String(v.(string)) } + if v, ok := d.GetOk("schedule_offset"); ok { + params.ScheduleOffset = aws.Int64(int64(v.(int))) + } + if v, ok := d.GetOk("start_date"); ok { params.StartDate = aws.String(v.(string)) } @@ -208,6 +223,7 @@ func resourceAwsSsmMaintenanceWindowRead(d *schema.ResourceData, meta interface{ d.Set("end_date", resp.EndDate) d.Set("name", resp.Name) d.Set("schedule_timezone", resp.ScheduleTimezone) + d.Set("schedule_offset", resp.ScheduleOffset) d.Set("schedule", resp.Schedule) d.Set("start_date", resp.StartDate) d.Set("description", resp.Description) diff --git a/aws/resource_aws_ssm_maintenance_window_test.go b/aws/resource_aws_ssm_maintenance_window_test.go index f954c4dc1aa..489b037b31b 100644 --- a/aws/resource_aws_ssm_maintenance_window_test.go +++ b/aws/resource_aws_ssm_maintenance_window_test.go @@ -96,6 +96,7 @@ func TestAccAWSSSMMaintenanceWindow_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "end_date", ""), resource.TestCheckResourceAttr(resourceName, "name", rName), resource.TestCheckResourceAttr(resourceName, "schedule_timezone", ""), + resource.TestCheckResourceAttr(resourceName, "schedule_offset", "0"), resource.TestCheckResourceAttr(resourceName, "schedule", "cron(0 16 ? * TUE *)"), resource.TestCheckResourceAttr(resourceName, "start_date", ""), resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), @@ -462,6 +463,39 @@ func TestAccAWSSSMMaintenanceWindow_ScheduleTimezone(t *testing.T) { }) } +func TestAccAWSSSMMaintenanceWindow_ScheduleOffset(t *testing.T) { + var maintenanceWindow1, maintenanceWindow2 ssm.MaintenanceWindowIdentity + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_ssm_maintenance_window.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMMaintenanceWindowDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMMaintenanceWindowConfigScheduleOffset(rName, 2), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMMaintenanceWindowExists(resourceName, &maintenanceWindow1), + resource.TestCheckResourceAttr(resourceName, "schedule_offset", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSSSMMaintenanceWindowConfigScheduleOffset(rName, 5), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMMaintenanceWindowExists(resourceName, &maintenanceWindow2), + resource.TestCheckResourceAttr(resourceName, "schedule_offset", "5"), + ), + }, + }, + }) +} + func TestAccAWSSSMMaintenanceWindow_StartDate(t *testing.T) { var maintenanceWindow1, maintenanceWindow2, maintenanceWindow3 ssm.MaintenanceWindowIdentity startDate1 := time.Now().UTC().Add(1 * time.Hour).Format(time.RFC3339) @@ -719,6 +753,18 @@ resource "aws_ssm_maintenance_window" "test" { `, rName, scheduleTimezone) } +func testAccAWSSSMMaintenanceWindowConfigScheduleOffset(rName string, scheduleOffset int) string { + return fmt.Sprintf(` +resource "aws_ssm_maintenance_window" "test" { + cutoff = 1 + duration = 3 + name = %q + schedule = "cron(0 16 ? * TUE *)" + schedule_offset = %d +} +`, rName, scheduleOffset) +} + func testAccAWSSSMMaintenanceWindowConfigStartDate(rName, startDate string) string { return fmt.Sprintf(` resource "aws_ssm_maintenance_window" "test" { diff --git a/website/docs/r/ssm_maintenance_window.html.markdown b/website/docs/r/ssm_maintenance_window.html.markdown index af0899bb009..41c0bee3794 100644 --- a/website/docs/r/ssm_maintenance_window.html.markdown +++ b/website/docs/r/ssm_maintenance_window.html.markdown @@ -34,6 +34,7 @@ The following arguments are supported: * `enabled` - (Optional) Whether the maintenance window is enabled. Default: `true`. * `end_date` - (Optional) Timestamp in [ISO-8601 extended format](https://www.iso.org/iso-8601-date-and-time-format.html) when to no longer run the maintenance window. * `schedule_timezone` - (Optional) Timezone for schedule in [Internet Assigned Numbers Authority (IANA) Time Zone Database format](https://www.iana.org/time-zones). For example: `America/Los_Angeles`, `etc/UTC`, or `Asia/Seoul`. +* `schedule_offset` - (Optional) The number of days to wait after the date and time specified by a CRON expression before running the maintenance window. * `start_date` - (Optional) Timestamp in [ISO-8601 extended format](https://www.iso.org/iso-8601-date-and-time-format.html) when to begin the maintenance window. * `tags` - (Optional) A map of tags to assign to the resource.