mirror of
https://github.com/coder/coder.git
synced 2025-07-08 11:39:50 +00:00
feat(coder): Add PATCH /templateversions/:templateversion endpoint (#6698)
This commit is contained in:
53
coderd/apidoc/docs.go
generated
53
coderd/apidoc/docs.go
generated
@ -2255,6 +2255,51 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Templates"
|
||||
],
|
||||
"summary": "Patch template version by ID",
|
||||
"operationId": "patch-template-version-by-id",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Template version ID",
|
||||
"name": "templateversion",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Patch template version request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.PatchTemplateVersionRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TemplateVersion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/templateversions/{templateversion}/cancel": {
|
||||
@ -7400,6 +7445,14 @@ const docTemplate = `{
|
||||
"ParameterSourceSchemeData"
|
||||
]
|
||||
},
|
||||
"codersdk.PatchTemplateVersionRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.PprofConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
47
coderd/apidoc/swagger.json
generated
47
coderd/apidoc/swagger.json
generated
@ -1971,6 +1971,45 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"consumes": ["application/json"],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Templates"],
|
||||
"summary": "Patch template version by ID",
|
||||
"operationId": "patch-template-version-by-id",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Template version ID",
|
||||
"name": "templateversion",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"description": "Patch template version request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.PatchTemplateVersionRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/codersdk.TemplateVersion"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/templateversions/{templateversion}/cancel": {
|
||||
@ -6620,6 +6659,14 @@
|
||||
"ParameterSourceSchemeData"
|
||||
]
|
||||
},
|
||||
"codersdk.PatchTemplateVersionRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.PprofConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -500,6 +500,7 @@ func New(options *Options) *API {
|
||||
httpmw.ExtractTemplateVersionParam(options.Database),
|
||||
)
|
||||
r.Get("/", api.templateVersion)
|
||||
r.Patch("/", api.patchTemplateVersion)
|
||||
r.Patch("/cancel", api.patchCancelTemplateVersion)
|
||||
r.Get("/schema", api.templateVersionSchema)
|
||||
r.Get("/parameters", api.templateVersionParameters)
|
||||
|
@ -850,13 +850,13 @@ func (q *querier) UpdateTemplateScheduleByID(ctx context.Context, arg database.U
|
||||
return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateTemplateScheduleByID)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpdateTemplateVersionByID(ctx context.Context, arg database.UpdateTemplateVersionByIDParams) error {
|
||||
func (q *querier) UpdateTemplateVersionByID(ctx context.Context, arg database.UpdateTemplateVersionByIDParams) (database.TemplateVersion, error) {
|
||||
template, err := q.db.GetTemplateByID(ctx, arg.TemplateID.UUID)
|
||||
if err != nil {
|
||||
return err
|
||||
return database.TemplateVersion{}, err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, rbac.ActionUpdate, template); err != nil {
|
||||
return err
|
||||
return database.TemplateVersion{}, err
|
||||
}
|
||||
return q.db.UpdateTemplateVersionByID(ctx, arg)
|
||||
}
|
||||
|
@ -721,7 +721,9 @@ func (s *MethodTestSuite) TestTemplate() {
|
||||
check.Args(database.UpdateTemplateVersionByIDParams{
|
||||
ID: tv.ID,
|
||||
TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true},
|
||||
}).Asserts(t1, rbac.ActionUpdate).Returns()
|
||||
Name: tv.Name,
|
||||
UpdatedAt: tv.UpdatedAt,
|
||||
}).Asserts(t1, rbac.ActionUpdate).Returns(tv)
|
||||
}))
|
||||
s.Run("UpdateTemplateVersionDescriptionByJobID", s.Subtest(func(db database.Store, check *expects) {
|
||||
jobID := uuid.New()
|
||||
|
@ -3413,9 +3413,9 @@ func (q *fakeQuerier) UpdateTemplateACLByID(_ context.Context, arg database.Upda
|
||||
return database.Template{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateTemplateVersionByID(_ context.Context, arg database.UpdateTemplateVersionByIDParams) error {
|
||||
func (q *fakeQuerier) UpdateTemplateVersionByID(_ context.Context, arg database.UpdateTemplateVersionByIDParams) (database.TemplateVersion, error) {
|
||||
if err := validateDatabaseType(arg); err != nil {
|
||||
return err
|
||||
return database.TemplateVersion{}, err
|
||||
}
|
||||
|
||||
q.mutex.Lock()
|
||||
@ -3427,10 +3427,11 @@ func (q *fakeQuerier) UpdateTemplateVersionByID(_ context.Context, arg database.
|
||||
}
|
||||
templateVersion.TemplateID = arg.TemplateID
|
||||
templateVersion.UpdatedAt = arg.UpdatedAt
|
||||
templateVersion.Name = arg.Name
|
||||
q.templateVersions[index] = templateVersion
|
||||
return nil
|
||||
return templateVersion, nil
|
||||
}
|
||||
return sql.ErrNoRows
|
||||
return database.TemplateVersion{}, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (q *fakeQuerier) UpdateTemplateVersionDescriptionByJobID(_ context.Context, arg database.UpdateTemplateVersionDescriptionByJobIDParams) error {
|
||||
|
@ -210,7 +210,7 @@ type sqlcQuerier interface {
|
||||
UpdateTemplateDeletedByID(ctx context.Context, arg UpdateTemplateDeletedByIDParams) error
|
||||
UpdateTemplateMetaByID(ctx context.Context, arg UpdateTemplateMetaByIDParams) (Template, error)
|
||||
UpdateTemplateScheduleByID(ctx context.Context, arg UpdateTemplateScheduleByIDParams) (Template, error)
|
||||
UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) error
|
||||
UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) (TemplateVersion, error)
|
||||
UpdateTemplateVersionDescriptionByJobID(ctx context.Context, arg UpdateTemplateVersionDescriptionByJobIDParams) error
|
||||
UpdateTemplateVersionGitAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionGitAuthProvidersByJobIDParams) error
|
||||
UpdateUserDeletedByID(ctx context.Context, arg UpdateUserDeletedByIDParams) error
|
||||
|
@ -4095,25 +4095,45 @@ func (q *sqlQuerier) InsertTemplateVersion(ctx context.Context, arg InsertTempla
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateTemplateVersionByID = `-- name: UpdateTemplateVersionByID :exec
|
||||
const updateTemplateVersionByID = `-- name: UpdateTemplateVersionByID :one
|
||||
UPDATE
|
||||
template_versions
|
||||
SET
|
||||
template_id = $2,
|
||||
updated_at = $3
|
||||
updated_at = $3,
|
||||
name = $4
|
||||
WHERE
|
||||
id = $1
|
||||
id = $1 RETURNING id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, git_auth_providers
|
||||
`
|
||||
|
||||
type UpdateTemplateVersionByIDParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
TemplateID uuid.NullUUID `db:"template_id" json:"template_id"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
|
||||
Name string `db:"name" json:"name"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) error {
|
||||
_, err := q.db.ExecContext(ctx, updateTemplateVersionByID, arg.ID, arg.TemplateID, arg.UpdatedAt)
|
||||
return err
|
||||
func (q *sqlQuerier) UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) (TemplateVersion, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateTemplateVersionByID,
|
||||
arg.ID,
|
||||
arg.TemplateID,
|
||||
arg.UpdatedAt,
|
||||
arg.Name,
|
||||
)
|
||||
var i TemplateVersion
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.TemplateID,
|
||||
&i.OrganizationID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.Name,
|
||||
&i.Readme,
|
||||
&i.JobID,
|
||||
&i.CreatedBy,
|
||||
pq.Array(&i.GitAuthProviders),
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateTemplateVersionDescriptionByJobID = `-- name: UpdateTemplateVersionDescriptionByJobID :exec
|
||||
|
@ -84,14 +84,15 @@ INSERT INTO
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateVersionByID :exec
|
||||
-- name: UpdateTemplateVersionByID :one
|
||||
UPDATE
|
||||
template_versions
|
||||
SET
|
||||
template_id = $2,
|
||||
updated_at = $3
|
||||
updated_at = $3,
|
||||
name = $4
|
||||
WHERE
|
||||
id = $1;
|
||||
id = $1 RETURNING *;
|
||||
|
||||
-- name: UpdateTemplateVersionDescriptionByJobID :exec
|
||||
UPDATE
|
||||
|
@ -269,13 +269,14 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
|
||||
|
||||
templateAudit.New = dbTemplate
|
||||
|
||||
err = tx.UpdateTemplateVersionByID(ctx, database.UpdateTemplateVersionByIDParams{
|
||||
_, err = tx.UpdateTemplateVersionByID(ctx, database.UpdateTemplateVersionByIDParams{
|
||||
ID: templateVersion.ID,
|
||||
TemplateID: uuid.NullUUID{
|
||||
UUID: dbTemplate.ID,
|
||||
Valid: true,
|
||||
},
|
||||
UpdatedAt: database.Now(),
|
||||
Name: templateVersion.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return xerrors.Errorf("insert template version: %s", err)
|
||||
|
@ -63,6 +63,66 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job), user))
|
||||
}
|
||||
|
||||
// @Summary Patch template version by ID
|
||||
// @ID patch-template-version-by-id
|
||||
// @Security CoderSessionToken
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Tags Templates
|
||||
// @Param templateversion path string true "Template version ID" format(uuid)
|
||||
// @Param request body codersdk.PatchTemplateVersionRequest true "Patch template version request"
|
||||
// @Success 200 {object} codersdk.TemplateVersion
|
||||
// @Router /templateversions/{templateversion} [patch]
|
||||
func (api *API) patchTemplateVersion(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
templateVersion := httpmw.TemplateVersionParam(r)
|
||||
|
||||
var params codersdk.PatchTemplateVersionRequest
|
||||
if !httpapi.Read(ctx, rw, r, ¶ms) {
|
||||
return
|
||||
}
|
||||
|
||||
updateParams := database.UpdateTemplateVersionByIDParams{
|
||||
ID: templateVersion.ID,
|
||||
TemplateID: templateVersion.TemplateID,
|
||||
UpdatedAt: database.Now(),
|
||||
Name: templateVersion.Name,
|
||||
}
|
||||
|
||||
if params.Name != "" {
|
||||
updateParams.Name = params.Name
|
||||
}
|
||||
// It is not allowed to "patch" the template ID, and reassign it.
|
||||
updatedTemplateVersion, err := api.Database.UpdateTemplateVersionByID(ctx, updateParams)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Error on patching template version.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
job, err := api.Database.GetProvisionerJobByID(ctx, templateVersion.JobID)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching provisioner job.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
user, err := api.Database.GetUserByID(ctx, templateVersion.CreatedBy)
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error on fetching user.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, convertTemplateVersion(updatedTemplateVersion, convertProvisionerJob(job), user))
|
||||
}
|
||||
|
||||
// @Summary Cancel template version by ID
|
||||
// @ID cancel-template-version-by-id
|
||||
// @Security CoderSessionToken
|
||||
|
@ -1334,3 +1334,68 @@ func TestTemplateVersionVariables(t *testing.T) {
|
||||
require.Equal(t, "*redacted*", actualVariables[0].Value)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTemplateVersionPatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("Update the name", 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)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
const newName = "new_name"
|
||||
updatedVersion, err := client.UpdateTemplateVersion(ctx, version.ID, codersdk.PatchTemplateVersionRequest{
|
||||
Name: newName,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, newName, updatedVersion.Name)
|
||||
assert.NotEqual(t, updatedVersion.Name, version.Name)
|
||||
})
|
||||
|
||||
t.Run("Use the same name if a new name is not passed", 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)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
updatedVersion, err := client.UpdateTemplateVersion(ctx, version.ID, codersdk.PatchTemplateVersionRequest{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, version.Name, updatedVersion.Name)
|
||||
})
|
||||
|
||||
t.Run("Use the same name for two different templates", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, nil)
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID)
|
||||
version2 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
coderdtest.CreateTemplate(t, client, user.OrganizationID, version2.ID)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
const commonTemplateVersionName = "common-template-version-name"
|
||||
updatedVersion1, err := client.UpdateTemplateVersion(ctx, version1.ID, codersdk.PatchTemplateVersionRequest{
|
||||
Name: commonTemplateVersionName,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updatedVersion2, err := client.UpdateTemplateVersion(ctx, version2.ID, codersdk.PatchTemplateVersionRequest{
|
||||
Name: commonTemplateVersionName,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotEqual(t, updatedVersion1.ID, updatedVersion2.ID)
|
||||
assert.Equal(t, updatedVersion1.Name, updatedVersion2.Name)
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user