mirror of
https://github.com/coder/coder.git
synced 2025-07-13 21:36:50 +00:00
feat: allow disabling autostart and custom autostop for template (#6933)
API only, frontend in upcoming PR.
This commit is contained in:
@ -306,6 +306,10 @@ func (q *querier) GetDeploymentWorkspaceStats(ctx context.Context) (database.Get
|
||||
return q.db.GetDeploymentWorkspaceStats(ctx)
|
||||
}
|
||||
|
||||
func (q *querier) GetWorkspacesEligibleForAutoStartStop(ctx context.Context, now time.Time) ([]database.Workspace, error) {
|
||||
return q.db.GetWorkspacesEligibleForAutoStartStop(ctx, now)
|
||||
}
|
||||
|
||||
func (q *querier) GetParameterSchemasCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ParameterSchema, error) {
|
||||
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return nil, err
|
||||
|
@ -1902,6 +1902,8 @@ func (q *fakeQuerier) UpdateTemplateScheduleByID(_ context.Context, arg database
|
||||
if tpl.ID != arg.ID {
|
||||
continue
|
||||
}
|
||||
tpl.AllowUserAutostart = arg.AllowUserAutostart
|
||||
tpl.AllowUserAutostop = arg.AllowUserAutostop
|
||||
tpl.UpdatedAt = database.Now()
|
||||
tpl.DefaultTTL = arg.DefaultTTL
|
||||
tpl.MaxTTL = arg.MaxTTL
|
||||
@ -2903,6 +2905,8 @@ func (q *fakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl
|
||||
DisplayName: arg.DisplayName,
|
||||
Icon: arg.Icon,
|
||||
AllowUserCancelWorkspaceJobs: arg.AllowUserCancelWorkspaceJobs,
|
||||
AllowUserAutostart: true,
|
||||
AllowUserAutostop: true,
|
||||
}
|
||||
q.templates = append(q.templates, template)
|
||||
return template.DeepCopy(), nil
|
||||
@ -3977,6 +3981,31 @@ func (q *fakeQuerier) GetWorkspaceAgentStats(_ context.Context, createdAfter tim
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) GetWorkspacesEligibleForAutoStartStop(ctx context.Context, now time.Time) ([]database.Workspace, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
workspaces := []database.Workspace{}
|
||||
for _, workspace := range q.workspaces {
|
||||
build, err := q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx, workspace.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if build.Transition == database.WorkspaceTransitionStart && !build.Deadline.IsZero() && build.Deadline.Before(now) {
|
||||
workspaces = append(workspaces, workspace)
|
||||
continue
|
||||
}
|
||||
|
||||
if build.Transition == database.WorkspaceTransitionStop && workspace.AutostartSchedule.Valid {
|
||||
workspaces = append(workspaces, workspace)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return workspaces, nil
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateWorkspaceTTLToBeWithinTemplateMax(_ context.Context, arg database.UpdateWorkspaceTTLToBeWithinTemplateMaxParams) error {
|
||||
if err := validateDatabaseType(arg); err != nil {
|
||||
return err
|
||||
|
10
coderd/database/dump.sql
generated
10
coderd/database/dump.sql
generated
@ -445,15 +445,21 @@ CREATE TABLE templates (
|
||||
group_acl jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
display_name character varying(64) DEFAULT ''::character varying NOT NULL,
|
||||
allow_user_cancel_workspace_jobs boolean DEFAULT true NOT NULL,
|
||||
max_ttl bigint DEFAULT '0'::bigint NOT NULL
|
||||
max_ttl bigint DEFAULT '0'::bigint NOT NULL,
|
||||
allow_user_autostart boolean DEFAULT true NOT NULL,
|
||||
allow_user_autostop boolean DEFAULT true NOT NULL
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for auto-stop for workspaces created from this template.';
|
||||
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.';
|
||||
|
||||
COMMENT ON COLUMN templates.display_name IS 'Display name is a custom, human-friendly template name that user can set.';
|
||||
|
||||
COMMENT ON COLUMN templates.allow_user_cancel_workspace_jobs IS 'Allow users to cancel in-progress workspace jobs.';
|
||||
|
||||
COMMENT ON COLUMN templates.allow_user_autostart IS 'Allow users to specify an autostart schedule for workspaces (enterprise).';
|
||||
|
||||
COMMENT ON COLUMN templates.allow_user_autostop IS 'Allow users to specify custom autostop values for workspaces (enterprise).';
|
||||
|
||||
CREATE TABLE user_links (
|
||||
user_id uuid NOT NULL,
|
||||
login_type login_type NOT NULL,
|
||||
|
@ -3,4 +3,4 @@ ALTER TABLE "templates" DROP COLUMN "min_autostart_interval";
|
||||
|
||||
-- rename "max_ttl" to "default_ttl" on "templates" table
|
||||
ALTER TABLE "templates" RENAME COLUMN "max_ttl" TO "default_ttl";
|
||||
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for auto-stop for workspaces created from this template.';
|
||||
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.';
|
||||
|
@ -0,0 +1,3 @@
|
||||
ALTER TABLE "templates"
|
||||
DROP COLUMN "allow_user_autostart",
|
||||
DROP COLUMN "allow_user_autostop";
|
@ -0,0 +1,9 @@
|
||||
ALTER TABLE "templates"
|
||||
ADD COLUMN "allow_user_autostart" boolean DEFAULT true NOT NULL,
|
||||
ADD COLUMN "allow_user_autostop" boolean DEFAULT true NOT NULL;
|
||||
|
||||
COMMENT ON COLUMN "templates"."allow_user_autostart"
|
||||
IS 'Allow users to specify an autostart schedule for workspaces (enterprise).';
|
||||
|
||||
COMMENT ON COLUMN "templates"."allow_user_autostop"
|
||||
IS 'Allow users to specify custom autostop values for workspaces (enterprise).';
|
@ -78,6 +78,8 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1415,7 +1415,7 @@ type Template struct {
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
Description string `db:"description" json:"description"`
|
||||
// The default duration for auto-stop for workspaces created from this template.
|
||||
// The default duration for autostop for workspaces created from this template.
|
||||
DefaultTTL int64 `db:"default_ttl" json:"default_ttl"`
|
||||
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
|
||||
Icon string `db:"icon" json:"icon"`
|
||||
@ -1426,6 +1426,10 @@ type Template struct {
|
||||
// Allow users to cancel in-progress workspace jobs.
|
||||
AllowUserCancelWorkspaceJobs bool `db:"allow_user_cancel_workspace_jobs" json:"allow_user_cancel_workspace_jobs"`
|
||||
MaxTTL int64 `db:"max_ttl" json:"max_ttl"`
|
||||
// Allow users to specify an autostart schedule for workspaces (enterprise).
|
||||
AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"`
|
||||
// Allow users to specify custom autostop values for workspaces (enterprise).
|
||||
AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"`
|
||||
}
|
||||
|
||||
type TemplateVersion struct {
|
||||
|
@ -153,6 +153,7 @@ type sqlcQuerier interface {
|
||||
GetWorkspaceResourcesByJobIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceResource, error)
|
||||
GetWorkspaceResourcesCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceResource, error)
|
||||
GetWorkspaces(ctx context.Context, arg GetWorkspacesParams) ([]GetWorkspacesRow, error)
|
||||
GetWorkspacesEligibleForAutoStartStop(ctx context.Context, now time.Time) ([]Workspace, error)
|
||||
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
|
||||
// We use the organization_id as the id
|
||||
// for simplicity since all users is
|
||||
|
@ -3195,7 +3195,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
|
||||
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
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@ -3225,13 +3225,15 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@ -3269,12 +3271,14 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
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 FROM 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 FROM templates
|
||||
ORDER BY (name, id) ASC
|
||||
`
|
||||
|
||||
@ -3305,6 +3309,8 @@ func (q *sqlQuerier) GetTemplates(ctx context.Context) ([]Template, error) {
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -3321,7 +3327,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
|
||||
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
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@ -3389,6 +3395,8 @@ func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplate
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -3422,7 +3430,7 @@ INSERT INTO
|
||||
allow_user_cancel_workspace_jobs
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING 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
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING 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
|
||||
`
|
||||
|
||||
type InsertTemplateParams struct {
|
||||
@ -3478,6 +3486,8 @@ func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParam
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -3491,7 +3501,7 @@ SET
|
||||
WHERE
|
||||
id = $3
|
||||
RETURNING
|
||||
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
|
||||
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
|
||||
`
|
||||
|
||||
type UpdateTemplateACLByIDParams struct {
|
||||
@ -3521,6 +3531,8 @@ func (q *sqlQuerier) UpdateTemplateACLByID(ctx context.Context, arg UpdateTempla
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -3580,7 +3592,7 @@ SET
|
||||
WHERE
|
||||
id = $1
|
||||
RETURNING
|
||||
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
|
||||
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
|
||||
`
|
||||
|
||||
type UpdateTemplateMetaByIDParams struct {
|
||||
@ -3622,6 +3634,8 @@ func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTempl
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -3631,25 +3645,31 @@ UPDATE
|
||||
templates
|
||||
SET
|
||||
updated_at = $2,
|
||||
default_ttl = $3,
|
||||
max_ttl = $4
|
||||
allow_user_autostart = $3,
|
||||
allow_user_autostop = $4,
|
||||
default_ttl = $5,
|
||||
max_ttl = $6
|
||||
WHERE
|
||||
id = $1
|
||||
RETURNING
|
||||
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
|
||||
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
|
||||
`
|
||||
|
||||
type UpdateTemplateScheduleByIDParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
DefaultTTL int64 `db:"default_ttl" json:"default_ttl"`
|
||||
MaxTTL int64 `db:"max_ttl" json:"max_ttl"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
AllowUserAutostart bool `db:"allow_user_autostart" json:"allow_user_autostart"`
|
||||
AllowUserAutostop bool `db:"allow_user_autostop" json:"allow_user_autostop"`
|
||||
DefaultTTL int64 `db:"default_ttl" json:"default_ttl"`
|
||||
MaxTTL int64 `db:"max_ttl" json:"max_ttl"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateTemplateScheduleByID(ctx context.Context, arg UpdateTemplateScheduleByIDParams) (Template, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateTemplateScheduleByID,
|
||||
arg.ID,
|
||||
arg.UpdatedAt,
|
||||
arg.AllowUserAutostart,
|
||||
arg.AllowUserAutostop,
|
||||
arg.DefaultTTL,
|
||||
arg.MaxTTL,
|
||||
)
|
||||
@ -3672,6 +3692,8 @@ func (q *sqlQuerier) UpdateTemplateScheduleByID(ctx context.Context, arg UpdateT
|
||||
&i.DisplayName,
|
||||
&i.AllowUserCancelWorkspaceJobs,
|
||||
&i.MaxTTL,
|
||||
&i.AllowUserAutostart,
|
||||
&i.AllowUserAutostop,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -7906,6 +7928,81 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getWorkspacesEligibleForAutoStartStop = `-- name: GetWorkspacesEligibleForAutoStartStop :many
|
||||
SELECT
|
||||
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at
|
||||
FROM
|
||||
workspaces
|
||||
LEFT JOIN
|
||||
workspace_builds ON workspace_builds.workspace_id = workspaces.id
|
||||
WHERE
|
||||
workspace_builds.build_number = (
|
||||
SELECT
|
||||
MAX(build_number)
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
workspace_builds.workspace_id = workspaces.id
|
||||
) AND
|
||||
|
||||
(
|
||||
-- If the workspace build was a start transition, the workspace is
|
||||
-- potentially eligible for autostop if it's past the deadline. The
|
||||
-- deadline is computed at build time upon success and is bumped based
|
||||
-- on activity (up the max deadline if set). We don't need to check
|
||||
-- license here since that's done when the values are written to the build.
|
||||
(
|
||||
workspace_builds.transition = 'start'::workspace_transition AND
|
||||
workspace_builds.deadline IS NOT NULL AND
|
||||
workspace_builds.deadline < $1 :: timestamptz
|
||||
) OR
|
||||
|
||||
-- If the workspace build was a stop transition, the workspace is
|
||||
-- potentially eligible for autostart if it has a schedule set. The
|
||||
-- caller must check if the template allows autostart in a license-aware
|
||||
-- fashion as we cannot check it here.
|
||||
(
|
||||
workspace_builds.transition = 'stop'::workspace_transition AND
|
||||
workspaces.autostart_schedule IS NOT NULL
|
||||
)
|
||||
)
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetWorkspacesEligibleForAutoStartStop(ctx context.Context, now time.Time) ([]Workspace, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getWorkspacesEligibleForAutoStartStop, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Workspace
|
||||
for rows.Next() {
|
||||
var i Workspace
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.OwnerID,
|
||||
&i.OrganizationID,
|
||||
&i.TemplateID,
|
||||
&i.Deleted,
|
||||
&i.Name,
|
||||
&i.AutostartSchedule,
|
||||
&i.Ttl,
|
||||
&i.LastUsedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const insertWorkspace = `-- name: InsertWorkspace :one
|
||||
INSERT INTO
|
||||
workspaces (
|
||||
|
@ -115,8 +115,10 @@ UPDATE
|
||||
templates
|
||||
SET
|
||||
updated_at = $2,
|
||||
default_ttl = $3,
|
||||
max_ttl = $4
|
||||
allow_user_autostart = $3,
|
||||
allow_user_autostop = $4,
|
||||
default_ttl = $5,
|
||||
max_ttl = $6
|
||||
WHERE
|
||||
id = $1
|
||||
RETURNING
|
||||
|
@ -392,3 +392,42 @@ SELECT
|
||||
failed_workspaces.count AS failed_workspaces,
|
||||
stopped_workspaces.count AS stopped_workspaces
|
||||
FROM pending_workspaces, building_workspaces, running_workspaces, failed_workspaces, stopped_workspaces;
|
||||
|
||||
-- name: GetWorkspacesEligibleForAutoStartStop :many
|
||||
SELECT
|
||||
workspaces.*
|
||||
FROM
|
||||
workspaces
|
||||
LEFT JOIN
|
||||
workspace_builds ON workspace_builds.workspace_id = workspaces.id
|
||||
WHERE
|
||||
workspace_builds.build_number = (
|
||||
SELECT
|
||||
MAX(build_number)
|
||||
FROM
|
||||
workspace_builds
|
||||
WHERE
|
||||
workspace_builds.workspace_id = workspaces.id
|
||||
) AND
|
||||
|
||||
(
|
||||
-- If the workspace build was a start transition, the workspace is
|
||||
-- potentially eligible for autostop if it's past the deadline. The
|
||||
-- deadline is computed at build time upon success and is bumped based
|
||||
-- on activity (up the max deadline if set). We don't need to check
|
||||
-- license here since that's done when the values are written to the build.
|
||||
(
|
||||
workspace_builds.transition = 'start'::workspace_transition AND
|
||||
workspace_builds.deadline IS NOT NULL AND
|
||||
workspace_builds.deadline < @now :: timestamptz
|
||||
) OR
|
||||
|
||||
-- If the workspace build was a stop transition, the workspace is
|
||||
-- potentially eligible for autostart if it has a schedule set. The
|
||||
-- caller must check if the template allows autostart in a license-aware
|
||||
-- fashion as we cannot check it here.
|
||||
(
|
||||
workspace_builds.transition = 'stop'::workspace_transition AND
|
||||
workspaces.autostart_schedule IS NOT NULL
|
||||
)
|
||||
);
|
||||
|
Reference in New Issue
Block a user