forked from wrenn/wrenn
Implement three new recipe commands for the admin template builder: - USER <name>: creates the user (adduser + passwordless sudo), switches execution context so subsequent RUN/START commands run as that user via su wrapping. Last USER becomes the template's default_user. - COPY <src> <dst>: copies files from an uploaded build archive (tar/tar.gz/zip) into the sandbox. Source paths validated against traversal. Ownership set to the current USER. - ENV persistence: accumulated env vars stored in templates.default_env (JSONB) and injected via PostInit when sandboxes are created from the template, mirroring Docker's image metadata approach. Supporting changes: - Pre-build creates wrenn-user as default (via USER command) - WORKDIR now creates the directory if it doesn't exist (mkdir -p) - Per-step progress updates (ProgressFunc callback) for live UI - Multipart form support on POST /v1/admin/builds for archive upload - Proto: default_user/default_env fields on Create/ResumeSandboxRequest - Host agent: SetDefaults calls PostInitWithDefaults on envd - Control plane: reads template defaults, passes on sandbox create/resume - Frontend: file upload widget, recipe copy button, keyword colors for USER/COPY, fixed Svelte whitespace stripping in step display - Admin panel defaults to /admin/templates instead of /admin/hosts - Migration adds default_user and default_env to templates and template_builds tables
376 lines
9.4 KiB
Go
376 lines
9.4 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: templates.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const deleteTemplate = `-- name: DeleteTemplate :exec
|
|
DELETE FROM templates WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) DeleteTemplate(ctx context.Context, id pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, deleteTemplate, id)
|
|
return err
|
|
}
|
|
|
|
const deleteTemplateByTeam = `-- name: DeleteTemplateByTeam :exec
|
|
DELETE FROM templates WHERE name = $1 AND team_id = $2
|
|
`
|
|
|
|
type DeleteTemplateByTeamParams struct {
|
|
Name string `json:"name"`
|
|
TeamID pgtype.UUID `json:"team_id"`
|
|
}
|
|
|
|
func (q *Queries) DeleteTemplateByTeam(ctx context.Context, arg DeleteTemplateByTeamParams) error {
|
|
_, err := q.db.Exec(ctx, deleteTemplateByTeam, arg.Name, arg.TeamID)
|
|
return err
|
|
}
|
|
|
|
const deleteTemplatesByTeam = `-- name: DeleteTemplatesByTeam :exec
|
|
DELETE FROM templates WHERE team_id = $1
|
|
`
|
|
|
|
// Bulk delete all templates owned by a team (for team soft-delete cleanup).
|
|
func (q *Queries) DeleteTemplatesByTeam(ctx context.Context, teamID pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, deleteTemplatesByTeam, teamID)
|
|
return err
|
|
}
|
|
|
|
const getPlatformTemplateByName = `-- name: GetPlatformTemplateByName :one
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE team_id = '00000000-0000-0000-0000-000000000000' AND name = $1
|
|
`
|
|
|
|
// Check if a global (platform) template exists with the given name.
|
|
func (q *Queries) GetPlatformTemplateByName(ctx context.Context, name string) (Template, error) {
|
|
row := q.db.QueryRow(ctx, getPlatformTemplateByName, name)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTemplate = `-- name: GetTemplate :one
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) GetTemplate(ctx context.Context, id pgtype.UUID) (Template, error) {
|
|
row := q.db.QueryRow(ctx, getTemplate, id)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTemplateByName = `-- name: GetTemplateByName :one
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE team_id = $1 AND name = $2
|
|
`
|
|
|
|
type GetTemplateByNameParams struct {
|
|
TeamID pgtype.UUID `json:"team_id"`
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
// Look up a template by team_id and name (exact team match, no global fallback).
|
|
func (q *Queries) GetTemplateByName(ctx context.Context, arg GetTemplateByNameParams) (Template, error) {
|
|
row := q.db.QueryRow(ctx, getTemplateByName, arg.TeamID, arg.Name)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const getTemplateByTeam = `-- name: GetTemplateByTeam :one
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE name = $1 AND (team_id = $2 OR team_id = '00000000-0000-0000-0000-000000000000')
|
|
`
|
|
|
|
type GetTemplateByTeamParams struct {
|
|
Name string `json:"name"`
|
|
TeamID pgtype.UUID `json:"team_id"`
|
|
}
|
|
|
|
// Platform templates (team_id = 00000000-...) are visible to all teams.
|
|
func (q *Queries) GetTemplateByTeam(ctx context.Context, arg GetTemplateByTeamParams) (Template, error) {
|
|
row := q.db.QueryRow(ctx, getTemplateByTeam, arg.Name, arg.TeamID)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const insertTemplate = `-- name: InsertTemplate :one
|
|
INSERT INTO templates (id, name, type, vcpus, memory_mb, size_bytes, team_id, default_user, default_env)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
RETURNING name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env
|
|
`
|
|
|
|
type InsertTemplateParams struct {
|
|
ID pgtype.UUID `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Vcpus int32 `json:"vcpus"`
|
|
MemoryMb int32 `json:"memory_mb"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
TeamID pgtype.UUID `json:"team_id"`
|
|
DefaultUser string `json:"default_user"`
|
|
DefaultEnv []byte `json:"default_env"`
|
|
}
|
|
|
|
func (q *Queries) InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error) {
|
|
row := q.db.QueryRow(ctx, insertTemplate,
|
|
arg.ID,
|
|
arg.Name,
|
|
arg.Type,
|
|
arg.Vcpus,
|
|
arg.MemoryMb,
|
|
arg.SizeBytes,
|
|
arg.TeamID,
|
|
arg.DefaultUser,
|
|
arg.DefaultEnv,
|
|
)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listTemplates = `-- name: ListTemplates :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates ORDER BY created_at DESC
|
|
`
|
|
|
|
func (q *Queries) ListTemplates(ctx context.Context) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplates)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTemplatesByTeam = `-- name: ListTemplatesByTeam :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE (team_id = $1 OR team_id = '00000000-0000-0000-0000-000000000000') ORDER BY created_at DESC
|
|
`
|
|
|
|
// Platform templates are visible to all teams.
|
|
func (q *Queries) ListTemplatesByTeam(ctx context.Context, teamID pgtype.UUID) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplatesByTeam, teamID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTemplatesByTeamAndType = `-- name: ListTemplatesByTeamAndType :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE (team_id = $1 OR team_id = '00000000-0000-0000-0000-000000000000') AND type = $2 ORDER BY created_at DESC
|
|
`
|
|
|
|
type ListTemplatesByTeamAndTypeParams struct {
|
|
TeamID pgtype.UUID `json:"team_id"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// Platform templates are visible to all teams.
|
|
func (q *Queries) ListTemplatesByTeamAndType(ctx context.Context, arg ListTemplatesByTeamAndTypeParams) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplatesByTeamAndType, arg.TeamID, arg.Type)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTemplatesByTeamOnly = `-- name: ListTemplatesByTeamOnly :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE team_id = $1 ORDER BY created_at DESC
|
|
`
|
|
|
|
// List templates owned by a specific team (NOT including platform templates).
|
|
func (q *Queries) ListTemplatesByTeamOnly(ctx context.Context, teamID pgtype.UUID) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplatesByTeamOnly, teamID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTemplatesByType = `-- name: ListTemplatesByType :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at, team_id, id, default_user, default_env FROM templates WHERE type = $1 ORDER BY created_at DESC
|
|
`
|
|
|
|
func (q *Queries) ListTemplatesByType(ctx context.Context, type_ string) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplatesByType, type_)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
&i.TeamID,
|
|
&i.ID,
|
|
&i.DefaultUser,
|
|
&i.DefaultEnv,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|