Skip to content

Commit 7c595e2

Browse files
feat: allow removing deadline for running workspace (coder#16085)
Fixes coder#9775 When a workspace's TTL is removed, and the workspace is running, the deadline is removed from the workspace. This also modifies the frontend to not show a confirmation dialog when the change is to remove autostop.
1 parent 048a10a commit 7c595e2

File tree

4 files changed

+114
-32
lines changed

4 files changed

+114
-32
lines changed

coderd/autobuild/lifecycle_executor_test.go

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -722,45 +722,17 @@ func TestExecutorWorkspaceAutostopNoWaitChangedMyMind(t *testing.T) {
722722
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{TTLMillis: nil})
723723
require.NoError(t, err)
724724

725-
// Then: the deadline should still be the original value
725+
// Then: the deadline should be set to zero
726726
updated := coderdtest.MustWorkspace(t, client, workspace.ID)
727-
assert.WithinDuration(t, workspace.LatestBuild.Deadline.Time, updated.LatestBuild.Deadline.Time, time.Minute)
727+
assert.True(t, !updated.LatestBuild.Deadline.Valid)
728728

729729
// When: the autobuild executor ticks after the original deadline
730730
go func() {
731731
tickCh <- workspace.LatestBuild.Deadline.Time.Add(time.Minute)
732732
}()
733733

734-
// Then: the workspace should stop
735-
stats := <-statsCh
736-
assert.Len(t, stats.Errors, 0)
737-
assert.Len(t, stats.Transitions, 1)
738-
assert.Equal(t, stats.Transitions[workspace.ID], database.WorkspaceTransitionStop)
739-
740-
// Wait for stop to complete
741-
updated = coderdtest.MustWorkspace(t, client, workspace.ID)
742-
_ = coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, updated.LatestBuild.ID)
743-
744-
// Start the workspace again
745-
workspace = coderdtest.MustTransitionWorkspace(t, client, workspace.ID, database.WorkspaceTransitionStop, database.WorkspaceTransitionStart)
746-
747-
// Given: the user changes their mind again and wants to enable autostop
748-
newTTL := 8 * time.Hour
749-
err = client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{TTLMillis: ptr.Ref(newTTL.Milliseconds())})
750-
require.NoError(t, err)
751-
752-
// Then: the deadline should remain at the zero value
753-
updated = coderdtest.MustWorkspace(t, client, workspace.ID)
754-
assert.Zero(t, updated.LatestBuild.Deadline)
755-
756-
// When: the relentless onward march of time continues
757-
go func() {
758-
tickCh <- workspace.LatestBuild.Deadline.Time.Add(newTTL + time.Minute)
759-
close(tickCh)
760-
}()
761-
762734
// Then: the workspace should not stop
763-
stats = <-statsCh
735+
stats := <-statsCh
764736
assert.Len(t, stats.Errors, 0)
765737
assert.Len(t, stats.Transitions, 0)
766738
}

coderd/workspaces.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,26 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
10291029
return xerrors.Errorf("update workspace time until shutdown: %w", err)
10301030
}
10311031

1032+
// If autostop has been disabled, we want to remove the deadline from the
1033+
// existing workspace build (if there is one).
1034+
if !dbTTL.Valid {
1035+
build, err := s.GetLatestWorkspaceBuildByWorkspaceID(ctx, workspace.ID)
1036+
if err != nil {
1037+
return xerrors.Errorf("get latest workspace build: %w", err)
1038+
}
1039+
1040+
if build.Transition == database.WorkspaceTransitionStart {
1041+
if err = s.UpdateWorkspaceBuildDeadlineByID(ctx, database.UpdateWorkspaceBuildDeadlineByIDParams{
1042+
ID: build.ID,
1043+
Deadline: time.Time{},
1044+
MaxDeadline: build.MaxDeadline,
1045+
UpdatedAt: dbtime.Time(api.Clock.Now()),
1046+
}); err != nil {
1047+
return xerrors.Errorf("update workspace build deadline: %w", err)
1048+
}
1049+
}
1050+
}
1051+
10321052
return nil
10331053
}, nil)
10341054
if err != nil {

coderd/workspaces_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,6 +2394,93 @@ func TestWorkspaceUpdateTTL(t *testing.T) {
23942394
})
23952395
}
23962396

