mirror of
https://github.com/coder/coder.git
synced 2025-07-03 16:13:58 +00:00
feat: allow disabling autostart and custom autostop for template (#6933)
API only, frontend in upcoming PR.
This commit is contained in:
@ -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 (
|
||||
|
Reference in New Issue
Block a user