mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: rename template restart requirement to autostop requirement (#9295)
This commit is contained in:
@@ -26,7 +26,7 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// deadline allows you to forcibly set a max_deadline on the build. This
|
||||
// doesn't use template restart requirements and instead edits the
|
||||
// doesn't use template autostop requirements and instead edits the
|
||||
// max_deadline on the build directly in the database.
|
||||
setupActivityTest := func(t *testing.T, deadline ...time.Duration) (client *codersdk.Client, workspace codersdk.Workspace, assertBumped func(want bool)) {
|
||||
const ttl = time.Minute
|
||||
@@ -49,7 +49,7 @@ func TestWorkspaceActivityBump(t *testing.T) {
|
||||
UserAutostopEnabled: true,
|
||||
DefaultTTL: ttl,
|
||||
// We set max_deadline manually below.
|
||||
RestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
AutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
|
||||
Generated
+45
-45
@@ -7390,6 +7390,14 @@ const docTemplate = `{
|
||||
"description": "Allow users to cancel in-progress workspace jobs.\n*bool as the default value is \"true\".",
|
||||
"type": "boolean"
|
||||
},
|
||||
"autostop_requirement": {
|
||||
"description": "AutostopRequirement allows optionally specifying the autostop requirement\nfor workspaces created from this template. This is an enterprise feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateAutostopRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_ttl_ms": {
|
||||
"description": "DefaultTTLMillis allows optionally specifying the default TTL\nfor all workspaces created from this template.",
|
||||
"type": "integer"
|
||||
@@ -7423,21 +7431,13 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
},
|
||||
"max_ttl_ms": {
|
||||
"description": "TODO(@dean): remove max_ttl once restart_requirement is matured",
|
||||
"description": "TODO(@dean): remove max_ttl once autostop_requirement is matured",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is the name of the template.",
|
||||
"type": "string"
|
||||
},
|
||||
"restart_requirement": {
|
||||
"description": "RestartRequirement allows optionally specifying the restart requirement\nfor workspaces created from this template. This is an enterprise feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateRestartRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"template_version_id": {
|
||||
"description": "VersionID is an in-progress or completed job to use as an initial version\nof the template.\n\nThis is required on creation to enable a user-flow of validating a\ntemplate works. There is no reason the data-model cannot support empty\ntemplates, but it doesn't make sense for users.",
|
||||
"type": "string",
|
||||
@@ -8124,7 +8124,7 @@ const docTemplate = `{
|
||||
"workspace_actions",
|
||||
"tailnet_pg_coordinator",
|
||||
"single_tailnet",
|
||||
"template_restart_requirement",
|
||||
"template_autostop_requirement",
|
||||
"deployment_health_page",
|
||||
"workspaces_batch_actions"
|
||||
],
|
||||
@@ -8133,7 +8133,7 @@ const docTemplate = `{
|
||||
"ExperimentWorkspaceActions",
|
||||
"ExperimentTailnetPGCoordinator",
|
||||
"ExperimentSingleTailnet",
|
||||
"ExperimentTemplateRestartRequirement",
|
||||
"ExperimentTemplateAutostopRequirement",
|
||||
"ExperimentDeploymentHealthPage",
|
||||
"ExperimentWorkspacesBatchActions"
|
||||
]
|
||||
@@ -9516,6 +9516,14 @@ const docTemplate = `{
|
||||
"allow_user_cancel_workspace_jobs": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"autostop_requirement": {
|
||||
"description": "AutostopRequirement is an enterprise feature. Its value is only used if\nyour license is entitled to use the advanced template scheduling feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateAutostopRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"build_time_stats": {
|
||||
"$ref": "#/definitions/codersdk.TemplateBuildTimeStats"
|
||||
},
|
||||
@@ -9551,7 +9559,7 @@ const docTemplate = `{
|
||||
"format": "uuid"
|
||||
},
|
||||
"max_ttl_ms": {
|
||||
"description": "TODO(@dean): remove max_ttl once restart_requirement is matured",
|
||||
"description": "TODO(@dean): remove max_ttl once autostop_requirement is matured",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
@@ -9567,14 +9575,6 @@ const docTemplate = `{
|
||||
"terraform"
|
||||
]
|
||||
},
|
||||
"restart_requirement": {
|
||||
"description": "RestartRequirement is an enterprise feature. Its value is only used if\nyour license is entitled to use the advanced template scheduling feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateRestartRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time_til_dormant_autodelete_ms": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -9633,6 +9633,31 @@ const docTemplate = `{
|
||||
"TemplateAppsTypeApp"
|
||||
]
|
||||
},
|
||||
"codersdk.TemplateAutostopRequirement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_week": {
|
||||
"description": "DaysOfWeek is a list of days of the week on which restarts are required.\nRestarts happen within the user's quiet hours (in their configured\ntimezone). If no days are specified, restarts are not required. Weekdays\ncannot be specified twice.\n\nRestarts will only happen on weekdays in this list on weeks which line up\nwith Weeks.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
"sunday"
|
||||
]
|
||||
}
|
||||
},
|
||||
"weeks": {
|
||||
"description": "Weeks is the number of weeks between required restarts. Weeks are synced\nacross all workspaces (and Coder deployments) using modulo math on a\nhardcoded epoch week of January 2nd, 2023 (the first Monday of 2023).\nValues of 0 or 1 indicate weekly restarts. Values of 2 indicate\nfortnightly restarts, etc.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateBuildTimeStats": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
@@ -9793,31 +9818,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateRestartRequirement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_week": {
|
||||
"description": "DaysOfWeek is a list of days of the week on which restarts are required.\nRestarts happen within the user's quiet hours (in their configured\ntimezone). If no days are specified, restarts are not required. Weekdays\ncannot be specified twice.\n\nRestarts will only happen on weekdays in this list on weeks which line up\nwith Weeks.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
"sunday"
|
||||
]
|
||||
}
|
||||
},
|
||||
"weeks": {
|
||||
"description": "Weeks is the number of weeks between required restarts. Weeks are synced\nacross all workspaces (and Coder deployments) using modulo math on a\nhardcoded epoch week of January 2nd, 2023 (the first Monday of 2023).\nValues of 0 or 1 indicate weekly restarts. Values of 2 indicate\nfortnightly restarts, etc.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateRole": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
||||
Generated
+45
-45
@@ -6583,6 +6583,14 @@
|
||||
"description": "Allow users to cancel in-progress workspace jobs.\n*bool as the default value is \"true\".",
|
||||
"type": "boolean"
|
||||
},
|
||||
"autostop_requirement": {
|
||||
"description": "AutostopRequirement allows optionally specifying the autostop requirement\nfor workspaces created from this template. This is an enterprise feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateAutostopRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"default_ttl_ms": {
|
||||
"description": "DefaultTTLMillis allows optionally specifying the default TTL\nfor all workspaces created from this template.",
|
||||
"type": "integer"
|
||||
@@ -6616,21 +6624,13 @@
|
||||
"type": "string"
|
||||
},
|
||||
"max_ttl_ms": {
|
||||
"description": "TODO(@dean): remove max_ttl once restart_requirement is matured",
|
||||
"description": "TODO(@dean): remove max_ttl once autostop_requirement is matured",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is the name of the template.",
|
||||
"type": "string"
|
||||
},
|
||||
"restart_requirement": {
|
||||
"description": "RestartRequirement allows optionally specifying the restart requirement\nfor workspaces created from this template. This is an enterprise feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateRestartRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"template_version_id": {
|
||||
"description": "VersionID is an in-progress or completed job to use as an initial version\nof the template.\n\nThis is required on creation to enable a user-flow of validating a\ntemplate works. There is no reason the data-model cannot support empty\ntemplates, but it doesn't make sense for users.",
|
||||
"type": "string",
|
||||
@@ -7275,7 +7275,7 @@
|
||||
"workspace_actions",
|
||||
"tailnet_pg_coordinator",
|
||||
"single_tailnet",
|
||||
"template_restart_requirement",
|
||||
"template_autostop_requirement",
|
||||
"deployment_health_page",
|
||||
"workspaces_batch_actions"
|
||||
],
|
||||
@@ -7284,7 +7284,7 @@
|
||||
"ExperimentWorkspaceActions",
|
||||
"ExperimentTailnetPGCoordinator",
|
||||
"ExperimentSingleTailnet",
|
||||
"ExperimentTemplateRestartRequirement",
|
||||
"ExperimentTemplateAutostopRequirement",
|
||||
"ExperimentDeploymentHealthPage",
|
||||
"ExperimentWorkspacesBatchActions"
|
||||
]
|
||||
@@ -8585,6 +8585,14 @@
|
||||
"allow_user_cancel_workspace_jobs": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"autostop_requirement": {
|
||||
"description": "AutostopRequirement is an enterprise feature. Its value is only used if\nyour license is entitled to use the advanced template scheduling feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateAutostopRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"build_time_stats": {
|
||||
"$ref": "#/definitions/codersdk.TemplateBuildTimeStats"
|
||||
},
|
||||
@@ -8620,7 +8628,7 @@
|
||||
"format": "uuid"
|
||||
},
|
||||
"max_ttl_ms": {
|
||||
"description": "TODO(@dean): remove max_ttl once restart_requirement is matured",
|
||||
"description": "TODO(@dean): remove max_ttl once autostop_requirement is matured",
|
||||
"type": "integer"
|
||||
},
|
||||
"name": {
|
||||
@@ -8634,14 +8642,6 @@
|
||||
"type": "string",
|
||||
"enum": ["terraform"]
|
||||
},
|
||||
"restart_requirement": {
|
||||
"description": "RestartRequirement is an enterprise feature. Its value is only used if\nyour license is entitled to use the advanced template scheduling feature.",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/codersdk.TemplateRestartRequirement"
|
||||
}
|
||||
]
|
||||
},
|
||||
"time_til_dormant_autodelete_ms": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -8694,6 +8694,31 @@
|
||||
"enum": ["builtin", "app"],
|
||||
"x-enum-varnames": ["TemplateAppsTypeBuiltin", "TemplateAppsTypeApp"]
|
||||
},
|
||||
"codersdk.TemplateAutostopRequirement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_week": {
|
||||
"description": "DaysOfWeek is a list of days of the week on which restarts are required.\nRestarts happen within the user's quiet hours (in their configured\ntimezone). If no days are specified, restarts are not required. Weekdays\ncannot be specified twice.\n\nRestarts will only happen on weekdays in this list on weeks which line up\nwith Weeks.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
"sunday"
|
||||
]
|
||||
}
|
||||
},
|
||||
"weeks": {
|
||||
"description": "Weeks is the number of weeks between required restarts. Weeks are synced\nacross all workspaces (and Coder deployments) using modulo math on a\nhardcoded epoch week of January 2nd, 2023 (the first Monday of 2023).\nValues of 0 or 1 indicate weekly restarts. Values of 2 indicate\nfortnightly restarts, etc.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateBuildTimeStats": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
@@ -8854,31 +8879,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateRestartRequirement": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"days_of_week": {
|
||||
"description": "DaysOfWeek is a list of days of the week on which restarts are required.\nRestarts happen within the user's quiet hours (in their configured\ntimezone). If no days are specified, restarts are not required. Weekdays\ncannot be specified twice.\n\nRestarts will only happen on weekdays in this list on weeks which line up\nwith Weeks.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
"sunday"
|
||||
]
|
||||
}
|
||||
},
|
||||
"weeks": {
|
||||
"description": "Weeks is the number of weeks between required restarts. Weeks are synced\nacross all workspaces (and Coder deployments) using modulo math on a\nhardcoded epoch week of January 2nd, 2023 (the first Monday of 2023).\nValues of 0 or 1 indicate weekly restarts. Values of 2 indicate\nfortnightly restarts, etc.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.TemplateRole": {
|
||||
"type": "string",
|
||||
"enum": ["admin", "use", ""],
|
||||
|
||||
@@ -623,7 +623,7 @@ func TestExecutorAutostartTemplateDisabled(t *testing.T) {
|
||||
UserAutostartEnabled: false,
|
||||
UserAutostopEnabled: true,
|
||||
DefaultTTL: 0,
|
||||
RestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
AutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
}, nil
|
||||
},
|
||||
},
|
||||
|
||||
@@ -5127,8 +5127,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.TimeTilDormant = arg.TimeTilDormant
|
||||
tpl.TimeTilDormantAutoDelete = arg.TimeTilDormantAutoDelete
|
||||
|
||||
Generated
+6
-6
@@ -637,8 +637,8 @@ CREATE TABLE templates (
|
||||
failure_ttl bigint DEFAULT 0 NOT NULL,
|
||||
time_til_dormant bigint DEFAULT 0 NOT NULL,
|
||||
time_til_dormant_autodelete 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.';
|
||||
@@ -651,9 +651,9 @@ COMMENT ON COLUMN templates.allow_user_autostart IS 'Allow users to specify an a
|
||||
|
||||
COMMENT ON COLUMN templates.allow_user_autostop IS 'Allow users to specify custom autostop values for workspaces (enterprise).';
|
||||
|
||||
COMMENT ON COLUMN templates.restart_requirement_days_of_week IS '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.';
|
||||
COMMENT ON COLUMN templates.autostop_requirement_days_of_week IS '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.';
|
||||
|
||||
COMMENT ON COLUMN templates.restart_requirement_weeks IS '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.';
|
||||
COMMENT ON COLUMN templates.autostop_requirement_weeks IS '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.';
|
||||
|
||||
CREATE VIEW template_with_users AS
|
||||
SELECT templates.id,
|
||||
@@ -678,8 +678,8 @@ CREATE VIEW template_with_users AS
|
||||
templates.failure_ttl,
|
||||
templates.time_til_dormant,
|
||||
templates.time_til_dormant_autodelete,
|
||||
templates.restart_requirement_days_of_week,
|
||||
templates.restart_requirement_weeks,
|
||||
templates.autostop_requirement_days_of_week,
|
||||
templates.autostop_requirement_weeks,
|
||||
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
|
||||
COALESCE(visible_users.username, ''::text) AS created_by_username
|
||||
FROM (public.templates
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE templates RENAME COLUMN autostop_requirement_days_of_week TO restart_requirement_days_of_week;
|
||||
|
||||
ALTER TABLE templates RENAME COLUMN autostop_requirement_weeks TO restart_requirement_weeks;
|
||||
|
||||
COMMIT;
|
||||
@@ -0,0 +1,25 @@
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE templates RENAME COLUMN restart_requirement_days_of_week TO autostop_requirement_days_of_week;
|
||||
|
||||
ALTER TABLE templates RENAME COLUMN restart_requirement_weeks TO autostop_requirement_weeks;
|
||||
|
||||
DROP VIEW template_with_users;
|
||||
|
||||
CREATE VIEW
|
||||
template_with_users
|
||||
AS
|
||||
SELECT
|
||||
templates.*,
|
||||
coalesce(visible_users.avatar_url, '') AS created_by_avatar_url,
|
||||
coalesce(visible_users.username, '') AS created_by_username
|
||||
FROM
|
||||
templates
|
||||
LEFT JOIN
|
||||
visible_users
|
||||
ON
|
||||
templates.created_by = visible_users.id;
|
||||
|
||||
COMMENT ON VIEW template_with_users IS 'Joins in the username + avatar url of the created by user.';
|
||||
|
||||
COMMIT;
|
||||
@@ -83,8 +83,8 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
|
||||
&i.FailureTTL,
|
||||
&i.TimeTilDormant,
|
||||
&i.TimeTilDormantAutoDelete,
|
||||
&i.RestartRequirementDaysOfWeek,
|
||||
&i.RestartRequirementWeeks,
|
||||
&i.AutostopRequirementDaysOfWeek,
|
||||
&i.AutostopRequirementWeeks,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
); err != nil {
|
||||
|
||||
+28
-28
@@ -1709,32 +1709,32 @@ type TailnetCoordinator struct {
|
||||
|
||||
// Joins in the username + avatar url of the created by user.
|
||||
type Template struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
Description string `db:"description" json:"description"`
|
||||
DefaultTTL int64 `db:"default_ttl" json:"default_ttl"`
|
||||
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
|
||||
Icon string `db:"icon" json:"icon"`
|
||||
UserACL TemplateACL `db:"user_acl" json:"user_acl"`
|
||||
GroupACL TemplateACL `db:"group_acl" json:"group_acl"`
|
||||
DisplayName string `db:"display_name" json:"display_name"`
|
||||
AllowUserCancelWorkspaceJobs bool `db:"allow_user_cancel_workspace_jobs" json:"allow_user_cancel_workspace_jobs"`
|
||||
MaxTTL int64 `db:"max_ttl" json:"max_ttl"`
|
||||
AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"`
|
||||
AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"`
|
||||
FailureTTL int64 `db:"failure_ttl" json:"failure_ttl"`
|
||||
TimeTilDormant int64 `db:"time_til_dormant" json:"time_til_dormant"`
|
||||
TimeTilDormantAutoDelete int64 `db:"time_til_dormant_autodelete" json:"time_til_dormant_autodelete"`
|
||||
RestartRequirementDaysOfWeek int16 `db:"restart_requirement_days_of_week" json:"restart_requirement_days_of_week"`
|
||||
RestartRequirementWeeks 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"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
|
||||
Deleted bool `db:"deleted" json:"deleted"`
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
Description string `db:"description" json:"description"`
|
||||
DefaultTTL int64 `db:"default_ttl" json:"default_ttl"`
|
||||
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
|
||||
Icon string `db:"icon" json:"icon"`
|
||||
UserACL TemplateACL `db:"user_acl" json:"user_acl"`
|
||||
GroupACL TemplateACL `db:"group_acl" json:"group_acl"`
|
||||
DisplayName string `db:"display_name" json:"display_name"`
|
||||
AllowUserCancelWorkspaceJobs bool `db:"allow_user_cancel_workspace_jobs" json:"allow_user_cancel_workspace_jobs"`
|
||||
MaxTTL int64 `db:"max_ttl" json:"max_ttl"`
|
||||
AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"`
|
||||
AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"`
|
||||
FailureTTL int64 `db:"failure_ttl" json:"failure_ttl"`
|
||||
TimeTilDormant int64 `db:"time_til_dormant" json:"time_til_dormant"`
|
||||
TimeTilDormantAutoDelete int64 `db:"time_til_dormant_autodelete" json:"time_til_dormant_autodelete"`
|
||||
AutostopRequirementDaysOfWeek int16 `db:"autostop_requirement_days_of_week" json:"autostop_requirement_days_of_week"`
|
||||
AutostopRequirementWeeks int64 `db:"autostop_requirement_weeks" json:"autostop_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"`
|
||||
}
|
||||
|
||||
type TemplateTable struct {
|
||||
@@ -1766,9 +1766,9 @@ type TemplateTable struct {
|
||||
TimeTilDormant int64 `db:"time_til_dormant" json:"time_til_dormant"`
|
||||
TimeTilDormantAutoDelete int64 `db:"time_til_dormant_autodelete" json:"time_til_dormant_autodelete"`
|
||||
// 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:"autostop_requirement_days_of_week" json:"autostop_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:"autostop_requirement_weeks" json:"autostop_requirement_weeks"`
|
||||
}
|
||||
|
||||
// Joins in the username + avatar url of the created by user.
|
||||
|
||||
@@ -4317,7 +4317,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, time_til_dormant, time_til_dormant_autodelete, 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, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username
|
||||
FROM
|
||||
template_with_users
|
||||
WHERE
|
||||
@@ -4352,8 +4352,8 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat
|
||||
&i.FailureTTL,
|
||||
&i.TimeTilDormant,
|
||||
&i.TimeTilDormantAutoDelete,
|
||||
&i.RestartRequirementDaysOfWeek,
|
||||
&i.RestartRequirementWeeks,
|
||||
&i.AutostopRequirementDaysOfWeek,
|
||||
&i.AutostopRequirementWeeks,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
)
|
||||
@@ -4362,7 +4362,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, time_til_dormant, time_til_dormant_autodelete, 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, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username
|
||||
FROM
|
||||
template_with_users AS templates
|
||||
WHERE
|
||||
@@ -4405,8 +4405,8 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
&i.FailureTTL,
|
||||
&i.TimeTilDormant,
|
||||
&i.TimeTilDormantAutoDelete,
|
||||
&i.RestartRequirementDaysOfWeek,
|
||||
&i.RestartRequirementWeeks,
|
||||
&i.AutostopRequirementDaysOfWeek,
|
||||
&i.AutostopRequirementWeeks,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
)
|
||||
@@ -4414,7 +4414,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, time_til_dormant, time_til_dormant_autodelete, 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, time_til_dormant, time_til_dormant_autodelete, 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
|
||||
`
|
||||
|
||||
@@ -4450,8 +4450,8 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) {
|
||||
&i.FailureTTL,
|
||||
&i.TimeTilDormant,
|
||||
&i.TimeTilDormantAutoDelete,
|
||||
&i.RestartRequirementDaysOfWeek,
|
||||
&i.RestartRequirementWeeks,
|
||||
&i.AutostopRequirementDaysOfWeek,
|
||||
&i.AutostopRequirementWeeks,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
); err != nil {
|
||||
@@ -4470,7 +4470,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, time_til_dormant, time_til_dormant_autodelete, 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, time_til_dormant, time_til_dormant_autodelete, autostop_requirement_days_of_week, autostop_requirement_weeks, created_by_avatar_url, created_by_username
|
||||
FROM
|
||||
template_with_users AS templates
|
||||
WHERE
|
||||
@@ -4543,8 +4543,8 @@ func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplate
|
||||
&i.FailureTTL,
|
||||
&i.TimeTilDormant,
|
||||
&i.TimeTilDormantAutoDelete,
|
||||
&i.RestartRequirementDaysOfWeek,
|
||||
&i.RestartRequirementWeeks,
|
||||
&i.AutostopRequirementDaysOfWeek,
|
||||
&i.AutostopRequirementWeeks,
|
||||
&i.CreatedByAvatarURL,
|
||||
&i.CreatedByUsername,
|
||||
); err != nil {
|
||||
@@ -4729,8 +4729,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,
|
||||
time_til_dormant = $10,
|
||||
time_til_dormant_autodelete = $11
|
||||
@@ -4739,17 +4739,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"`
|
||||
TimeTilDormant int64 `db:"time_til_dormant" json:"time_til_dormant"`
|
||||
TimeTilDormantAutoDelete int64 `db:"time_til_dormant_autodelete" json:"time_til_dormant_autodelete"`
|
||||
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"`
|
||||
TimeTilDormant int64 `db:"time_til_dormant" json:"time_til_dormant"`
|
||||
TimeTilDormantAutoDelete int64 `db:"time_til_dormant_autodelete" json:"time_til_dormant_autodelete"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateTemplateScheduleByID(ctx context.Context, arg UpdateTemplateScheduleByIDParams) error {
|
||||
@@ -4760,8 +4760,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.TimeTilDormant,
|
||||
arg.TimeTilDormantAutoDelete,
|
||||
|
||||
@@ -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,
|
||||
time_til_dormant = $10,
|
||||
time_til_dormant_autodelete = $11
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
@@ -1155,7 +1155,7 @@ func TestCompleteJob(t *testing.T) {
|
||||
|
||||
// Wednesday the 8th of February 2023 at midnight. This date was
|
||||
// specifically chosen as it doesn't fall on a applicable week for both
|
||||
// fortnightly and triweekly restart requirements.
|
||||
// fortnightly and triweekly autostop requirements.
|
||||
wednesdayMidnightUTC := time.Date(2023, 2, 8, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
sydneyQuietHours := "CRON_TZ=Australia/Sydney 0 0 * * *"
|
||||
@@ -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)
|
||||
|
||||
+32
-32
@@ -13,17 +13,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// restartRequirementLeeway is the duration of time before a restart
|
||||
// autostopRequirementLeeway is the duration of time before a autostop
|
||||
// requirement where we skip the requirement and fall back to the next
|
||||
// scheduled restart. This avoids workspaces being restarted too soon.
|
||||
// scheduled stop. This avoids workspaces being stopped too soon.
|
||||
//
|
||||
// E.g. If the workspace is started within an hour of the quiet hours, we
|
||||
// will skip the restart requirement and use the next scheduled restart
|
||||
// requirement.
|
||||
restartRequirementLeeway = 1 * time.Hour
|
||||
// will skip the autostop requirement and use the next scheduled
|
||||
// stop time instead.
|
||||
autostopRequirementLeeway = 1 * time.Hour
|
||||
|
||||
// restartRequirementBuffer is the duration of time we subtract from the
|
||||
// time when calculating the next scheduled restart time. This avoids issues
|
||||
// autostopRequirementBuffer is the duration of time we subtract from the
|
||||
// time when calculating the next scheduled stop time. This avoids issues
|
||||
// where autostart happens on the hour and the scheduled quiet hours are
|
||||
// also on the hour.
|
||||
//
|
||||
@@ -37,7 +37,7 @@ const (
|
||||
//
|
||||
// This resolves that problem by subtracting 15 minutes from midnight
|
||||
// when we check the next cron time.
|
||||
restartRequirementBuffer = -15 * time.Minute
|
||||
autostopRequirementBuffer = -15 * time.Minute
|
||||
)
|
||||
|
||||
type CalculateAutostopParams struct {
|
||||
@@ -68,7 +68,7 @@ type AutostopTime struct {
|
||||
//
|
||||
// MaxDeadline is the maximum value for deadline. The deadline cannot be bumped
|
||||
// past this value, so it denotes the absolute deadline that the workspace build
|
||||
// must be stopped by. MaxDeadline is calculated using the template's "restart
|
||||
// must be stopped by. MaxDeadline is calculated using the template's "autostop
|
||||
// requirement" settings and the user's "quiet hours" settings to pick a time
|
||||
// outside of working hours.
|
||||
//
|
||||
@@ -113,13 +113,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// Use the old algorithm for calculating max_deadline if the instance isn't
|
||||
// configured or entitled to use the new feature flag yet.
|
||||
// TODO(@dean): remove this once the feature flag is enabled for all
|
||||
if !templateSchedule.UseRestartRequirement && templateSchedule.MaxTTL > 0 {
|
||||
if !templateSchedule.UseAutostopRequirement && templateSchedule.MaxTTL > 0 {
|
||||
autostop.MaxDeadline = now.Add(templateSchedule.MaxTTL)
|
||||
}
|
||||
|
||||
// TODO(@dean): remove extra conditional
|
||||
if templateSchedule.UseRestartRequirement && templateSchedule.RestartRequirement.DaysOfWeek != 0 {
|
||||
// The template has a restart requirement, so determine the max deadline
|
||||
if templateSchedule.UseAutostopRequirement && templateSchedule.AutostopRequirement.DaysOfWeek != 0 {
|
||||
// The template has a autostop requirement, so determine the max deadline
|
||||
// of this workspace build.
|
||||
|
||||
// First, get the user's quiet hours schedule (this will return the
|
||||
@@ -137,13 +137,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
now := now.In(loc)
|
||||
// Add the leeway here so we avoid checking today's quiet hours if
|
||||
// the workspace was started <1h before midnight.
|
||||
startOfStopDay := truncateMidnight(now.Add(restartRequirementLeeway))
|
||||
startOfStopDay := truncateMidnight(now.Add(autostopRequirementLeeway))
|
||||
|
||||
// If the template schedule wants to only restart on n-th weeks then
|
||||
// change the startOfDay to be the Monday of the next applicable
|
||||
// week.
|
||||
if templateSchedule.RestartRequirement.Weeks > 1 {
|
||||
startOfStopDay, err = GetNextApplicableMondayOfNWeeks(startOfStopDay, templateSchedule.RestartRequirement.Weeks)
|
||||
// If the template schedule wants to only autostop on n-th weeks
|
||||
// then change the startOfDay to be the Monday of the next
|
||||
// applicable week.
|
||||
if templateSchedule.AutostopRequirement.Weeks > 1 {
|
||||
startOfStopDay, err = GetNextApplicableMondayOfNWeeks(startOfStopDay, templateSchedule.AutostopRequirement.Weeks)
|
||||
if err != nil {
|
||||
return autostop, xerrors.Errorf("determine start of stop week: %w", err)
|
||||
}
|
||||
@@ -155,30 +155,30 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// Allow an hour of leeway (i.e. any workspaces started within an
|
||||
// hour of the scheduled stop time will always bounce to the next
|
||||
// stop window).
|
||||
checkSchedule := userQuietHoursSchedule.Schedule.Next(startOfStopDay.Add(restartRequirementBuffer))
|
||||
if checkSchedule.Before(now.Add(restartRequirementLeeway)) {
|
||||
checkSchedule := userQuietHoursSchedule.Schedule.Next(startOfStopDay.Add(autostopRequirementBuffer))
|
||||
if checkSchedule.Before(now.Add(autostopRequirementLeeway)) {
|
||||
// Set the first stop day we try to tomorrow because today's
|
||||
// schedule is too close to now or has already passed.
|
||||
startOfStopDay = nextDayMidnight(startOfStopDay)
|
||||
}
|
||||
|
||||
// Iterate from 0 to 7, check if the current startOfDay is in the
|
||||
// restart requirement. If it isn't then add a day and try again.
|
||||
requirementDays := templateSchedule.RestartRequirement.DaysMap()
|
||||
// autostop requirement. If it isn't then add a day and try again.
|
||||
requirementDays := templateSchedule.AutostopRequirement.DaysMap()
|
||||
for i := 0; i < len(DaysOfWeek)+1; i++ {
|
||||
if i == len(DaysOfWeek) {
|
||||
// We've wrapped, so somehow we couldn't find a day in the
|
||||
// restart requirement in the next week.
|
||||
// autostop requirement in the next week.
|
||||
//
|
||||
// This shouldn't be able to happen, as we've already
|
||||
// checked that there is a day in the restart requirement
|
||||
// checked that there is a day in the autostop requirement
|
||||
// above with the
|
||||
// `if templateSchedule.RestartRequirement.DaysOfWeek != 0`
|
||||
// `if templateSchedule.AutoStopRequirement.DaysOfWeek != 0`
|
||||
// check.
|
||||
//
|
||||
// The eighth bit shouldn't be set, as we validate the
|
||||
// bitmap in the enterprise TemplateScheduleStore.
|
||||
return autostop, xerrors.New("could not find suitable day for template restart requirement in the next 7 days")
|
||||
return autostop, xerrors.New("could not find suitable day for template autostop requirement in the next 7 days")
|
||||
}
|
||||
if requirementDays[startOfStopDay.Weekday()] {
|
||||
break
|
||||
@@ -194,13 +194,13 @@ func CalculateAutostop(ctx context.Context, params CalculateAutostopParams) (Aut
|
||||
// If it's not within an hour of now, subtract 15 minutes to
|
||||
// give a little leeway. This prevents skipped stop events
|
||||
// because autostart perfectly lines up with autostop.
|
||||
checkTime = checkTime.Add(restartRequirementBuffer)
|
||||
checkTime = checkTime.Add(autostopRequirementBuffer)
|
||||
}
|
||||
|
||||
// Get the next occurrence of the restart schedule.
|
||||
// Get the next occurrence of the schedule.
|
||||
autostop.MaxDeadline = userQuietHoursSchedule.Schedule.Next(checkTime)
|
||||
if autostop.MaxDeadline.IsZero() {
|
||||
return autostop, xerrors.New("could not find next occurrence of template restart requirement in user quiet hours schedule")
|
||||
return autostop, xerrors.Errorf("could not find next occurrence of template autostop requirement in user quiet hours schedule, checked from time %q", checkTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,9 +244,9 @@ func nextDayMidnight(t time.Time) time.Time {
|
||||
//
|
||||
// The timezone embedded in the time object is used to determine the epoch.
|
||||
func WeeksSinceEpoch(now time.Time) (int64, error) {
|
||||
epoch := TemplateRestartRequirementEpoch(now.Location())
|
||||
epoch := TemplateAutostopRequirementEpoch(now.Location())
|
||||
if now.Before(epoch) {
|
||||
return 0, xerrors.New("coder server system clock is incorrect, cannot calculate template restart requirement")
|
||||
return 0, xerrors.New("coder server system clock is incorrect, cannot calculate template autostop requirement")
|
||||
}
|
||||
|
||||
// This calculation needs to be done using YearDay, as dividing by the
|
||||
@@ -290,7 +290,7 @@ func GetMondayOfWeek(loc *time.Location, n int64) (time.Time, error) {
|
||||
if n < 0 {
|
||||
return time.Time{}, xerrors.New("weeks since epoch must be positive")
|
||||
}
|
||||
epoch := TemplateRestartRequirementEpoch(loc)
|
||||
epoch := TemplateAutostopRequirementEpoch(loc)
|
||||
monday := epoch.AddDate(0, 0, int(n*7))
|
||||
|
||||
y, m, d := monday.Date()
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
|
||||
// Wednesday the 8th of February 2023 at midnight. This date was
|
||||
// specifically chosen as it doesn't fall on a applicable week for both
|
||||
// fortnightly and triweekly restart requirements.
|
||||
// fortnightly and triweekly autostop requirements.
|
||||
wednesdayMidnightUTC := time.Date(2023, 2, 8, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
sydneyQuietHours := "CRON_TZ=Australia/Sydney 0 0 * * *"
|
||||
@@ -73,10 +73,10 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop bool
|
||||
templateDefaultTTL time.Duration
|
||||
// TODO(@dean): remove max_ttl tests
|
||||
useMaxTTL bool
|
||||
templateMaxTTL time.Duration
|
||||
templateRestartRequirement schedule.TemplateRestartRequirement
|
||||
userQuietHoursSchedule string
|
||||
useMaxTTL bool
|
||||
templateMaxTTL time.Duration
|
||||
templateAutostopRequirement schedule.TemplateAutostopRequirement
|
||||
userQuietHoursSchedule string
|
||||
// workspaceTTL is usually copied from the template's TTL when the
|
||||
// workspace is made, so it takes precedence unless
|
||||
// templateAllowAutostop is false.
|
||||
@@ -88,72 +88,72 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
errContains string
|
||||
}{
|
||||
{
|
||||
name: "OK",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "OK",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "Delete",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "Delete",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "WorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateDefaultTTLIgnored",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "TemplateDefaultTTLIgnored",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 0,
|
||||
expectedDeadline: time.Time{},
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 2 * time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "WorkspaceTTLOverridesTemplateDefaultTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 2 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: time.Hour,
|
||||
expectedDeadline: now.Add(time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateBlockWorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{},
|
||||
workspaceTTL: 4 * time.Hour,
|
||||
expectedDeadline: now.Add(3 * time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
name: "TemplateBlockWorkspaceTTL",
|
||||
now: now,
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{},
|
||||
workspaceTTL: 4 * time.Hour,
|
||||
expectedDeadline: now.Add(3 * time.Hour),
|
||||
expectedMaxDeadline: time.Time{},
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirement",
|
||||
name: "TemplateAutostopRequirement",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -162,12 +162,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirement1HourSkip",
|
||||
name: "TemplateAutostopRequirement1HourSkip",
|
||||
now: saturdayMidnightSydney.Add(-59 * time.Minute),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // 1 also means weekly
|
||||
},
|
||||
@@ -176,14 +176,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.Add(7 * 24 * time.Hour).In(time.UTC),
|
||||
},
|
||||
{
|
||||
// The next restart requirement should be skipped if the
|
||||
// The next autostop requirement should be skipped if the
|
||||
// workspace is started within 1 hour of it.
|
||||
name: "TemplateRestartRequirementDaily",
|
||||
name: "TemplateAutostopRequirementDaily",
|
||||
now: fridayEveningSydney,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01111111, // daily
|
||||
Weeks: 0, // all weeks
|
||||
},
|
||||
@@ -192,12 +192,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementFortnightly/Skip",
|
||||
name: "TemplateAutostopRequirementFortnightly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every 2 weeks
|
||||
},
|
||||
@@ -206,12 +206,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementFortnightly/NoSkip",
|
||||
name: "TemplateAutostopRequirementFortnightly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every 2 weeks
|
||||
},
|
||||
@@ -220,28 +220,28 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementTriweekly/Skip",
|
||||
name: "TemplateAutostopRequirementTriweekly/Skip",
|
||||
now: wednesdayMidnightUTC,
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 3, // every 3 weeks
|
||||
},
|
||||
workspaceTTL: 0,
|
||||
// expectedDeadline is copied from expectedMaxDeadline.
|
||||
// The next triweekly restart requirement happens next week
|
||||
// The next triweekly autostop requirement happens next week
|
||||
// according to the epoch.
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementTriweekly/NoSkip",
|
||||
name: "TemplateAutostopRequirementTriweekly/NoSkip",
|
||||
now: wednesdayMidnightUTC.AddDate(0, 0, 7),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 3, // every 3 weeks
|
||||
},
|
||||
@@ -250,14 +250,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.AddDate(0, 0, 7).In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementOverridesWorkspaceTTL",
|
||||
name: "TemplateAutostopRequirementOverridesWorkspaceTTL",
|
||||
// now doesn't have to be UTC, but it helps us ensure that
|
||||
// timezones are compared correctly in this test.
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -266,12 +266,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "TemplateRestartRequirementOverridesTemplateDefaultTTL",
|
||||
name: "TemplateAutostopRequirementOverridesTemplateDefaultTTL",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 3 * time.Hour,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -288,7 +288,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 2, // every fortnight
|
||||
},
|
||||
@@ -301,7 +301,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -315,7 +315,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -329,7 +329,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -343,7 +343,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstInQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01000000, // Sunday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -357,7 +357,7 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateAllowAutostop: true,
|
||||
templateDefaultTTL: 0,
|
||||
userQuietHoursSchedule: dstOutQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b01000000, // Sunday
|
||||
Weeks: 1, // weekly
|
||||
},
|
||||
@@ -368,14 +368,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
|
||||
// TODO(@dean): remove max_ttl tests
|
||||
{
|
||||
name: "RestartRequirementIgnoresMaxTTL",
|
||||
name: "AutostopRequirementIgnoresMaxTTL",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 0,
|
||||
useMaxTTL: false,
|
||||
templateMaxTTL: time.Hour, // should be ignored
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -384,14 +384,14 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
expectedMaxDeadline: saturdayMidnightSydney.In(time.UTC),
|
||||
},
|
||||
{
|
||||
name: "MaxTTLIgnoresRestartRequirement",
|
||||
name: "MaxTTLIgnoresAutostopRequirement",
|
||||
now: fridayEveningSydney.In(time.UTC),
|
||||
templateAllowAutostop: false,
|
||||
templateDefaultTTL: 0,
|
||||
useMaxTTL: true,
|
||||
templateMaxTTL: time.Hour, // should NOT be ignored
|
||||
userQuietHoursSchedule: sydneyQuietHours,
|
||||
templateRestartRequirement: schedule.TemplateRestartRequirement{
|
||||
templateAutostopRequirement: schedule.TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0b00100000, // Saturday
|
||||
Weeks: 0, // weekly
|
||||
},
|
||||
@@ -413,12 +413,12 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
templateScheduleStore := schedule.MockTemplateScheduleStore{
|
||||
GetFn: func(_ context.Context, _ database.Store, _ uuid.UUID) (schedule.TemplateScheduleOptions, error) {
|
||||
return schedule.TemplateScheduleOptions{
|
||||
UserAutostartEnabled: false,
|
||||
UserAutostopEnabled: c.templateAllowAutostop,
|
||||
DefaultTTL: c.templateDefaultTTL,
|
||||
MaxTTL: c.templateMaxTTL,
|
||||
UseRestartRequirement: !c.useMaxTTL,
|
||||
RestartRequirement: c.templateRestartRequirement,
|
||||
UserAutostartEnabled: false,
|
||||
UserAutostopEnabled: c.templateAllowAutostop,
|
||||
DefaultTTL: c.templateDefaultTTL,
|
||||
MaxTTL: c.templateMaxTTL,
|
||||
UseAutostopRequirement: !c.useMaxTTL,
|
||||
AutostopRequirement: c.templateAutostopRequirement,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
@@ -454,11 +454,11 @@ func TestCalculateAutoStop(t *testing.T) {
|
||||
CreatedBy: user.ID,
|
||||
})
|
||||
err := db.UpdateTemplateScheduleByID(ctx, database.UpdateTemplateScheduleByIDParams{
|
||||
ID: template.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
AllowUserAutostart: c.templateAllowAutostop,
|
||||
RestartRequirementDaysOfWeek: int16(c.templateRestartRequirement.DaysOfWeek),
|
||||
RestartRequirementWeeks: c.templateRestartRequirement.Weeks,
|
||||
ID: template.ID,
|
||||
UpdatedAt: database.Now(),
|
||||
AllowUserAutostart: c.templateAllowAutostop,
|
||||
AutostopRequirementDaysOfWeek: int16(c.templateAutostopRequirement.DaysOfWeek),
|
||||
AutostopRequirementWeeks: c.templateAutostopRequirement.Weeks,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
template, err = db.GetTemplateByID(ctx, template.ID)
|
||||
|
||||
+30
-30
@@ -11,9 +11,9 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/tracing"
|
||||
)
|
||||
|
||||
const MaxTemplateRestartRequirementWeeks = 16
|
||||
const MaxTemplateAutostopRequirementWeeks = 16
|
||||
|
||||
func TemplateRestartRequirementEpoch(loc *time.Location) time.Time {
|
||||
func TemplateAutostopRequirementEpoch(loc *time.Location) time.Time {
|
||||
// The "first week" starts on January 2nd, 2023, which is the first Monday
|
||||
// of 2023. All other weeks are counted using modulo arithmetic from that
|
||||
// date.
|
||||
@@ -34,7 +34,7 @@ var DaysOfWeek = []time.Weekday{
|
||||
time.Sunday,
|
||||
}
|
||||
|
||||
type TemplateRestartRequirement struct {
|
||||
type TemplateAutostopRequirement struct {
|
||||
// DaysOfWeek is a bitmap of which days of the week the workspace must be
|
||||
// restarted. If fully zero, the workspace is not required to be restarted
|
||||
// ever.
|
||||
@@ -55,7 +55,7 @@ type TemplateRestartRequirement struct {
|
||||
|
||||
// DaysMap returns a map of the days of the week that the workspace must be
|
||||
// restarted.
|
||||
func (r TemplateRestartRequirement) DaysMap() map[time.Weekday]bool {
|
||||
func (r TemplateAutostopRequirement) DaysMap() map[time.Weekday]bool {
|
||||
days := make(map[time.Weekday]bool)
|
||||
for i, day := range DaysOfWeek {
|
||||
days[day] = r.DaysOfWeek&(1<<uint(i)) != 0
|
||||
@@ -63,20 +63,20 @@ func (r TemplateRestartRequirement) DaysMap() map[time.Weekday]bool {
|
||||
return days
|
||||
}
|
||||
|
||||
// VerifyTemplateRestartRequirement returns an error if the restart requirement
|
||||
// is invalid.
|
||||
func VerifyTemplateRestartRequirement(days uint8, weeks int64) error {
|
||||
// VerifyTemplateAutostopRequirement returns an error if the autostop
|
||||
// requirement is invalid.
|
||||
func VerifyTemplateAutostopRequirement(days uint8, weeks int64) error {
|
||||
if days&0b10000000 != 0 {
|
||||
return xerrors.New("invalid restart requirement days, last bit is set")
|
||||
return xerrors.New("invalid autostop requirement days, last bit is set")
|
||||
}
|
||||
if days > 0b11111111 {
|
||||
return xerrors.New("invalid restart requirement days, too large")
|
||||
return xerrors.New("invalid autostop requirement days, too large")
|
||||
}
|
||||
if weeks < 0 {
|
||||
return xerrors.New("invalid restart requirement weeks, negative")
|
||||
return xerrors.New("invalid autostop requirement weeks, negative")
|
||||
}
|
||||
if weeks > MaxTemplateRestartRequirementWeeks {
|
||||
return xerrors.New("invalid restart requirement weeks, too large")
|
||||
if weeks > MaxTemplateAutostopRequirementWeeks {
|
||||
return xerrors.New("invalid autostop requirement weeks, too large")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -85,17 +85,17 @@ type TemplateScheduleOptions struct {
|
||||
UserAutostartEnabled bool `json:"user_autostart_enabled"`
|
||||
UserAutostopEnabled bool `json:"user_autostop_enabled"`
|
||||
DefaultTTL time.Duration `json:"default_ttl"`
|
||||
// TODO(@dean): remove MaxTTL once restart_requirement is matured and the
|
||||
// TODO(@dean): remove MaxTTL once autostop_requirement is matured and the
|
||||
// default
|
||||
MaxTTL time.Duration `json:"max_ttl"`
|
||||
// UseRestartRequirement dictates whether the restart requirement should be
|
||||
// used instead of MaxTTL. This is governed by the feature flag and
|
||||
// UseAutostopRequirement dictates whether the autostop requirement should
|
||||
// be used instead of MaxTTL. This is governed by the feature flag and
|
||||
// licensing.
|
||||
// TODO(@dean): remove this when we remove max_tll
|
||||
UseRestartRequirement bool
|
||||
// RestartRequirement dictates when the workspace must be restarted. This
|
||||
UseAutostopRequirement bool
|
||||
// AutostopRequirement dictates when the workspace must be restarted. This
|
||||
// used to be handled by MaxTTL.
|
||||
RestartRequirement TemplateRestartRequirement `json:"restart_requirement"`
|
||||
AutostopRequirement TemplateAutostopRequirement `json:"autostop_requirement"`
|
||||
// FailureTTL dictates the duration after which failed workspaces will be
|
||||
// stopped automatically.
|
||||
FailureTTL time.Duration `json:"failure_ttl"`
|
||||
@@ -149,11 +149,11 @@ func (*agplTemplateScheduleStore) Get(ctx context.Context, db database.Store, te
|
||||
UserAutostartEnabled: true,
|
||||
UserAutostopEnabled: true,
|
||||
DefaultTTL: time.Duration(tpl.DefaultTTL),
|
||||
// Disregard the values in the database, since RestartRequirement,
|
||||
// Disregard the values in the database, since AutostopRequirement,
|
||||
// FailureTTL, TimeTilDormant, and TimeTilDormantAutoDelete are enterprise features.
|
||||
UseRestartRequirement: false,
|
||||
MaxTTL: 0,
|
||||
RestartRequirement: TemplateRestartRequirement{
|
||||
UseAutostopRequirement: false,
|
||||
MaxTTL: 0,
|
||||
AutostopRequirement: TemplateAutostopRequirement{
|
||||
DaysOfWeek: 0,
|
||||
Weeks: 0,
|
||||
},
|
||||
@@ -180,14 +180,14 @@ func (*agplTemplateScheduleStore) Set(ctx context.Context, db database.Store, tp
|
||||
DefaultTTL: int64(opts.DefaultTTL),
|
||||
// Don't allow changing these settings, but keep the value in the DB (to
|
||||
// avoid clearing settings if the license has an issue).
|
||||
MaxTTL: tpl.MaxTTL,
|
||||
RestartRequirementDaysOfWeek: tpl.RestartRequirementDaysOfWeek,
|
||||
RestartRequirementWeeks: tpl.RestartRequirementWeeks,
|
||||
AllowUserAutostart: tpl.AllowUserAutostart,
|
||||
AllowUserAutostop: tpl.AllowUserAutostop,
|
||||
FailureTTL: tpl.FailureTTL,
|
||||
TimeTilDormant: tpl.TimeTilDormant,
|
||||
TimeTilDormantAutoDelete: tpl.TimeTilDormantAutoDelete,
|
||||
MaxTTL: tpl.MaxTTL,
|
||||
AutostopRequirementDaysOfWeek: tpl.AutostopRequirementDaysOfWeek,
|
||||
AutostopRequirementWeeks: tpl.AutostopRequirementWeeks,
|
||||
AllowUserAutostart: tpl.AllowUserAutostart,
|
||||
AllowUserAutostop: tpl.AllowUserAutostop,
|
||||
FailureTTL: tpl.FailureTTL,
|
||||
TimeTilDormant: tpl.TimeTilDormant,
|
||||
TimeTilDormantAutoDelete: tpl.TimeTilDormantAutoDelete,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("update template schedule: %w", err)
|
||||
|
||||
+45
-45
@@ -214,20 +214,20 @@ 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
|
||||
dormantTTL time.Duration
|
||||
dormantAutoDeletionTTL time.Duration
|
||||
// TODO(@dean): remove max_ttl once autostop_requirement is ready
|
||||
maxTTL time.Duration
|
||||
autostopRequirementDaysOfWeek []string
|
||||
autostopRequirementWeeks int64
|
||||
failureTTL time.Duration
|
||||
dormantTTL time.Duration
|
||||
dormantAutoDeletionTTL 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,20 +252,20 @@ 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()})
|
||||
validErrs = append(validErrs, codersdk.ValidationError{Field: "autostop_requirement.days_of_week", Detail: err.Error()})
|
||||
}
|
||||
}
|
||||
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: "autostop_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,
|
||||
TimeTilDormant: dormantTTL,
|
||||
@@ -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()})
|
||||
validErrs = append(validErrs, codersdk.ValidationError{Field: "autostop_requirement.days_of_week", Detail: err.Error()})
|
||||
}
|
||||
}
|
||||
if req.RestartRequirement.Weeks < 0 {
|
||||
validErrs = append(validErrs, codersdk.ValidationError{Field: "restart_requirement.weeks", Detail: "Must be a positive integer."})
|
||||
if req.AutostopRequirement.Weeks < 0 {
|
||||
validErrs = append(validErrs, codersdk.ValidationError{Field: "autostop_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: "autostop_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.TimeTilDormantMillis == time.Duration(template.TimeTilDormant).Milliseconds() &&
|
||||
req.TimeTilDormantAutoDeleteMillis == time.Duration(template.TimeTilDormantAutoDelete).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.TimeTilDormant) ||
|
||||
timeTilDormantAutoDelete != time.Duration(template.TimeTilDormantAutoDelete) ||
|
||||
@@ -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,
|
||||
TimeTilDormant: inactivityTTL,
|
||||
@@ -760,9 +760,9 @@ func (api *API) convertTemplate(
|
||||
FailureTTLMillis: time.Duration(template.FailureTTL).Milliseconds(),
|
||||
TimeTilDormantMillis: time.Duration(template.TimeTilDormant).Milliseconds(),
|
||||
TimeTilDormantAutoDeleteMillis: time.Duration(template.TimeTilDormantAutoDelete).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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+111
-111
@@ -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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
})
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
})
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
})
|
||||
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(),
|
||||
TimeTilDormantMillis: 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(),
|
||||
TimeTilDormantMillis: 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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
})
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
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),
|
||||
TimeTilDormant: int64(options.TimeTilDormant),
|
||||
TimeTilDormantAutoDelete: int64(options.TimeTilDormantAutoDelete),
|
||||
})
|
||||
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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -384,8 +384,8 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
|
||||
}
|
||||
|
||||
maxTTL := templateSchedule.MaxTTL
|
||||
if templateSchedule.UseRestartRequirement {
|
||||
// If we're using restart requirements, there isn't a max TTL.
|
||||
if templateSchedule.UseAutostopRequirement {
|
||||
// If we're using autostop requirements, there isn't a max TTL.
|
||||
maxTTL = 0
|
||||
}
|
||||
|
||||
@@ -721,8 +721,8 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
maxTTL := templateSchedule.MaxTTL
|
||||
if templateSchedule.UseRestartRequirement {
|
||||
// If we're using restart requirements, there isn't a max TTL.
|
||||
if templateSchedule.UseAutostopRequirement {
|
||||
// If we're using autostop requirements, there isn't a max TTL.
|
||||
maxTTL = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -1839,7 +1839,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) {
|
||||
@@ -2006,7 +2006,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) {
|
||||
|
||||
Reference in New Issue
Block a user