Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 49 additions & 12 deletions api/types/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ var validWeekdays = [7]time.Weekday{
time.Saturday,
}

// parseWeekday attempts to interpret a string as a time.Weekday. In the interest of flexibility,
// ParseWeekday attempts to interpret a string as a time.Weekday. In the interest of flexibility,
// parsing is case-insensitive and supports the common three-letter shorthand accepted by many
// common scheduling utilites (e.g. contab, systemd timers).
func parseWeekday(s string) (day time.Weekday, ok bool) {
func ParseWeekday(s string) (day time.Weekday, ok bool) {
for _, w := range validWeekdays {
if strings.EqualFold(w.String(), s) || strings.EqualFold(w.String()[:3], s) {
return w, true
Expand All @@ -58,6 +58,42 @@ func parseWeekday(s string) (day time.Weekday, ok bool) {
return time.Sunday, false
}

// ParseWeekdays attempts to parse a slice of strings representing week days.
// The slice must not be empty but can also contain a single value "*", representing the whole week.
// Day order doesn't matter but the same week day must not be present multiple times.
// In the interest of flexibility, parsing is case-insensitive and supports the common three-letter shorthand
// accepted by many common scheduling utilites (e.g. contab, systemd timers).
func ParseWeekdays(days []string) (map[time.Weekday]struct{}, error) {
if len(days) == 0 {
return nil, trace.BadParameter("empty weekdays list")
}
// Special case, we support wildcards.
if len(days) == 1 && days[0] == Wildcard {
return map[time.Weekday]struct{}{
time.Monday: {},
time.Tuesday: {},
time.Wednesday: {},
time.Thursday: {},
time.Friday: {},
time.Saturday: {},
time.Sunday: {},
}, nil
}
weekdays := make(map[time.Weekday]struct{}, 7)
for _, day := range days {
weekday, ok := ParseWeekday(day)
if !ok {
return nil, trace.BadParameter("failed to parse weekday: %v", day)
}
// Check if this is a duplicate
if _, ok := weekdays[weekday]; ok {
return nil, trace.BadParameter("duplicate weekday: %v", weekday.String())
}
weekdays[weekday] = struct{}{}
}
return weekdays, nil
}

// generator builds a closure that iterates valid maintenance config from the current day onward. Used in
// schedule export logic and tests.
func (w *AgentUpgradeWindow) generator(from time.Time) func() (start time.Time, end time.Time) {
Expand All @@ -75,7 +111,7 @@ func (w *AgentUpgradeWindow) generator(from time.Time) func() (start time.Time,

var weekdays []time.Weekday
for _, d := range w.Weekdays {
if p, ok := parseWeekday(d); ok {
if p, ok := ParseWeekday(d); ok {
weekdays = append(weekdays, p)
}
}
Expand Down Expand Up @@ -203,7 +239,7 @@ func (m *ClusterMaintenanceConfigV1) CheckAndSetDefaults() error {
}

for _, day := range m.Spec.AgentUpgrades.Weekdays {
if _, ok := parseWeekday(day); !ok {
if _, ok := ParseWeekday(day); !ok {
return trace.BadParameter("invalid weekday in agent upgrade window: %q", day)
}
}
Expand Down Expand Up @@ -248,13 +284,14 @@ func (m *ClusterMaintenanceConfigV1) WithinUpgradeWindow(t time.Time) bool {
}
}

weekday := t.Weekday().String()
for _, upgradeWeekday := range upgradeWindow.Weekdays {
if weekday == upgradeWeekday {
if int(upgradeWindow.UTCStartHour) == t.Hour() {
return true
}
}
upgradeWeekDays, err := ParseWeekdays(upgradeWindow.Weekdays)
if err != nil {
return false
}
return false

if _, ok := upgradeWeekDays[t.Weekday()]; !ok {
return false
}

return int(upgradeWindow.UTCStartHour) == t.Hour()
}
6 changes: 3 additions & 3 deletions api/types/maintenance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func TestWeekdayParser(t *testing.T) {
}

for _, tt := range tts {
day, ok := parseWeekday(tt.input)
day, ok := ParseWeekday(tt.input)
if tt.fail {
require.False(t, ok)
continue
Expand Down Expand Up @@ -244,7 +244,7 @@ func TestWithinUpgradeWindow(t *testing.T) {
desc: "within upgrade window weekday",
upgradeWindow: AgentUpgradeWindow{
UTCStartHour: 8,
Weekdays: []string{"Monday"},
Weekdays: []string{"Mon"},
},
date: "Mon, 02 Jan 2006 08:04:05 UTC",
withinWindow: true,
Expand All @@ -253,7 +253,7 @@ func TestWithinUpgradeWindow(t *testing.T) {
desc: "not within upgrade window weekday",
upgradeWindow: AgentUpgradeWindow{
UTCStartHour: 8,
Weekdays: []string{"Tuesday"},
Weekdays: []string{"Tue"},
},
date: "Mon, 02 Jan 2006 08:04:05 UTC",
withinWindow: false,
Expand Down
Loading