feat(coderd/database): add support for presets (#16509)

This pull requests adds the necessary migrations and queries to support
presets within the coderd database. Future PRs will build functionality
to the provisioners and the frontend.
This commit is contained in:
Sas Swart
2025-02-11 13:55:09 +02:00
committed by GitHub
parent 0e728a7a9b
commit 34b46f9205
20 changed files with 948 additions and 144 deletions

View File

@ -5395,6 +5395,185 @@ func (q *sqlQuerier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.
return items, nil
}
const getPresetByWorkspaceBuildID = `-- name: GetPresetByWorkspaceBuildID :one
SELECT
template_version_presets.id, template_version_presets.template_version_id, template_version_presets.name, template_version_presets.created_at
FROM
template_version_presets
INNER JOIN workspace_builds ON workspace_builds.template_version_preset_id = template_version_presets.id
WHERE
workspace_builds.id = $1
`
func (q *sqlQuerier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceBuildID uuid.UUID) (TemplateVersionPreset, error) {
row := q.db.QueryRowContext(ctx, getPresetByWorkspaceBuildID, workspaceBuildID)
var i TemplateVersionPreset
err := row.Scan(
&i.ID,
&i.TemplateVersionID,
&i.Name,
&i.CreatedAt,
)
return i, err
}
const getPresetParametersByTemplateVersionID = `-- name: GetPresetParametersByTemplateVersionID :many
SELECT
template_version_preset_parameters.id, template_version_preset_parameters.template_version_preset_id, template_version_preset_parameters.name, template_version_preset_parameters.value
FROM
template_version_preset_parameters
INNER JOIN template_version_presets ON template_version_preset_parameters.template_version_preset_id = template_version_presets.id
WHERE
template_version_presets.template_version_id = $1
`
func (q *sqlQuerier) GetPresetParametersByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]TemplateVersionPresetParameter, error) {
rows, err := q.db.QueryContext(ctx, getPresetParametersByTemplateVersionID, templateVersionID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TemplateVersionPresetParameter
for rows.Next() {
var i TemplateVersionPresetParameter
if err := rows.Scan(
&i.ID,
&i.TemplateVersionPresetID,
&i.Name,
&i.Value,
); 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 getPresetsByTemplateVersionID = `-- name: GetPresetsByTemplateVersionID :many
SELECT
id, template_version_id, name, created_at
FROM
template_version_presets
WHERE
template_version_id = $1
`
func (q *sqlQuerier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]TemplateVersionPreset, error) {
rows, err := q.db.QueryContext(ctx, getPresetsByTemplateVersionID, templateVersionID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TemplateVersionPreset
for rows.Next() {
var i TemplateVersionPreset
if err := rows.Scan(
&i.ID,
&i.TemplateVersionID,
&i.Name,
&i.CreatedAt,
); 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 insertPreset = `-- name: InsertPreset :one
INSERT INTO
template_version_presets (id, template_version_id, name, created_at)
VALUES
($1, $2, $3, $4) RETURNING id, template_version_id, name, created_at
`
type InsertPresetParams struct {
ID uuid.UUID `db:"id" json:"id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
Name string `db:"name" json:"name"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
func (q *sqlQuerier) InsertPreset(ctx context.Context, arg InsertPresetParams) (TemplateVersionPreset, error) {
row := q.db.QueryRowContext(ctx, insertPreset,
arg.ID,
arg.TemplateVersionID,
arg.Name,
arg.CreatedAt,
)
var i TemplateVersionPreset
err := row.Scan(
&i.ID,
&i.TemplateVersionID,
&i.Name,
&i.CreatedAt,
)
return i, err
}
const insertPresetParameters = `-- name: InsertPresetParameters :many
INSERT INTO
template_version_preset_parameters (id, template_version_preset_id, name, value)
SELECT
$1,
$2,
unnest($3 :: TEXT[]),
unnest($4 :: TEXT[])
RETURNING id, template_version_preset_id, name, value
`
type InsertPresetParametersParams struct {
ID uuid.UUID `db:"id" json:"id"`
TemplateVersionPresetID uuid.UUID `db:"template_version_preset_id" json:"template_version_preset_id"`
Names []string `db:"names" json:"names"`
Values []string `db:"values" json:"values"`
}
func (q *sqlQuerier) InsertPresetParameters(ctx context.Context, arg InsertPresetParametersParams) ([]TemplateVersionPresetParameter, error) {
rows, err := q.db.QueryContext(ctx, insertPresetParameters,
arg.ID,
arg.TemplateVersionPresetID,
pq.Array(arg.Names),
pq.Array(arg.Values),
)
if err != nil {
return nil, err
}
defer rows.Close()
var items []TemplateVersionPresetParameter
for rows.Next() {
var i TemplateVersionPresetParameter
if err := rows.Scan(
&i.ID,
&i.TemplateVersionPresetID,
&i.Name,
&i.Value,
); 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 deleteOldProvisionerDaemons = `-- name: DeleteOldProvisionerDaemons :exec
DELETE FROM provisioner_daemons WHERE (
(created_at < (NOW() - INTERVAL '7 days') AND last_seen_at IS NULL) OR
@ -11993,7 +12172,7 @@ const getWorkspaceAgentAndLatestBuildByAuthToken = `-- name: GetWorkspaceAgentAn
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, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, workspaces.next_start_at,
workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.expanded_directory, workspace_agents.logs_length, workspace_agents.logs_overflowed, workspace_agents.started_at, workspace_agents.ready_at, workspace_agents.subsystems, workspace_agents.display_apps, workspace_agents.api_version, workspace_agents.display_order,
workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username
workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.template_version_preset_id, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username
FROM
workspace_agents
JOIN
@ -12096,6 +12275,7 @@ func (q *sqlQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(ctx context.Cont
&i.WorkspaceBuild.Reason,
&i.WorkspaceBuild.DailyCost,
&i.WorkspaceBuild.MaxDeadline,
&i.WorkspaceBuild.TemplateVersionPresetID,
&i.WorkspaceBuild.InitiatorByAvatarUrl,
&i.WorkspaceBuild.InitiatorByUsername,
)
@ -14299,7 +14479,7 @@ func (q *sqlQuerier) InsertWorkspaceBuildParameters(ctx context.Context, arg Ins
}
const getActiveWorkspaceBuildsByTemplateID = `-- name: GetActiveWorkspaceBuildsByTemplateID :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.initiator_by_avatar_url, wb.initiator_by_username
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@ -14353,6 +14533,7 @@ func (q *sqlQuerier) GetActiveWorkspaceBuildsByTemplateID(ctx context.Context, t
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14448,7 +14629,7 @@ func (q *sqlQuerier) GetFailedWorkspaceBuildsByTemplateID(ctx context.Context, a
const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username
FROM
workspace_build_with_user AS workspace_builds
WHERE
@ -14477,6 +14658,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14484,7 +14666,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
}
const getLatestWorkspaceBuilds = `-- name: GetLatestWorkspaceBuilds :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.initiator_by_avatar_url, wb.initiator_by_username
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@ -14522,6 +14704,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceB
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14539,7 +14722,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceB
}
const getLatestWorkspaceBuildsByWorkspaceIDs = `-- name: GetLatestWorkspaceBuildsByWorkspaceIDs :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.initiator_by_avatar_url, wb.initiator_by_username
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.initiator_by_avatar_url, wb.initiator_by_username
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@ -14579,6 +14762,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14597,7 +14781,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
const getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username
FROM
workspace_build_with_user AS workspace_builds
WHERE
@ -14624,6 +14808,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14632,7 +14817,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username
FROM
workspace_build_with_user AS workspace_builds
WHERE
@ -14659,6 +14844,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14667,7 +14853,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
const getWorkspaceBuildByWorkspaceIDAndBuildNumber = `-- name: GetWorkspaceBuildByWorkspaceIDAndBuildNumber :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username
FROM
workspace_build_with_user AS workspace_builds
WHERE
@ -14698,6 +14884,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Co
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14773,7 +14960,7 @@ func (q *sqlQuerier) GetWorkspaceBuildStatsByTemplates(ctx context.Context, sinc
const getWorkspaceBuildsByWorkspaceID = `-- name: GetWorkspaceBuildsByWorkspaceID :many
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username
FROM
workspace_build_with_user AS workspace_builds
WHERE
@ -14843,6 +15030,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14860,7 +15048,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge
}
const getWorkspaceBuildsCreatedAfter = `-- name: GetWorkspaceBuildsCreatedAfter :many
SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, initiator_by_avatar_url, initiator_by_username FROM workspace_build_with_user WHERE created_at > $1
SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, initiator_by_avatar_url, initiator_by_username FROM workspace_build_with_user WHERE created_at > $1
`
func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error) {
@ -14887,6 +15075,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, created
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14918,26 +15107,28 @@ INSERT INTO
provisioner_state,
deadline,
max_deadline,
reason
reason,
template_version_preset_id
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
`
type InsertWorkspaceBuildParams 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"`
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
BuildNumber int32 `db:"build_number" json:"build_number"`
Transition WorkspaceTransition `db:"transition" json:"transition"`
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
JobID uuid.UUID `db:"job_id" json:"job_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
Deadline time.Time `db:"deadline" json:"deadline"`
MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"`
Reason BuildReason `db:"reason" json:"reason"`
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"`
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
BuildNumber int32 `db:"build_number" json:"build_number"`
Transition WorkspaceTransition `db:"transition" json:"transition"`
InitiatorID uuid.UUID `db:"initiator_id" json:"initiator_id"`
JobID uuid.UUID `db:"job_id" json:"job_id"`
ProvisionerState []byte `db:"provisioner_state" json:"provisioner_state"`
Deadline time.Time `db:"deadline" json:"deadline"`
MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"`
Reason BuildReason `db:"reason" json:"reason"`
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
}
func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspaceBuildParams) error {
@ -14955,6 +15146,7 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
arg.Deadline,
arg.MaxDeadline,
arg.Reason,
arg.TemplateVersionPresetID,
)
return err
}