mirror of
https://github.com/zalando-incubator/kube-metrics-adapter.git
synced 2024-12-22 11:06:04 +00:00
Merge pull request #505 from zalando-incubator/update-scalingschedule-config
Update scalingschedule config
This commit is contained in:
commit
070f9ab299
@ -55,9 +55,14 @@ spec:
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
description: The duration in minutes that the configured value
|
||||
will be returned for the defined schedule.
|
||||
description: The duration in minutes (default 0) that the configured
|
||||
value will be returned for the defined schedule.
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formated date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
description: Defines the details of a Repeating schedule.
|
||||
properties:
|
||||
@ -76,6 +81,10 @@ spec:
|
||||
- Sat
|
||||
type: string
|
||||
type: array
|
||||
endTime:
|
||||
description: The endTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
type: string
|
||||
startTime:
|
||||
description: The startTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
@ -103,7 +112,6 @@ spec:
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- durationMinutes
|
||||
- type
|
||||
- value
|
||||
type: object
|
||||
|
@ -55,9 +55,14 @@ spec:
|
||||
format: date-time
|
||||
type: string
|
||||
durationMinutes:
|
||||
description: The duration in minutes that the configured value
|
||||
will be returned for the defined schedule.
|
||||
description: The duration in minutes (default 0) that the configured
|
||||
value will be returned for the defined schedule.
|
||||
type: integer
|
||||
endDate:
|
||||
description: Defines the ending date of a OneTime schedule.
|
||||
It must be a RFC3339 formated date.
|
||||
format: date-time
|
||||
type: string
|
||||
period:
|
||||
description: Defines the details of a Repeating schedule.
|
||||
properties:
|
||||
@ -76,6 +81,10 @@ spec:
|
||||
- Sat
|
||||
type: string
|
||||
type: array
|
||||
endTime:
|
||||
description: The endTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
type: string
|
||||
startTime:
|
||||
description: The startTime has the format HH:MM
|
||||
pattern: (([0-1][0-9])|([2][0-3])):([0-5][0-9])
|
||||
@ -103,7 +112,6 @@ spec:
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- durationMinutes
|
||||
- type
|
||||
- value
|
||||
type: object
|
||||
|
@ -61,8 +61,13 @@ type Schedule struct {
|
||||
// be a RFC3339 formated date.
|
||||
// +optional
|
||||
Date *ScheduleDate `json:"date,omitempty"`
|
||||
// The duration in minutes that the configured value will be
|
||||
// Defines the ending date of a OneTime schedule. It must be
|
||||
// a RFC3339 formated date.
|
||||
// +optional
|
||||
EndDate *ScheduleDate `json:"endDate,omitempty"`
|
||||
// The duration in minutes (default 0) that the configured value will be
|
||||
// returned for the defined schedule.
|
||||
// +optional
|
||||
DurationMinutes int `json:"durationMinutes"`
|
||||
// The metric value that will be returned for the defined schedule.
|
||||
Value int64 `json:"value"`
|
||||
@ -90,6 +95,10 @@ type SchedulePeriod struct {
|
||||
// The startTime has the format HH:MM
|
||||
// +kubebuilder:validation:Pattern="(([0-1][0-9])|([2][0-3])):([0-5][0-9])"
|
||||
StartTime string `json:"startTime"`
|
||||
// The endTime has the format HH:MM
|
||||
// +kubebuilder:validation:Pattern="(([0-1][0-9])|([2][0-3])):([0-5][0-9])"
|
||||
// +optional
|
||||
EndTime string `json:"endTime"`
|
||||
// The days that this schedule will be active.
|
||||
Days []ScheduleDay `json:"days"`
|
||||
// The location name corresponding to a file in the IANA
|
||||
|
@ -186,6 +186,11 @@ func (in *Schedule) DeepCopyInto(out *Schedule) {
|
||||
*out = new(ScheduleDate)
|
||||
**out = **in
|
||||
}
|
||||
if in.EndDate != nil {
|
||||
in, out := &in.EndDate, &out.EndDate
|
||||
*out = new(ScheduleDate)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -259,6 +259,7 @@ func calculateMetrics(spec v1.ScalingScheduleSpec, defaultScalingWindow time.Dur
|
||||
}
|
||||
|
||||
value := int64(0)
|
||||
var scheduledEndTime time.Time
|
||||
for _, schedule := range spec.Schedules {
|
||||
switch schedule.Type {
|
||||
case v1.RepeatingSchedule:
|
||||
@ -292,7 +293,34 @@ func calculateMetrics(spec v1.ScalingScheduleSpec, defaultScalingWindow time.Dur
|
||||
parsedStartTime.Nanosecond(),
|
||||
location,
|
||||
)
|
||||
value = maxInt64(value, valueForEntry(now, scheduledTime, schedule.Duration(), scalingWindowDuration, rampSteps, schedule.Value))
|
||||
|
||||
// If no end time was provided, set it to equal the start time
|
||||
if schedule.Period.EndTime == "" {
|
||||
scheduledEndTime = scheduledTime
|
||||
} else {
|
||||
parsedEndTime, err := time.Parse(hourColonMinuteLayout, schedule.Period.EndTime)
|
||||
if err != nil {
|
||||
return nil, ErrInvalidScheduleDate
|
||||
}
|
||||
scheduledEndTime = time.Date(
|
||||
// v1.SchedulePeriod.StartTime can't define the
|
||||
// year, month or day, so we compute it as the
|
||||
// current date in the configured location.
|
||||
nowInLocation.Year(),
|
||||
nowInLocation.Month(),
|
||||
nowInLocation.Day(),
|
||||
// Hours and minute are configured in the
|
||||
// v1.SchedulePeriod.StartTime.
|
||||
parsedEndTime.Hour(),
|
||||
parsedEndTime.Minute(),
|
||||
parsedEndTime.Second(),
|
||||
parsedEndTime.Nanosecond(),
|
||||
location,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
value = maxInt64(value, valueForEntry(now, scheduledTime, schedule.Duration(), scheduledEndTime, scalingWindowDuration, rampSteps, schedule.Value))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -302,7 +330,17 @@ func calculateMetrics(spec v1.ScalingScheduleSpec, defaultScalingWindow time.Dur
|
||||
return nil, ErrInvalidScheduleDate
|
||||
}
|
||||
|
||||
value = maxInt64(value, valueForEntry(now, scheduledTime, schedule.Duration(), scalingWindowDuration, rampSteps, schedule.Value))
|
||||
// If no end time was provided, set it to equal the start time
|
||||
if (string(*schedule.EndDate)) == "" {
|
||||
scheduledEndTime = scheduledTime
|
||||
} else {
|
||||
scheduledEndTime, err = time.Parse(time.RFC3339, string(*schedule.EndDate))
|
||||
if err != nil {
|
||||
return nil, ErrInvalidScheduleDate
|
||||
}
|
||||
}
|
||||
|
||||
value = maxInt64(value, valueForEntry(now, scheduledTime, schedule.Duration(), scheduledEndTime, scalingWindowDuration, rampSteps, schedule.Value))
|
||||
}
|
||||
}
|
||||
|
||||
@ -320,9 +358,18 @@ func calculateMetrics(spec v1.ScalingScheduleSpec, defaultScalingWindow time.Dur
|
||||
}, nil
|
||||
}
|
||||
|
||||
func valueForEntry(timestamp time.Time, startTime time.Time, entryDuration time.Duration, scalingWindowDuration time.Duration, rampSteps int, value int64) int64 {
|
||||
func valueForEntry(timestamp time.Time, startTime time.Time, entryDuration time.Duration, scheduledEndTime time.Time, scalingWindowDuration time.Duration, rampSteps int, value int64) int64 {
|
||||
scaleUpStart := startTime.Add(-scalingWindowDuration)
|
||||
endTime := startTime.Add(entryDuration)
|
||||
var endTime time.Time
|
||||
|
||||
// Use either the defined end time/date or the start time/date + the
|
||||
// duration, whichever is longer.
|
||||
if startTime.Add(entryDuration).Before(scheduledEndTime) {
|
||||
endTime = scheduledEndTime
|
||||
} else {
|
||||
endTime = startTime.Add(entryDuration)
|
||||
}
|
||||
|
||||
scaleUpEnd := endTime.Add(scalingWindowDuration)
|
||||
|
||||
if between(timestamp, startTime, endTime) {
|
||||
|
@ -21,7 +21,9 @@ const (
|
||||
type schedule struct {
|
||||
kind string
|
||||
date string
|
||||
endDate string
|
||||
startTime string
|
||||
endTime string
|
||||
days []v1.ScheduleDay
|
||||
timezone string
|
||||
duration int
|
||||
@ -75,6 +77,55 @@ func TestScalingScheduleCollector(t *testing.T) {
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value - utilise end date instead of start date + duration for one time config",
|
||||
schedules: []schedule{
|
||||
{
|
||||
date: nowTime.Add(-2 * time.Hour).Format(time.RFC3339),
|
||||
kind: "OneTime",
|
||||
duration: 60,
|
||||
endDate: nowTime.Add(1 * time.Hour).Format(time.RFC3339),
|
||||
value: 100,
|
||||
},
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value - utilise start date + duration instead of end date for one time config",
|
||||
schedules: []schedule{
|
||||
{
|
||||
date: nowTime.Add(-2 * time.Hour).Format(time.RFC3339),
|
||||
kind: "OneTime",
|
||||
duration: 150,
|
||||
endDate: nowTime.Add(-1 * time.Hour).Format(time.RFC3339),
|
||||
value: 100,
|
||||
},
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value - use end date with no duration set for one time config",
|
||||
schedules: []schedule{
|
||||
{
|
||||
date: nowTime.Add(-2 * time.Hour).Format(time.RFC3339),
|
||||
kind: "OneTime",
|
||||
endDate: nowTime.Add(1 * time.Hour).Format(time.RFC3339),
|
||||
value: 100,
|
||||
},
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value (0) for one time config no duration or end date set",
|
||||
schedules: []schedule{
|
||||
{
|
||||
date: nowTime.Add(time.Minute * 1).Format(time.RFC3339),
|
||||
kind: "OneTime",
|
||||
value: 100,
|
||||
},
|
||||
},
|
||||
expectedValue: 0,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value for one time config - 30 seconds before ending",
|
||||
schedules: []schedule{
|
||||
@ -255,6 +306,35 @@ func TestScalingScheduleCollector(t *testing.T) {
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value - utilise end date instead of start time + duration for repeating schedule",
|
||||
schedules: []schedule{
|
||||
{
|
||||
kind: "Repeating",
|
||||
duration: 60,
|
||||
value: 100,
|
||||
startTime: nowTime.Add(-2 * time.Hour).Format(hHMMFormat),
|
||||
// nowTime + 59m = 23:59.
|
||||
endTime: nowTime.Add(59 * time.Minute).Format(hHMMFormat),
|
||||
days: []v1.ScheduleDay{nowWeekday},
|
||||
},
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value - utilise start time + duration instead of end time for repeating schedule",
|
||||
schedules: []schedule{
|
||||
{
|
||||
kind: "Repeating",
|
||||
duration: 150,
|
||||
value: 100,
|
||||
startTime: nowTime.Add(-2 * time.Hour).Format(hHMMFormat),
|
||||
endTime: nowTime.Add(-1 * time.Hour).Format(hHMMFormat),
|
||||
days: []v1.ScheduleDay{nowWeekday},
|
||||
},
|
||||
},
|
||||
expectedValue: 100,
|
||||
},
|
||||
{
|
||||
msg: "Return the right value for a repeating schedule - 5 minutes after started",
|
||||
schedules: []schedule{
|
||||
@ -750,10 +830,12 @@ func getSchedules(schedules []schedule) (result []v1.Schedule) {
|
||||
switch schedule.kind {
|
||||
case string(v1.OneTimeSchedule):
|
||||
date := v1.ScheduleDate(schedule.date)
|
||||
endDate := v1.ScheduleDate(schedule.endDate)
|
||||
result = append(result,
|
||||
v1.Schedule{
|
||||
Type: v1.OneTimeSchedule,
|
||||
Date: &date,
|
||||
EndDate: &endDate,
|
||||
DurationMinutes: schedule.duration,
|
||||
Value: schedule.value,
|
||||
},
|
||||
@ -761,6 +843,7 @@ func getSchedules(schedules []schedule) (result []v1.Schedule) {
|
||||
case string(v1.RepeatingSchedule):
|
||||
period := v1.SchedulePeriod{
|
||||
StartTime: schedule.startTime,
|
||||
EndTime: schedule.endTime,
|
||||
Days: schedule.days,
|
||||
Timezone: schedule.timezone,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user