Skip to content

Commit 0ce8aa3

Browse files
committed
add some tests/fix some minor bugs
1 parent 8a39344 commit 0ce8aa3

File tree

6 files changed

+102
-4
lines changed

6 files changed

+102
-4
lines changed

coderd/autobuild/lifecycle_executor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ func (e *Executor) runOnce(t time.Time) Stats {
245245
// as well as the reason for why it is transitioning. It is possible
246246
// for this function to return a nil error as well as an empty transition.
247247
// In such cases it means no provisioning should occur but the workspace
248-
// may be "transitioning" to a new state (such as a inactive, stopped
248+
// may be "transitioning" to a new state (such as an inactive, stopped
249249
// workspace transitioning to the locked state).
250250
func getNextTransition(
251251
ws database.Workspace,

coderd/database/dbfake/dbfake.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5229,6 +5229,7 @@ func (q *fakeQuerier) UpdateWorkspaceLockedAt(_ context.Context, arg database.Up
52295229
continue
52305230
}
52315231
workspace.LockedAt = arg.LockedAt
5232+
workspace.LastUsedAt = database.Now()
52325233
q.workspaces[index] = workspace
52335234
return nil
52345235
}

coderd/database/queries.sql.go

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/workspaces.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ WHERE
474474
UPDATE
475475
workspaces
476476
SET
477-
locked_at = $2
477+
locked_at = $2,
478+
last_used_at = now() at time zone 'utc'
478479
WHERE
479480
id = $1;

coderd/workspaces_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2399,11 +2399,12 @@ func TestWorkspaceLock(t *testing.T) {
23992399
})
24002400
require.NoError(t, err)
24012401

2402-
workspace, err = client.Workspace(ctx, workspace.ID)
2402+
workspace = coderdtest.MustWorkspace(t, client, workspace.ID)
24032403
require.NoError(t, err, "fetch provisioned workspace")
24042404
require.NotNil(t, workspace.LockedAt)
24052405
require.WithinRange(t, *workspace.LockedAt, time.Now().Add(-time.Second*10), time.Now())
24062406

2407+
lastUsedAt := workspace.LastUsedAt
24072408
err = client.UpdateWorkspaceLock(ctx, workspace.ID, codersdk.UpdateWorkspaceLock{
24082409
Lock: false,
24092410
})
@@ -2412,6 +2413,7 @@ func TestWorkspaceLock(t *testing.T) {
24122413
workspace, err = client.Workspace(ctx, workspace.ID)
24132414
require.NoError(t, err, "fetch provisioned workspace")
24142415
require.Nil(t, workspace.LockedAt)
2416+
require.True(t, workspace.LastUsedAt.After(lastUsedAt))
24152417
})
24162418

