diff --git a/internal/daemon/api_workshops.go b/internal/daemon/api_workshops.go index ca8fe1aea..12947771c 100644 --- a/internal/daemon/api_workshops.go +++ b/internal/daemon/api_workshops.go @@ -662,7 +662,9 @@ func v1PostProjectWorkshop(c *Command, r *http.Request, _ *userState) Response { return changeConflictErrorResponse(changeConflictErr) case errors.Is(err, conflict.ErrorNoWaitingChange): return noWaitingChangeResponse(err) - case err != nil: + case errors.Is(err, workshop.ErrWorkshopNotLaunched): + return statusNotFound("%w", err) + default: return statusBadRequest("%w", err) } diff --git a/internal/daemon/api_workshops_test.go b/internal/daemon/api_workshops_test.go index 4954d9905..028b3bbbd 100644 --- a/internal/daemon/api_workshops_test.go +++ b/internal/daemon/api_workshops_test.go @@ -4330,8 +4330,8 @@ func (s *apiSuite) TestValidateIncorrectActionModeInputs(c *check.C) { }, { cmd: "remove", result: map[string]string{ - "": `cannot remove "basic": workshop not launched`, - "transactional": `cannot remove "basic": workshop not launched`, + "": `cannot remove "basic": workshop already removed`, + "transactional": `cannot remove "basic": workshop already removed`, "wait-on-error": `cannot remove: mode "wait-on-error" is not valid with the "remove" command`, "continue": `cannot remove: mode "continue" is not valid with the "remove" command`, "abort": `cannot remove: mode "abort" is not valid with the "remove" command`, @@ -4353,6 +4353,9 @@ func (s *apiSuite) TestValidateIncorrectActionModeInputs(c *check.C) { Status: http.StatusBadRequest, Message: experr, } + if strings.HasSuffix(experr, "workshop not launched") || strings.HasSuffix(experr, "workshop already removed") { + exp.Status = http.StatusNotFound + } // Execute rsp := v1PostProjectWorkshop(apiCmd("/v1/projects/{id}/workshops"), req, nil).(*resp) @@ -5418,8 +5421,8 @@ func (s *apiSuite) TestRemoveWorkshopNotFound(c *check.C) { expected := []*expectedResp{ { Type: ResponseTypeError, - Status: http.StatusBadRequest, - Message: `cannot remove "workshopconns": workshop not launched`, + Status: http.StatusNotFound, + Message: `cannot remove "workshopconns": workshop already removed`, }, } s.runActionTest(c, requests, expected) diff --git a/internal/overlord/workshopstate/manifest.go b/internal/overlord/workshopstate/manifest.go index 581c56e9d..0dd8e69b6 100644 --- a/internal/overlord/workshopstate/manifest.go +++ b/internal/overlord/workshopstate/manifest.go @@ -142,6 +142,9 @@ func (w *WorkshopManager) RemoveManifests(ctx context.Context, projectId string, running = make(map[string]bool, len(names)) for _, name := range names { wp, err := w.backend.Workshop(ctx, name) + if errors.Is(err, workshop.ErrWorkshopNotLaunched) { + err = errAlreadyRemoved{} + } if err != nil { return nil, nil, nil, fmt.Errorf("cannot remove %q: %w", name, err) } @@ -171,6 +174,16 @@ func (w *WorkshopManager) RemoveManifests(ctx context.Context, projectId string, return stashed, current, running, nil } +type errAlreadyRemoved struct{} + +func (errAlreadyRemoved) Error() string { + return "workshop already removed" +} + +func (errAlreadyRemoved) Unwrap() error { + return workshop.ErrWorkshopNotLaunched +} + func (w *WorkshopManager) maybeDiscardWaitingRefresh(projectId string, file *workshop.File) (*Manifest, error) { err := conflict.CheckChangeConflict(w.state, projectId, file.Name, []string{"exec"}) if err == nil {