fix: invalid switchover scheduling with default maintenance windows (#3058)

This commit is contained in:
Ida Novindasari
2026-03-24 12:57:15 +01:00
committed by GitHub
parent d495825f4b
commit 421bd6d664
3 changed files with 63 additions and 7 deletions
+19 -1
View File
@@ -1784,7 +1784,20 @@ func (c *Cluster) GetSwitchoverSchedule() string {
func (c *Cluster) getSwitchoverScheduleAtTime(now time.Time) string {
var possibleSwitchover, schedule time.Time
for _, window := range c.Spec.MaintenanceWindows {
maintenanceWindows := c.Spec.MaintenanceWindows
if len(maintenanceWindows) == 0 {
maintenanceWindows = make([]acidv1.MaintenanceWindow, 0, len(c.OpConfig.MaintenanceWindows))
for _, windowStr := range c.OpConfig.MaintenanceWindows {
var window acidv1.MaintenanceWindow
if err := window.UnmarshalJSON([]byte(windowStr)); err != nil {
c.logger.Errorf("could not parse default maintenance window %q: %v", windowStr, err)
continue
}
maintenanceWindows = append(maintenanceWindows, window)
}
}
for _, window := range maintenanceWindows {
// in the best case it is possible today
possibleSwitchover = time.Date(now.Year(), now.Month(), now.Day(), window.StartTime.Hour(), window.StartTime.Minute(), 0, 0, time.UTC)
if window.Everyday {
@@ -1806,6 +1819,11 @@ func (c *Cluster) getSwitchoverScheduleAtTime(now time.Time) string {
schedule = possibleSwitchover
}
}
if schedule.IsZero() {
return ""
}
return schedule.Format("2006-01-02T15:04+00")
}
+35 -3
View File
@@ -2125,10 +2125,13 @@ func TestGetSwitchoverSchedule(t *testing.T) {
pastWindowTimeStart := pastTimeStart.Format("15:04")
pastWindowTimeEnd := now.Add(-1 * time.Hour).Format("15:04")
defaultWindowStr := fmt.Sprintf("%s-%s", futureWindowTimeStart, futureWindowTimeEnd)
tests := []struct {
name string
windows []acidv1.MaintenanceWindow
expected string
name string
windows []acidv1.MaintenanceWindow
defaultWindows []string
expected string
}{
{
name: "everyday maintenance windows is later today",
@@ -2190,11 +2193,40 @@ func TestGetSwitchoverSchedule(t *testing.T) {
},
expected: pastTimeStart.AddDate(0, 0, 1).Format("2006-01-02T15:04+00"),
},
{
name: "fallback to operator default window when spec is empty",
windows: []acidv1.MaintenanceWindow{},
defaultWindows: []string{defaultWindowStr},
expected: futureTimeStart.Format("2006-01-02T15:04+00"),
},
{
name: "no windows defined returns empty string",
windows: []acidv1.MaintenanceWindow{},
defaultWindows: nil,
expected: "",
},
{
name: "choose the earliest window from multiple in spec",
windows: []acidv1.MaintenanceWindow{
{
Weekday: now.AddDate(0, 0, 2).Weekday(),
StartTime: mustParseTime(futureWindowTimeStart),
EndTime: mustParseTime(futureWindowTimeEnd),
},
{
Weekday: now.AddDate(0, 0, 1).Weekday(),
StartTime: mustParseTime(pastWindowTimeStart),
EndTime: mustParseTime(pastWindowTimeEnd),
},
},
expected: pastTimeStart.AddDate(0, 0, 1).Format("2006-01-02T15:04+00"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cluster.Spec.MaintenanceWindows = tt.windows
cluster.OpConfig.MaintenanceWindows = tt.defaultWindows
schedule := cluster.getSwitchoverScheduleAtTime(now)
if schedule != tt.expected {
t.Errorf("Expected GetSwitchoverSchedule to return %s, returned: %s", tt.expected, schedule)