From 90ef5c37881b2ed139c473e28a8d55dec3b7cee3 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Thu, 24 Aug 2023 15:21:54 +1000 Subject: [PATCH 1/2] chore: rename template restart requirement to autostop requirement --- cli/schedule_test.go | 4 +- cli/templateedit.go | 50 ++-- cli/templateedit_test.go | 38 +-- coderd/activitybump_test.go | 2 +- coderd/autobuild/lifecycle_executor_test.go | 2 +- coderd/database/dbfake/dbfake.go | 4 +- coderd/database/dump.sql | 4 +- ...name_template_restart_requirement.down.sql | 3 + ...rename_template_restart_requirement.up.sql | 3 + coderd/database/modelqueries.go | 4 +- coderd/database/models.go | 8 +- coderd/database/queries.sql.go | 54 ++--- coderd/database/queries/templates.sql | 4 +- .../provisionerdserver_test.go | 84 +++---- coderd/schedule/autostop.go | 64 ++--- coderd/schedule/autostop_test.go | 182 +++++++------- coderd/schedule/template.go | 46 ++-- coderd/templates.go | 82 +++---- coderd/templates_test.go | 222 +++++++++--------- coderd/workspaces.go | 4 +- coderd/workspaces_test.go | 4 +- codersdk/deployment.go | 36 +-- codersdk/organizations.go | 4 +- codersdk/templates.go | 26 +- enterprise/coderd/coderd.go | 28 +-- enterprise/coderd/schedule/template.go | 64 ++--- enterprise/coderd/schedule/template_test.go | 28 +-- enterprise/coderd/templates_test.go | 16 +- enterprise/coderd/users.go | 8 +- enterprise/coderd/users_test.go | 20 +- 30 files changed, 553 insertions(+), 545 deletions(-) create mode 100644 coderd/database/migrations/000151_rename_template_restart_requirement.down.sql create mode 100644 coderd/database/migrations/000151_rename_template_restart_requirement.up.sql diff --git a/cli/schedule_test.go b/cli/schedule_test.go index 65e2b23ec5db9..54d3574697c80 100644 --- a/cli/schedule_test.go +++ b/cli/schedule_test.go @@ -316,8 +316,8 @@ func TestScheduleOverride(t *testing.T) { stdoutBuf = &bytes.Buffer{} ) require.Zero(t, template.DefaultTTLMillis) - require.Empty(t, template.RestartRequirement.DaysOfWeek) - require.Zero(t, template.RestartRequirement.Weeks) + require.Empty(t, template.AutostopRequirement.DaysOfWeek) + require.Zero(t, template.AutostopRequirement.Weeks) // Unset the workspace TTL err = client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{TTLMillis: nil}) diff --git a/cli/templateedit.go b/cli/templateedit.go index 7ce8fb00daec0..b8bf59048bdf0 100644 --- a/cli/templateedit.go +++ b/cli/templateedit.go @@ -15,19 +15,19 @@ import ( func (r *RootCmd) templateEdit() *clibase.Cmd { var ( - name string - displayName string - description string - icon string - defaultTTL time.Duration - maxTTL time.Duration - restartRequirementDaysOfWeek []string - restartRequirementWeeks int64 - failureTTL time.Duration - inactivityTTL time.Duration - allowUserCancelWorkspaceJobs bool - allowUserAutostart bool - allowUserAutostop bool + name string + displayName string + description string + icon string + defaultTTL time.Duration + maxTTL time.Duration + autostopRequirementDaysOfWeek []string + autostopRequirementWeeks int64 + failureTTL time.Duration + inactivityTTL time.Duration + allowUserCancelWorkspaceJobs bool + allowUserAutostart bool + allowUserAutostop bool ) client := new(codersdk.Client) @@ -51,9 +51,9 @@ func (r *RootCmd) templateEdit() *clibase.Cmd { } } - unsetRestartRequirementDaysOfWeek := len(restartRequirementDaysOfWeek) == 1 && restartRequirementDaysOfWeek[0] == "none" - requiresEntitlement := (len(restartRequirementDaysOfWeek) > 0 && !unsetRestartRequirementDaysOfWeek) || - restartRequirementWeeks > 0 || + unsetAutostopRequirementDaysOfWeek := len(autostopRequirementDaysOfWeek) == 1 && autostopRequirementDaysOfWeek[0] == "none" + requiresEntitlement := (len(autostopRequirementDaysOfWeek) > 0 && !unsetAutostopRequirementDaysOfWeek) || + autostopRequirementWeeks > 0 || !allowUserAutostart || !allowUserAutostop || maxTTL != 0 || @@ -84,11 +84,11 @@ func (r *RootCmd) templateEdit() *clibase.Cmd { // Copy the default value if the list is empty, or if the user // specified the "none" value clear the list. - if len(restartRequirementDaysOfWeek) == 0 { - restartRequirementDaysOfWeek = template.RestartRequirement.DaysOfWeek + if len(autostopRequirementDaysOfWeek) == 0 { + autostopRequirementDaysOfWeek = template.AutostopRequirement.DaysOfWeek } - if unsetRestartRequirementDaysOfWeek { - restartRequirementDaysOfWeek = []string{} + if unsetAutostopRequirementDaysOfWeek { + autostopRequirementDaysOfWeek = []string{} } // NOTE: coderd will ignore empty fields. @@ -99,9 +99,9 @@ func (r *RootCmd) templateEdit() *clibase.Cmd { Icon: icon, DefaultTTLMillis: defaultTTL.Milliseconds(), MaxTTLMillis: maxTTL.Milliseconds(), - RestartRequirement: &codersdk.TemplateRestartRequirement{ - DaysOfWeek: restartRequirementDaysOfWeek, - Weeks: restartRequirementWeeks, + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ + DaysOfWeek: autostopRequirementDaysOfWeek, + Weeks: autostopRequirementWeeks, }, FailureTTLMillis: failureTTL.Milliseconds(), InactivityTTLMillis: inactivityTTL.Milliseconds(), @@ -155,7 +155,7 @@ func (r *RootCmd) templateEdit() *clibase.Cmd { Description: "Edit the template restart requirement weekdays - workspaces created from this template must be restarted on the given weekdays. To unset this value for the template (and disable the restart requirement for the template), pass 'none'.", // TODO(@dean): unhide when we delete max_ttl Hidden: true, - Value: clibase.Validate(clibase.StringArrayOf(&restartRequirementDaysOfWeek), func(value *clibase.StringArray) error { + Value: clibase.Validate(clibase.StringArrayOf(&autostopRequirementDaysOfWeek), func(value *clibase.StringArray) error { v := value.GetSlice() if len(v) == 1 && v[0] == "none" { return nil @@ -172,7 +172,7 @@ func (r *RootCmd) templateEdit() *clibase.Cmd { Description: "Edit the template restart requirement weeks - workspaces created from this template must be restarted on an n-weekly basis.", // TODO(@dean): unhide when we delete max_ttl Hidden: true, - Value: clibase.Int64Of(&restartRequirementWeeks), + Value: clibase.Int64Of(&autostopRequirementWeeks), }, { Flag: "failure-ttl", diff --git a/cli/templateedit_test.go b/cli/templateedit_test.go index 775a25f91c6bd..b72204780de0b 100644 --- a/cli/templateedit_test.go +++ b/cli/templateedit_test.go @@ -242,7 +242,7 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, "", updated.Icon) assert.Equal(t, "", updated.DisplayName) }) - t.Run("RestartRequirement", func(t *testing.T) { + t.Run("AutostopRequirement", func(t *testing.T) { t.Parallel() t.Run("BlockedAGPL", func(t *testing.T) { t.Parallel() @@ -252,7 +252,7 @@ func TestTemplateEdit(t *testing.T) { _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.DefaultTTLMillis = nil - ctr.RestartRequirement = nil + ctr.AutostopRequirement = nil }) cases := []struct { @@ -312,8 +312,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) }) } }) @@ -326,7 +326,7 @@ func TestTemplateEdit(t *testing.T) { _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.DefaultTTLMillis = nil - ctr.RestartRequirement = nil + ctr.AutostopRequirement = nil }) // Make a proxy server that will return a valid entitlements @@ -426,8 +426,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) }) } }) @@ -439,7 +439,7 @@ func TestTemplateEdit(t *testing.T) { _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.DefaultTTLMillis = nil - ctr.RestartRequirement = nil + ctr.AutostopRequirement = nil }) // Make a proxy server that will return a valid entitlements @@ -475,8 +475,8 @@ func TestTemplateEdit(t *testing.T) { var req codersdk.UpdateTemplateMeta err = json.Unmarshal(body, &req) require.NoError(t, err) - assert.Equal(t, req.RestartRequirement.DaysOfWeek, []string{"monday", "tuesday"}) - assert.EqualValues(t, req.RestartRequirement.Weeks, 3) + assert.Equal(t, req.AutostopRequirement.DaysOfWeek, []string{"monday", "tuesday"}) + assert.EqualValues(t, req.AutostopRequirement.Weeks, 3) r.Body = io.NopCloser(bytes.NewReader(body)) atomic.AddInt64(&updateTemplateCalled, 1) @@ -525,8 +525,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) }) }) // TODO(@dean): remove this test when we remove max_ttl @@ -750,7 +750,7 @@ func TestTemplateEdit(t *testing.T) { _ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { ctr.DefaultTTLMillis = nil - ctr.RestartRequirement = nil + ctr.AutostopRequirement = nil ctr.FailureTTLMillis = nil ctr.InactivityTTLMillis = nil }) @@ -793,8 +793,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) assert.Equal(t, template.AllowUserAutostart, updated.AllowUserAutostart) assert.Equal(t, template.AllowUserAutostop, updated.AllowUserAutostop) assert.Equal(t, template.FailureTTLMillis, updated.FailureTTLMillis) @@ -887,8 +887,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) assert.Equal(t, template.AllowUserAutostart, updated.AllowUserAutostart) assert.Equal(t, template.AllowUserAutostop, updated.AllowUserAutostop) assert.Equal(t, template.FailureTTLMillis, updated.FailureTTLMillis) @@ -985,8 +985,8 @@ func TestTemplateEdit(t *testing.T) { assert.Equal(t, template.Icon, updated.Icon) assert.Equal(t, template.DisplayName, updated.DisplayName) assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis) - assert.Equal(t, template.RestartRequirement.DaysOfWeek, updated.RestartRequirement.DaysOfWeek) - assert.Equal(t, template.RestartRequirement.Weeks, updated.RestartRequirement.Weeks) + assert.Equal(t, template.AutostopRequirement.DaysOfWeek, updated.AutostopRequirement.DaysOfWeek) + assert.Equal(t, template.AutostopRequirement.Weeks, updated.AutostopRequirement.Weeks) assert.Equal(t, template.AllowUserAutostart, updated.AllowUserAutostart) assert.Equal(t, template.AllowUserAutostop, updated.AllowUserAutostop) assert.Equal(t, template.FailureTTLMillis, updated.FailureTTLMillis) diff --git a/coderd/activitybump_test.go b/coderd/activitybump_test.go index 15965f5ab1fea..34aa853223fae 100644 --- a/coderd/activitybump_test.go +++ b/coderd/activitybump_test.go @@ -50,7 +50,7 @@ func TestWorkspaceActivityBump(t *testing.T) { UserAutostopEnabled: true, DefaultTTL: ttl, // We set max_deadline manually below. - RestartRequirement: schedule.TemplateRestartRequirement{}, + AutostopRequirement: schedule.TemplateAutostopRequirement{}, }, nil }, }, diff --git a/coderd/autobuild/lifecycle_executor_test.go b/coderd/autobuild/lifecycle_executor_test.go index b1b854167e4b2..69f7894fb793c 100644 --- a/coderd/autobuild/lifecycle_executor_test.go +++ b/coderd/autobuild/lifecycle_executor_test.go @@ -623,7 +623,7 @@ func TestExecutorAutostartTemplateDisabled(t *testing.T) { UserAutostartEnabled: false, UserAutostopEnabled: true, DefaultTTL: 0, - RestartRequirement: schedule.TemplateRestartRequirement{}, + AutostopRequirement: schedule.TemplateAutostopRequirement{}, }, nil }, }, diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index 605f8000afba4..b3a39faeb71cd 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -5125,8 +5125,8 @@ func (q *FakeQuerier) UpdateTemplateScheduleByID(_ context.Context, arg database tpl.UpdatedAt = database.Now() tpl.DefaultTTL = arg.DefaultTTL tpl.MaxTTL = arg.MaxTTL - tpl.RestartRequirementDaysOfWeek = arg.RestartRequirementDaysOfWeek - tpl.RestartRequirementWeeks = arg.RestartRequirementWeeks + tpl.AutostopRequirementDaysOfWeek = arg.AutostopRequirementDaysOfWeek + tpl.AutostopRequirementWeeks = arg.AutostopRequirementWeeks tpl.FailureTTL = arg.FailureTTL tpl.InactivityTTL = arg.InactivityTTL tpl.LockedTTL = arg.LockedTTL diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 71106e5da771d..acd396f014f89 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -637,8 +637,8 @@ CREATE TABLE templates ( failure_ttl bigint DEFAULT 0 NOT NULL, inactivity_ttl bigint DEFAULT 0 NOT NULL, locked_ttl bigint DEFAULT 0 NOT NULL, - restart_requirement_days_of_week smallint DEFAULT 0 NOT NULL, - restart_requirement_weeks bigint DEFAULT 0 NOT NULL + autostop_requirement_days_of_week smallint DEFAULT 0 NOT NULL, + autostop_requirement_weeks bigint DEFAULT 0 NOT NULL ); COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.'; diff --git a/coderd/database/migrations/000151_rename_template_restart_requirement.down.sql b/coderd/database/migrations/000151_rename_template_restart_requirement.down.sql new file mode 100644 index 0000000000000..800ed0cbc4aee --- /dev/null +++ b/coderd/database/migrations/000151_rename_template_restart_requirement.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE templates + RENAME COLUMN autostop_requirement_days_of_week TO restart_requirement_days_of_week, + RENAME COLUMN autostop_requirement_weeks TO restart_requirement_weeks; diff --git a/coderd/database/migrations/000151_rename_template_restart_requirement.up.sql b/coderd/database/migrations/000151_rename_template_restart_requirement.up.sql new file mode 100644 index 0000000000000..9835356cf9467 --- /dev/null +++ b/coderd/database/migrations/000151_rename_template_restart_requirement.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE templates + RENAME COLUMN restart_requirement_days_of_week TO autostop_requirement_days_of_week, + RENAME COLUMN restart_requirement_weeks TO autostop_requirement_weeks; diff --git a/coderd/database/modelqueries.go b/coderd/database/modelqueries.go index 193a046f5cec1..c2083c33d8b15 100644 --- a/coderd/database/modelqueries.go +++ b/coderd/database/modelqueries.go @@ -83,8 +83,8 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate &i.FailureTTL, &i.InactivityTTL, &i.LockedTTL, - &i.RestartRequirementDaysOfWeek, - &i.RestartRequirementWeeks, + &i.AutostopRequirementDaysOfWeek, + &i.AutostopRequirementWeeks, &i.CreatedByAvatarURL, &i.CreatedByUsername, ); err != nil { diff --git a/coderd/database/models.go b/coderd/database/models.go index e795049c16413..6363b7a93624d 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -1731,8 +1731,8 @@ type Template struct { FailureTTL int64 `db:"failure_ttl" json:"failure_ttl"` InactivityTTL int64 `db:"inactivity_ttl" json:"inactivity_ttl"` LockedTTL int64 `db:"locked_ttl" json:"locked_ttl"` - RestartRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"` - RestartRequirementWeeks int64 `db:"restart_requirement_weeks" json:"restart_requirement_weeks"` + AutostopRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"` + AutostopRequirementWeeks int64 `db:"restart_requirement_weeks" json:"restart_requirement_weeks"` CreatedByAvatarURL sql.NullString `db:"created_by_avatar_url" json:"created_by_avatar_url"` CreatedByUsername string `db:"created_by_username" json:"created_by_username"` } @@ -1766,9 +1766,9 @@ type TemplateTable struct { InactivityTTL int64 `db:"inactivity_ttl" json:"inactivity_ttl"` LockedTTL int64 `db:"locked_ttl" json:"locked_ttl"` // A bitmap of days of week to restart the workspace on, starting with Monday as the 0th bit, and Sunday as the 6th bit. The 7th bit is unused. - RestartRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"` + AutostopRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"` // The number of weeks between restarts. 0 or 1 weeks means "every week", 2 week means "every second week", etc. Weeks are counted from January 2, 2023, which is the first Monday of 2023. This is to ensure workspaces are started consistently for all customers on the same n-week cycles. - RestartRequirementWeeks int64 `db:"restart_requirement_weeks" json:"restart_requirement_weeks"` + AutostopRequirementWeeks int64 `db:"restart_requirement_weeks" json:"restart_requirement_weeks"` } // Joins in the username + avatar url of the created by user. diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index f1bb80a6e0afd..622c186692107 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -4339,7 +4339,7 @@ func (q *sqlQuerier) GetTemplateAverageBuildTime(ctx context.Context, arg GetTem const getTemplateByID = `-- name: GetTemplateByID :one SELECT - id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, restart_requirement_days_of_week, restart_requirement_weeks, created_by_avatar_url, created_by_username + id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username FROM template_with_users WHERE @@ -4374,8 +4374,8 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat &i.FailureTTL, &i.InactivityTTL, &i.LockedTTL, - &i.RestartRequirementDaysOfWeek, - &i.RestartRequirementWeeks, + &i.AutostopRequirementDaysOfWeek, + &i.AutostopRequirementWeeks, &i.CreatedByAvatarURL, &i.CreatedByUsername, ) @@ -4384,7 +4384,7 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat const getTemplateByOrganizationAndName = `-- name: GetTemplateByOrganizationAndName :one SELECT - id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, restart_requirement_days_of_week, restart_requirement_weeks, created_by_avatar_url, created_by_username + id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username FROM template_with_users AS templates WHERE @@ -4427,8 +4427,8 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G &i.FailureTTL, &i.InactivityTTL, &i.LockedTTL, - &i.RestartRequirementDaysOfWeek, - &i.RestartRequirementWeeks, + &i.AutostopRequirementDaysOfWeek, + &i.AutostopRequirementWeeks, &i.CreatedByAvatarURL, &i.CreatedByUsername, ) @@ -4436,7 +4436,7 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G } const getTemplates = `-- name: GetTemplates :many -SELECT id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, restart_requirement_days_of_week, restart_requirement_weeks, created_by_avatar_url, created_by_username FROM template_with_users AS templates +SELECT id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username FROM template_with_users AS templates ORDER BY (name, id) ASC ` @@ -4472,8 +4472,8 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) { &i.FailureTTL, &i.InactivityTTL, &i.LockedTTL, - &i.RestartRequirementDaysOfWeek, - &i.RestartRequirementWeeks, + &i.AutostopRequirementDaysOfWeek, + &i.AutostopRequirementWeeks, &i.CreatedByAvatarURL, &i.CreatedByUsername, ); err != nil { @@ -4492,7 +4492,7 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) { const getTemplatesWithFilter = `-- name: GetTemplatesWithFilter :many SELECT - id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, restart_requirement_days_of_week, restart_requirement_weeks, created_by_avatar_url, created_by_username + id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description, default_ttl, created_by, icon, user_acl, group_acl, display_name, allow_user_cancel_workspace_jobs, max_ttl, allow_user_autostart, allow_user_autostop, failure_ttl, inactivity_ttl, locked_ttl, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username FROM template_with_users AS templates WHERE @@ -4565,8 +4565,8 @@ func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplate &i.FailureTTL, &i.InactivityTTL, &i.LockedTTL, - &i.RestartRequirementDaysOfWeek, - &i.RestartRequirementWeeks, + &i.AutostopRequirementDaysOfWeek, + &i.AutostopRequirementWeeks, &i.CreatedByAvatarURL, &i.CreatedByUsername, ); err != nil { @@ -4751,8 +4751,8 @@ SET allow_user_autostop = $4, default_ttl = $5, max_ttl = $6, - restart_requirement_days_of_week = $7, - restart_requirement_weeks = $8, + autostop_requirement_days_of_week = $7, + autostop_requirement_weeks = $8, failure_ttl = $9, inactivity_ttl = $10, locked_ttl = $11 @@ -4761,17 +4761,17 @@ WHERE ` type UpdateTemplateScheduleByIDParams struct { - ID uuid.UUID `db:"id" json:"id"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` - AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"` - AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"` - DefaultTTL int64 `db:"default_ttl" json:"default_ttl"` - MaxTTL int64 `db:"max_ttl" json:"max_ttl"` - RestartRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"` - RestartRequirementWeeks int64 `db:"restart_requirement_weeks" json:"restart_requirement_weeks"` - FailureTTL int64 `db:"failure_ttl" json:"failure_ttl"` - InactivityTTL int64 `db:"inactivity_ttl" json:"inactivity_ttl"` - LockedTTL int64 `db:"locked_ttl" json:"locked_ttl"` + ID uuid.UUID `db:"id" json:"id"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"` + AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"` + DefaultTTL int64 `db:"default_ttl" json:"default_ttl"` + MaxTTL int64 `db:"max_ttl" json:"max_ttl"` + AutostopRequirementDaysOfWeek int16 `db:"autostop_requirement_days_of_week" json:"autostop_requirement_days_of_week"` + AutostopRequirementWeeks int64 `db:"autostop_requirement_weeks" json:"autostop_requirement_weeks"` + FailureTTL int64 `db:"failure_ttl" json:"failure_ttl"` + InactivityTTL int64 `db:"inactivity_ttl" json:"inactivity_ttl"` + LockedTTL int64 `db:"locked_ttl" json:"locked_ttl"` } func (q *sqlQuerier) UpdateTemplateScheduleByID(ctx context.Context, arg UpdateTemplateScheduleByIDParams) error { @@ -4782,8 +4782,8 @@ func (q *sqlQuerier) UpdateTemplateScheduleByID(ctx context.Context, arg UpdateT arg.AllowUserAutostop, arg.DefaultTTL, arg.MaxTTL, - arg.RestartRequirementDaysOfWeek, - arg.RestartRequirementWeeks, + arg.AutostopRequirementDaysOfWeek, + arg.AutostopRequirementWeeks, arg.FailureTTL, arg.InactivityTTL, arg.LockedTTL, diff --git a/coderd/database/queries/templates.sql b/coderd/database/queries/templates.sql index 7f4c9ce5de4ab..ab67635381e33 100644 --- a/coderd/database/queries/templates.sql +++ b/coderd/database/queries/templates.sql @@ -118,8 +118,8 @@ SET allow_user_autostop = $4, default_ttl = $5, max_ttl = $6, - restart_requirement_days_of_week = $7, - restart_requirement_weeks = $8, + autostop_requirement_days_of_week = $7, + autostop_requirement_weeks = $8, failure_ttl = $9, inactivity_ttl = $10, locked_ttl = $11 diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index f53933722458c..6f3f7ae13edd6 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -1027,11 +1027,11 @@ func TestCompleteJob(t *testing.T) { var store schedule.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: false, + UserAutostartEnabled: false, + UserAutostopEnabled: c.templateAllowAutostop, + DefaultTTL: c.templateDefaultTTL, + MaxTTL: c.templateMaxTTL, + UseAutostopRequirement: false, }, nil }, } @@ -1175,44 +1175,44 @@ func TestCompleteJob(t *testing.T) { transition database.WorkspaceTransition // These fields are only used when testing max deadline. - userQuietHoursSchedule string - templateRestartRequirement schedule.TemplateRestartRequirement + userQuietHoursSchedule string + templateAutostopRequirement schedule.TemplateAutostopRequirement expectedDeadline time.Time expectedMaxDeadline time.Time }{ { - name: "OK", - now: now, - templateRestartRequirement: schedule.TemplateRestartRequirement{}, - workspaceTTL: 0, - transition: database.WorkspaceTransitionStart, - expectedDeadline: time.Time{}, - expectedMaxDeadline: time.Time{}, + name: "OK", + now: now, + templateAutostopRequirement: schedule.TemplateAutostopRequirement{}, + workspaceTTL: 0, + transition: database.WorkspaceTransitionStart, + expectedDeadline: time.Time{}, + expectedMaxDeadline: time.Time{}, }, { - name: "Delete", - now: now, - templateRestartRequirement: schedule.TemplateRestartRequirement{}, - workspaceTTL: 0, - transition: database.WorkspaceTransitionDelete, - expectedDeadline: time.Time{}, - expectedMaxDeadline: time.Time{}, + name: "Delete", + now: now, + templateAutostopRequirement: schedule.TemplateAutostopRequirement{}, + workspaceTTL: 0, + transition: database.WorkspaceTransitionDelete, + expectedDeadline: time.Time{}, + expectedMaxDeadline: time.Time{}, }, { - name: "WorkspaceTTL", - now: now, - templateRestartRequirement: schedule.TemplateRestartRequirement{}, - workspaceTTL: time.Hour, - transition: database.WorkspaceTransitionStart, - expectedDeadline: now.Add(time.Hour), - expectedMaxDeadline: time.Time{}, + name: "WorkspaceTTL", + now: now, + templateAutostopRequirement: schedule.TemplateAutostopRequirement{}, + workspaceTTL: time.Hour, + transition: database.WorkspaceTransitionStart, + expectedDeadline: now.Add(time.Hour), + expectedMaxDeadline: time.Time{}, }, { - name: "TemplateRestartRequirement", + name: "TemplateAutostopRequirement", now: wednesdayMidnightUTC, userQuietHoursSchedule: sydneyQuietHours, - templateRestartRequirement: schedule.TemplateRestartRequirement{ + templateAutostopRequirement: schedule.TemplateAutostopRequirement{ DaysOfWeek: 0b00100000, // Saturday Weeks: 0, // weekly }, @@ -1241,11 +1241,11 @@ func TestCompleteJob(t *testing.T) { var templateScheduleStore schedule.TemplateScheduleStore = schedule.MockTemplateScheduleStore{ GetFn: func(_ context.Context, _ database.Store, _ uuid.UUID) (schedule.TemplateScheduleOptions, error) { return schedule.TemplateScheduleOptions{ - UserAutostartEnabled: false, - UserAutostopEnabled: true, - DefaultTTL: 0, - UseRestartRequirement: true, - RestartRequirement: c.templateRestartRequirement, + UserAutostartEnabled: false, + UserAutostopEnabled: true, + DefaultTTL: 0, + UseAutostopRequirement: true, + AutostopRequirement: c.templateAutostopRequirement, }, nil }, } @@ -1280,13 +1280,13 @@ func TestCompleteJob(t *testing.T) { Provisioner: database.ProvisionerTypeEcho, }) err := srv.Database.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: false, - AllowUserAutostop: true, - DefaultTTL: 0, - RestartRequirementDaysOfWeek: int16(c.templateRestartRequirement.DaysOfWeek), - RestartRequirementWeeks: c.templateRestartRequirement.Weeks, + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: false, + AllowUserAutostop: true, + DefaultTTL: 0, + AutostopRequirementDaysOfWeek: int16(c.templateAutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: c.templateAutostopRequirement.Weeks, }) require.NoError(t, err) template, err = srv.Database.GetTemplateByID(ctx, template.ID) diff --git a/coderd/schedule/autostop.go b/coderd/schedule/autostop.go index 6fe3d5848db02..8cf645b52f5de 100644 --- a/coderd/schedule/autostop.go +++ b/coderd/schedule/autostop.go @@ -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() diff --git a/coderd/schedule/autostop_test.go b/coderd/schedule/autostop_test.go index 8a93c819698b4..69675ae638ec8 100644 --- a/coderd/schedule/autostop_test.go +++ b/coderd/schedule/autostop_test.go @@ -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 }, @@ -178,12 +178,12 @@ func TestCalculateAutoStop(t *testing.T) { { // The next restart 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,12 +220,12 @@ 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 }, @@ -236,12 +236,12 @@ func TestCalculateAutoStop(t *testing.T) { 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) diff --git a/coderd/schedule/template.go b/coderd/schedule/template.go index 0e3774b798358..88e7d614f4a6c 100644 --- a/coderd/schedule/template.go +++ b/coderd/schedule/template.go @@ -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< MaxTemplateRestartRequirementWeeks { + if weeks > MaxTemplateAutostopRequirementWeeks { return xerrors.New("invalid restart requirement weeks, too large") } return nil @@ -88,14 +88,14 @@ type TemplateScheduleOptions struct { // TODO(@dean): remove MaxTTL once restart_requirement is matured and the // default MaxTTL time.Duration `json:"max_ttl"` - // UseRestartRequirement dictates whether the restart requirement should be + // UseAutostopRequirement dictates whether the restart 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:"restart_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, InactivityTTL, and LockedTTL 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, - InactivityTTL: tpl.InactivityTTL, - LockedTTL: tpl.LockedTTL, + MaxTTL: tpl.MaxTTL, + AutostopRequirementDaysOfWeek: tpl.AutostopRequirementDaysOfWeek, + AutostopRequirementWeeks: tpl.AutostopRequirementWeeks, + AllowUserAutostart: tpl.AllowUserAutostart, + AllowUserAutostop: tpl.AllowUserAutostop, + FailureTTL: tpl.FailureTTL, + InactivityTTL: tpl.InactivityTTL, + LockedTTL: tpl.LockedTTL, }) if err != nil { return xerrors.Errorf("update template schedule: %w", err) diff --git a/coderd/templates.go b/coderd/templates.go index f51f42668e1a1..9b9893d9b4d4b 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -215,19 +215,19 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque var ( defaultTTL time.Duration // TODO(@dean): remove max_ttl once restart_requirement is ready - maxTTL time.Duration - restartRequirementDaysOfWeek []string - restartRequirementWeeks int64 - failureTTL time.Duration - inactivityTTL time.Duration - lockedTTL time.Duration + maxTTL time.Duration + autostopRequirementDaysOfWeek []string + autostopRequirementWeeks int64 + failureTTL time.Duration + inactivityTTL time.Duration + lockedTTL time.Duration ) if createTemplate.DefaultTTLMillis != nil { defaultTTL = time.Duration(*createTemplate.DefaultTTLMillis) * time.Millisecond } - if createTemplate.RestartRequirement != nil { - restartRequirementDaysOfWeek = createTemplate.RestartRequirement.DaysOfWeek - restartRequirementWeeks = createTemplate.RestartRequirement.Weeks + if createTemplate.AutostopRequirement != nil { + autostopRequirementDaysOfWeek = createTemplate.AutostopRequirement.DaysOfWeek + autostopRequirementWeeks = createTemplate.AutostopRequirement.Weeks } if createTemplate.FailureTTLMillis != nil { failureTTL = time.Duration(*createTemplate.FailureTTLMillis) * time.Millisecond @@ -240,8 +240,8 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque } var ( - validErrs []codersdk.ValidationError - restartRequirementDaysOfWeekParsed uint8 + validErrs []codersdk.ValidationError + autostopRequirementDaysOfWeekParsed uint8 ) if defaultTTL < 0 { validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be a positive integer."}) @@ -252,8 +252,8 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque if maxTTL != 0 && defaultTTL > maxTTL { validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be less than or equal to max_ttl_ms if max_ttl_ms is set."}) } - if len(restartRequirementDaysOfWeek) > 0 { - restartRequirementDaysOfWeekParsed, err = codersdk.WeekdaysToBitmap(restartRequirementDaysOfWeek) + if len(autostopRequirementDaysOfWeek) > 0 { + autostopRequirementDaysOfWeekParsed, err = codersdk.WeekdaysToBitmap(autostopRequirementDaysOfWeek) if err != nil { validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.days_of_week", Detail: err.Error()}) } @@ -261,11 +261,11 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque if createTemplate.MaxTTLMillis != nil { maxTTL = time.Duration(*createTemplate.MaxTTLMillis) * time.Millisecond } - if restartRequirementWeeks < 0 { - validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: "Must be a positive integer."}) + if autostopRequirementWeeks < 0 { + validErrs = append(validErrs, codersdk.ValidationError{Field: "autostop_requirement.weeks", Detail: "Must be a positive integer."}) } - if restartRequirementWeeks > schedule.MaxTemplateRestartRequirementWeeks { - validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: fmt.Sprintf("Must be less than %d.", schedule.MaxTemplateRestartRequirementWeeks)}) + if autostopRequirementWeeks > schedule.MaxTemplateAutostopRequirementWeeks { + validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: fmt.Sprintf("Must be less than %d.", schedule.MaxTemplateAutostopRequirementWeeks)}) } if failureTTL < 0 { validErrs = append(validErrs, codersdk.ValidationError{Field: "failure_ttl_ms", Detail: "Must be a positive integer."}) @@ -336,9 +336,9 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque // Some of these values are enterprise-only, but the // TemplateScheduleStore will handle avoiding setting them if // unlicensed. - RestartRequirement: schedule.TemplateRestartRequirement{ - DaysOfWeek: restartRequirementDaysOfWeekParsed, - Weeks: restartRequirementWeeks, + AutostopRequirement: schedule.TemplateAutostopRequirement{ + DaysOfWeek: autostopRequirementDaysOfWeekParsed, + Weeks: autostopRequirementWeeks, }, FailureTTL: failureTTL, InactivityTTL: inactivityTTL, @@ -500,8 +500,8 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) { } var ( - validErrs []codersdk.ValidationError - restartRequirementDaysOfWeekParsed uint8 + validErrs []codersdk.ValidationError + autostopRequirementDaysOfWeekParsed uint8 ) if req.DefaultTTLMillis < 0 { validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be a positive integer."}) @@ -512,23 +512,23 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) { if req.MaxTTLMillis != 0 && req.DefaultTTLMillis > req.MaxTTLMillis { validErrs = append(validErrs, codersdk.ValidationError{Field: "default_ttl_ms", Detail: "Must be less than or equal to max_ttl_ms if max_ttl_ms is set."}) } - if req.RestartRequirement == nil { - req.RestartRequirement = &codersdk.TemplateRestartRequirement{ - DaysOfWeek: codersdk.BitmapToWeekdays(scheduleOpts.RestartRequirement.DaysOfWeek), - Weeks: scheduleOpts.RestartRequirement.Weeks, + if req.AutostopRequirement == nil { + req.AutostopRequirement = &codersdk.TemplateAutostopRequirement{ + DaysOfWeek: codersdk.BitmapToWeekdays(scheduleOpts.AutostopRequirement.DaysOfWeek), + Weeks: scheduleOpts.AutostopRequirement.Weeks, } } - if len(req.RestartRequirement.DaysOfWeek) > 0 { - restartRequirementDaysOfWeekParsed, err = codersdk.WeekdaysToBitmap(req.RestartRequirement.DaysOfWeek) + if len(req.AutostopRequirement.DaysOfWeek) > 0 { + autostopRequirementDaysOfWeekParsed, err = codersdk.WeekdaysToBitmap(req.AutostopRequirement.DaysOfWeek) if err != nil { validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.days_of_week", Detail: err.Error()}) } } - if req.RestartRequirement.Weeks < 0 { + if req.AutostopRequirement.Weeks < 0 { validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: "Must be a positive integer."}) } - if req.RestartRequirement.Weeks > schedule.MaxTemplateRestartRequirementWeeks { - validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: fmt.Sprintf("Must be less than %d.", schedule.MaxTemplateRestartRequirementWeeks)}) + if req.AutostopRequirement.Weeks > schedule.MaxTemplateAutostopRequirementWeeks { + validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: fmt.Sprintf("Must be less than %d.", schedule.MaxTemplateAutostopRequirementWeeks)}) } if req.FailureTTLMillis < 0 { validErrs = append(validErrs, codersdk.ValidationError{Field: "failure_ttl_ms", Detail: "Must be a positive integer."}) @@ -562,8 +562,8 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) { req.AllowUserCancelWorkspaceJobs == template.AllowUserCancelWorkspaceJobs && req.DefaultTTLMillis == time.Duration(template.DefaultTTL).Milliseconds() && req.MaxTTLMillis == time.Duration(template.MaxTTL).Milliseconds() && - restartRequirementDaysOfWeekParsed == scheduleOpts.RestartRequirement.DaysOfWeek && - req.RestartRequirement.Weeks == scheduleOpts.RestartRequirement.Weeks && + autostopRequirementDaysOfWeekParsed == scheduleOpts.AutostopRequirement.DaysOfWeek && + req.AutostopRequirement.Weeks == scheduleOpts.AutostopRequirement.Weeks && req.FailureTTLMillis == time.Duration(template.FailureTTL).Milliseconds() && req.InactivityTTLMillis == time.Duration(template.InactivityTTL).Milliseconds() && req.LockedTTLMillis == time.Duration(template.LockedTTL).Milliseconds() { @@ -603,8 +603,8 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) { if defaultTTL != time.Duration(template.DefaultTTL) || maxTTL != time.Duration(template.MaxTTL) || - restartRequirementDaysOfWeekParsed != scheduleOpts.RestartRequirement.DaysOfWeek || - req.RestartRequirement.Weeks != scheduleOpts.RestartRequirement.Weeks || + autostopRequirementDaysOfWeekParsed != scheduleOpts.AutostopRequirement.DaysOfWeek || + req.AutostopRequirement.Weeks != scheduleOpts.AutostopRequirement.Weeks || failureTTL != time.Duration(template.FailureTTL) || inactivityTTL != time.Duration(template.InactivityTTL) || lockedTTL != time.Duration(template.LockedTTL) || @@ -618,9 +618,9 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) { UserAutostopEnabled: req.AllowUserAutostop, DefaultTTL: defaultTTL, MaxTTL: maxTTL, - RestartRequirement: schedule.TemplateRestartRequirement{ - DaysOfWeek: restartRequirementDaysOfWeekParsed, - Weeks: req.RestartRequirement.Weeks, + AutostopRequirement: schedule.TemplateAutostopRequirement{ + DaysOfWeek: autostopRequirementDaysOfWeekParsed, + Weeks: req.AutostopRequirement.Weeks, }, FailureTTL: failureTTL, InactivityTTL: inactivityTTL, @@ -760,9 +760,9 @@ func (api *API) convertTemplate( FailureTTLMillis: time.Duration(template.FailureTTL).Milliseconds(), InactivityTTLMillis: time.Duration(template.InactivityTTL).Milliseconds(), LockedTTLMillis: time.Duration(template.LockedTTL).Milliseconds(), - RestartRequirement: codersdk.TemplateRestartRequirement{ - DaysOfWeek: codersdk.BitmapToWeekdays(uint8(template.RestartRequirementDaysOfWeek)), - Weeks: template.RestartRequirementWeeks, + AutostopRequirement: codersdk.TemplateAutostopRequirement{ + DaysOfWeek: codersdk.BitmapToWeekdays(uint8(template.AutostopRequirementDaysOfWeek)), + Weeks: template.AutostopRequirementWeeks, }, } } diff --git a/coderd/templates_test.go b/coderd/templates_test.go index 92a67710902dd..78a4084c169ae 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -246,7 +246,7 @@ func TestPostTemplateByOrganization(t *testing.T) { require.Equal(t, http.StatusNotFound, apiErr.StatusCode()) }) - t.Run("RestartRequirement", func(t *testing.T) { + t.Run("AutostopRequirement", func(t *testing.T) { t.Parallel() t.Run("None", func(t *testing.T) { @@ -257,21 +257,21 @@ func TestPostTemplateByOrganization(t *testing.T) { TemplateScheduleStore: schedule.MockTemplateScheduleStore{ SetFn: func(ctx context.Context, db database.Store, template database.Template, options schedule.TemplateScheduleOptions) (database.Template, error) { atomic.AddInt64(&setCalled, 1) - assert.Zero(t, options.RestartRequirement.DaysOfWeek) - assert.Zero(t, options.RestartRequirement.Weeks) + assert.Zero(t, options.AutostopRequirement.DaysOfWeek) + assert.Zero(t, options.AutostopRequirement.Weeks) err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: options.UserAutostartEnabled, - AllowUserAutostop: options.UserAutostopEnabled, - DefaultTTL: int64(options.DefaultTTL), - MaxTTL: int64(options.MaxTTL), - RestartRequirementDaysOfWeek: int16(options.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: options.RestartRequirement.Weeks, - FailureTTL: int64(options.FailureTTL), - InactivityTTL: int64(options.InactivityTTL), - LockedTTL: int64(options.LockedTTL), + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: options.UserAutostartEnabled, + AllowUserAutostop: options.UserAutostopEnabled, + DefaultTTL: int64(options.DefaultTTL), + MaxTTL: int64(options.MaxTTL), + AutostopRequirementDaysOfWeek: int16(options.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: options.AutostopRequirement.Weeks, + FailureTTL: int64(options.FailureTTL), + InactivityTTL: int64(options.InactivityTTL), + LockedTTL: int64(options.LockedTTL), }) if !assert.NoError(t, err) { return database.Template{}, err @@ -288,15 +288,15 @@ func TestPostTemplateByOrganization(t *testing.T) { defer cancel() got, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{ - Name: "testing", - VersionID: version.ID, - RestartRequirement: nil, + Name: "testing", + VersionID: version.ID, + AutostopRequirement: nil, }) require.NoError(t, err) require.EqualValues(t, 1, atomic.LoadInt64(&setCalled)) - require.Empty(t, got.RestartRequirement.DaysOfWeek) - require.Zero(t, got.RestartRequirement.Weeks) + require.Empty(t, got.AutostopRequirement.DaysOfWeek) + require.Zero(t, got.AutostopRequirement.Weeks) }) t.Run("OK", func(t *testing.T) { @@ -307,21 +307,21 @@ func TestPostTemplateByOrganization(t *testing.T) { TemplateScheduleStore: schedule.MockTemplateScheduleStore{ SetFn: func(ctx context.Context, db database.Store, template database.Template, options schedule.TemplateScheduleOptions) (database.Template, error) { atomic.AddInt64(&setCalled, 1) - assert.EqualValues(t, 0b00110000, options.RestartRequirement.DaysOfWeek) - assert.EqualValues(t, 2, options.RestartRequirement.Weeks) + assert.EqualValues(t, 0b00110000, options.AutostopRequirement.DaysOfWeek) + assert.EqualValues(t, 2, options.AutostopRequirement.Weeks) err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: options.UserAutostartEnabled, - AllowUserAutostop: options.UserAutostopEnabled, - DefaultTTL: int64(options.DefaultTTL), - MaxTTL: int64(options.MaxTTL), - RestartRequirementDaysOfWeek: int16(options.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: options.RestartRequirement.Weeks, - FailureTTL: int64(options.FailureTTL), - InactivityTTL: int64(options.InactivityTTL), - LockedTTL: int64(options.LockedTTL), + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: options.UserAutostartEnabled, + AllowUserAutostop: options.UserAutostopEnabled, + DefaultTTL: int64(options.DefaultTTL), + MaxTTL: int64(options.MaxTTL), + AutostopRequirementDaysOfWeek: int16(options.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: options.AutostopRequirement.Weeks, + FailureTTL: int64(options.FailureTTL), + InactivityTTL: int64(options.InactivityTTL), + LockedTTL: int64(options.LockedTTL), }) if !assert.NoError(t, err) { return database.Template{}, err @@ -340,7 +340,7 @@ func TestPostTemplateByOrganization(t *testing.T) { got, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{ Name: "testing", VersionID: version.ID, - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ // wrong order DaysOfWeek: []string{"saturday", "friday"}, Weeks: 2, @@ -349,13 +349,13 @@ func TestPostTemplateByOrganization(t *testing.T) { require.NoError(t, err) require.EqualValues(t, 1, atomic.LoadInt64(&setCalled)) - require.Equal(t, []string{"friday", "saturday"}, got.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 2, got.RestartRequirement.Weeks) + require.Equal(t, []string{"friday", "saturday"}, got.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 2, got.AutostopRequirement.Weeks) got, err = client.Template(ctx, got.ID) require.NoError(t, err) - require.Equal(t, []string{"friday", "saturday"}, got.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 2, got.RestartRequirement.Weeks) + require.Equal(t, []string{"friday", "saturday"}, got.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 2, got.AutostopRequirement.Weeks) }) t.Run("IgnoredUnlicensed", func(t *testing.T) { @@ -371,15 +371,15 @@ func TestPostTemplateByOrganization(t *testing.T) { got, err := client.CreateTemplate(ctx, user.OrganizationID, codersdk.CreateTemplateRequest{ Name: "testing", VersionID: version.ID, - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ DaysOfWeek: []string{"friday", "saturday"}, Weeks: 2, }, }) require.NoError(t, err) // ignored and use AGPL defaults - require.Empty(t, got.RestartRequirement.DaysOfWeek) - require.Zero(t, got.RestartRequirement.Weeks) + require.Empty(t, got.AutostopRequirement.DaysOfWeek) + require.Zero(t, got.AutostopRequirement.Weeks) }) }) } @@ -589,17 +589,17 @@ func TestPatchTemplateMeta(t *testing.T) { } err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: options.UserAutostartEnabled, - AllowUserAutostop: options.UserAutostopEnabled, - DefaultTTL: int64(options.DefaultTTL), - MaxTTL: int64(options.MaxTTL), - RestartRequirementDaysOfWeek: int16(options.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: options.RestartRequirement.Weeks, - FailureTTL: int64(options.FailureTTL), - InactivityTTL: int64(options.InactivityTTL), - LockedTTL: int64(options.LockedTTL), + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: options.UserAutostartEnabled, + AllowUserAutostop: options.UserAutostopEnabled, + DefaultTTL: int64(options.DefaultTTL), + MaxTTL: int64(options.MaxTTL), + AutostopRequirementDaysOfWeek: int16(options.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: options.AutostopRequirement.Weeks, + FailureTTL: int64(options.FailureTTL), + InactivityTTL: int64(options.InactivityTTL), + LockedTTL: int64(options.LockedTTL), }) if !assert.NoError(t, err) { return database.Template{}, err @@ -738,7 +738,7 @@ func TestPatchTemplateMeta(t *testing.T) { Description: template.Description, Icon: template.Icon, DefaultTTLMillis: 0, - RestartRequirement: &template.RestartRequirement, + AutostopRequirement: &template.AutostopRequirement, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, FailureTTLMillis: failureTTL.Milliseconds(), InactivityTTLMillis: inactivityTTL.Milliseconds(), @@ -773,7 +773,7 @@ func TestPatchTemplateMeta(t *testing.T) { Description: template.Description, Icon: template.Icon, DefaultTTLMillis: template.DefaultTTLMillis, - RestartRequirement: &template.RestartRequirement, + AutostopRequirement: &template.AutostopRequirement, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, FailureTTLMillis: failureTTL.Milliseconds(), InactivityTTLMillis: inactivityTTL.Milliseconds(), @@ -832,7 +832,7 @@ func TestPatchTemplateMeta(t *testing.T) { Description: template.Description, Icon: template.Icon, DefaultTTLMillis: template.DefaultTTLMillis, - RestartRequirement: &template.RestartRequirement, + AutostopRequirement: &template.AutostopRequirement, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, AllowUserAutostart: allowAutostart.Load(), AllowUserAutostop: allowAutostop.Load(), @@ -864,7 +864,7 @@ func TestPatchTemplateMeta(t *testing.T) { Icon: template.Icon, // Increase the default TTL to avoid error "not modified". DefaultTTLMillis: template.DefaultTTLMillis + 1, - RestartRequirement: &template.RestartRequirement, + AutostopRequirement: &template.AutostopRequirement, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, AllowUserAutostart: false, AllowUserAutostop: false, @@ -891,13 +891,13 @@ func TestPatchTemplateMeta(t *testing.T) { defer cancel() req := codersdk.UpdateTemplateMeta{ - Name: template.Name, - Description: template.Description, - Icon: template.Icon, - DefaultTTLMillis: template.DefaultTTLMillis, - RestartRequirement: nil, - AllowUserAutostart: template.AllowUserAutostart, - AllowUserAutostop: template.AllowUserAutostop, + Name: template.Name, + Description: template.Description, + Icon: template.Icon, + DefaultTTLMillis: template.DefaultTTLMillis, + AutostopRequirement: nil, + AllowUserAutostart: template.AllowUserAutostart, + AllowUserAutostop: template.AllowUserAutostop, } _, err := client.UpdateTemplateMeta(ctx, template.ID, req) require.ErrorContains(t, err, "not modified") @@ -964,7 +964,7 @@ func TestPatchTemplateMeta(t *testing.T) { assert.Equal(t, updated.Icon, "") }) - t.Run("RestartRequirement", func(t *testing.T) { + t.Run("AutostopRequirement", func(t *testing.T) { t.Parallel() t.Run("OK", func(t *testing.T) { @@ -975,22 +975,22 @@ func TestPatchTemplateMeta(t *testing.T) { TemplateScheduleStore: schedule.MockTemplateScheduleStore{ SetFn: func(ctx context.Context, db database.Store, template database.Template, options schedule.TemplateScheduleOptions) (database.Template, error) { if atomic.AddInt64(&setCalled, 1) == 2 { - assert.EqualValues(t, 0b0110000, options.RestartRequirement.DaysOfWeek) - assert.EqualValues(t, 2, options.RestartRequirement.Weeks) + assert.EqualValues(t, 0b0110000, options.AutostopRequirement.DaysOfWeek) + assert.EqualValues(t, 2, options.AutostopRequirement.Weeks) } err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: options.UserAutostartEnabled, - AllowUserAutostop: options.UserAutostopEnabled, - DefaultTTL: int64(options.DefaultTTL), - MaxTTL: int64(options.MaxTTL), - RestartRequirementDaysOfWeek: int16(options.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: options.RestartRequirement.Weeks, - FailureTTL: int64(options.FailureTTL), - InactivityTTL: int64(options.InactivityTTL), - LockedTTL: int64(options.LockedTTL), + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: options.UserAutostartEnabled, + AllowUserAutostop: options.UserAutostopEnabled, + DefaultTTL: int64(options.DefaultTTL), + MaxTTL: int64(options.MaxTTL), + AutostopRequirementDaysOfWeek: int16(options.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: options.AutostopRequirement.Weeks, + FailureTTL: int64(options.FailureTTL), + InactivityTTL: int64(options.InactivityTTL), + LockedTTL: int64(options.LockedTTL), }) if !assert.NoError(t, err) { return database.Template{}, err @@ -1005,8 +1005,8 @@ func TestPatchTemplateMeta(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) require.EqualValues(t, 1, atomic.LoadInt64(&setCalled)) - require.Empty(t, template.RestartRequirement.DaysOfWeek) - require.Zero(t, template.RestartRequirement.Weeks) + require.Empty(t, template.AutostopRequirement.DaysOfWeek) + require.Zero(t, template.AutostopRequirement.Weeks) req := codersdk.UpdateTemplateMeta{ Name: template.Name, DisplayName: template.DisplayName, @@ -1014,7 +1014,7 @@ func TestPatchTemplateMeta(t *testing.T) { Icon: template.Icon, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, DefaultTTLMillis: time.Hour.Milliseconds(), - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ // wrong order DaysOfWeek: []string{"saturday", "friday"}, Weeks: 2, @@ -1027,13 +1027,13 @@ func TestPatchTemplateMeta(t *testing.T) { updated, err := client.UpdateTemplateMeta(ctx, template.ID, req) require.NoError(t, err) require.EqualValues(t, 2, atomic.LoadInt64(&setCalled)) - require.Equal(t, []string{"friday", "saturday"}, updated.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 2, updated.RestartRequirement.Weeks) + require.Equal(t, []string{"friday", "saturday"}, updated.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 2, updated.AutostopRequirement.Weeks) template, err = client.Template(ctx, template.ID) require.NoError(t, err) - require.Equal(t, []string{"friday", "saturday"}, template.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 2, template.RestartRequirement.Weeks) + require.Equal(t, []string{"friday", "saturday"}, template.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 2, template.AutostopRequirement.Weeks) }) t.Run("Unset", func(t *testing.T) { @@ -1044,22 +1044,22 @@ func TestPatchTemplateMeta(t *testing.T) { TemplateScheduleStore: schedule.MockTemplateScheduleStore{ SetFn: func(ctx context.Context, db database.Store, template database.Template, options schedule.TemplateScheduleOptions) (database.Template, error) { if atomic.AddInt64(&setCalled, 1) == 2 { - assert.EqualValues(t, 0, options.RestartRequirement.DaysOfWeek) - assert.EqualValues(t, 0, options.RestartRequirement.Weeks) + assert.EqualValues(t, 0, options.AutostopRequirement.DaysOfWeek) + assert.EqualValues(t, 0, options.AutostopRequirement.Weeks) } err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: template.ID, - UpdatedAt: database.Now(), - AllowUserAutostart: options.UserAutostartEnabled, - AllowUserAutostop: options.UserAutostopEnabled, - DefaultTTL: int64(options.DefaultTTL), - MaxTTL: int64(options.MaxTTL), - RestartRequirementDaysOfWeek: int16(options.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: options.RestartRequirement.Weeks, - FailureTTL: int64(options.FailureTTL), - InactivityTTL: int64(options.InactivityTTL), - LockedTTL: int64(options.LockedTTL), + ID: template.ID, + UpdatedAt: database.Now(), + AllowUserAutostart: options.UserAutostartEnabled, + AllowUserAutostop: options.UserAutostopEnabled, + DefaultTTL: int64(options.DefaultTTL), + MaxTTL: int64(options.MaxTTL), + AutostopRequirementDaysOfWeek: int16(options.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: options.AutostopRequirement.Weeks, + FailureTTL: int64(options.FailureTTL), + InactivityTTL: int64(options.InactivityTTL), + LockedTTL: int64(options.LockedTTL), }) if !assert.NoError(t, err) { return database.Template{}, err @@ -1073,15 +1073,15 @@ func TestPatchTemplateMeta(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { - ctr.RestartRequirement = &codersdk.TemplateRestartRequirement{ + ctr.AutostopRequirement = &codersdk.TemplateAutostopRequirement{ // wrong order DaysOfWeek: []string{"sunday", "saturday", "friday", "thursday", "wednesday", "tuesday", "monday"}, Weeks: 2, } }) require.EqualValues(t, 1, atomic.LoadInt64(&setCalled)) - require.Equal(t, []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}, template.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 2, template.RestartRequirement.Weeks) + require.Equal(t, []string{"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"}, template.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 2, template.AutostopRequirement.Weeks) req := codersdk.UpdateTemplateMeta{ Name: template.Name, DisplayName: template.DisplayName, @@ -1089,7 +1089,7 @@ func TestPatchTemplateMeta(t *testing.T) { Icon: template.Icon, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, DefaultTTLMillis: time.Hour.Milliseconds(), - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ DaysOfWeek: []string{}, Weeks: 0, }, @@ -1101,13 +1101,13 @@ func TestPatchTemplateMeta(t *testing.T) { updated, err := client.UpdateTemplateMeta(ctx, template.ID, req) require.NoError(t, err) require.EqualValues(t, 2, atomic.LoadInt64(&setCalled)) - require.Empty(t, updated.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 0, updated.RestartRequirement.Weeks) + require.Empty(t, updated.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 0, updated.AutostopRequirement.Weeks) template, err = client.Template(ctx, template.ID) require.NoError(t, err) - require.Empty(t, template.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 0, template.RestartRequirement.Weeks) + require.Empty(t, template.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 0, template.AutostopRequirement.Weeks) }) t.Run("EnterpriseOnly", func(t *testing.T) { @@ -1117,8 +1117,8 @@ func TestPatchTemplateMeta(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - require.Empty(t, template.RestartRequirement.DaysOfWeek) - require.Zero(t, template.RestartRequirement.Weeks) + require.Empty(t, template.AutostopRequirement.DaysOfWeek) + require.Zero(t, template.AutostopRequirement.Weeks) req := codersdk.UpdateTemplateMeta{ Name: template.Name, DisplayName: template.DisplayName, @@ -1126,7 +1126,7 @@ func TestPatchTemplateMeta(t *testing.T) { Icon: template.Icon, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, DefaultTTLMillis: time.Hour.Milliseconds(), - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ DaysOfWeek: []string{"monday"}, Weeks: 2, }, @@ -1137,13 +1137,13 @@ func TestPatchTemplateMeta(t *testing.T) { updated, err := client.UpdateTemplateMeta(ctx, template.ID, req) require.NoError(t, err) - require.Empty(t, updated.RestartRequirement.DaysOfWeek) - require.Zero(t, updated.RestartRequirement.Weeks) + require.Empty(t, updated.AutostopRequirement.DaysOfWeek) + require.Zero(t, updated.AutostopRequirement.Weeks) template, err = client.Template(ctx, template.ID) require.NoError(t, err) - require.Empty(t, template.RestartRequirement.DaysOfWeek) - require.Zero(t, template.RestartRequirement.Weeks) + require.Empty(t, template.AutostopRequirement.DaysOfWeek) + require.Zero(t, template.AutostopRequirement.Weeks) }) }) } diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 0f493e5995b24..62c9f48f2593a 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -384,7 +384,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req } maxTTL := templateSchedule.MaxTTL - if templateSchedule.UseRestartRequirement { + if templateSchedule.UseAutostopRequirement { // If we're using restart requirements, there isn't a max TTL. maxTTL = 0 } @@ -721,7 +721,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) { } maxTTL := templateSchedule.MaxTTL - if templateSchedule.UseRestartRequirement { + if templateSchedule.UseAutostopRequirement { // If we're using restart requirements, there isn't a max TTL. maxTTL = 0 } diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index b42f4517db82d..d73b2cfc920ee 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -1837,7 +1837,7 @@ func TestWorkspaceUpdateAutostart(t *testing.T) { UserAutostartEnabled: false, UserAutostopEnabled: false, DefaultTTL: 0, - RestartRequirement: schedule.TemplateRestartRequirement{}, + AutostopRequirement: schedule.TemplateAutostopRequirement{}, }, nil }, SetFn: func(_ context.Context, _ database.Store, tpl database.Template, _ schedule.TemplateScheduleOptions) (database.Template, error) { @@ -2004,7 +2004,7 @@ func TestWorkspaceUpdateTTL(t *testing.T) { UserAutostartEnabled: false, UserAutostopEnabled: false, DefaultTTL: 0, - RestartRequirement: schedule.TemplateRestartRequirement{}, + AutostopRequirement: schedule.TemplateAutostopRequirement{}, }, nil }, SetFn: func(_ context.Context, _ database.Store, tpl database.Template, _ schedule.TemplateScheduleOptions) (database.Template, error) { diff --git a/codersdk/deployment.go b/codersdk/deployment.go index 708bc9e899784..5fcdea168503b 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -35,19 +35,19 @@ const ( type FeatureName string const ( - FeatureUserLimit FeatureName = "user_limit" - FeatureAuditLog FeatureName = "audit_log" - FeatureBrowserOnly FeatureName = "browser_only" - FeatureSCIM FeatureName = "scim" - FeatureTemplateRBAC FeatureName = "template_rbac" - FeatureUserRoleManagement FeatureName = "user_role_management" - FeatureHighAvailability FeatureName = "high_availability" - FeatureMultipleGitAuth FeatureName = "multiple_git_auth" - FeatureExternalProvisionerDaemons FeatureName = "external_provisioner_daemons" - FeatureAppearance FeatureName = "appearance" - FeatureAdvancedTemplateScheduling FeatureName = "advanced_template_scheduling" - FeatureTemplateRestartRequirement FeatureName = "template_restart_requirement" - FeatureWorkspaceProxy FeatureName = "workspace_proxy" + FeatureUserLimit FeatureName = "user_limit" + FeatureAuditLog FeatureName = "audit_log" + FeatureBrowserOnly FeatureName = "browser_only" + FeatureSCIM FeatureName = "scim" + FeatureTemplateRBAC FeatureName = "template_rbac" + FeatureUserRoleManagement FeatureName = "user_role_management" + FeatureHighAvailability FeatureName = "high_availability" + FeatureMultipleGitAuth FeatureName = "multiple_git_auth" + FeatureExternalProvisionerDaemons FeatureName = "external_provisioner_daemons" + FeatureAppearance FeatureName = "appearance" + FeatureAdvancedTemplateScheduling FeatureName = "advanced_template_scheduling" + FeatureTemplateAutostopRequirement FeatureName = "template_restart_requirement" + FeatureWorkspaceProxy FeatureName = "workspace_proxy" ) // FeatureNames must be kept in-sync with the Feature enum above. @@ -1914,17 +1914,19 @@ const ( // WARNING: This cannot be enabled when using HA. ExperimentSingleTailnet Experiment = "single_tailnet" - // ExperimentTemplateRestartRequirement allows template admins to have more + // ExperimentTemplateAutostopRequirement allows template admins to have more // control over when workspaces created on a template are required to - // restart, and allows users to ensure these restarts never happen during - // their business hours. + // stop, and allows users to ensure these restarts never happen during their + // business hours. + // + // This will replace the MaxTTL setting on templates. // // Enables: // - User quiet hours schedule settings // - Template restart requirement settings // - Changes the max_deadline algorithm to use restart requirement and user // quiet hours instead of max_ttl. - ExperimentTemplateRestartRequirement Experiment = "template_restart_requirement" + ExperimentTemplateAutostopRequirement Experiment = "template_autostop_requirement" // Deployment health page ExperimentDeploymentHealthPage Experiment = "deployment_health_page" diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 96b026a3197a5..e1458618ac53b 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -86,9 +86,9 @@ type CreateTemplateRequest struct { DefaultTTLMillis *int64 `json:"default_ttl_ms,omitempty"` // TODO(@dean): remove max_ttl once restart_requirement is matured MaxTTLMillis *int64 `json:"max_ttl_ms,omitempty"` - // RestartRequirement allows optionally specifying the restart requirement + // AutostopRequirement allows optionally specifying the restart requirement // for workspaces created from this template. This is an enterprise feature. - RestartRequirement *TemplateRestartRequirement `json:"restart_requirement,omitempty"` + AutostopRequirement *TemplateAutostopRequirement `json:"restart_requirement,omitempty"` // Allow users to cancel in-progress workspace jobs. // *bool as the default value is "true". diff --git a/codersdk/templates.go b/codersdk/templates.go index f566ac4f2ce32..ddc09d1a3ad8e 100644 --- a/codersdk/templates.go +++ b/codersdk/templates.go @@ -31,11 +31,11 @@ type Template struct { DefaultTTLMillis int64 `json:"default_ttl_ms"` // TODO(@dean): remove max_ttl once restart_requirement is matured MaxTTLMillis int64 `json:"max_ttl_ms"` - // RestartRequirement is an enterprise feature. Its value is only used if + // AutostopRequirement is an enterprise feature. Its value is only used if // your license is entitled to use the advanced template scheduling feature. - RestartRequirement TemplateRestartRequirement `json:"restart_requirement"` - CreatedByID uuid.UUID `json:"created_by_id" format:"uuid"` - CreatedByName string `json:"created_by_name"` + AutostopRequirement TemplateAutostopRequirement `json:"restart_requirement"` + CreatedByID uuid.UUID `json:"created_by_id" format:"uuid"` + CreatedByName string `json:"created_by_name"` // AllowUserAutostart and AllowUserAutostop are enterprise-only. Their // values are only used if your license is entitled to use the advanced @@ -107,7 +107,7 @@ func BitmapToWeekdays(bitmap uint8) []string { return days } -type TemplateRestartRequirement struct { +type TemplateAutostopRequirement struct { // DaysOfWeek is a list of days of the week on which restarts are required. // Restarts happen within the user's quiet hours (in their configured // timezone). If no days are specified, restarts are not required. Weekdays @@ -182,16 +182,16 @@ type UpdateTemplateMeta struct { DefaultTTLMillis int64 `json:"default_ttl_ms,omitempty"` // TODO(@dean): remove max_ttl once restart_requirement is matured MaxTTLMillis int64 `json:"max_ttl_ms,omitempty"` - // RestartRequirement can only be set if your license includes the advanced + // AutostopRequirement can only be set if your license includes the advanced // template scheduling feature. If you attempt to set this value while // unlicensed, it will be ignored. - RestartRequirement *TemplateRestartRequirement `json:"restart_requirement,omitempty"` - AllowUserAutostart bool `json:"allow_user_autostart,omitempty"` - AllowUserAutostop bool `json:"allow_user_autostop,omitempty"` - AllowUserCancelWorkspaceJobs bool `json:"allow_user_cancel_workspace_jobs,omitempty"` - FailureTTLMillis int64 `json:"failure_ttl_ms,omitempty"` - InactivityTTLMillis int64 `json:"inactivity_ttl_ms,omitempty"` - LockedTTLMillis int64 `json:"locked_ttl_ms,omitempty"` + AutostopRequirement *TemplateAutostopRequirement `json:"restart_requirement,omitempty"` + AllowUserAutostart bool `json:"allow_user_autostart,omitempty"` + AllowUserAutostop bool `json:"allow_user_autostop,omitempty"` + AllowUserCancelWorkspaceJobs bool `json:"allow_user_cancel_workspace_jobs,omitempty"` + FailureTTLMillis int64 `json:"failure_ttl_ms,omitempty"` + InactivityTTLMillis int64 `json:"inactivity_ttl_ms,omitempty"` + LockedTTLMillis int64 `json:"locked_ttl_ms,omitempty"` // UpdateWorkspaceLastUsedAt updates the last_used_at field of workspaces // spawned from the template. This is useful for preventing workspaces being // immediately locked when updating the inactivity_ttl field to a new, shorter diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index a2be3e466e2ab..7943c701dee33 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -265,7 +265,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) { }) r.Route("/users/{user}/quiet-hours", func(r chi.Router) { r.Use( - api.restartRequirementEnabledMW, + api.autostopRequirementEnabledMW, apiKeyMiddleware, httpmw.ExtractUserParam(options.Database, false), ) @@ -432,11 +432,11 @@ func (api *API) updateEntitlements(ctx context.Context) error { codersdk.FeatureTemplateRBAC: api.RBAC, codersdk.FeatureExternalProvisionerDaemons: true, codersdk.FeatureAdvancedTemplateScheduling: true, - // FeatureTemplateRestartRequirement depends on + // FeatureTemplateAutostopRequirement depends on // FeatureAdvancedTemplateScheduling. - codersdk.FeatureTemplateRestartRequirement: api.DefaultQuietHoursSchedule != "", - codersdk.FeatureWorkspaceProxy: true, - codersdk.FeatureUserRoleManagement: true, + codersdk.FeatureTemplateAutostopRequirement: api.DefaultQuietHoursSchedule != "", + codersdk.FeatureWorkspaceProxy: true, + codersdk.FeatureUserRoleManagement: true, }) if err != nil { return err @@ -455,15 +455,15 @@ func (api *API) updateEntitlements(ctx context.Context) error { return nil } - if entitlements.Features[codersdk.FeatureTemplateRestartRequirement].Enabled && !entitlements.Features[codersdk.FeatureAdvancedTemplateScheduling].Enabled { + if entitlements.Features[codersdk.FeatureTemplateAutostopRequirement].Enabled && !entitlements.Features[codersdk.FeatureAdvancedTemplateScheduling].Enabled { api.entitlements.Errors = []string{ - `Your license is entitled to the feature "template restart ` + + `Your license is entitled to the feature "template autostop ` + `requirement" (and you have it enabled by setting the ` + "default quiet hours schedule), but you are not entitled to " + `the dependency feature "advanced template scheduling". ` + "Please contact support for a new license.", } - api.Logger.Error(ctx, "license is entitled to template restart requirement but not advanced template scheduling") + api.Logger.Error(ctx, "license is entitled to template autostop requirement but not advanced template scheduling") return nil } @@ -524,30 +524,30 @@ func (api *API) updateEntitlements(ctx context.Context) error { } } - if initial, changed, enabled := featureChanged(codersdk.FeatureTemplateRestartRequirement); shouldUpdate(initial, changed, enabled) { + if initial, changed, enabled := featureChanged(codersdk.FeatureTemplateAutostopRequirement); shouldUpdate(initial, changed, enabled) { if enabled { templateStore := *(api.AGPL.TemplateScheduleStore.Load()) enterpriseTemplateStore, ok := templateStore.(*schedule.EnterpriseTemplateScheduleStore) if !ok { - api.Logger.Error(ctx, "unable to set up enterprise template schedule store, template restart requirements will not be applied to workspace builds") + api.Logger.Error(ctx, "unable to set up enterprise template schedule store, template autostop requirements will not be applied to workspace builds") } - enterpriseTemplateStore.UseRestartRequirement.Store(true) + enterpriseTemplateStore.UseAutostopRequirement.Store(true) quietHoursStore, err := schedule.NewEnterpriseUserQuietHoursScheduleStore(api.DefaultQuietHoursSchedule) if err != nil { - api.Logger.Error(ctx, "unable to set up enterprise user quiet hours schedule store, template restart requirements will not be applied to workspace builds", slog.Error(err)) + api.Logger.Error(ctx, "unable to set up enterprise user quiet hours schedule store, template autostop requirements will not be applied to workspace builds", slog.Error(err)) } else { api.AGPL.UserQuietHoursScheduleStore.Store(&quietHoursStore) } } else { if api.DefaultQuietHoursSchedule != "" { - api.Logger.Warn(ctx, "template restart requirements are not enabled (due to setting default quiet hours schedule) as your license is not entitled to this feature") + api.Logger.Warn(ctx, "template autostop requirements are not enabled (due to setting default quiet hours schedule) as your license is not entitled to this feature") } templateStore := *(api.AGPL.TemplateScheduleStore.Load()) enterpriseTemplateStore, ok := templateStore.(*schedule.EnterpriseTemplateScheduleStore) if ok { - enterpriseTemplateStore.UseRestartRequirement.Store(false) + enterpriseTemplateStore.UseAutostopRequirement.Store(false) } quietHoursStore := agplschedule.NewAGPLUserQuietHoursScheduleStore() diff --git a/enterprise/coderd/schedule/template.go b/enterprise/coderd/schedule/template.go index c5613c44e7880..80be7577adb78 100644 --- a/enterprise/coderd/schedule/template.go +++ b/enterprise/coderd/schedule/template.go @@ -21,11 +21,11 @@ import ( // EnterpriseTemplateScheduleStore provides an agpl.TemplateScheduleStore that // has all fields implemented for enterprise customers. type EnterpriseTemplateScheduleStore struct { - // UseRestartRequirement decides whether the RestartRequirement field should - // be used instead of the MaxTTL field for determining the max deadline of a - // workspace build. This value is determined by a feature flag, licensing, - // and whether a default user quiet hours schedule is set. - UseRestartRequirement atomic.Bool + // UseAutostopRequirement decides whether the AutostopRequirement field + // should be used instead of the MaxTTL field for determining the max + // deadline of a workspace build. This value is determined by a feature + // flag, licensing, and whether a default user quiet hours schedule is set. + UseAutostopRequirement atomic.Bool // UserQuietHoursScheduleStore is used when recalculating build deadlines on // update. @@ -62,26 +62,26 @@ func (s *EnterpriseTemplateScheduleStore) Get(ctx context.Context, db database.S // These extra checks have to be done before the conversion because we lose // precision and signs when converting to the agpl types from the database. - if tpl.RestartRequirementDaysOfWeek < 0 { + if tpl.AutostopRequirementDaysOfWeek < 0 { return agpl.TemplateScheduleOptions{}, xerrors.New("invalid restart requirement days, negative") } - if tpl.RestartRequirementDaysOfWeek > 0b11111111 { + if tpl.AutostopRequirementDaysOfWeek > 0b11111111 { return agpl.TemplateScheduleOptions{}, xerrors.New("invalid restart requirement days, too large") } - err = agpl.VerifyTemplateRestartRequirement(uint8(tpl.RestartRequirementDaysOfWeek), tpl.RestartRequirementWeeks) + err = agpl.VerifyTemplateAutostopRequirement(uint8(tpl.AutostopRequirementDaysOfWeek), tpl.AutostopRequirementWeeks) if err != nil { return agpl.TemplateScheduleOptions{}, err } return agpl.TemplateScheduleOptions{ - UserAutostartEnabled: tpl.AllowUserAutostart, - UserAutostopEnabled: tpl.AllowUserAutostop, - DefaultTTL: time.Duration(tpl.DefaultTTL), - MaxTTL: time.Duration(tpl.MaxTTL), - UseRestartRequirement: s.UseRestartRequirement.Load(), - RestartRequirement: agpl.TemplateRestartRequirement{ - DaysOfWeek: uint8(tpl.RestartRequirementDaysOfWeek), - Weeks: tpl.RestartRequirementWeeks, + UserAutostartEnabled: tpl.AllowUserAutostart, + UserAutostopEnabled: tpl.AllowUserAutostop, + DefaultTTL: time.Duration(tpl.DefaultTTL), + MaxTTL: time.Duration(tpl.MaxTTL), + UseAutostopRequirement: s.UseAutostopRequirement.Load(), + AutostopRequirement: agpl.TemplateAutostopRequirement{ + DaysOfWeek: uint8(tpl.AutostopRequirementDaysOfWeek), + Weeks: tpl.AutostopRequirementWeeks, }, FailureTTL: time.Duration(tpl.FailureTTL), InactivityTTL: time.Duration(tpl.InactivityTTL), @@ -96,8 +96,8 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S if int64(opts.DefaultTTL) == tpl.DefaultTTL && int64(opts.MaxTTL) == tpl.MaxTTL && - int16(opts.RestartRequirement.DaysOfWeek) == tpl.RestartRequirementDaysOfWeek && - opts.RestartRequirement.Weeks == tpl.RestartRequirementWeeks && + int16(opts.AutostopRequirement.DaysOfWeek) == tpl.AutostopRequirementDaysOfWeek && + opts.AutostopRequirement.Weeks == tpl.AutostopRequirementWeeks && int64(opts.FailureTTL) == tpl.FailureTTL && int64(opts.InactivityTTL) == tpl.InactivityTTL && int64(opts.LockedTTL) == tpl.LockedTTL && @@ -107,7 +107,7 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S return tpl, nil } - err := agpl.VerifyTemplateRestartRequirement(opts.RestartRequirement.DaysOfWeek, opts.RestartRequirement.Weeks) + err := agpl.VerifyTemplateAutostopRequirement(opts.AutostopRequirement.DaysOfWeek, opts.AutostopRequirement.Weeks) if err != nil { return database.Template{}, err } @@ -118,17 +118,17 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S defer span.End() err := tx.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{ - ID: tpl.ID, - UpdatedAt: s.now(), - AllowUserAutostart: opts.UserAutostartEnabled, - AllowUserAutostop: opts.UserAutostopEnabled, - DefaultTTL: int64(opts.DefaultTTL), - MaxTTL: int64(opts.MaxTTL), - RestartRequirementDaysOfWeek: int16(opts.RestartRequirement.DaysOfWeek), - RestartRequirementWeeks: opts.RestartRequirement.Weeks, - FailureTTL: int64(opts.FailureTTL), - InactivityTTL: int64(opts.InactivityTTL), - LockedTTL: int64(opts.LockedTTL), + ID: tpl.ID, + UpdatedAt: s.now(), + AllowUserAutostart: opts.UserAutostartEnabled, + AllowUserAutostop: opts.UserAutostopEnabled, + DefaultTTL: int64(opts.DefaultTTL), + MaxTTL: int64(opts.MaxTTL), + AutostopRequirementDaysOfWeek: int16(opts.AutostopRequirement.DaysOfWeek), + AutostopRequirementWeeks: opts.AutostopRequirement.Weeks, + FailureTTL: int64(opts.FailureTTL), + InactivityTTL: int64(opts.InactivityTTL), + LockedTTL: int64(opts.LockedTTL), }) if err != nil { return xerrors.Errorf("update template schedule: %w", err) @@ -170,7 +170,7 @@ func (s *EnterpriseTemplateScheduleStore) Set(ctx context.Context, db database.S // Recalculate max_deadline and deadline for all running workspace // builds on this template. - if s.UseRestartRequirement.Load() { + if s.UseAutostopRequirement.Load() { err = s.updateWorkspaceBuilds(ctx, tx, template) if err != nil { return xerrors.Errorf("update workspace builds: %w", err) @@ -238,7 +238,7 @@ func (s *EnterpriseTemplateScheduleStore) updateWorkspaceBuild(ctx context.Conte // If the job completed before the autostop epoch, then it must be skipped // to avoid failures below. Add a week to account for timezones. - if job.CompletedAt.Time.Before(agpl.TemplateRestartRequirementEpoch(time.UTC).Add(time.Hour * 7 * 24)) { + if job.CompletedAt.Time.Before(agpl.TemplateAutostopRequirementEpoch(time.UTC).Add(time.Hour * 7 * 24)) { return nil } diff --git a/enterprise/coderd/schedule/template_test.go b/enterprise/coderd/schedule/template_test.go index aff7e2364fcec..e05dfa17a53ac 100644 --- a/enterprise/coderd/schedule/template_test.go +++ b/enterprise/coderd/schedule/template_test.go @@ -210,17 +210,17 @@ func TestTemplateUpdateBuildDeadlines(t *testing.T) { // Set the template policy. templateScheduleStore := schedule.NewEnterpriseTemplateScheduleStore(userQuietHoursStorePtr) - templateScheduleStore.UseRestartRequirement.Store(true) + templateScheduleStore.UseAutostopRequirement.Store(true) templateScheduleStore.TimeNowFn = func() time.Time { return c.now } _, err = templateScheduleStore.Set(ctx, db, template, agplschedule.TemplateScheduleOptions{ - UserAutostartEnabled: false, - UserAutostopEnabled: false, - DefaultTTL: 0, - MaxTTL: 0, - UseRestartRequirement: true, - RestartRequirement: agplschedule.TemplateRestartRequirement{ + UserAutostartEnabled: false, + UserAutostopEnabled: false, + DefaultTTL: 0, + MaxTTL: 0, + UseAutostopRequirement: true, + AutostopRequirement: agplschedule.TemplateAutostopRequirement{ // Every day DaysOfWeek: 0b01111111, Weeks: 0, @@ -485,17 +485,17 @@ func TestTemplateUpdateBuildDeadlinesSkip(t *testing.T) { // Set the template policy. templateScheduleStore := schedule.NewEnterpriseTemplateScheduleStore(userQuietHoursStorePtr) - templateScheduleStore.UseRestartRequirement.Store(true) + templateScheduleStore.UseAutostopRequirement.Store(true) templateScheduleStore.TimeNowFn = func() time.Time { return now } _, err = templateScheduleStore.Set(ctx, db, template, agplschedule.TemplateScheduleOptions{ - UserAutostartEnabled: false, - UserAutostopEnabled: false, - DefaultTTL: 0, - MaxTTL: 0, - UseRestartRequirement: true, - RestartRequirement: agplschedule.TemplateRestartRequirement{ + UserAutostartEnabled: false, + UserAutostopEnabled: false, + DefaultTTL: 0, + MaxTTL: 0, + UseAutostopRequirement: true, + AutostopRequirement: agplschedule.TemplateAutostopRequirement{ // Every day DaysOfWeek: 0b01111111, Weeks: 0, diff --git a/enterprise/coderd/templates_test.go b/enterprise/coderd/templates_test.go index af364d3578b1c..8a2b8afab8016 100644 --- a/enterprise/coderd/templates_test.go +++ b/enterprise/coderd/templates_test.go @@ -140,7 +140,7 @@ func TestTemplates(t *testing.T) { require.EqualValues(t, exp, *ws.TTLMillis) }) - t.Run("SetRestartRequirement", func(t *testing.T) { + t.Run("SetAutostopRequirement", func(t *testing.T) { t.Parallel() client, user := coderdenttest.New(t, &coderdenttest.Options{ @@ -157,8 +157,8 @@ func TestTemplates(t *testing.T) { version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) coderdtest.AwaitTemplateVersionJob(t, client, version.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) - require.Empty(t, 0, template.RestartRequirement.DaysOfWeek) - require.Zero(t, template.RestartRequirement.Weeks) + require.Empty(t, 0, template.AutostopRequirement.DaysOfWeek) + require.Zero(t, template.AutostopRequirement.Weeks) // ctx := testutil.Context(t, testutil.WaitLong) ctx := context.Background() @@ -169,19 +169,19 @@ func TestTemplates(t *testing.T) { Icon: template.Icon, AllowUserCancelWorkspaceJobs: template.AllowUserCancelWorkspaceJobs, DefaultTTLMillis: time.Hour.Milliseconds(), - RestartRequirement: &codersdk.TemplateRestartRequirement{ + AutostopRequirement: &codersdk.TemplateAutostopRequirement{ DaysOfWeek: []string{"monday", "saturday"}, Weeks: 3, }, }) require.NoError(t, err) - require.Equal(t, []string{"monday", "saturday"}, updated.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 3, updated.RestartRequirement.Weeks) + require.Equal(t, []string{"monday", "saturday"}, updated.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 3, updated.AutostopRequirement.Weeks) template, err = client.Template(ctx, template.ID) require.NoError(t, err) - require.Equal(t, []string{"monday", "saturday"}, template.RestartRequirement.DaysOfWeek) - require.EqualValues(t, 3, template.RestartRequirement.Weeks) + require.Equal(t, []string{"monday", "saturday"}, template.AutostopRequirement.DaysOfWeek) + require.EqualValues(t, 3, template.AutostopRequirement.Weeks) }) t.Run("CleanupTTLs", func(t *testing.T) { diff --git a/enterprise/coderd/users.go b/enterprise/coderd/users.go index 4b576c3856464..bafbb7b73faf9 100644 --- a/enterprise/coderd/users.go +++ b/enterprise/coderd/users.go @@ -11,18 +11,18 @@ import ( "github.com/coder/coder/v2/codersdk" ) -func (api *API) restartRequirementEnabledMW(next http.Handler) http.Handler { +func (api *API) autostopRequirementEnabledMW(next http.Handler) http.Handler { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { // The experiment must be enabled. - if !api.AGPL.Experiments.Enabled(codersdk.ExperimentTemplateRestartRequirement) { + if !api.AGPL.Experiments.Enabled(codersdk.ExperimentTemplateAutostopRequirement) { httpapi.RouteNotFound(rw) return } // Entitlement must be enabled. api.entitlementsMu.RLock() - entitled := api.entitlements.Features[codersdk.FeatureTemplateRestartRequirement].Entitlement != codersdk.EntitlementNotEntitled - enabled := api.entitlements.Features[codersdk.FeatureTemplateRestartRequirement].Enabled + entitled := api.entitlements.Features[codersdk.FeatureTemplateAutostopRequirement].Entitlement != codersdk.EntitlementNotEntitled + enabled := api.entitlements.Features[codersdk.FeatureTemplateAutostopRequirement].Enabled api.entitlementsMu.RUnlock() if !entitled { httpapi.Write(r.Context(), rw, http.StatusForbidden, codersdk.Response{ diff --git a/enterprise/coderd/users_test.go b/enterprise/coderd/users_test.go index bd8080a6b052a..6ad93b2d92e06 100644 --- a/enterprise/coderd/users_test.go +++ b/enterprise/coderd/users_test.go @@ -35,7 +35,7 @@ func TestUserQuietHours(t *testing.T) { dv := coderdtest.DeploymentValues(t) dv.UserQuietHoursSchedule.DefaultSchedule.Set(defaultQuietHoursSchedule) - dv.Experiments.Set(string(codersdk.ExperimentTemplateRestartRequirement)) + dv.Experiments.Set(string(codersdk.ExperimentTemplateAutostopRequirement)) client, user := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -43,8 +43,8 @@ func TestUserQuietHours(t *testing.T) { }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ - codersdk.FeatureAdvancedTemplateScheduling: 1, - codersdk.FeatureTemplateRestartRequirement: 1, + codersdk.FeatureAdvancedTemplateScheduling: 1, + codersdk.FeatureTemplateAutostopRequirement: 1, }, }, }) @@ -133,7 +133,7 @@ func TestUserQuietHours(t *testing.T) { dv := coderdtest.DeploymentValues(t) dv.UserQuietHoursSchedule.DefaultSchedule.Set("CRON_TZ=America/Chicago 0 0 * * *") - dv.Experiments.Set(string(codersdk.ExperimentTemplateRestartRequirement)) + dv.Experiments.Set(string(codersdk.ExperimentTemplateAutostopRequirement)) client, user := coderdenttest.New(t, &coderdenttest.Options{ Options: &coderdtest.Options{ @@ -143,7 +143,7 @@ func TestUserQuietHours(t *testing.T) { Features: license.Features{ codersdk.FeatureAdvancedTemplateScheduling: 1, // Not entitled. - // codersdk.FeatureTemplateRestartRequirement: 1, + // codersdk.FeatureTemplateAutostopRequirement: 1, }, }, }) @@ -161,7 +161,7 @@ func TestUserQuietHours(t *testing.T) { dv := coderdtest.DeploymentValues(t) dv.UserQuietHoursSchedule.DefaultSchedule.Set("") - dv.Experiments.Set(string(codersdk.ExperimentTemplateRestartRequirement)) + dv.Experiments.Set(string(codersdk.ExperimentTemplateAutostopRequirement)) client, user := coderdenttest.New(t, &coderdenttest.Options{ NoDefaultQuietHoursSchedule: true, @@ -170,8 +170,8 @@ func TestUserQuietHours(t *testing.T) { }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ - codersdk.FeatureAdvancedTemplateScheduling: 1, - codersdk.FeatureTemplateRestartRequirement: 1, + codersdk.FeatureAdvancedTemplateScheduling: 1, + codersdk.FeatureTemplateAutostopRequirement: 1, }, }, }) @@ -197,8 +197,8 @@ func TestUserQuietHours(t *testing.T) { }, LicenseOptions: &coderdenttest.LicenseOptions{ Features: license.Features{ - codersdk.FeatureAdvancedTemplateScheduling: 1, - codersdk.FeatureTemplateRestartRequirement: 1, + codersdk.FeatureAdvancedTemplateScheduling: 1, + codersdk.FeatureTemplateAutostopRequirement: 1, }, }, }) From d0643065b9e99a6919036798ec390bb600528d82 Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Tue, 29 Aug 2023 18:04:24 +0000 Subject: [PATCH 2/2] fixup! Merge branch 'main' into dean/rename-restart-requirement --- provisionerd/proto/provisionerd.pb.go | 4 ++-- provisionerd/proto/provisionerd_drpc.pb.go | 2 +- provisionersdk/proto/provisioner.pb.go | 4 ++-- provisionersdk/proto/provisioner_drpc.pb.go | 6 +++++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index a2843bf929c42..018e0f25ac8e1 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v3.21.12 +// protoc-gen-go v1.30.0 +// protoc v4.23.3 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionerd/proto/provisionerd_drpc.pb.go b/provisionerd/proto/provisionerd_drpc.pb.go index 058af595809b8..ed3155fb21eaa 100644 --- a/provisionerd/proto/provisionerd_drpc.pb.go +++ b/provisionerd/proto/provisionerd_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.33 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index f7f13b19f5b2e..c0ea0be327953 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v3.21.12 +// protoc-gen-go v1.30.0 +// protoc v4.23.3 // source: provisionersdk/proto/provisioner.proto package proto diff --git a/provisionersdk/proto/provisioner_drpc.pb.go b/provisionersdk/proto/provisioner_drpc.pb.go index 06b331bce5f6f..de310e779dcaa 100644 --- a/provisionersdk/proto/provisioner_drpc.pb.go +++ b/provisionersdk/proto/provisioner_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.33 // source: provisionersdk/proto/provisioner.proto package proto @@ -70,6 +70,10 @@ type drpcProvisioner_SessionClient struct { drpc.Stream } +func (x *drpcProvisioner_SessionClient) GetStream() drpc.Stream { + return x.Stream +} + func (x *drpcProvisioner_SessionClient) Send(m *Request) error { return x.MsgSend(m, drpcEncoding_File_provisionersdk_proto_provisioner_proto{}) }