mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
feat: add template description (#1489)
This commit is contained in:
@@ -69,6 +69,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
|
||||
"name": ActionTrack,
|
||||
"provisioner": ActionTrack,
|
||||
"active_version_id": ActionTrack,
|
||||
"description": ActionTrack,
|
||||
},
|
||||
&database.TemplateVersion{}: {
|
||||
"id": ActionTrack,
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@ func New(options *Options) (http.Handler, func()) {
|
||||
r.Get("/provisionerdaemons", api.provisionerDaemonsByOrganization)
|
||||
r.Post("/templateversions", api.postTemplateVersionsByOrganization)
|
||||
r.Route("/templates", func(r chi.Router) {
|
||||
r.Post("/", api.postTemplatesByOrganization)
|
||||
r.Post("/", api.postTemplateByOrganization)
|
||||
r.Get("/", api.templatesByOrganization)
|
||||
r.Get("/{templatename}", api.templateByOrganizationAndName)
|
||||
})
|
||||
|
||||
@@ -291,8 +291,9 @@ func CreateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID
|
||||
// compatibility with testing. The name assigned is randomly generated.
|
||||
func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUID, version uuid.UUID) codersdk.Template {
|
||||
template, err := client.CreateTemplate(context.Background(), organization, codersdk.CreateTemplateRequest{
|
||||
Name: randomUsername(),
|
||||
VersionID: version,
|
||||
Name: randomUsername(),
|
||||
Description: randomUsername(),
|
||||
VersionID: version,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
return template
|
||||
|
||||
@@ -1171,6 +1171,7 @@ func (q *fakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl
|
||||
Name: arg.Name,
|
||||
Provisioner: arg.Provisioner,
|
||||
ActiveVersionID: arg.ActiveVersionID,
|
||||
Description: arg.Description,
|
||||
}
|
||||
q.templates = append(q.templates, template)
|
||||
return template, nil
|
||||
|
||||
Generated
+2
-1
@@ -246,7 +246,8 @@ CREATE TABLE templates (
|
||||
deleted boolean DEFAULT false NOT NULL,
|
||||
name character varying(64) NOT NULL,
|
||||
provisioner provisioner_type NOT NULL,
|
||||
active_version_id uuid NOT NULL
|
||||
active_version_id uuid NOT NULL,
|
||||
description character varying(128) DEFAULT ''::character varying NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE users (
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE templates DROP COLUMN description;
|
||||
@@ -0,0 +1 @@
|
||||
ALTER TABLE templates ADD COLUMN description VARCHAR(128) NOT NULL DEFAULT '';
|
||||
@@ -436,6 +436,7 @@ type Template struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
Description string `db:"description" json:"description"`
|
||||
}
|
||||
|
||||
type TemplateVersion struct {
|
||||
|
||||
@@ -1585,7 +1585,7 @@ func (q *sqlQuerier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, a
|
||||
|
||||
const getTemplateByID = `-- name: GetTemplateByID :one
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@@ -1606,13 +1606,14 @@ func (q *sqlQuerier) GetTemplateByID(ctx context.Context, id uuid.UUID) (Templat
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplateByOrganizationAndName = `-- name: GetTemplateByOrganizationAndName :one
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@@ -1641,13 +1642,14 @@ func (q *sqlQuerier) GetTemplateByOrganizationAndName(ctx context.Context, arg G
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTemplatesByIDs = `-- name: GetTemplatesByIDs :many
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@@ -1672,6 +1674,7 @@ func (q *sqlQuerier) GetTemplatesByIDs(ctx context.Context, ids []uuid.UUID) ([]
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1688,7 +1691,7 @@ func (q *sqlQuerier) GetTemplatesByIDs(ctx context.Context, ids []uuid.UUID) ([]
|
||||
|
||||
const getTemplatesByOrganization = `-- name: GetTemplatesByOrganization :many
|
||||
SELECT
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id
|
||||
id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description
|
||||
FROM
|
||||
templates
|
||||
WHERE
|
||||
@@ -1719,6 +1722,7 @@ func (q *sqlQuerier) GetTemplatesByOrganization(ctx context.Context, arg GetTemp
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1742,10 +1746,11 @@ INSERT INTO
|
||||
organization_id,
|
||||
"name",
|
||||
provisioner,
|
||||
active_version_id
|
||||
active_version_id,
|
||||
description
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7) RETURNING id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING id, created_at, updated_at, organization_id, deleted, name, provisioner, active_version_id, description
|
||||
`
|
||||
|
||||
type InsertTemplateParams struct {
|
||||
@@ -1756,6 +1761,7 @@ type InsertTemplateParams struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Provisioner ProvisionerType `db:"provisioner" json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `db:"active_version_id" json:"active_version_id"`
|
||||
Description string `db:"description" json:"description"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error) {
|
||||
@@ -1767,6 +1773,7 @@ func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParam
|
||||
arg.Name,
|
||||
arg.Provisioner,
|
||||
arg.ActiveVersionID,
|
||||
arg.Description,
|
||||
)
|
||||
var i Template
|
||||
err := row.Scan(
|
||||
@@ -1778,6 +1785,7 @@ func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParam
|
||||
&i.Name,
|
||||
&i.Provisioner,
|
||||
&i.ActiveVersionID,
|
||||
&i.Description,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -46,10 +46,11 @@ INSERT INTO
|
||||
organization_id,
|
||||
"name",
|
||||
provisioner,
|
||||
active_version_id
|
||||
active_version_id,
|
||||
description
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateActiveVersionByID :exec
|
||||
UPDATE
|
||||
|
||||
+4
-2
@@ -75,7 +75,7 @@ func (api *api) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Create a new template in an organization.
|
||||
func (api *api) postTemplatesByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
func (api *api) postTemplateByOrganization(rw http.ResponseWriter, r *http.Request) {
|
||||
var createTemplate codersdk.CreateTemplateRequest
|
||||
if !httpapi.Read(rw, r, &createTemplate) {
|
||||
return
|
||||
@@ -90,7 +90,7 @@ func (api *api) postTemplatesByOrganization(rw http.ResponseWriter, r *http.Requ
|
||||
Message: fmt.Sprintf("template %q already exists", createTemplate.Name),
|
||||
Errors: []httpapi.Error{{
|
||||
Field: "name",
|
||||
Detail: "this value is already in use and should be unique",
|
||||
Detail: "This value is already in use and should be unique.",
|
||||
}},
|
||||
})
|
||||
return
|
||||
@@ -133,6 +133,7 @@ func (api *api) postTemplatesByOrganization(rw http.ResponseWriter, r *http.Requ
|
||||
Name: createTemplate.Name,
|
||||
Provisioner: importJob.Provisioner,
|
||||
ActiveVersionID: templateVersion.ID,
|
||||
Description: createTemplate.Description,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert template: %s", err)
|
||||
@@ -280,5 +281,6 @@ func convertTemplate(template database.Template, workspaceOwnerCount uint32) cod
|
||||
Provisioner: template.Provisioner,
|
||||
ActiveVersionID: template.ActiveVersionID,
|
||||
WorkspaceOwnerCount: workspaceOwnerCount,
|
||||
Description: template.Description,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/coderd/coderdtest"
|
||||
@@ -26,14 +27,21 @@ func TestTemplate(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPostTemplatesByOrganization(t *testing.T) {
|
||||
func TestPostTemplateByOrganization(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Create", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
expected := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
|
||||
got, err := client.Template(context.Background(), expected.ID)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, expected.Name, got.Name)
|
||||
assert.Equal(t, expected.Description, got.Description)
|
||||
})
|
||||
|
||||
t.Run("AlreadyExists", func(t *testing.T) {
|
||||
|
||||
@@ -36,14 +36,18 @@ type CreateTemplateVersionRequest struct {
|
||||
|
||||
// CreateTemplateRequest provides options when creating a template.
|
||||
type CreateTemplateRequest struct {
|
||||
// Name is the name of the template.
|
||||
Name string `json:"name" validate:"username,required"`
|
||||
// Description is a description of what the template contains. It must be
|
||||
// less than 128 bytes.
|
||||
Description string `json:"description,omitempty" validate:"lt=128"`
|
||||
|
||||
// VersionID is an in-progress or completed job to use as
|
||||
// an initial version of the template.
|
||||
// VersionID is an in-progress or completed job to use as an initial version
|
||||
// of the template.
|
||||
//
|
||||
// This is required on creation to enable a user-flow of validating a
|
||||
// template works. There is no reason the data-model cannot support
|
||||
// empty templates, but it doesn't make sense for users.
|
||||
// template works. There is no reason the data-model cannot support empty
|
||||
// templates, but it doesn't make sense for users.
|
||||
VersionID uuid.UUID `json:"template_version_id" validate:"required"`
|
||||
ParameterValues []CreateParameterRequest `json:"parameter_values,omitempty"`
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type Template struct {
|
||||
Provisioner database.ProvisionerType `json:"provisioner"`
|
||||
ActiveVersionID uuid.UUID `json:"active_version_id"`
|
||||
WorkspaceOwnerCount uint32 `json:"workspace_owner_count"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type UpdateActiveTemplateVersion struct {
|
||||
|
||||
@@ -62,6 +62,7 @@ export interface CreateParameterRequest {
|
||||
// From codersdk/organizations.go:38:6
|
||||
export interface CreateTemplateRequest {
|
||||
readonly name: string
|
||||
readonly description?: string
|
||||
readonly template_version_id: string
|
||||
readonly parameter_values?: CreateParameterRequest[]
|
||||
}
|
||||
@@ -94,7 +95,7 @@ export interface CreateWorkspaceBuildRequest {
|
||||
readonly state?: string
|
||||
}
|
||||
|
||||
// From codersdk/organizations.go:52:6
|
||||
// From codersdk/organizations.go:56:6
|
||||
export interface CreateWorkspaceRequest {
|
||||
readonly template_id: string
|
||||
readonly name: string
|
||||
@@ -219,6 +220,7 @@ export interface Template {
|
||||
readonly provisioner: string
|
||||
readonly active_version_id: string
|
||||
readonly workspace_owner_count: number
|
||||
readonly description: string
|
||||
}
|
||||
|
||||
// From codersdk/templateversions.go:17:6
|
||||
@@ -263,12 +265,12 @@ export interface TemplateVersionParameterSchema {
|
||||
readonly validation_value_type: string
|
||||
}
|
||||
|
||||
// From codersdk/templates.go:74:6
|
||||
// From codersdk/templates.go:75:6
|
||||
export interface TemplateVersionsByTemplateRequest extends Pagination {
|
||||
readonly template_id: string
|
||||
}
|
||||
|
||||
// From codersdk/templates.go:28:6
|
||||
// From codersdk/templates.go:29:6
|
||||
export interface UpdateActiveTemplateVersion {
|
||||
readonly id: string
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ export const MockTemplate: TypesGen.Template = {
|
||||
provisioner: MockProvisioner.id,
|
||||
active_version_id: "",
|
||||
workspace_owner_count: 1,
|
||||
description: "This is a test description.",
|
||||
}
|
||||
|
||||
export const MockWorkspaceAutostartDisabled: TypesGen.UpdateWorkspaceAutostartRequest = {
|
||||
|
||||
Reference in New Issue
Block a user