Skip to content

Commit faea7fc

Browse files
committed
Merge branch 'main' of github.com:/coder/coder into dk/system-notifications-lib
2 parents 613e074 + fecc5b3 commit faea7fc

File tree

9 files changed

+88
-11
lines changed

9 files changed

+88
-11
lines changed

coderd/autobuild/lifecycle_executor.go

+7-3
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/autobuild/lifecycle_executor_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,52 @@ func TestExecutorWorkspaceAutostopBeforeDeadline(t *testing.T) {
563563
assert.Len(t, stats.Transitions, 0)
564564
}
565565

566+
func TestExecuteAutostopSuspendedUser(t *testing.T) {
567+
t.Parallel()
568+
569+
var (
570+
ctx = testutil.Context(t, testutil.WaitShort)
571+
tickCh = make(chan time.Time)
572+
statsCh = make(chan autobuild.Stats)
573+
client = coderdtest.New(t, &coderdtest.Options{
574+
AutobuildTicker: tickCh,
575+
IncludeProvisionerDaemon: true,
576+
AutobuildStats: statsCh,
577+
})
578+
)
579+
580+
admin := coderdtest.CreateFirstUser(t, client)
581+
version := coderdtest.CreateTemplateVersion(t, client, admin.OrganizationID, nil)
582+
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
583+
template := coderdtest.CreateTemplate(t, client, admin.OrganizationID, version.ID)
584+
userClient, user := coderdtest.CreateAnotherUser(t, client, admin.OrganizationID)
585+
workspace := coderdtest.CreateWorkspace(t, userClient, admin.OrganizationID, template.ID)
586+
coderdtest.AwaitWorkspaceBuildJobCompleted(t, userClient, workspace.LatestBuild.ID)
587+
588+
// Given: workspace is running, and the user is suspended.
589+
workspace = coderdtest.MustWorkspace(t, userClient, workspace.ID)
590+
require.Equal(t, codersdk.WorkspaceStatusRunning, workspace.LatestBuild.Status)
591+
_, err := client.UpdateUserStatus(ctx, user.ID.String(), codersdk.UserStatusSuspended)
592+
require.NoError(t, err, "update user status")
593+
594+
// When: the autobuild executor ticks after the scheduled time
595+
go func() {
596+
tickCh <- time.Unix(0, 0) // the exact time is not important
597+
close(tickCh)
598+
}()
599+
600+
// Then: the workspace should be stopped
601+
stats := <-statsCh
602+
assert.Len(t, stats.Errors, 0)
603+
assert.Len(t, stats.Transitions, 1)
604+
assert.Equal(t, stats.Transitions[workspace.ID], database.WorkspaceTransitionStop)
605+
606+
// Wait for stop to complete
607+
workspace = coderdtest.MustWorkspace(t, client, workspace.ID)
608+
workspaceBuild := coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
609+
assert.Equal(t, codersdk.WorkspaceStatusStopped, workspaceBuild.Status)
610+
}
611+
566612
func TestExecutorWorkspaceAutostopNoWaitChangedMyMind(t *testing.T) {
567613
t.Parallel()
568614

coderd/database/dbmem/dbmem.go

+9
Original file line numberDiff line numberDiff line change
@@ -5937,6 +5937,15 @@ func (q *FakeQuerier) GetWorkspacesEligibleForTransition(ctx context.Context, no
59375937
workspaces = append(workspaces, workspace)
59385938
continue
59395939
}
5940+
5941+
user, err := q.getUserByIDNoLock(workspace.OwnerID)
5942+
if err != nil {
5943+
return nil, xerrors.Errorf("get user by ID: %w", err)
5944+
}
5945+
if user.Status == database.UserStatusSuspended && build.Transition == database.WorkspaceTransitionStart {
5946+
workspaces = append(workspaces, workspace)
5947+
continue
5948+
}
59405949
}
59415950

59425951
return workspaces, nil

coderd/database/queries.sql.go

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/workspaces.sql

+8
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

codersdk/agentsdk/logs.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ type LogSender struct {
284284
outputLen int
285285
}
286286

287-
type logDest interface {
287+
type LogDest interface {
288288
BatchCreateLogs(ctx context.Context, request *proto.BatchCreateLogsRequest) (*proto.BatchCreateLogsResponse, error)
289289
}
290290

@@ -360,7 +360,7 @@ var LogLimitExceededError = xerrors.New("Log limit exceeded")
360360
// SendLoop sends any pending logs until it hits an error or the context is canceled. It does not
361361
// retry as it is expected that a higher layer retries establishing connection to the agent API and
362362
// calls SendLoop again.
363-
func (l *LogSender) SendLoop(ctx context.Context, dest logDest) error {
363+
func (l *LogSender) SendLoop(ctx context.Context, dest LogDest) error {
364364
l.L.Lock()
365365
defer l.L.Unlock()
366366
if l.exceededLogLimit {

docs/install/kubernetes.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ locally in order to log in and manage templates.
145145
helm install coder coder-v2/coder \
146146
--namespace coder \
147147
--values values.yaml \
148-
--version 2.11.4
148+
--version 2.12.3
149149
```
150150

151151
You can watch Coder start up by running `kubectl get pods -n coder`. Once

docs/install/releases.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ their infrastructure on a staging environment before upgrading a production
88
deployment.
99

1010
We support two release channels:
11-
[mainline](https://github.com/coder/coder/releases/tag/v2.10.1) for the bleeding
11+
[mainline](https://github.com/coder/coder/releases/tag/v2.13.0) for the bleeding
1212
edge version of Coder and
1313
[stable](https://github.com/coder/coder/releases/latest) for those with lower
1414
tolerance for fault. We field our mainline releases publicly for one month
@@ -52,7 +52,8 @@ pages.
5252
| 2.7.x | January 01, 2024 | Not Supported |
5353
| 2.8.x | February 06, 2024 | Not Supported |
5454
| 2.9.x | March 07, 2024 | Not Supported |
55-
| 2.10.x | April 03, 2024 | Security Support |
56-
| 2.11.x | May 07, 2024 | Stable |
57-
| 2.12.x | June 04, 2024 | Mainline |
58-
| 2.13.x | July 02, 2024 | Not Released |
55+
| 2.10.x | April 03, 2024 | Not Supported |
56+
| 2.11.x | May 07, 2024 | Security Support |
57+
| 2.12.x | June 04, 2024 | Stable |
58+
| 2.13.x | July 02, 2024 | Mainline |
59+
| 2.14.x | Aigust 06, 2024 | Not Released |

dogfood/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ SHELL ["/bin/bash", "-c"]
9191
RUN apt-get update && apt-get install --yes ca-certificates
9292

9393
COPY files /
94+
RUN chown -R 0:0 /etc/sudoers.d # workaround for coder/envbuilder#70
9495

9596
# Install packages from apt repositories
9697
ARG DEBIAN_FRONTEND="noninteractive"

0 commit comments

Comments
 (0)