-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
azurerm_automation_schedule - Add missing properties for the advanced schedule #1626
Changes from 5 commits
5e8bad9
ab3ca15
adab682
22a9c1c
980066b
7cdf594
279678b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,94 @@ 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 | ||
"advanced_schedule": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
MaxItems: 1, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"week_days": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Since |
||
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, | ||
}, | ||
"month_days": { | ||
Type: schema.TypeSet, | ||
Optional: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeInt, | ||
ValidateFunc: validate.IntBetweenAndNot(-1, 31, 0), | ||
}, | ||
Set: set.HashInt, | ||
}, | ||
|
||
"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: validation.IntBetween(1, 5), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Can you confirm whether Go SDK supports |
||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
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 not OneTime") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
advancedSchedules, hasAdvancedSchedule := diff.GetOk("advanced_schedule") | ||
if hasAdvancedSchedule { | ||
if asl := advancedSchedules.([]interface{}); len(asl) > 0 { | ||
if frequency != "week" && frequency != "month" { | ||
return fmt.Errorf("`advanced_schedule` can only be set when frequency is `Week` or `Month`") | ||
} | ||
|
||
as := asl[0].(map[string]interface{}) | ||
if frequency == "week" && as["week_days"].(*schema.Set).Len() == 0 { | ||
return fmt.Errorf("`week_days` must be set when frequency is `Week`") | ||
} | ||
if frequency == "month" && as["month_days"].(*schema.Set).Len() == 0 && len(as["monthly_occurrence"].([]interface{})) == 0 { | ||
return fmt.Errorf("Either `month_days` or `monthly_occurrence` must be set when frequency is `Month`") | ||
} | ||
} | ||
} | ||
|
||
_, hasAccount := diff.GetOk("automation_account_name") | ||
|
@@ -193,6 +274,28 @@ func resourceArmAutomationScheduleCreateUpdate(d *schema.ResourceData, meta inte | |
properties.Interval = 1 | ||
} | ||
} | ||
|
||
//only pay attention to the advanced schedule if frequency is either Week or Month | ||
if properties.Frequency == automation.Week || properties.Frequency == automation.Month { | ||
isUpdate := d.Id() != "" | ||
if v, ok := d.GetOk("advanced_schedule"); ok { | ||
if vl := v.([]interface{}); len(vl) > 0 { | ||
advancedRef, err := expandArmAutomationScheduleAdvanced(vl, isUpdate) | ||
if err != nil { | ||
return err | ||
} | ||
properties.AdvancedSchedule = advancedRef | ||
} | ||
} else if isUpdate { | ||
// To make sure all the properties are unset in the event of removal update, pass in an empty skeleton object | ||
properties.AdvancedSchedule = &automation.AdvancedSchedule{ | ||
WeekDays: &[]string{}, | ||
MonthDays: &[]int32{}, | ||
MonthlyOccurrences: &[]automation.AdvancedScheduleMonthlyOccurrence{}, | ||
} | ||
} | ||
} | ||
|
||
_, err := client.CreateOrUpdate(ctx, resGroup, accountName, name, parameters) | ||
if err != nil { | ||
return err | ||
|
@@ -257,6 +360,9 @@ func resourceArmAutomationScheduleRead(d *schema.ResourceData, meta interface{}) | |
if v := resp.TimeZone; v != nil { | ||
d.Set("timezone", v) | ||
} | ||
if err := d.Set("advanced_schedule", flattenArmAutomationScheduleAdvanced(resp.AdvancedSchedule)); err != nil { | ||
return fmt.Errorf("Error setting `advanced_schedule`: %+v", err) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we ensure we set this all the time and move the nil-check within the flatten function? that ensures changes to this are detected. in addition - given this is a complex object can we check for errors when setting it? e.g.
|
||
return nil | ||
} | ||
|
||
|
@@ -282,3 +388,85 @@ func resourceArmAutomationScheduleDelete(d *schema.ResourceData, meta interface{ | |
|
||
return nil | ||
} | ||
|
||
func expandArmAutomationScheduleAdvanced(v []interface{}, isUpdate bool) (*automation.AdvancedSchedule, error) { | ||
|
||
// Get the one and only advance schedule configuration | ||
advancedSchedule := v[0].(map[string]interface{}) | ||
weekDays := advancedSchedule["week_days"].(*schema.Set).List() | ||
monthDays := advancedSchedule["month_days"].(*schema.Set).List() | ||
monthlyOccurrences := advancedSchedule["monthly_occurrence"].([]interface{}) | ||
|
||
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 len(weekDays) > 0 || isUpdate { | ||
expandedWeekDays := make([]string, len(weekDays)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so this second argument is the starting position in the array, if we make this |
||
for i := range weekDays { | ||
expandedWeekDays[i] = weekDays[i].(string) | ||
} | ||
expandedAdvancedSchedule.WeekDays = &expandedWeekDays | ||
} | ||
|
||
// Same as above with `week_days` | ||
if len(monthDays) > 0 || isUpdate { | ||
expandedMonthDays := make([]int32, len(monthDays)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so this second argument is the starting position in the array, if we make this |
||
for i := range monthDays { | ||
expandedMonthDays[i] = int32(monthDays[i].(int)) | ||
} | ||
expandedAdvancedSchedule.MonthDays = &expandedMonthDays | ||
} | ||
|
||
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 flattenArmAutomationScheduleAdvanced(v *automation.AdvancedSchedule) []interface{} { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given we're now passing in a nil-value here, can we return an empty list e.g.
|
||
// If all the elements in the advanced schedule are `nil` it's assumed it doesn't exist | ||
if v == nil || (v.WeekDays == nil && v.MonthDays == nil && v.MonthlyOccurrences == nil) { | ||
return []interface{}{} | ||
} | ||
|
||
result := make(map[string]interface{}) | ||
|
||
flattenedWeekDays := schema.NewSet(set.HashStringIgnoreCase, []interface{}{}) | ||
if v.WeekDays != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this could be written as: if weekDays := v.WeekDays; weekdays != nil {
for i, v := range *weekDays {
flattenedWeekDays.Add(v)
}
} |
||
for i := range *v.WeekDays { | ||
flattenedWeekDays.Add((*v.WeekDays)[i]) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we update this to be:
this allows this to be set even if nil's returned from the API - which means diff's will be shown |
||
result["week_days"] = flattenedWeekDays | ||
|
||
flattenedMonthDays := schema.NewSet(set.HashInt, []interface{}{}) | ||
if v.MonthDays != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The same as above, could definitely be simplified. |
||
for i := range *v.MonthDays { | ||
flattenedMonthDays.Add(int(((*v.MonthDays)[i]))) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (as above) |
||
result["month_days"] = flattenedMonthDays | ||
|
||
flattenedMonthlyOccurrences := make([]map[string]interface{}, 0) | ||
if v.MonthlyOccurrences != nil { | ||
for i := range *v.MonthlyOccurrences { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, could use the syntax: |
||
f := make(map[string]interface{}) | ||
f["day"] = (*v.MonthlyOccurrences)[i].Day | ||
f["occurrence"] = int(*(*v.MonthlyOccurrences)[i].Occurrence) | ||
flattenedMonthlyOccurrences = append(flattenedMonthlyOccurrences, f) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (as above) |
||
result["monthly_occurrence"] = flattenedMonthlyOccurrences | ||
|
||
return []interface{}{result} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion We don't need to introduce wrapper
advanced_schedule
object here. What I mean is to move the mutual exclusive objectsweek_days
,month_days
andmonthly_occurrence
to the top level so we can reduce the depth of the hierarchy.