feat: add template version creator (#2991)

This commit is contained in:
Abhineet Jain
2022-07-14 13:44:33 -07:00
committed by GitHub
parent 6ef8a625d5
commit aea3b3b83e
14 changed files with 106 additions and 16 deletions

View File

@ -114,12 +114,14 @@ func TestDiff(t *testing.T) {
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
OrganizationID: uuid.UUID{3}, OrganizationID: uuid.UUID{3},
Name: "rust", Name: "rust",
CreatedBy: uuid.UUID{4},
}, },
exp: audit.Map{ exp: audit.Map{
"id": uuid.UUID{1}.String(), "id": uuid.UUID{1}.String(),
"template_id": uuid.UUID{2}.String(), "template_id": uuid.UUID{2}.String(),
"organization_id": uuid.UUID{3}.String(), "organization_id": uuid.UUID{3}.String(),
"name": "rust", "name": "rust",
"created_by": uuid.UUID{4}.String(),
}, },
}, },
{ {
@ -132,11 +134,13 @@ func TestDiff(t *testing.T) {
UpdatedAt: time.Now(), UpdatedAt: time.Now(),
OrganizationID: uuid.UUID{3}, OrganizationID: uuid.UUID{3},
Name: "rust", Name: "rust",
CreatedBy: uuid.UUID{4},
}, },
exp: audit.Map{ exp: audit.Map{
"id": uuid.UUID{1}.String(), "id": uuid.UUID{1}.String(),
"organization_id": uuid.UUID{3}.String(), "organization_id": uuid.UUID{3}.String(),
"name": "rust", "name": "rust",
"created_by": uuid.UUID{4}.String(),
}, },
}, },
}) })

View File

@ -83,6 +83,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
"name": ActionTrack, "name": ActionTrack,
"readme": ActionTrack, "readme": ActionTrack,
"job_id": ActionIgnore, // Not helpful in a diff because jobs aren't tracked in audit logs. "job_id": ActionIgnore, // Not helpful in a diff because jobs aren't tracked in audit logs.
"created_by": ActionTrack,
}, },
&database.User{}: { &database.User{}: {
"id": ActionTrack, "id": ActionTrack,

View File

@ -1511,6 +1511,7 @@ func (q *fakeQuerier) InsertTemplateVersion(_ context.Context, arg database.Inse
Name: arg.Name, Name: arg.Name,
Readme: arg.Readme, Readme: arg.Readme,
JobID: arg.JobID, JobID: arg.JobID,
CreatedBy: arg.CreatedBy,
} }
q.templateVersions = append(q.templateVersions, version) q.templateVersions = append(q.templateVersions, version)
return version, nil return version, nil

View File

@ -247,7 +247,8 @@ CREATE TABLE template_versions (
updated_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL,
name character varying(64) NOT NULL, name character varying(64) NOT NULL,
readme character varying(1048576) NOT NULL, readme character varying(1048576) NOT NULL,
job_id uuid NOT NULL job_id uuid NOT NULL,
created_by uuid NOT NULL
); );
CREATE TABLE templates ( CREATE TABLE templates (
@ -486,6 +487,9 @@ ALTER TABLE ONLY provisioner_job_logs
ALTER TABLE ONLY provisioner_jobs ALTER TABLE ONLY provisioner_jobs
ADD CONSTRAINT provisioner_jobs_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; 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 ALTER TABLE ONLY template_versions
ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE; ADD CONSTRAINT template_versions_organization_id_fkey FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE;

View File

@ -0,0 +1 @@
ALTER TABLE ONLY template_versions DROP COLUMN IF EXISTS created_by;

View File

@ -0,0 +1,14 @@
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;
ALTER TABLE ONLY template_versions ALTER COLUMN created_by SET NOT NULL;

View File

@ -478,6 +478,7 @@ type TemplateVersion struct {
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
Readme string `db:"readme" json:"readme"` Readme string `db:"readme" json:"readme"`
JobID uuid.UUID `db:"job_id" json:"job_id"` JobID uuid.UUID `db:"job_id" json:"job_id"`
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
} }
type User struct { type User struct {

View File

@ -2145,7 +2145,7 @@ func (q *sqlQuerier) UpdateTemplateMetaByID(ctx context.Context, arg UpdateTempl
const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one
SELECT 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 FROM
template_versions template_versions
WHERE WHERE
@ -2164,13 +2164,14 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
&i.Name, &i.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
) )
return i, err return i, err
} }
const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one
SELECT 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 FROM
template_versions template_versions
WHERE WHERE
@ -2189,13 +2190,14 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
&i.Name, &i.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
) )
return i, err return i, err
} }
const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one
SELECT 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 FROM
template_versions template_versions
WHERE WHERE
@ -2220,13 +2222,14 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
&i.Name, &i.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
) )
return i, err return i, err
} }
const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many
SELECT 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 FROM
template_versions template_versions
WHERE WHERE
@ -2289,6 +2292,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
&i.Name, &i.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -2304,7 +2308,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
} }
const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many 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) { 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.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@ -2349,10 +2354,11 @@ INSERT INTO
updated_at, updated_at,
"name", "name",
readme, readme,
job_id job_id,
created_by
) )
VALUES 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 { type InsertTemplateVersionParams struct {
@ -2364,6 +2370,7 @@ type InsertTemplateVersionParams struct {
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
Readme string `db:"readme" json:"readme"` Readme string `db:"readme" json:"readme"`
JobID uuid.UUID `db:"job_id" json:"job_id"` JobID uuid.UUID `db:"job_id" json:"job_id"`
CreatedBy uuid.UUID `db:"created_by" json:"created_by"`
} }
func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTemplateVersionParams) (TemplateVersion, error) { 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.Name,
arg.Readme, arg.Readme,
arg.JobID, arg.JobID,
arg.CreatedBy,
) )
var i TemplateVersion var i TemplateVersion
err := row.Scan( err := row.Scan(
@ -2387,6 +2395,7 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
&i.Name, &i.Name,
&i.Readme, &i.Readme,
&i.JobID, &i.JobID,
&i.CreatedBy,
) )
return i, err return i, err
} }

