From 764376bcaf9fee1482a9bb91fd10b031bb4a7380 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Mon, 6 May 2024 14:59:14 +0000 Subject: [PATCH 1/4] fix: don't allow extend if template doesn't allow --- coderd/workspaces.go | 12 ++++++++++++ coderd/workspaces_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 87aea6919a351..12a955ce0d7c2 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -1052,6 +1052,18 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) { return xerrors.Errorf("workspace shutdown is manual") } + tmpl, err := s.GetTemplateByID(ctx, workspace.TemplateID) + if err != nil { + code = http.StatusInternalServerError + resp.Message = "Error fetching template." + return xerrors.Errorf("get template: %w", err) + } + if !tmpl.AllowUserAutostop { + code = http.StatusBadRequest + resp.Message = "Cannot extend workspace: template does not allow user autostop." + return xerrors.New("Cannot extend workspace: template does not allow user autostop") + } + newDeadline := req.Deadline.UTC() if err := validWorkspaceDeadline(job.CompletedAt.Time, newDeadline); err != nil { // NOTE(Cian): Putting the error in the Message field on request from the FE folks. diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index c01f9689d6ace..c6dbe06ec4091 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -2410,6 +2410,31 @@ func TestWorkspaceExtend(t *testing.T) { require.WithinDuration(t, oldDeadline.Add(-time.Hour), updated.LatestBuild.Deadline.Time, time.Minute) } +func TestWorkspaceExtendWithoutTemplateAllowingUserAutostop(t *testing.T) { + t.Parallel() + var ( + client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user = coderdtest.CreateFirstUser(t, client) + version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + tmpl = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) { + v := false + req.AllowUserAutostop = &v + }) + workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, tmpl.ID) + ) + + ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) + defer cancel() + + newDeadline := time.Now().Add(9 * time.Hour).UTC() + req := codersdk.PutExtendWorkspaceRequest{ + Deadline: newDeadline, + } + err := client.PutExtendWorkspace(ctx, workspace.ID, req) + + require.ErrorContains(t, err, "template does not allow user autostop") +} + func TestWorkspaceUpdateAutomaticUpdates_OK(t *testing.T) { t.Parallel() From 2e15829f1608afeb818871e4b03043d947254d22 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Mon, 6 May 2024 18:11:41 +0000 Subject: [PATCH 2/4] Fix extend test --- coderd/workspaces_test.go | 25 -------------------- enterprise/coderd/workspaces_test.go | 34 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/coderd/workspaces_test.go b/coderd/workspaces_test.go index c6dbe06ec4091..c01f9689d6ace 100644 --- a/coderd/workspaces_test.go +++ b/coderd/workspaces_test.go @@ -2410,31 +2410,6 @@ func TestWorkspaceExtend(t *testing.T) { require.WithinDuration(t, oldDeadline.Add(-time.Hour), updated.LatestBuild.Deadline.Time, time.Minute) } -func TestWorkspaceExtendWithoutTemplateAllowingUserAutostop(t *testing.T) { - t.Parallel() - var ( - client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) - user = coderdtest.CreateFirstUser(t, client) - version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) - tmpl = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) { - v := false - req.AllowUserAutostop = &v - }) - workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, tmpl.ID) - ) - - ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong) - defer cancel() - - newDeadline := time.Now().Add(9 * time.Hour).UTC() - req := codersdk.PutExtendWorkspaceRequest{ - Deadline: newDeadline, - } - err := client.PutExtendWorkspace(ctx, workspace.ID, req) - - require.ErrorContains(t, err, "template does not allow user autostop") -} - func TestWorkspaceUpdateAutomaticUpdates_OK(t *testing.T) { t.Parallel() diff --git a/enterprise/coderd/workspaces_test.go b/enterprise/coderd/workspaces_test.go index b44357c5b5dde..9cb86f55ba55f 100644 --- a/enterprise/coderd/workspaces_test.go +++ b/enterprise/coderd/workspaces_test.go @@ -913,8 +913,12 @@ func TestWorkspaceAutobuild(t *testing.T) { ws = coderdtest.MustWorkspace(t, client, ws.ID) require.Equal(t, version2.ID, ws.LatestBuild.TemplateVersionID) }) +} + +func TestTemplateDoesNotAllowUserAutostop(t *testing.T) { + t.Parallel() - t.Run("TemplateDoesNotAllowUserAutostop", func(t *testing.T) { + t.Run("TTLSetByTemplate", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, @@ -951,6 +955,34 @@ func TestWorkspaceAutobuild(t *testing.T) { require.Equal(t, templateTTL, template.DefaultTTLMillis) require.Equal(t, templateTTL, *workspace.TTLMillis) }) + + t.Run("ExtendIsNotEnabledByTemplate", func(t *testing.T) { + t.Parallel() + client := coderdtest.New(t, &coderdtest.Options{ + IncludeProvisionerDaemon: true, + TemplateScheduleStore: schedule.NewEnterpriseTemplateScheduleStore(agplUserQuietHoursScheduleStore()), + }) + user := coderdtest.CreateFirstUser(t, client) + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID, func(ctr *codersdk.CreateTemplateRequest) { + ctr.AllowUserAutostop = ptr.Ref(false) + }) + coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID) + workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID) + coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID) + + require.Equal(t, false, template.AllowUserAutostop, "template should have AllowUserAutostop as false") + + ctx := testutil.Context(t, testutil.WaitShort) + ttl := 8 * time.Hour + newDeadline := time.Now().Add(ttl + time.Hour).UTC() + + err := client.PutExtendWorkspace(ctx, workspace.ID, codersdk.PutExtendWorkspaceRequest{ + Deadline: newDeadline, + }) + + require.ErrorContains(t, err, "template does not allow user autostop") + }) } // Blocked by autostart requirements From 9b00a670f03c603d9acf42bd48a0f10882c7c5e0 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Mon, 6 May 2024 19:02:38 +0000 Subject: [PATCH 3/4] Does not show schedule controls when template does not allow user autostop --- .../WorkspacePage/WorkspaceTopbar.stories.tsx | 18 ++++++++++++++++++ .../pages/WorkspacePage/WorkspaceTopbar.tsx | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/site/src/pages/WorkspacePage/WorkspaceTopbar.stories.tsx b/site/src/pages/WorkspacePage/WorkspaceTopbar.stories.tsx index 8b0334b1dccfc..1cf8eeec78a67 100644 --- a/site/src/pages/WorkspacePage/WorkspaceTopbar.stories.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceTopbar.stories.tsx @@ -275,3 +275,21 @@ export const WithQuota: Story = { ], }, }; + +export const TemplateDoesNotAllowAutostop: Story = { + args: { + workspace: { + ...MockWorkspace, + latest_build: { + ...MockWorkspace.latest_build, + get deadline() { + return addHours(new Date(), 8).toISOString(); + }, + }, + }, + template: { + ...MockTemplate, + allow_user_autostop: false, + }, + }, +}; diff --git a/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx b/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx index e2337fd8a0bd5..d05f7c7c66453 100644 --- a/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx @@ -204,7 +204,9 @@ export const WorkspaceTopbar: FC = ({ )} From 87ab15cd3d7ae2e9cbd5dcf385790a6c4f1545e2 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 7 May 2024 09:58:59 -0300 Subject: [PATCH 4/4] Update error copy Co-authored-by: Mathias Fredriksson --- coderd/workspaces.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 12a955ce0d7c2..6f398b34488d6 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -1061,7 +1061,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) { if !tmpl.AllowUserAutostop { code = http.StatusBadRequest resp.Message = "Cannot extend workspace: template does not allow user autostop." - return xerrors.New("Cannot extend workspace: template does not allow user autostop") + return xerrors.New("cannot extend workspace: template does not allow user autostop") } newDeadline := req.Deadline.UTC()