24172419
t.Run("CannotStart", func(t *testing.T) {

enterprise/coderd/workspaces_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/coder/coder/coderd/autobuild"
1616
"github.com/coder/coder/coderd/coderdtest"
1717
"github.com/coder/coder/coderd/database"
18+
"github.com/coder/coder/coderd/schedule"
1819
"github.com/coder/coder/coderd/util/ptr"
1920
"github.com/coder/coder/codersdk"
2021
"github.com/coder/coder/enterprise/coderd"
@@ -235,6 +236,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
235236
t.Parallel()
236237

237238
var (
239+
ctx = testutil.Context(t, testutil.WaitMedium)
238240
ticker = make(chan time.Time)
239241
statCh = make(chan autobuild.Stats)
240242
inactiveTTL = time.Millisecond
@@ -277,6 +279,15 @@ func TestWorkspaceAutobuild(t *testing.T) {
277279
ws = coderdtest.MustWorkspace(t, client, ws.ID)
278280
// The workspace should be locked.
279281
require.NotNil(t, ws.LockedAt)
282+
lastUsedAt := ws.LastUsedAt
283+
284+
err := client.UpdateWorkspaceLock(ctx, ws.ID, codersdk.UpdateWorkspaceLock{Lock: false})
285+
require.NoError(t, err)
286+
287+
// Assert that we updated our last_used_at so that we don't immediately
288+
// retrigger another lock action.
289+
ws = coderdtest.MustWorkspace(t, client, ws.ID)
290+
require.True(t, ws.LastUsedAt.After(lastUsedAt))
280291
})
281292

282293
t.Run("InactiveTTLTooEarly", func(t *testing.T) {
@@ -496,6 +507,88 @@ func TestWorkspaceAutobuild(t *testing.T) {
496507
require.True(t, ok)
497508
require.Equal(t, http.StatusGone, cerr.StatusCode())
498509
})
510+
511+
t.Run("LockedNoAutostart", func(t *testing.T) {
512+
t.Parallel()
513+
514+
var (
515+
ctx = testutil.Context(t, testutil.WaitMedium)
516+
tickCh = make(chan time.Time)
517+
statsCh = make(chan autobuild.Stats)
518+
client = coderdenttest.New(t, &coderdenttest.Options{
519+
Options: &coderdtest.Options{
520+
AutobuildTicker: tickCh,
521+
IncludeProvisionerDaemon: true,
522+
AutobuildStats: statsCh,
523+
TemplateScheduleStore: &coderd.EnterpriseTemplateScheduleStore{},
524+
},
525+
})
526+
inactiveTTL = time.Millisecond
527+
)
528+
529+
user := coderdtest.CreateFirstUser(t, client)
530+
_ = coderdenttest.AddFullLicense(t, client)
531+
532+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
533+
Parse: echo.ParseComplete,
534+
ProvisionPlan: echo.ProvisionComplete,
535+
ProvisionApply: echo.ProvisionComplete,
536+
})
537+
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
538+
539+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
540+
541+
sched, err := schedule.Weekly("CRON_TZ=UTC 0 * * * *")
542+
require.NoError(t, err)
543+
544+
ws := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID, func(cwr *codersdk.CreateWorkspaceRequest) {
545+
cwr.AutostartSchedule = ptr.Ref(sched.String())
546+
})
547+
coderdtest.AwaitWorkspaceBuildJob(t, client, ws.LatestBuild.ID)
548+
coderdtest.MustTransitionWorkspace(t, client, ws.ID, database.WorkspaceTransitionStart, database.WorkspaceTransitionStop)
549+
550+
// Assert that autostart works when the workspace isn't locked..
551+
tickCh <- sched.Next(ws.LatestBuild.CreatedAt)
552+
// Then: the workspace should eventually be started
553+
stats := <-statsCh
554+
require.NoError(t, stats.Error)
555+
require.Len(t, stats.Transitions, 1)
556+
require.Contains(t, stats.Transitions, ws.ID)
557+
require.Equal(t, database.WorkspaceTransitionStart, stats.Transitions[ws.ID])
558+
ws = coderdtest.MustWorkspace(t, client, ws.ID)
559+
coderdtest.AwaitWorkspaceBuildJob(t, client, ws.LatestBuild.ID)
560+
561+
// Now that we've validated that the workspace is eligible for autostart
562+
// lets cause it to become locked.
563+
_, err = client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{
564+
InactivityTTLMillis: inactiveTTL.Milliseconds(),
565+
})
566+
require.NoError(t, err)
567+
// Wait for the workspace to breach the inactivity threshold.
568+
require.Eventually(t,
569+
func() bool {
570+
return database.Now().Sub(ws.LastUsedAt) > inactiveTTL
571+
},
572+
testutil.IntervalMedium, testutil.IntervalFast)
573+
574+
tickCh <- time.Now()
575+
// Then: the workspace should eventually be started
576+
stats = <-statsCh
577+
require.NoError(t, stats.Error)
578+
require.Len(t, stats.Transitions, 1)
579+
require.Contains(t, stats.Transitions, ws.ID)
580+
require.Equal(t, database.WorkspaceTransitionStop, stats.Transitions[ws.ID])
581+
ws = coderdtest.MustWorkspace(t, client, ws.ID)
582+
coderdtest.AwaitWorkspaceBuildJob(t, client, ws.LatestBuild.ID)
583+
// The workspace should be locked now.
584+
require.NotNil(t, ws.LockedAt)
585+
586+
// Assert that autostart is no longer triggered since workspace is locked.
587+
tickCh <- sched.Next(ws.LatestBuild.CreatedAt)
588+
// Then: the workspace should eventually be started
589+
stats = <-statsCh
590+
require.Len(t, stats.Transitions, 0)
591+
})
499592
}
500593

501594
func TestWorkspacesFiltering(t *testing.T) {

0 commit comments

Comments
 (0)