View File

@ -70,10 +70,11 @@ INSERT INTO
updated_at, updated_at,
"name", "name",
readme, readme,
job_id job_id,
created_by
) )
VALUES VALUES
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *; ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *;
-- name: UpdateTemplateVersionByID :exec -- name: UpdateTemplateVersionByID :exec
UPDATE UPDATE

View File

@ -209,6 +209,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
UUID: dbTemplate.ID, UUID: dbTemplate.ID,
Valid: true, Valid: true,
}, },
UpdatedAt: database.Now(),
}) })
if err != nil { if err != nil {
return xerrors.Errorf("insert template version: %s", err) return xerrors.Errorf("insert template version: %s", err)

View File

@ -1,6 +1,7 @@
package coderd package coderd
import ( import (
"context"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"errors" "errors"
@ -36,7 +37,16 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
return 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) { 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 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 return nil
@ -525,7 +543,16 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
return 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) { func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) {
@ -735,6 +762,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
Name: namesgenerator.GetRandomName(1), Name: namesgenerator.GetRandomName(1),
Readme: "", Readme: "",
JobID: provisionerJob.ID, JobID: provisionerJob.ID,
CreatedBy: apiKey.UserID,
}) })
if err != nil { if err != nil {
return xerrors.Errorf("insert template version: %w", err) return xerrors.Errorf("insert template version: %w", err)
@ -748,7 +776,16 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
return 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 // templateVersionResources returns the workspace agent resources associated
@ -796,7 +833,15 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
api.provisionerJobLogs(rw, r, job) 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.UUID) (string, error) {
user, err := db.GetUserByID(ctx, userID)
if err != nil {
return "", err
}
return user.Username, nil
}
func convertTemplateVersion(version database.TemplateVersion, job codersdk.ProvisionerJob, createdByName string) codersdk.TemplateVersion {
return codersdk.TemplateVersion{ return codersdk.TemplateVersion{
ID: version.ID, ID: version.ID,
TemplateID: &version.TemplateID.UUID, TemplateID: &version.TemplateID.UUID,
@ -806,5 +851,7 @@ func convertTemplateVersion(version database.TemplateVersion, job codersdk.Provi
Name: version.Name, Name: version.Name,
Job: job, Job: job,
Readme: version.Readme, Readme: version.Readme,
CreatedByID: version.CreatedBy,
CreatedByName: createdByName,
} }
} }

View File

@ -20,6 +20,8 @@ type TemplateVersion struct {
Name string `json:"name"` Name string `json:"name"`
Job ProvisionerJob `json:"job"` Job ProvisionerJob `json:"job"`
Readme string `json:"readme"` Readme string `json:"readme"`
CreatedByID uuid.UUID `json:"created_by_id"`
CreatedByName string `json:"created_by_name"`
} }
// TemplateVersion returns a template version by ID. // TemplateVersion returns a template version by ID.

View File

@ -87,7 +87,7 @@ export interface CreateTemplateRequest {
readonly min_autostart_interval_ms?: number readonly min_autostart_interval_ms?: number
} }
// From codersdk/templateversions.go:106:6 // From codersdk/templateversions.go:108:6
export interface CreateTemplateVersionDryRunRequest { export interface CreateTemplateVersionDryRunRequest {
readonly WorkspaceName: string readonly WorkspaceName: string
readonly ParameterValues: CreateParameterRequest[] readonly ParameterValues: CreateParameterRequest[]
@ -290,6 +290,8 @@ export interface TemplateVersion {
readonly name: string readonly name: string
readonly job: ProvisionerJob readonly job: ProvisionerJob
readonly readme: string readonly readme: string
readonly created_by_id: string
readonly created_by_name: string
} }
// From codersdk/templates.go:100:6 // From codersdk/templates.go:100:6

View File

@ -112,6 +112,8 @@ name:Template test
You can add instructions here You can add instructions here
[Some link info](https://coder.com)`, [Some link info](https://coder.com)`,
created_by_id: "test-creator-id",
created_by_name: "test_creator",
} }
export const MockTemplate: TypesGen.Template = { export const MockTemplate: TypesGen.Template = {