Skip to content

Commit 938f256

Browse files
committed
Add unarchive
1 parent d4e54b2 commit 938f256

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

coderd/coderd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ func New(options *Options) *API {
685685
r.Get("/", api.templateVersion)
686686
r.Patch("/", api.patchTemplateVersion)
687687
r.Patch("/cancel", api.patchCancelTemplateVersion)
688+
r.Post("/archive", api.postArchiveTemplateVersion())
689+
r.Post("/unarchive", api.postUnarchiveTemplateVersion())
688690
// Old agents may expect a non-error response from /schema and /parameters endpoints.
689691
// The idea is to return an empty [], so that the coder CLI won't get blocked accidentally.
690692
r.Get("/schema", templateVersionSchemaDeprecated)

coderd/templateversions.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,91 @@ func (api *API) postArchiveTemplateVersions(rw http.ResponseWriter, r *http.Requ
10761076
})
10771077
}
10781078

1079+
// @Summary Archive template version
1080+
// @ID archive-template-version
1081+
// @Security CoderSessionToken
1082+
// @Accept json
1083+
// @Tags Templates
1084+
// @Param templateversion path string true "Template version ID" format(uuid)
1085+
// @Success 200 {object} codersdk.Response
1086+
// @Router /templateversions/{templateversion}/archive [post]
1087+
func (api *API) postArchiveTemplateVersion() func(rw http.ResponseWriter, r *http.Request) {
1088+
return api.setArchiveTemplateVersion(true)
1089+
}
1090+
1091+
// @Summary Unarchive template version
1092+
// @ID unarchive-template-version
1093+
// @Security CoderSessionToken
1094+
// @Accept json
1095+
// @Tags Templates
1096+
// @Param templateversion path string true "Template version ID" format(uuid)
1097+
// @Success 200 {object} codersdk.Response
1098+
// @Router /templateversions/{templateversion}/unarchive [post]
1099+
func (api *API) postUnarchiveTemplateVersion() func(rw http.ResponseWriter, r *http.Request) {
1100+
return api.setArchiveTemplateVersion(false)
1101+
}
1102+
1103+
func (api *API) setArchiveTemplateVersion(archive bool) func(rw http.ResponseWriter, r *http.Request) {
1104+
return func(rw http.ResponseWriter, r *http.Request) {
1105+
var (
1106+
ctx = r.Context()
1107+
templateVersion = httpmw.TemplateVersionParam(r)
1108+
auditor = *api.Auditor.Load()
1109+
aReq, commitAudit = audit.InitRequest[database.TemplateVersion](rw, &audit.RequestParams{
1110+
Audit: auditor,
1111+
Log: api.Logger,
1112+
Request: r,
1113+
Action: database.AuditActionWrite,
1114+
})
1115+
)
1116+
defer commitAudit()
1117+
aReq.Old = templateVersion
1118+
1119+
verb := "archived"
1120+
if !archive {
1121+
verb = "unarchived"
1122+
}
1123+
if templateVersion.Archived == archive {
1124+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
1125+
Message: fmt.Sprintf("Template version already %s", verb),
1126+
})
1127+
return
1128+
}
1129+
1130+
if !templateVersion.TemplateID.Valid {
1131+
// Maybe we should allow this?
1132+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
1133+
Message: "Cannot archive template versions not associate with a template.",
1134+
})
1135+
return
1136+
}
1137+
1138+
archived, err := api.Database.ArchiveUnusedTemplateVersions(ctx, database.ArchiveUnusedTemplateVersionsParams{
1139+
UpdatedAt: dbtime.Now(),
1140+
TemplateID: templateVersion.TemplateID.UUID,
1141+
TemplateVersionID: templateVersion.ID,
1142+
JobStatus: database.NullProvisionerJobStatus{},
1143+
Unarchive: !archive,
1144+
})
1145+
1146+
if httpapi.Is404Error(err) || (len(archived) == 0 && err == nil) {
1147+
httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{
1148+
Message: "Template or template versions not found.",
1149+
})
1150+
return
1151+
}
1152+
if err != nil {
1153+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
1154+
Message: "Internal error fetching template version.",
1155+
Detail: err.Error(),
1156+
})
1157+
return
1158+
}
1159+
1160+
httpapi.Write(ctx, rw, http.StatusOK, fmt.Sprintf("template version %q %s", templateVersion.ID.String(), verb))
1161+
}
1162+
}
1163+
10791164
// @Summary Update active template version by template ID
10801165
// @ID update-active-template-version-by-template-id
10811166
// @Security CoderSessionToken

coderd/templateversions_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,4 +1610,22 @@ func TestTemplateArchiveVersions(t *testing.T) {
16101610
})
16111611
require.NoError(t, err, "fetch all versions")
16121612
require.Len(t, remaining, totalVersions-len(expArchived)-len(allFailed), "remaining versions")
1613+
1614+
// Unarchive a version
1615+
err = client.SetArchiveTemplateVersion(ctx, expArchived[0], false)
1616+
require.NoError(t, err, "unarchive a version")
1617+
1618+
tv, err := client.TemplateVersion(ctx, expArchived[0])
1619+
require.NoError(t, err, "fetch version")
1620+
require.False(t, tv.Archived, "expect unarchived")
1621+
1622+
// Check the remaining again
1623+
remaining, err = client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
1624+
TemplateID: template.ID,
1625+
Pagination: codersdk.Pagination{
1626+
Limit: 100,
1627+
},
1628+
})
1629+
require.NoError(t, err, "fetch all versions")
1630+
require.Len(t, remaining, totalVersions-len(expArchived)-len(allFailed)+1, "remaining versions")
16131631
}

codersdk/templates.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ func (c *Client) ArchiveTemplateVersions(ctx context.Context, template uuid.UUID
256256
return resp, json.NewDecoder(res.Body).Decode(&resp)
257257
}
258258

259+
func (c *Client) SetArchiveTemplateVersion(ctx context.Context, templateVersion uuid.UUID, archive bool) error {
260+
u := fmt.Sprintf("/api/v2/templateversions/%s", templateVersion.String())
261+
if archive {
262+
u += "/archive"
263+
} else {
264+
u += "/unarchive"
265+
}
266+
res, err := c.Request(ctx, http.MethodPost, u, nil)
267+
if err != nil {
268+
return err
269+
}
270+
defer res.Body.Close()
271+
if res.StatusCode != http.StatusOK {
272+
return ReadBodyAsError(res)
273+
}
274+
275+
return nil
276+
}
277+
259278
func (c *Client) DeleteTemplate(ctx context.Context, template uuid.UUID) error {
260279
res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/templates/%s", template), nil)
261280
if err != nil {

0 commit comments

Comments
 (0)