adds support for workspace presets to the coderd database. Support in the API and web frontend will be added in subsequent pull requests. This is the smallest meaningful contribution that I could get passing tests for.

* Add workspace preset tables to the database in a migration
* Add queries to manipulate workspace presets to the database
* Generate db related code for the newly added queries
* Implement new methods to satisfy the Querier interface in dbauthz, dbmem, dbmock and querymetrics
* Implement the required tests for dbauthz
* Update the audit table to track changes to the new column in workspace builds
This commit is contained in:
Sas Swart
2025-01-20 16:11:44 +00:00
parent 7f44189ed2
commit 2fca3693fc
17 changed files with 822 additions and 127 deletions

View File

@ -5395,6 +5395,157 @@ 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.name,
template_version_presets.created_at,
template_version_presets.updated_at
FROM
workspace_builds
LEFT JOIN template_version_presets ON workspace_builds.template_version_preset_id = template_version_presets.id
WHERE
workspace_builds.id = $1
`
type GetPresetByWorkspaceBuildIDRow struct {
ID uuid.NullUUID `db:"id" json:"id"`
Name sql.NullString `db:"name" json:"name"`
CreatedAt sql.NullTime `db:"created_at" json:"created_at"`
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
}
func (q *sqlQuerier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceBuildID uuid.UUID) (GetPresetByWorkspaceBuildIDRow, error) {
row := q.db.QueryRowContext(ctx, getPresetByWorkspaceBuildID, workspaceBuildID)
var i GetPresetByWorkspaceBuildIDRow
err := row.Scan(
&i.ID,
&i.Name,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const getPresetParametersByPresetID = `-- name: GetPresetParametersByPresetID :many
SELECT
id,
name,
value
FROM
template_version_preset_parameters
WHERE
template_version_preset_id = $1
`
type GetPresetParametersByPresetIDRow struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
Value string `db:"value" json:"value"`
}
func (q *sqlQuerier) GetPresetParametersByPresetID(ctx context.Context, templateVersionPresetID uuid.UUID) ([]GetPresetParametersByPresetIDRow, error) {
rows, err := q.db.QueryContext(ctx, getPresetParametersByPresetID, templateVersionPresetID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetPresetParametersByPresetIDRow
for rows.Next() {
var i GetPresetParametersByPresetIDRow
if err := rows.Scan(&i.ID, &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,
name,
created_at,
updated_at
FROM
template_version_presets
WHERE
template_version_id = $1
`
type GetPresetsByTemplateVersionIDRow struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
}
func (q *sqlQuerier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]GetPresetsByTemplateVersionIDRow, error) {
rows, err := q.db.QueryContext(ctx, getPresetsByTemplateVersionID, templateVersionID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetPresetsByTemplateVersionIDRow
for rows.Next() {
var i GetPresetsByTemplateVersionIDRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.CreatedAt,
&i.UpdatedAt,
); 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 (template_version_id, name, created_at, updated_at)
VALUES
($1, $2, $3, $4) RETURNING id, template_version_id, name, created_at, updated_at
`
type InsertPresetParams struct {
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"`
UpdatedAt sql.NullTime `db:"updated_at" json:"updated_at"`
}
func (q *sqlQuerier) InsertPreset(ctx context.Context, arg InsertPresetParams) (TemplateVersionPreset, error) {
row := q.db.QueryRowContext(ctx, insertPreset,
arg.TemplateVersionID,
arg.Name,
arg.CreatedAt,
arg.UpdatedAt,
)
var i TemplateVersionPreset
err := row.Scan(
&i.ID,
&i.TemplateVersionID,
&i.Name,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const deleteOldProvisionerDaemons = `-- name: DeleteOldProvisionerDaemons :exec
DELETE FROM provisioner_daemons WHERE (
(created_at < (NOW() - INTERVAL '7 days') AND last_seen_at IS NULL) OR
@ -11955,7 +12106,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
@ -12058,6 +12209,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,
)
@ -14261,7 +14413,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
@ -14315,6 +14467,7 @@ func (q *sqlQuerier) GetActiveWorkspaceBuildsByTemplateID(ctx context.Context, t
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14410,7 +14563,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
@ -14439,6 +14592,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14446,7 +14600,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
@ -14484,6 +14638,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuilds(ctx context.Context) ([]WorkspaceB
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14501,7 +14656,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
@ -14541,6 +14696,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14559,7 +14715,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
@ -14586,6 +14742,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14594,7 +14751,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
@ -14621,6 +14778,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14629,7 +14787,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
@ -14660,6 +14818,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Co
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
)
@ -14735,7 +14894,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
@ -14805,6 +14964,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {
@ -14822,7 +14982,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) {
@ -14849,6 +15009,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, created
&i.Reason,
&i.DailyCost,
&i.MaxDeadline,
&i.TemplateVersionPresetID,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
); err != nil {