2397+
t.Run("ModifyAutostopWithRunningWorkspace", func(t *testing.T) {
2398+
t.Parallel()
2399+
2400+
testCases := []struct {
2401+
name string
2402+
fromTTL *int64
2403+
toTTL *int64
2404+
afterUpdate func(t *testing.T, before, after codersdk.NullTime)
2405+
}{
2406+
{
2407+
name: "RemoveAutostopRemovesDeadline",
2408+
fromTTL: ptr.Ref((8 * time.Hour).Milliseconds()),
2409+
toTTL: nil,
2410+
afterUpdate: func(t *testing.T, before, after codersdk.NullTime) {
2411+
require.NotZero(t, before)
2412+
require.Zero(t, after)
2413+
},
2414+
},
2415+
{
2416+
name: "AddAutostopDoesNotAddDeadline",
2417+
fromTTL: nil,
2418+
toTTL: ptr.Ref((8 * time.Hour).Milliseconds()),
2419+
afterUpdate: func(t *testing.T, before, after codersdk.NullTime) {
2420+
require.Zero(t, before)
2421+
require.Zero(t, after)
2422+
},
2423+
},
2424+
{
2425+
name: "IncreaseAutostopDoesNotModifyDeadline",
2426+
fromTTL: ptr.Ref((4 * time.Hour).Milliseconds()),
2427+
toTTL: ptr.Ref((8 * time.Hour).Milliseconds()),
2428+
afterUpdate: func(t *testing.T, before, after codersdk.NullTime) {
2429+
require.NotZero(t, before)
2430+
require.NotZero(t, after)
2431+
require.Equal(t, before, after)
2432+
},
2433+
},
2434+
{
2435+
name: "DecreaseAutostopDoesNotModifyDeadline",
2436+
fromTTL: ptr.Ref((8 * time.Hour).Milliseconds()),
2437+
toTTL: ptr.Ref((4 * time.Hour).Milliseconds()),
2438+
afterUpdate: func(t *testing.T, before, after codersdk.NullTime) {
2439+
require.NotZero(t, before)
2440+
require.NotZero(t, after)
2441+
require.Equal(t, before, after)
2442+
},
2443+
},
2444+
}
2445+
2446+
for _, testCase := range testCases {
2447+
testCase := testCase
2448+
2449+
t.Run(testCase.name, func(t *testing.T) {
2450+
t.Parallel()
2451+
2452+
var (
2453+
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
2454+
user = coderdtest.CreateFirstUser(t, client)
2455+
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
2456+
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
2457+
template = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
2458+
workspace = coderdtest.CreateWorkspace(t, client, template.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
2459+
cwr.TTLMillis = testCase.fromTTL
2460+
})
2461+
build = coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
2462+
)
2463+
2464+
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
2465+
defer cancel()
2466+
2467+
err := client.UpdateWorkspaceTTL(ctx, workspace.ID, codersdk.UpdateWorkspaceTTLRequest{
2468+
TTLMillis: testCase.toTTL,
2469+
})
2470+
require.NoError(t, err)
2471+
2472+
deadlineBefore := build.Deadline
2473+
2474+
build, err = client.WorkspaceBuild(ctx, build.ID)
2475+
require.NoError(t, err)
2476+
2477+
deadlineAfter := build.Deadline
2478+
2479+
testCase.afterUpdate(t, deadlineBefore, deadlineAfter)
2480+
})
2481+
}
2482+
})
2483+
23972484
t.Run("CustomAutostopDisabledByTemplate", func(t *testing.T) {
23982485
t.Parallel()
23992486
var (

site/src/pages/WorkspaceSettingsPage/WorkspaceSchedulePage/WorkspaceSchedulePage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,10 @@ export const WorkspaceSchedulePage: FC = () => {
118118

119119
await submitScheduleMutation.mutateAsync(data);
120120

121-
if (data.autostopChanged) {
121+
if (
122+
data.autostopChanged &&
123+
getAutostop(workspace).autostopEnabled
124+
) {
122125
setIsConfirmingApply(true);
123126
}
124127
}}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy