mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: rename template restart requirement to autostop requirement (#9295)
This commit is contained in:
+32
-32
@@ -13,17 +13,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// restartRequirementLeeway is the duration of time before a restart
|
||||
// autostopRequirementLeeway is the duration of time before a autostop
|
||||
// requirement where we skip the requirement and fall back to the next
|
||||
// scheduled restart. This avoids workspaces being restarted too soon.
|
||||
// scheduled stop. This avoids workspaces being stopped too soon.
|
||||
//
|
||||
// E.g. If the workspace is started within an hour of the quiet hours, we
|
||||
// will skip the restart requirement and use the next scheduled restart
|
||||
// requirement.
|
||||
restartRequirementLeeway = 1 * time.Hour
|
||||
// will skip the autostop requirement and use the next scheduled
|
||||
// stop time instead.
|
||||
autostopRequirementLeeway = 1 * time.Hour
|
||||
|
||||
// restartRequirementBuffer is the duration of time we subtract from the
|
||||
// time when calculating the next scheduled restart time. This avoids issues
|
||||
// autostopRequirementBuffer is the duration of time we subtract from the
|
||||
// time when calculating the next scheduled stop time. This avoids issues
|
||||
// where autostart happens on the hour and the scheduled quiet hours are
|
||||
// also on the hour.
|
||||
//
|
||||
@@ -37,7 +37,7 @@ const (
|
||||
//
|
||||
// This resolves that problem by subtracting 15 minutes from midnight
|
||||
// when we check the next cron time.
|
||||
restartRequirementBuffer = -15 * time.Minute
|
||||
autostopRequirementBuffer = -15 * time.Minute
|
||||
)
|
||||
|
||||
type CalculateAutostopParams struct {
|
||||
@@ -68,7 +68,7 @@ type AutostopTime struct {
|
||||
//
|
||||
// MaxDeadline is the maximum value for deadline. The deadline cannot be bumped
|
||||
// past this value, so it denotes the absolute deadline that the workspace build
|
||||
// must be stopped by. MaxDeadline is calculated using the template's "restart
|
||||
// must be stopped by. MaxDeadline is calculated using the template's "autostop
|
||||
// requirement" settings and the user's "quiet hours" settings to pick a time
|
||||
// outside of working hours.
|
||||
//
|
||||
@@ -113,13 +113,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// Use the old algorithm for calculating max_deadline if the instance isn't
|
||||
// configured or entitled to use the new feature flag yet.
|
||||
// TODO(@dean): remove this once the feature flag is enabled for all
|
||||
if !templateSchedule.UseRestartRequirement && templateSchedule.MaxTTL > 0 {
|
||||
if !templateSchedule.UseAutostopRequirement && templateSchedule.MaxTTL > 0 {
|
||||
autostop.MaxDeadline = now.Add(templateSchedule.MaxTTL)
|
||||
}
|
||||
|
||||
// TODO(@dean): remove extra conditional
|
||||
if templateSchedule.UseRestartRequirement && templateSchedule.RestartRequirement.DaysOfWeek != 0 {
|
||||
// The template has a restart requirement, so determine the max deadline
|
||||
if templateSchedule.UseAutostopRequirement && templateSchedule.AutostopRequirement.DaysOfWeek != 0 {
|
||||
// The template has a autostop requirement, so determine the max deadline
|
||||
// of this workspace build.
|
||||
|
||||
// First, get the user's quiet hours schedule (this will return the
|
||||
@@ -137,13 +137,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
now := now.In(loc)
|
||||
// Add the leeway here so we avoid checking today's quiet hours if
|
||||
// the workspace was started <1h before midnight.
|
||||
startOfStopDay := truncateMidnight(now.Add(restartRequirementLeeway))
|
||||
startOfStopDay := truncateMidnight(now.Add(autostopRequirementLeeway))
|
||||
|
||||
// If the template schedule wants to only restart on n-th weeks then
|
||||
// change the startOfDay to be the Monday of the next applicable
|
||||
// week.
|
||||
if templateSchedule.RestartRequirement.Weeks > 1 {
|
||||
startOfStopDay, err = GetNextApplicableMondayOfNWeeks(startOfStopDay, templateSchedule.RestartRequirement.Weeks)
|
||||
// If the template schedule wants to only autostop on n-th weeks
|
||||
// then change the startOfDay to be the Monday of the next
|
||||
// applicable week.
|
||||
if templateSchedule.AutostopRequirement.Weeks > 1 {
|
||||
startOfStopDay, err = GetNextApplicableMondayOfNWeeks(startOfStopDay, templateSchedule.AutostopRequirement.Weeks)
|
||||
if err != nil {
|
||||
return autostop, xerrors.Errorf("determine start of stop week: %w", err)
|
||||
}
|
||||
@@ -155,30 +155,30 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// Allow an hour of leeway (i.e. any workspaces started within an
|
||||
// hour of the scheduled stop time will always bounce to the next
|
||||
// stop window).
|
||||
checkSchedule := userQuietHoursSchedule.Schedule.Next(startOfStopDay.Add(restartRequirementBuffer))
|
||||
if checkSchedule.Before(now.Add(restartRequirementLeeway)) {
|
||||
checkSchedule := userQuietHoursSchedule.Schedule.Next(startOfStopDay.Add(autostopRequirementBuffer))
|
||||
if checkSchedule.Before(now.Add(autostopRequirementLeeway)) {
|
||||
// Set the first stop day we try to tomorrow because today's
|
||||
// schedule is too close to now or has already passed.
|
||||
startOfStopDay = nextDayMidnight(startOfStopDay)
|
||||
}
|
||||
|
||||
// Iterate from 0 to 7, check if the current startOfDay is in the
|
||||
// restart requirement. If it isn't then add a day and try again.
|
||||
requirementDays := templateSchedule.RestartRequirement.DaysMap()
|
||||
// autostop requirement. If it isn't then add a day and try again.
|
||||
requirementDays := templateSchedule.AutostopRequirement.DaysMap()
|
||||
for i := 0; i < len(DaysOfWeek)+1; i++ {
|
||||
if i == len(DaysOfWeek) {
|
||||
// We've wrapped, so somehow we couldn't find a day in the
|
||||
// restart requirement in the next week.
|
||||
// autostop requirement in the next week.
|
||||
//
|
||||
// This shouldn't be able to happen, as we've already
|
||||
// checked that there is a day in the restart requirement
|
||||
// checked that there is a day in the autostop requirement
|
||||
// above with the
|
||||
// `if templateSchedule.RestartRequirement.DaysOfWeek != 0`
|
||||
// `if templateSchedule.AutoStopRequirement.DaysOfWeek != 0`
|
||||
// check.
|
||||
//
|
||||
// The eighth bit shouldn't be set, as we validate the
|
||||
// bitmap in the enterprise TemplateScheduleStore.
|
||||
return autostop, xerrors.New("could not find suitable day for template restart requirement in the next 7 days")
|
||||
return autostop, xerrors.New("could not find suitable day for template autostop requirement in the next 7 days")
|
||||
}
|
||||
if requirementDays[startOfStopDay.Weekday()] {
|
||||
break
|
||||
@@ -194,13 +194,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// If it's not within an hour of now, subtract 15 minutes to
|
||||
// give a little leeway. This prevents skipped stop events
|
||||
// because autostart perfectly lines up with autostop.
|
||||
checkTime = checkTime.Add(restartRequirementBuffer)
|
||||
checkTime = checkTime.Add(autostopRequirementBuffer)
|
||||
}
|
||||
|
||||
// Get the next occurrence of the restart schedule.
|
||||
// Get the next occurrence of the schedule.
|
||||
autostop.MaxDeadline = userQuietHoursSchedule.Schedule.Next(checkTime)
|
||||
if autostop.MaxDeadline.IsZero() {
|
||||
return autostop, xerrors.New("could not find next occurrence of template restart requirement in user quiet hours schedule")
|
||||
return autostop, xerrors.Errorf("could not find next occurrence of template autostop requirement in user quiet hours schedule, checked from time %q", checkTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,9 +244,9 @@ func nextDayMidnight(t time.Time) time.Time {
|
||||
//
|
||||
// The timezone embedded in the time object is used to determine the epoch.
|
||||
func WeeksSinceEpoch(now time.Time) (int64, error) {
|
||||
epoch := TemplateRestartRequirementEpoch(now.Location())
|
||||
epoch := TemplateAutostopRequirementEpoch(now.Location())
|
||||
if now.Before(epoch) {
|
||||
return 0, xerrors.New("coder server system clock is incorrect, cannot calculate template restart requirement")
|
||||
return 0, xerrors.New("coder server system clock is incorrect, cannot calculate template autostop requirement")
|
||||
}
|
||||
|
||||
// This calculation needs to be done using YearDay, as dividing by the
|
||||
@@ -290,7 +290,7 @@ func GetMondayOfWeek(loc *time.Location, n int64) (time.Time, error) {
|
||||
if n < 0 {
|
||||
return time.Time{}, xerrors.New("weeks since epoch must be positive")
|
||||
}
|
||||
epoch := TemplateRestartRequirementEpoch(loc)
|
||||
epoch := TemplateAutostopRequirementEpoch(loc)
|
||||
monday := epoch.AddDate(0, 0, int(n*7))
|
||||
|
||||
y, m, d := monday.Date()
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
|
||||
// Wednesday the 8th of February 2023 at midnight. This date was
|
||||
// specifically chosen as it doesn't fall on a applicable week for both
|
||||
// fortnightly and triweekly restart requirements.
|
||||
// fortnightly and triweekly autostop requirements.
|
||||
wednesdayMidnightUTC := time.Date(2023, 2, 8, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
sydneyQuietHours := "CRON_TZ=Australia/Sydney 0 0 * * *"
|
||||
@@ -73,10 +73,10 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop bool
|
||||
templateDefaultTTL time.Duration
|
||||
// TODO(@dean): remove max_ttl tests
|
||||
useMaxTTL bool
|
||||
templateMaxTTL time.Duration
|
||||
templateRestartRequirement schedule.TemplateRestartRequirement
|
||||
userQuietHoursSchedule string
|
||||
useMaxTTL bool
|
||||
templateMaxTTL time.Duration
|
||||
templateAutostopRequirement schedule.TemplateAutostopRequirement
|
||||
userQuietHoursSchedule string
|
||||
// workspaceTTL is usually copied from the template's TTL when the
|
||||
// workspace is made, so it takes precedence unless
|
||||
// templateAllowAutostop is false.
|
||||
@@ -88,72 +88,72 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
name: "OK",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "OK",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "Delete",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "WorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateDefaultTTLIgnored",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "TemplateDefaultTTLIgnored",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 2 * time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 2 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateBlockWorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 4 * time.Hour,
|
||||
expectedDeadline: now.Add(3 * time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "TemplateBlockWorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 4 * time.Hour,
|
||||
expectedDeadline: now.Add(3 * time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirement",
|
||||
name: "TemplateAutostopRequirement",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -162,12 +162,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirement1HourSkip",
|
||||
name: "TemplateAutostopRequirement1HourSkip",
|
||||
now: saturdayMidnightSydney.Add(-59 * time.Minute),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // 1 also means weekly
|
||||
},
|
||||
@@ -176,14 +176,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.Add(7 * 24 * time.Hour).In(time.UTC),
|
||||
},
|
||||
{
|
||||
// The next restart requirement should be skipped if the
|
||||
// The next autostop requirement should be skipped if the
|
||||
// workspace is started within 1 hour of it.
|
||||
name: "TemplateRestartRequirementDaily",
|
||||
name: "TemplateAutostopRequirementDaily",
|
||||
now: fridayEveningSydney,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01111111, // daily
|
||||
Weeks: 0, // all weeks
|
||||
},
|
||||
@@ -192,12 +192,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementFortnightly/Skip",
|
||||
name: "TemplateAutostopRequirementFortnightly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every 2 weeks
|
||||
},
|
||||
@@ -206,12 +206,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementFortnightly/NoSkip",
|
||||
name: "TemplateAutostopRequirementFortnightly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every 2 weeks
|
||||
},
|
||||
@@ -220,28 +220,28 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementTriweekly/Skip",
|
||||
name: "TemplateAutostopRequirementTriweekly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 3, // every 3 weeks
|
||||
},
|
||||
workspaceTTL: 0,
|
||||
// expectedDeadline is copied from expectedMaxDeadline.
|
||||
// The next triweekly restart requirement happens next week
|
||||
// The next triweekly autostop requirement happens next week
|
||||
// according to the epoch.
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementTriweekly/NoSkip",
|
||||
name: "TemplateAutostopRequirementTriweekly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 3, // every 3 weeks
|
||||
},
|
||||
@@ -250,14 +250,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementOverridesWorkspaceTTL",
|
||||
name: "TemplateAutostopRequirementOverridesWorkspaceTTL",
|
||||
// now doesn't have to be UTC, but it helps us ensure that
|
||||
// timezones are compared correctly in this test.
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -266,12 +266,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementOverridesTemplateDefaultTTL",
|
||||
name: "TemplateAutostopRequirementOverridesTemplateDefaultTTL",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -288,7 +288,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every fortnight
|
||||
},
|
||||
@@ -301,7 +301,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -315,7 +315,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -329,7 +329,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -343,7 +343,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstInQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01000000, // Sunday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -357,7 +357,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstOutQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01000000, // Sunday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -368,14 +368,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
|
||||
// TODO(@dean): remove max_ttl tests
|
||||
{
|
||||
name: "RestartRequirementIgnoresMaxTTL",
|
||||
name: "AutostopRequirementIgnoresMaxTTL",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 0,
|
||||
useMaxTTL: false,
|
||||
templateMaxTTL: time.Hour, // should be ignored
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -384,14 +384,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "MaxTTLIgnoresRestartRequirement",
|
||||
name: "MaxTTLIgnoresAutostopRequirement",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 0,
|
||||
useMaxTTL: true,
|
||||
templateMaxTTL: time.Hour, // should NOT be ignored
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -413,12 +413,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateScheduleStore := schedule.MockTemplateScheduleStore{
|
||||
GetFn: func(_ context.Context, _ database.Store, _ uuid.UUID) (schedule.TemplateScheduleOptions, error) {
|
||||
return schedule.TemplateScheduleOptions{
|
||||
UserAutostartEnabled: false,
|
||||
UserAutostopEnabled: c.templateAllowAutostop,
|
||||
DefaultTTL: c.templateDefaultTTL,
|
||||
MaxTTL: c.templateMaxTTL,
|
||||
UseRestartRequirement: !c.useMaxTTL,
|
||||
RestartRequirement: c.templateRestartRequirement,
|
||||
UserAutostartEnabled: false,
|
||||
UserAutostopEnabled: c.templateAllowAutostop,
|
||||
DefaultTTL: c.templateDefaultTTL,
|
||||
MaxTTL: c.templateMaxTTL,
|
||||
UseAutostopRequirement: !c.useMaxTTL,
|
||||
AutostopRequirement: c.templateAutostopRequirement,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
@@ -454,11 +454,11 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
CreatedBy: user.ID,
|
||||
})
|
||||
err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{
|
||||
ID: template.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
AllowUserAutostart: c.templateAllowAutostop,
|
||||
RestartRequirementDaysOfWeek: int16(c.templateRestartRequirement.DaysOfWeek),
|
||||
RestartRequirementWeeks: c.templateRestartRequirement.Weeks,
|
||||
ID: template.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
AllowUserAutostart: c.templateAllowAutostop,
|
||||
AutostopRequirementDaysOfWeek: int16(c.templateAutostopRequirement.DaysOfWeek),
|
||||
AutostopRequirementWeeks: c.templateAutostopRequirement.Weeks,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
template, err = db.GetTemplateByID(ctx, template.ID)
|
||||
|
||||
+30
-30
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/tracing"
|
||||
)
|
||||
|
||||
const MaxTemplateRestartRequirementWeeks = 16
|
||||
const MaxTemplateAutostopRequirementWeeks = 16
|
||||
|
||||
func TemplateRestartRequirementEpoch(loc *time.Location) time.Time {
|
||||
func TemplateAutostopRequirementEpoch(loc *time.Location) time.Time {
|
||||
// The "first week" starts on January 2nd, 2023, which is the first Monday
|
||||
// of 2023. All other weeks are counted using modulo arithmetic from that
|
||||
// date.
|
||||
@@ -34,7 +34,7 @@ var DaysOfWeek = []time.Weekday{
|
||||
time.Sunday,
|
||||
}
|
||||
|
||||
type TemplateRestartRequirement struct {
|
||||
type TemplateAutostopRequirement struct {
|
||||
// DaysOfWeek is a bitmap of which days of the week the workspace must be
|
||||
// restarted. If fully zero, the workspace is not required to be restarted
|
||||
// ever.
|
||||
@@ -55,7 +55,7 @@ type TemplateRestartRequirement struct {
|
||||
|
||||
// DaysMap returns a map of the days of the week that the workspace must be
|
||||
// restarted.
|
||||
func (r TemplateRestartRequirement) DaysMap() map[time.Weekday]bool {
|
||||
func (r TemplateAutostopRequirement) DaysMap() map[time.Weekday]bool {
|
||||
days := make(map[time.Weekday]bool)
|
||||
for i, day := range DaysOfWeek {
|
||||
days[day] = r.DaysOfWeek&(1<<uint(i)) != 0
|
||||
@@ -63,20 +63,20 @@ func (r TemplateRestartRequirement) DaysMap() map[time.Weekday]bool {
|
||||
return days
|
||||
}
|
||||
|
||||
// VerifyTemplateRestartRequirement returns an error if the restart requirement
|
||||
// is invalid.
|
||||
func VerifyTemplateRestartRequirement(days uint8, weeks int64) error {
|
||||
// VerifyTemplateAutostopRequirement returns an error if the autostop
|
||||
// requirement is invalid.
|
||||
func VerifyTemplateAutostopRequirement(days uint8, weeks int64) error {
|
||||
if days&0b10000000 != 0 {
|
||||
return xerrors.New("invalid restart requirement days, last bit is set")
|
||||
return xerrors.New("invalid autostop requirement days, last bit is set")
|
||||
}
|
||||
if days > 0b11111111 {
|
||||
return xerrors.New("invalid restart requirement days, too large")
|
||||
return xerrors.New("invalid autostop requirement days, too large")
|
||||
}
|
||||
if weeks < 0 {
|
||||
return xerrors.New("invalid restart requirement weeks, negative")
|
||||
return xerrors.New("invalid autostop requirement weeks, negative")
|
||||
}
|
||||
if weeks > MaxTemplateRestartRequirementWeeks {
|
||||
return xerrors.New("invalid restart requirement weeks, too large")
|
||||
if weeks > MaxTemplateAutostopRequirementWeeks {
|
||||
return xerrors.New("invalid autostop requirement weeks, too large")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -85,17 +85,17 @@ type TemplateScheduleOptions struct {
|
||||
UserAutostartEnabled bool `json:"user_autostart_enabled"`
|
||||
UserAutostopEnabled bool `json:"user_autostop_enabled"`
|
||||
DefaultTTL time.Duration `json:"default_ttl"`
|
||||
// TODO(@dean): remove MaxTTL once restart_requirement is matured and the
|
||||
// TODO(@dean): remove MaxTTL once autostop_requirement is matured and the
|
||||
// default
|
||||
MaxTTL time.Duration `json:"max_ttl"`
|
||||
// UseRestartRequirement dictates whether the restart requirement should be
|
||||
// used instead of MaxTTL. This is governed by the feature flag and
|
||||
// UseAutostopRequirement dictates whether the autostop requirement should
|
||||
// be used instead of MaxTTL. This is governed by the feature flag and
|
||||
// licensing.
|
||||
// TODO(@dean): remove this when we remove max_tll
|
||||
UseRestartRequirement bool
|
||||
// RestartRequirement dictates when the workspace must be restarted. This
|
||||
UseAutostopRequirement bool
|
||||
// AutostopRequirement dictates when the workspace must be restarted. This
|
||||
// used to be handled by MaxTTL.
|
||||
RestartRequirement TemplateRestartRequirement `json:"restart_requirement"`
|
||||
AutostopRequirement TemplateAutostopRequirement `json:"autostop_requirement"`
|
||||
// FailureTTL dictates the duration after which failed workspaces will be
|
||||
// stopped automatically.
|
||||
FailureTTL time.Duration `json:"failure_ttl"`
|
||||
@@ -149,11 +149,11 @@ func (*agplTemplateScheduleStore) Get(ctx context.Context, db database.Store, te
|
||||
UserAutostartEnabled: true,
|
||||
UserAutostopEnabled: true,
|
||||
DefaultTTL: time.Duration(tpl.DefaultTTL),
|
||||
// Disregard the values in the database, since RestartRequirement,
|
||||
// Disregard the values in the database, since AutostopRequirement,
|
||||
// FailureTTL, TimeTilDormant, and TimeTilDormantAutoDelete are enterprise features.
|
||||
UseRestartRequirement: false,
|
||||
MaxTTL: 0,
|
||||
RestartRequirement: TemplateRestartRequirement{
|
||||
UseAutostopRequirement: false,
|
||||
MaxTTL: 0,
|
||||
AutostopRequirement: TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0,
|
||||
Weeks: 0,
|
||||
},
|
||||
@@ -180,14 +180,14 @@ func (*agplTemplateScheduleStore) Set(ctx context.Context, db database.Store, tp
|
||||
DefaultTTL: int64(opts.DefaultTTL),
|
||||
// Don't allow changing these settings, but keep the value in the DB (to
|
||||
// avoid clearing settings if the license has an issue).
|
||||
MaxTTL: tpl.MaxTTL,
|
||||
RestartRequirementDaysOfWeek: tpl.RestartRequirementDaysOfWeek,
|
||||
RestartRequirementWeeks: tpl.RestartRequirementWeeks,
|
||||
AllowUserAutostart: tpl.AllowUserAutostart,
|
||||
AllowUserAutostop: tpl.AllowUserAutostop,
|
||||
FailureTTL: tpl.FailureTTL,
|
||||
TimeTilDormant: tpl.TimeTilDormant,
|
||||
TimeTilDormantAutoDelete: tpl.TimeTilDormantAutoDelete,
|
||||
MaxTTL: tpl.MaxTTL,
|
||||
AutostopRequirementDaysOfWeek: tpl.AutostopRequirementDaysOfWeek,
|
||||
AutostopRequirementWeeks: tpl.AutostopRequirementWeeks,
|
||||
AllowUserAutostart: tpl.AllowUserAutostart,
|
||||
AllowUserAutostop: tpl.AllowUserAutostop,
|
||||
FailureTTL: tpl.FailureTTL,
|
||||
TimeTilDormant: tpl.TimeTilDormant,
|
||||
TimeTilDormantAutoDelete: tpl.TimeTilDormantAutoDelete,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update template schedule: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user