mirror of https://github.com/coder/coder.git
feat: add template version creator (#3001)
This commit is contained in:
parent
d26b3b7ba1
commit
d04ba2cc02
|
@ -114,12 +114,14 @@ func TestDiff(t *testing.T) {
|
|||
UpdatedAt: time.Now(),
|
||||
OrganizationID: uuid.UUID{3},
|
||||
Name: "rust",
|
||||
CreatedBy: uuid.NullUUID{UUID: uuid.UUID{4}, Valid: true},
|
||||
},
|
||||
exp: audit.Map{
|
||||
"id": uuid.UUID{1}.String(),
|
||||
"template_id": uuid.UUID{2}.String(),
|
||||
"organization_id": uuid.UUID{3}.String(),
|
||||
"name": "rust",
|
||||
"created_by": uuid.UUID{4}.String(),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -132,11 +134,13 @@ func TestDiff(t *testing.T) {
|
|||
UpdatedAt: time.Now(),
|
||||
OrganizationID: uuid.UUID{3},
|
||||
Name: "rust",
|
||||
CreatedBy: uuid.NullUUID{UUID: uuid.UUID{4}, Valid: true},
|
||||
},
|
||||
exp: audit.Map{
|
||||
"id": uuid.UUID{1}.String(),
|
||||
"organization_id": uuid.UUID{3}.String(),
|
||||
"name": "rust",
|
||||
"created_by": uuid.UUID{4}.String(),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
@ -83,6 +83,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
|
|||
"name": ActionTrack,
|
||||
"readme": ActionTrack,
|
||||
"job_id": ActionIgnore, // Not helpful in a diff because jobs aren't tracked in audit logs.
|
||||
"created_by": ActionTrack,
|
||||
},
|
||||
&database.User{}: {
|
||||
"id": ActionTrack,
|
||||
|
|
|
@ -1511,6 +1511,7 @@ func (q *fakeQuerier) InsertTemplateVersion(_ context.Context, arg database.Inse
|
|||
Name: arg.Name,
|
||||
Readme: arg.Readme,
|
||||
JobID: arg.JobID,
|
||||
CreatedBy: arg.CreatedBy,
|
||||
}
|
||||
q.templateVersions = append(q.templateVersions, version)
|
||||
return version, nil
|
||||
|
|
|
@ -247,7 +247,8 @@ CREATE TABLE template_versions (
|
|||
updated_at timestamp with time zone NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
readme character varying(1048576) NOT NULL,
|
||||
job_id uuid NOT NULL
|
||||
job_id uuid NOT NULL,
|
||||
created_by uuid
|
||||
);
|
||||
|
||||
CREATE TABLE templates (
|
||||
|
@ -486,6 +487,9 @@ ALTER TABLE ONLY provisioner_job_logs
|
|||
ALTER TABLE ONLY provisioner_jobs
|
||||
ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY template_versions
|
||||
ADD CONSTRAINT template_versions_created_by_fkey FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE RESTRICT;
|
||||
|
||||
ALTER TABLE ONLY template_versions
|
||||
ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE ONLY template_versions DROP COLUMN IF EXISTS created_by;
|
|
@ -0,0 +1,16 @@
|
|||
BEGIN;
|
||||
|
||||
ALTER TABLE ONLY template_versions ADD COLUMN IF NOT EXISTS created_by uuid REFERENCES users (id) ON DELETE RESTRICT;
|
||||
|
||||
UPDATE
|
||||
template_versions
|
||||
SET
|
||||
created_by = (
|
||||
SELECT created_by FROM templates
|
||||
WHERE template_versions.template_id = templates.id
|
||||
LIMIT 1
|
||||
)
|
||||
WHERE
|
||||
created_by IS NULL;
|
||||
|
||||
COMMIT;
|
|
@ -478,6 +478,7 @@ type TemplateVersion struct {
|
|||
Name string `db:"name" json:"name"`
|
||||
Readme string `db:"readme" json:"readme"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
CreatedBy uuid.NullUUID `db:"created_by" json:"created_by"`
|
||||
}
|
||||
|
||||
type User struct {
|
||||
|
|
|
@ -2145,7 +2145,7 @@ func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTempl
|
|||
|
||||
const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one
|
||||
SELECT
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
|
@ -2164,13 +2164,14 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one
|
||||
SELECT
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
|
@ -2189,13 +2190,14 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one
|
||||
SELECT
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
|
@ -2220,13 +2222,14 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many
|
||||
SELECT
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id
|
||||
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
|
||||
FROM
|
||||
template_versions
|
||||
WHERE
|
||||
|
@ -2289,6 +2292,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2304,7 +2308,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
|
|||
}
|
||||
|
||||
const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many
|
||||
SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id FROM template_versions WHERE created_at > $1
|
||||
SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by FROM template_versions WHERE created_at > $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) {
|
||||
|
@ -2325,6 +2329,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -2349,10 +2354,11 @@ INSERT INTO
|
|||
updated_at,
|
||||
"name",
|
||||
readme,
|
||||
job_id
|
||||
job_id,
|
||||
created_by
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id, template_id, organization_id, created_at, updated_at, name, readme, job_id
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by
|
||||
`
|
||||
|
||||
type InsertTemplateVersionParams struct {
|
||||
|
@ -2364,6 +2370,7 @@ type InsertTemplateVersionParams struct {
|
|||
Name string `db:"name" json:"name"`
|
||||
Readme string `db:"readme" json:"readme"`
|
||||
JobID uuid.UUID `db:"job_id" json:"job_id"`
|
||||
CreatedBy uuid.NullUUID `db:"created_by" json:"created_by"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error) {
|
||||
|
@ -2376,6 +2383,7 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
|
|||
arg.Name,
|
||||
arg.Readme,
|
||||
arg.JobID,
|
||||
arg.CreatedBy,
|
||||
)
|
||||
var i TemplateVersion
|
||||
err := row.Scan(
|
||||
|
@ -2387,6 +2395,7 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
|
|||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
|
|
@ -70,10 +70,11 @@ INSERT INTO
|
|||
updated_at,
|
||||
"name",
|
||||
readme,
|
||||
job_id
|
||||
job_id,
|
||||
created_by
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateVersionByID :exec
|
||||
UPDATE
|
||||
|
|
|
@ -209,6 +209,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
|
|||
UUID: dbTemplate.ID,
|
||||
Valid: true,
|
||||
},
|
||||
UpdatedAt: database.Now(),
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert template version: %s", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package coderd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -36,7 +37,16 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
|
||||
createdByName, err := getUsernameByUserID(r.Context(), api.Database, templateVersion.CreatedBy)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching creator name.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), createdByName))
|
||||
}
|
||||
|
||||
func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
|
@ -476,7 +486,15 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
|
|||
})
|
||||
return err
|
||||
}
|
||||
apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job)))
|
||||
createdByName, err := getUsernameByUserID(r.Context(), store, version.CreatedBy)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching creator name.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return err
|
||||
}
|
||||
apiVersions = append(apiVersions, convertTemplateVersion(version, convertProvisionerJob(job), createdByName))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -525,7 +543,16 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
|
||||
createdByName, err := getUsernameByUserID(r.Context(), api.Database, templateVersion.CreatedBy)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching creator name.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), createdByName))
|
||||
}
|
||||
|
||||
func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
|
@ -735,6 +762,10 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
|
|||
Name: namesgenerator.GetRandomName(1),
|
||||
Readme: "",
|
||||
JobID: provisionerJob.ID,
|
||||
CreatedBy: uuid.NullUUID{
|
||||
UUID: apiKey.UserID,
|
||||
Valid: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert template version: %w", err)
|
||||
|
@ -748,7 +779,16 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
|
|||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob)))
|
||||
createdByName, err := getUsernameByUserID(r.Context(), api.Database, templateVersion.CreatedBy)
|
||||
if err != nil {
|
||||
httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching creator name.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob), createdByName))
|
||||
}
|
||||
|
||||
// templateVersionResources returns the workspace agent resources associated
|
||||
|
@ -796,7 +836,18 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
|||
api.provisionerJobLogs(rw, r, job)
|
||||
}
|
||||
|
||||
func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob) codersdk.TemplateVersion {
|
||||
func getUsernameByUserID(ctx context.Context, db database.Store, userID uuid.NullUUID) (string, error) {
|
||||
if !userID.Valid {
|
||||
return "", nil
|
||||
}
|
||||
user, err := db.GetUserByID(ctx, userID.UUID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return user.Username, nil
|
||||
}
|
||||
|
||||
func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, createdByName string) codersdk.TemplateVersion {
|
||||
return codersdk.TemplateVersion{
|
||||
ID: version.ID,
|
||||
TemplateID: &version.TemplateID.UUID,
|
||||
|
@ -806,5 +857,7 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi
|
|||
Name: version.Name,
|
||||
Job: job,
|
||||
Readme: version.Readme,
|
||||
CreatedByID: version.CreatedBy.UUID,
|
||||
CreatedByName: createdByName,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ type TemplateVersion struct {
|
|||
Name string `json:"name"`
|
||||
Job ProvisionerJob `json:"job"`
|
||||
Readme string `json:"readme"`
|
||||
CreatedByID uuid.UUID `json:"created_by_id"`
|
||||
CreatedByName string `json:"created_by_name"`
|
||||
}
|
||||
|
||||
// TemplateVersion returns a template version by ID.
|
||||
|
|
|
@ -87,7 +87,7 @@ export interface CreateTemplateRequest {
|
|||
readonly min_autostart_interval_ms?: number
|
||||
}
|
||||
|
||||
// From codersdk/templateversions.go:106:6
|
||||
// From codersdk/templateversions.go:108:6
|
||||
export interface CreateTemplateVersionDryRunRequest {
|
||||
readonly WorkspaceName: string
|
||||
readonly ParameterValues: CreateParameterRequest[]
|
||||
|
@ -290,6 +290,8 @@ export interface TemplateVersion {
|
|||
readonly name: string
|
||||
readonly job: ProvisionerJob
|
||||
readonly readme: string
|
||||
readonly created_by_id: string
|
||||
readonly created_by_name: string
|
||||
}
|
||||
|
||||
// From codersdk/templates.go:100:6
|
||||
|
|
|
@ -112,6 +112,8 @@ name:Template test
|
|||
You can add instructions here
|
||||
|
||||
[Some link info](https://coder.com)`,
|
||||
created_by_id: "test-creator-id",
|
||||
created_by_name: "test_creator",
|
||||
}
|
||||
|
||||
export const MockTemplate: TypesGen.Template = {
|
||||
|
|
Loading…
Reference in New Issue