diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 1469807b8f6c7..8101772232e1e 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -34,6 +34,17 @@ import ( const workspaceDefaultTTL = 2 * time.Hour +var ( + ttlMin = time.Minute //nolint:revive // min here means 'minimum' not 'minutes' + ttlMax = 7 * 24 * time.Hour + + errTTLMin = xerrors.New("time until shutdown must be at least one minute") + errTTLMax = xerrors.New("time until shutdown must be less than 7 days") + errDeadlineTooSoon = xerrors.New("new deadline must be at least 30 minutes in the future") + errDeadlineBeforeStart = xerrors.New("new deadline must be before workspace start time") + errDeadlineOverTemplateMax = xerrors.New("new deadline is greater than template allows") +) + func (api *API) workspace(rw http.ResponseWriter, r *http.Request) { workspace := httpmw.WorkspaceParam(r) if !api.Authorize(r, rbac.ActionRead, workspace) { @@ -623,9 +634,11 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) { newDeadline := req.Deadline.UTC() if err := validWorkspaceDeadline(job.CompletedAt.Time, newDeadline, time.Duration(template.MaxTtl)); err != nil { + // NOTE(Cian): Putting the error in the Message field on request from the FE folks. + // Normally, we would put the validation error in Validations, but this endpoint is + // not tied to a form or specific named user input on the FE. code = http.StatusBadRequest - resp.Message = "Bad extend workspace request." - resp.Validations = append(resp.Validations, codersdk.ValidationError{Field: "deadline", Detail: err.Error()}) + resp.Message = "Cannot extend workspace: " + err.Error() return err } @@ -894,12 +907,12 @@ func validWorkspaceTTLMillis(millis *int64, max time.Duration) (sql.NullInt64, e dur := time.Duration(*millis) * time.Millisecond truncated := dur.Truncate(time.Minute) - if truncated < time.Minute { - return sql.NullInt64{}, xerrors.New("time until shutdown must be at least one minute") + if truncated < ttlMin { + return sql.NullInt64{}, errTTLMin } - if truncated > 24*7*time.Hour { - return sql.NullInt64{}, xerrors.New("time until shutdown must be less than 7 days") + if truncated > ttlMax { + return sql.NullInt64{}, errTTLMax } if truncated > max { @@ -915,17 +928,17 @@ func validWorkspaceTTLMillis(millis *int64, max time.Duration) (sql.NullInt64, e func validWorkspaceDeadline(startedAt, newDeadline time.Time, max time.Duration) error { soon := time.Now().Add(29 * time.Minute) if newDeadline.Before(soon) { - return xerrors.New("new deadline must be at least 30 minutes in the future") + return errDeadlineTooSoon } // No idea how this could happen. if newDeadline.Before(startedAt) { - return xerrors.Errorf("new deadline must be before workspace start time") + return errDeadlineBeforeStart } delta := newDeadline.Sub(startedAt) if delta > max { - return xerrors.New("new deadline is greater than template allows") + return errDeadlineOverTemplateMax } return nil diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index eb275e0f8a0bc..a958c260422e6 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -1063,14 +1063,15 @@ func TestWorkspaceExtend(t *testing.T) { err = client.PutExtendWorkspace(ctx, workspace.ID, codersdk.PutExtendWorkspaceRequest{ Deadline: deadlineTooSoon, }) - require.ErrorContains(t, err, "new deadline must be at least 30 minutes in the future", "setting a deadline less than 30 minutes in the future should fail") + require.ErrorContains(t, err, "unexpected status code 400: Cannot extend workspace: new deadline must be at least 30 minutes in the future", "setting a deadline less than 30 minutes in the future should fail") // And with a deadline greater than the template max_ttl should also fail deadlineExceedsMaxTTL := time.Now().Add(time.Duration(template.MaxTTLMillis) * time.Millisecond).Add(time.Minute) err = client.PutExtendWorkspace(ctx, workspace.ID, codersdk.PutExtendWorkspaceRequest{ Deadline: deadlineExceedsMaxTTL, }) - require.ErrorContains(t, err, "new deadline is greater than template allows", "setting a deadline greater than that allowed by the template should fail") + + require.ErrorContains(t, err, "unexpected status code 400: Cannot extend workspace: new deadline is greater than template allows", "setting a deadline greater than that allowed by the template should fail") // Updating with a deadline 30 minutes in the future should succeed deadlineJustSoonEnough := time.Now().Add(30 * time.Minute)