diff --git a/azurerm/resource_arm_automation_schedule.go b/azurerm/resource_arm_automation_schedule.go index 2c6a6b0f6024..d8b1edcc559c 100644 --- a/azurerm/resource_arm_automation_schedule.go +++ b/azurerm/resource_arm_automation_schedule.go @@ -11,6 +11,7 @@ import ( "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -107,14 +108,87 @@ func resourceArmAutomationSchedule() *schema.Resource { //todo figure out how to validate this properly }, - //todo missing properties: week_days, month_days, month_week_day from advanced automation section + "week_days": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(automation.Monday), + string(automation.Tuesday), + string(automation.Wednesday), + string(automation.Thursday), + string(automation.Friday), + string(automation.Saturday), + string(automation.Sunday), + }, true), + }, + Set: set.HashStringIgnoreCase, + ConflictsWith: []string{"month_days", "monthly_occurrence"}, + }, + + "month_days": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeInt, + ValidateFunc: validate.IntBetweenAndNot(-1, 31, 0), + }, + Set: set.HashInt, + ConflictsWith: []string{"week_days", "monthly_occurrence"}, + }, + + "monthly_occurrence": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "day": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: suppress.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(automation.Monday), + string(automation.Tuesday), + string(automation.Wednesday), + string(automation.Thursday), + string(automation.Friday), + string(automation.Saturday), + string(automation.Sunday), + }, true), + }, + "occurrence": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validate.IntBetweenAndNot(-1, 5, 0), + }, + }, + }, + ConflictsWith: []string{"week_days", "month_days"}, + }, }, CustomizeDiff: func(diff *schema.ResourceDiff, v interface{}) error { + frequency := strings.ToLower(diff.Get("frequency").(string)) interval, _ := diff.GetOk("interval") - if strings.ToLower(diff.Get("frequency").(string)) == "onetime" && interval.(int) > 0 { - return fmt.Errorf("interval canot be set when frequency is not OneTime") + if frequency == "onetime" && interval.(int) > 0 { + return fmt.Errorf("`interval` cannot be set when frequency is `OneTime`") + } + + _, hasWeekDays := diff.GetOk("week_days") + if hasWeekDays && frequency != "week" { + return fmt.Errorf("`week_days` can only be set when frequency is `Week`") + } + + _, hasMonthDays := diff.GetOk("month_days") + if hasMonthDays && frequency != "month" { + return fmt.Errorf("`month_days` can only be set when frequency is `Month`") + } + + _, hasMonthlyOccurances := diff.GetOk("monthly_occurrence") + if hasMonthlyOccurances && frequency != "month" { + return fmt.Errorf("`monthly_occurrence` can only be set when frequency is `Month`") } _, hasAccount := diff.GetOk("automation_account_name") @@ -193,6 +267,16 @@ func resourceArmAutomationScheduleCreateUpdate(d *schema.ResourceData, meta inte properties.Interval = 1 } } + + //only pay attention to the advanced schedule fields if frequency is either Week or Month + if properties.Frequency == automation.Week || properties.Frequency == automation.Month { + advancedRef, err := expandArmAutomationScheduleAdvanced(d, d.Id() != "") + if err != nil { + return err + } + properties.AdvancedSchedule = advancedRef + } + _, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters) if err != nil { return err @@ -257,6 +341,18 @@ func resourceArmAutomationScheduleRead(d *schema.ResourceData, meta interface{}) if v := resp.TimeZone; v != nil { d.Set("timezone", v) } + + if v := resp.AdvancedSchedule; v != nil { + if err := d.Set("week_days", flattenArmAutomationScheduleAdvancedWeekDays(v)); err != nil { + return fmt.Errorf("Error setting `week_days`: %+v", err) + } + if err := d.Set("month_days", flattenArmAutomationScheduleAdvancedMonthDays(v)); err != nil { + return fmt.Errorf("Error setting `month_days`: %+v", err) + } + if err := d.Set("monthly_occurrence", flattenArmAutomationScheduleAdvancedMonthlyOccurrences(v)); err != nil { + return fmt.Errorf("Error setting `monthly_occurrence`: %+v", err) + } + } return nil } @@ -282,3 +378,81 @@ func resourceArmAutomationScheduleDelete(d *schema.ResourceData, meta interface{ return nil } + +func expandArmAutomationScheduleAdvanced(d *schema.ResourceData, isUpdate bool) (*automation.AdvancedSchedule, error) { + + expandedAdvancedSchedule := automation.AdvancedSchedule{} + + // If frequency is set to `Month` the `week_days` array cannot be set (even empty), otherwise the API returns an error. + // During update it can be set and it will not return an error. Workaround for the APIs behavior + if v, ok := d.GetOk("week_days"); ok { + weekDays := v.(*schema.Set).List() + expandedWeekDays := make([]string, len(weekDays)) + for i := range weekDays { + expandedWeekDays[i] = weekDays[i].(string) + } + expandedAdvancedSchedule.WeekDays = &expandedWeekDays + } else if isUpdate { + expandedAdvancedSchedule.WeekDays = &[]string{} + } + + // Same as above with `week_days` + if v, ok := d.GetOk("month_days"); ok { + monthDays := v.(*schema.Set).List() + expandedMonthDays := make([]int32, len(monthDays)) + for i := range monthDays { + expandedMonthDays[i] = int32(monthDays[i].(int)) + } + expandedAdvancedSchedule.MonthDays = &expandedMonthDays + } else if isUpdate { + expandedAdvancedSchedule.MonthDays = &[]int32{} + } + + monthlyOccurrences := d.Get("monthly_occurrence").([]interface{}) + expandedMonthlyOccurrences := make([]automation.AdvancedScheduleMonthlyOccurrence, len(monthlyOccurrences)) + for i := range monthlyOccurrences { + m := monthlyOccurrences[i].(map[string]interface{}) + occurrence := int32(m["occurrence"].(int)) + + expandedMonthlyOccurrences[i] = automation.AdvancedScheduleMonthlyOccurrence{ + Occurrence: &occurrence, + Day: automation.ScheduleDay(m["day"].(string)), + } + } + expandedAdvancedSchedule.MonthlyOccurrences = &expandedMonthlyOccurrences + + return &expandedAdvancedSchedule, nil +} + +func flattenArmAutomationScheduleAdvancedWeekDays(s *automation.AdvancedSchedule) *schema.Set { + flattenedWeekDays := schema.NewSet(set.HashStringIgnoreCase, []interface{}{}) + if weekDays := s.WeekDays; weekDays != nil { + for _, v := range *weekDays { + flattenedWeekDays.Add(v) + } + } + return flattenedWeekDays +} + +func flattenArmAutomationScheduleAdvancedMonthDays(s *automation.AdvancedSchedule) *schema.Set { + flattenedMonthDays := schema.NewSet(set.HashInt, []interface{}{}) + if monthDays := s.MonthDays; monthDays != nil { + for _, v := range *monthDays { + flattenedMonthDays.Add(int(v)) + } + } + return flattenedMonthDays +} + +func flattenArmAutomationScheduleAdvancedMonthlyOccurrences(s *automation.AdvancedSchedule) []map[string]interface{} { + flattenedMonthlyOccurrences := make([]map[string]interface{}, 0) + if monthlyOccurrences := s.MonthlyOccurrences; monthlyOccurrences != nil { + for _, v := range *monthlyOccurrences { + f := make(map[string]interface{}) + f["day"] = v.Day + f["occurrence"] = int(*v.Occurrence) + flattenedMonthlyOccurrences = append(flattenedMonthlyOccurrences, f) + } + } + return flattenedMonthlyOccurrences +} diff --git a/azurerm/resource_arm_automation_schedule_test.go b/azurerm/resource_arm_automation_schedule_test.go index 74479f97d8e1..06a6173c343a 100644 --- a/azurerm/resource_arm_automation_schedule_test.go +++ b/azurerm/resource_arm_automation_schedule_test.go @@ -2,13 +2,14 @@ package azurerm import ( "fmt" + "strconv" + "testing" + "time" + "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" - "strconv" - "testing" - "time" ) func TestAccAzureRMAutomationSchedule_oneTime_basic(t *testing.T) { @@ -174,6 +175,72 @@ func TestAccAzureRMAutomationSchedule_monthly(t *testing.T) { }) } +func TestAccAzureRMAutomationSchedule_weekly_advanced(t *testing.T) { + resourceName := "azurerm_automation_schedule.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationSchedule_recurring_advanced_week(ri, testLocation(), "Monday"), + Check: checkAccAzureRMAutomationSchedule_recurring_advanced_week(resourceName, "Monday"), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAutomationSchedule_monthly_advanced_by_day(t *testing.T) { + resourceName := "azurerm_automation_schedule.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationSchedule_recurring_advanced_month(ri, testLocation(), 2), + Check: checkAccAzureRMAutomationSchedule_recurring_advanced_month(resourceName, 2), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAutomationSchedule_monthly_advanced_by_week_day(t *testing.T) { + resourceName := "azurerm_automation_schedule.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationSchedule_recurring_advanced_month_week_day(ri, testLocation(), "Monday", 2), + Check: checkAccAzureRMAutomationSchedule_recurring_advanced_month_week_day(resourceName, "Monday", 2), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMAutomationScheduleDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*ArmClient).automationScheduleClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -263,7 +330,7 @@ func testAccAzureRMAutomationSchedule_oneTime_basic(rInt int, location string) s %s resource "azurerm_automation_schedule" "test" { - name = "acctestAS-%d" + name = "acctestAS-%d" resource_group_name = "${azurerm_resource_group.test.name}" automation_account_name = "${azurerm_automation_account.test.name}" frequency = "OneTime" @@ -288,7 +355,7 @@ func testAccAzureRMAutomationSchedule_oneTime_complete(rInt int, location, start %s resource "azurerm_automation_schedule" "test" { - name = "acctestAS-%d" + name = "acctestAS-%d" resource_group_name = "${azurerm_resource_group.test.name}" automation_account_name = "${azurerm_automation_account.test.name}" frequency = "OneTime" @@ -317,7 +384,7 @@ func testAccAzureRMAutomationSchedule_recurring_basic(rInt int, location, freque %s resource "azurerm_automation_schedule" "test" { - name = "acctestAS-%d" + name = "acctestAS-%d" resource_group_name = "${azurerm_resource_group.test.name}" automation_account_name = "${azurerm_automation_account.test.name}" frequency = "%s" @@ -338,3 +405,97 @@ func checkAccAzureRMAutomationSchedule_recurring_basic(resourceName string, freq resource.TestCheckResourceAttr(resourceName, "timezone", "UTC"), ) } + +func testAccAzureRMAutomationSchedule_recurring_advanced_week(rInt int, location string, weekDay string) string { + return fmt.Sprintf(` +%s + +resource "azurerm_automation_schedule" "test" { + name = "acctestAS-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + frequency = "Week" + interval = "1" + week_days = ["%s"] +} +`, testAccAzureRMAutomationSchedule_prerequisites(rInt, location), rInt, weekDay) +} + +func checkAccAzureRMAutomationSchedule_recurring_advanced_week(resourceName string, weekDay string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMAutomationScheduleExists("azurerm_automation_schedule.test"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), + resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), + resource.TestCheckResourceAttrSet(resourceName, "start_time"), + resource.TestCheckResourceAttr(resourceName, "frequency", "Week"), + resource.TestCheckResourceAttr(resourceName, "interval", "1"), + resource.TestCheckResourceAttr(resourceName, "timezone", "UTC"), + resource.TestCheckResourceAttr(resourceName, "week_days.#", "1"), + ) +} + +func testAccAzureRMAutomationSchedule_recurring_advanced_month(rInt int, location string, monthDay int) string { + return fmt.Sprintf(` +%s + +resource "azurerm_automation_schedule" "test" { + name = "acctestAS-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + frequency = "Month" + interval = "1" + month_days = [%d] +} +`, testAccAzureRMAutomationSchedule_prerequisites(rInt, location), rInt, monthDay) +} + +func checkAccAzureRMAutomationSchedule_recurring_advanced_month(resourceName string, monthDay int) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMAutomationScheduleExists("azurerm_automation_schedule.test"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), + resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), + resource.TestCheckResourceAttrSet(resourceName, "start_time"), + resource.TestCheckResourceAttr(resourceName, "frequency", "Month"), + resource.TestCheckResourceAttr(resourceName, "interval", "1"), + resource.TestCheckResourceAttr(resourceName, "timezone", "UTC"), + resource.TestCheckResourceAttr(resourceName, "month_days.#", "1"), + ) +} + +func testAccAzureRMAutomationSchedule_recurring_advanced_month_week_day(rInt int, location string, weekDay string, weekDayOccurrence int) string { + + return fmt.Sprintf(` +%s + +resource "azurerm_automation_schedule" "test" { + name = "acctestAS-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + frequency = "Month" + interval = "1" + + monthly_occurrence { + day = "%s" + occurrence = "%d" + } +} +`, testAccAzureRMAutomationSchedule_prerequisites(rInt, location), rInt, weekDay, weekDayOccurrence) +} + +func checkAccAzureRMAutomationSchedule_recurring_advanced_month_week_day(resourceName string, monthWeekDay string, monthWeekOccurrence int) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMAutomationScheduleExists("azurerm_automation_schedule.test"), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), + resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), + resource.TestCheckResourceAttrSet(resourceName, "start_time"), + resource.TestCheckResourceAttr(resourceName, "frequency", "Month"), + resource.TestCheckResourceAttr(resourceName, "interval", "1"), + resource.TestCheckResourceAttr(resourceName, "timezone", "UTC"), + resource.TestCheckResourceAttr(resourceName, "monthly_occurrence.#", "1"), + resource.TestCheckResourceAttr(resourceName, "monthly_occurrence.0.day", monthWeekDay), + resource.TestCheckResourceAttr(resourceName, "monthly_occurrence.0.occurrence", strconv.Itoa(monthWeekOccurrence)), + ) +} diff --git a/website/docs/r/automation_schedule.html.markdown b/website/docs/r/automation_schedule.html.markdown index 0d0180ecaf1a..87e4e6e9f8fd 100644 --- a/website/docs/r/automation_schedule.html.markdown +++ b/website/docs/r/automation_schedule.html.markdown @@ -31,11 +31,15 @@ resource "azurerm_automation_schedule" "example" { name = "tfex-automation-schedule" resource_group_name = "${azurerm_resource_group.example.name}" automation_account_name = "${azurerm_automation_account.example.name}" - frequency = "Hour" + frequency = "Week" interval = 1 timezone = "Central Europe Standard Time" start_time = "2014-04-15T18:00:15+02:00" description = "This is an example schedule" + + advanced_schedule { + week_days = ["Friday"] + } } ``` @@ -53,7 +57,7 @@ The following arguments are supported: * `description` - (Optional) A description for this Schedule. -* `interval` - (Optional) The number of `frequency`s between runs. Only valid for `Day`, `Hour`, `Week`, or `Month` and defaults to `1`. +* `interval` - (Optional) The number of `frequency`s between runs. Only valid when frequency is `Day`, `Hour`, `Week`, or `Month` and defaults to `1`. * `start_time` - (Optional) Start time of the schedule. Must be at least five minutes in the future. Defaults to seven minutes in the future from the time the resource is created. @@ -61,6 +65,20 @@ The following arguments are supported: * `timezone` - (Optional) The timezone of the start time. Defaults to `UTC`. For possible values see: https://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx +* `week_days` - (Optional) List of days of the week that the job should execute on. Only valid when frequency is `Week`. + +* `month_days` - (Optional) List of days of the month that the job should execute on. Must be between `1` and `31`. `-1` for last day of the month. Only valid when frequency is `Month`. + +* `monthly_occurrence` - (Optional) List of occurrences of days within a month. Only valid when frequency is `Month`. The `monthly_occurrence` block supports fields documented below. + +--- + +The `monthly_occurrence` block supports: + +* `day` - (Required) Day of the occurrence. Must be one of `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday`, `Sunday`. + +* `occurrence` - (Required) Occurrence of the week within the month. Must be between `1` and `5`. `-1` for last week within the month. + ## Attributes Reference The following attributes are exported: