Skip to content

Commit c422f34

Browse files
committed
feat: autostop workspaces owned by suspended users
1 parent dd80958 commit c422f34

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

coderd/autobuild/lifecycle_executor.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func getNextTransition(
316316
error,
317317
) {
318318
switch {
319-
case isEligibleForAutostop(ws, latestBuild, latestJob, currentTick):
319+
case isEligibleForAutostop(user, ws, latestBuild, latestJob, currentTick):
320320
return database.WorkspaceTransitionStop, database.BuildReasonAutostop, nil
321321
case isEligibleForAutostart(user, ws, latestBuild, latestJob, templateSchedule, currentTick):
322322
return database.WorkspaceTransitionStart, database.BuildReasonAutostart, nil
@@ -376,8 +376,8 @@ func isEligibleForAutostart(user database.User, ws database.Workspace, build dat
376376
return !currentTick.Before(nextTransition)
377377
}
378378

379-
// isEligibleForAutostart returns true if the workspace should be autostopped.
380-
func isEligibleForAutostop(ws database.Workspace, build database.WorkspaceBuild, job database.ProvisionerJob, currentTick time.Time) bool {
379+
// isEligibleForAutostop returns true if the workspace should be autostopped.
380+
func isEligibleForAutostop(user database.User, ws database.Workspace, build database.WorkspaceBuild, job database.ProvisionerJob, currentTick time.Time) bool {
381381
if job.JobStatus == database.ProvisionerJobStatusFailed {
382382
return false
383383
}
@@ -387,6 +387,10 @@ func isEligibleForAutostop(ws database.Workspace, build database.WorkspaceBuild,
387387
return false
388388
}
389389

390+
if build.Transition == database.WorkspaceTransitionStart && user.Status == database.UserStatusSuspended {
391+
return true
392+
}
393+
390394
// A workspace must be started in order for it to be auto-stopped.
391395
return build.Transition == database.WorkspaceTransitionStart &&
392396
!build.Deadline.IsZero() &&

coderd/database/dbmem/dbmem.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5844,6 +5844,15 @@ func (q *FakeQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, no
58445844
workspaces = append(workspaces, workspace)
58455845
continue
58465846
}
5847+
5848+
user, err := q.getUserByIDNoLock(workspace.OwnerID)
5849+
if err != nil {
5850+
return nil, xerrors.Errorf("get user by ID: %w", err)
5851+
}
5852+
if user.Status == database.UserStatusSuspended && build.Transition == database.WorkspaceTransitionStart {
5853+
workspaces = append(workspaces, workspace)
5854+
continue
5855+
}
58475856
}
58485857

58495858
return workspaces, nil

coderd/database/queries/workspaces.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,8 @@ INNER JOIN
557557
provisioner_jobs ON workspace_builds.job_id = provisioner_jobs.id
558558
INNER JOIN
559559
templates ON workspaces.template_id = templates.id
560+
INNER JOIN
561+
users ON workspaces.owner_id = users.id
560562
WHERE
561563
workspace_builds.build_number = (
562564
SELECT
@@ -608,6 +610,12 @@ WHERE
608610
(
609611
templates.time_til_dormant_autodelete > 0 AND
610612
workspaces.dormant_at IS NOT NULL
613+
) OR
614+
615+
-- If the user account is suspended, and the workspace is running.
616+
(
617+
users.status = 'suspended'::user_status AND
618+
workspace_builds.transition = 'start'::workspace_transition
611619
)
612620
) AND workspaces.deleted = 'false';
613621

0 commit comments

Comments
 (0)