common/pkg/maintenance/windows.go (64 lines of code) (raw):
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package maintenance
import (
"errors"
"time"
commonv1alpha1 "github.com/GoogleCloudPlatform/elcarro-oracle-operator/common/api/v1alpha1"
)
// timeRangeInRange returns true iff the specified time lies in the range.
// The range check is inclusive for start-time and exclusive for end-time.
func timeRangeInRange(tr *commonv1alpha1.TimeRange, t time.Time) bool {
if !timeRangeIsValid(tr) {
return false
}
start := tr.Start.Rfc3339Copy().Time
if t.Before(start) {
return false
}
end := start.Add(tr.Duration.Duration)
return end.After(t)
}
// timeRangeIsValid verifies if fields on TimeRange are correctly set.
// In particular, Start and Duration fields should be set.
func timeRangeIsValid(tr *commonv1alpha1.TimeRange) bool {
return tr != nil && tr.Start != nil && tr.Duration != nil
}
// HasValidTimeRanges validates that there are non-zero time-ranges and all time-ranges specified are valid.
func HasValidTimeRanges(mw *commonv1alpha1.MaintenanceWindowSpec) bool {
if mw == nil || len(mw.TimeRanges) == 0 {
return false
}
for _, tr := range mw.TimeRanges {
if !timeRangeIsValid(&tr) {
return false
}
}
return true
}
// InRange returns true iff the specified time is in any one of the time ranges.
func InRange(mw *commonv1alpha1.MaintenanceWindowSpec, t time.Time) bool {
for _, tr := range mw.TimeRanges {
if timeRangeInRange(&tr, t) {
return true
}
}
return false
}
// NoFutureWindows error can be used by a caller to detect that
// there are no maintenance windows available.
var NoFutureWindows = errors.New("no future windows")
// NextWindow returns the start time of the current or next maintenance window,
// coupled with the duration of that window.
// If no future windows are available, NoFutureWindows error is returned.
func NextWindow(mw *commonv1alpha1.MaintenanceWindowSpec, t time.Time) (*time.Time, *time.Duration, error) {
var min *time.Time
var d *time.Duration
for _, tr := range mw.TimeRanges {
if !timeRangeIsValid(&tr) {
continue
}
trStart := tr.Start.Rfc3339Copy().Time
if t.Before(trStart) {
if min == nil {
min = &trStart
d = &tr.Duration.Duration
}
if min.After(trStart) {
min = &trStart
d = &tr.Duration.Duration
}
}
}
if min != nil {
return min, d, nil
}
return nil, nil, NoFutureWindows
}