From fec05fc0838a7fd0c9bfac1afff6fcb762876a1b Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 12:59:09 -0500 Subject: [PATCH 1/6] feat: add template description --- coderd/coderd.go | 2 +- coderd/coderdtest/coderdtest.go | 5 +++-- coderd/database/databasefake/databasefake.go | 1 + coderd/database/dump.sql | 3 ++- .../000011_template_description.down.sql | 1 + .../000011_template_description.up.sql | 1 + coderd/database/models.go | 1 + coderd/database/queries.sql.go | 20 +++++++++++++------ coderd/database/queries/templates.sql | 5 +++-- coderd/templates.go | 6 ++++-- coderd/templates_test.go | 12 +++++++++-- codersdk/organizations.go | 12 +++++++---- codersdk/templates.go | 1 + site/src/api/typesGenerated.ts | 8 +++++--- 14 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 coderd/database/migrations/000011_template_description.down.sql create mode 100644 coderd/database/migrations/000011_template_description.up.sql diff --git a/coderd/coderd.go b/coderd/coderd.go index 4d394cb9362ae..95c945bd2267c 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -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) }) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 75f49cea88380..789caf11c1cfd 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -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 diff --git a/coderd/database/databasefake/databasefake.go b/coderd/database/databasefake/databasefake.go index ae24c55cb8111..8455f522cc605 100644 --- a/coderd/database/databasefake/databasefake.go +++ b/coderd/database/databasefake/databasefake.go @@ -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 diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 46cfc646e8158..050a013ab3387 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -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(8192) DEFAULT ''::character varying NOT NULL ); CREATE TABLE users ( diff --git a/coderd/database/migrations/000011_template_description.down.sql b/coderd/database/migrations/000011_template_description.down.sql new file mode 100644 index 0000000000000..993c3de2bc167 --- /dev/null +++ b/coderd/database/migrations/000011_template_description.down.sql @@ -0,0 +1 @@ +ALTER TABLE templates DROP COLUMN description; diff --git a/coderd/database/migrations/000011_template_description.up.sql b/coderd/database/migrations/000011_template_description.up.sql new file mode 100644 index 0000000000000..c5dbfc87053bf --- /dev/null +++ b/coderd/database/migrations/000011_template_description.up.sql @@ -0,0 +1 @@ +ALTER TABLE templates ADD COLUMN description VARCHAR(8192) NOT NULL DEFAULT ''; diff --git a/coderd/database/models.go b/coderd/database/models.go index ad7277e32cbbe..1fc101a16ee1a 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -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 { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 7a4bea7c29148..946668cafe8d6 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -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 } diff --git a/coderd/database/queries/templates.sql b/coderd/database/queries/templates.sql index 465abf88d8a98..133d3b4c47e5c 100644 --- a/coderd/database/queries/templates.sql +++ b/coderd/database/queries/templates.sql @@ -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 diff --git a/coderd/templates.go b/coderd/templates.go index 89350c38c8f0c..4d719e3d85b25 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -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, } } diff --git a/coderd/templates_test.go b/coderd/templates_test.go index 425635f9b216c..1b204ed738f34 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -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) { diff --git a/codersdk/organizations.go b/codersdk/organizations.go index ca85dfbbc139e..cdd61d451dbc5 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -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 8192 bytes. + Description string `json:"description" validate:"lt=8192"` - // 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"` } diff --git a/codersdk/templates.go b/codersdk/templates.go index d1f3361c85671..14a14ed976650 100644 --- a/codersdk/templates.go +++ b/codersdk/templates.go @@ -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 { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 7f75b8968723c..ad71c4643bdf1 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -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 } From 0bc518ae280c171029e82c04078ab4cf509d117a Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 15:22:58 -0500 Subject: [PATCH 2/6] description < 128b --- coderd/audit/table.go | 1 + coderd/database/migrations/000011_template_description.up.sql | 2 +- codersdk/organizations.go | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/coderd/audit/table.go b/coderd/audit/table.go index 267988f2cd66c..1556d9d3a3909 100644 --- a/coderd/audit/table.go +++ b/coderd/audit/table.go @@ -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, diff --git a/coderd/database/migrations/000011_template_description.up.sql b/coderd/database/migrations/000011_template_description.up.sql index c5dbfc87053bf..a5e4466b91f92 100644 --- a/coderd/database/migrations/000011_template_description.up.sql +++ b/coderd/database/migrations/000011_template_description.up.sql @@ -1 +1 @@ -ALTER TABLE templates ADD COLUMN description VARCHAR(8192) NOT NULL DEFAULT ''; +ALTER TABLE templates ADD COLUMN description VARCHAR(128) NOT NULL DEFAULT ''; diff --git a/codersdk/organizations.go b/codersdk/organizations.go index cdd61d451dbc5..00dbbcaa0e0e2 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -40,7 +40,7 @@ type CreateTemplateRequest struct { Name string `json:"name" validate:"username,required"` // Description is a description of what the template contains. It must be // less than 8192 bytes. - Description string `json:"description" validate:"lt=8192"` + Description string `json:"description" validate:"lt=128"` // VersionID is an in-progress or completed job to use as an initial version // of the template. From 40b4d4a8b5f39ed8a25f4ac590ed0ceadc7b9d36 Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 15:23:25 -0500 Subject: [PATCH 3/6] fixup! description < 128b --- codersdk/organizations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 00dbbcaa0e0e2..734579aba7dde 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -39,7 +39,7 @@ 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 8192 bytes. + // less than 128 bytes. Description string `json:"description" validate:"lt=128"` // VersionID is an in-progress or completed job to use as an initial version From fc2ad7b852a048e9abb369d1434510fb8347f49c Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 15:27:31 -0500 Subject: [PATCH 4/6] fixup! description < 128b --- coderd/database/dump.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index 050a013ab3387..89ca22acab100 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -247,7 +247,7 @@ CREATE TABLE templates ( name character varying(64) NOT NULL, provisioner provisioner_type NOT NULL, active_version_id uuid NOT NULL, - description character varying(8192) DEFAULT ''::character varying NOT NULL + description character varying(128) DEFAULT ''::character varying NOT NULL ); CREATE TABLE users ( From bde9117e8990a1bfe66b4fad8945a18bba9c402b Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 15:37:49 -0500 Subject: [PATCH 5/6] fix js tests --- site/src/testHelpers/entities.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 8bedba4d6d767..36e989e494b5c 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -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 = { From 73186a73a7c9b332a12a24567660942d209be94e Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 16 May 2022 15:45:52 -0500 Subject: [PATCH 6/6] optional template description on create --- codersdk/organizations.go | 2 +- site/src/api/typesGenerated.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 734579aba7dde..8a1e7d367baa0 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -40,7 +40,7 @@ type CreateTemplateRequest struct { 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" validate:"lt=128"` + 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. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index ad71c4643bdf1..846dae8d608c4 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -62,7 +62,7 @@ export interface CreateParameterRequest { // From codersdk/organizations.go:38:6 export interface CreateTemplateRequest { readonly name: string - readonly description: string + readonly description?: string readonly template_version_id: string readonly parameter_values?: CreateParameterRequest[] }