@@ -210,25 +210,25 @@ func TestWorkspaceAutobuild(t *testing.T) {
210
210
})
211
211
)
212
212
user := coderdtest .CreateFirstUser (t , client )
213
- _ = coderdenttest .AddLicense (t , client , coderdenttest.LicenseOptions {
214
- Features : license.Features {
215
- codersdk .FeatureAdvancedTemplateScheduling : 1 ,
216
- },
217
- })
213
+ _ = coderdenttest .AddFullLicense (t , client )
218
214
version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
219
215
Parse : echo .ParseComplete ,
220
216
ProvisionPlan : echo .ProvisionComplete ,
221
217
ProvisionApply : echo .ProvisionComplete ,
222
218
})
223
219
// Create a template without setting a failure_ttl.
224
220
template := coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID )
221
+ require .Zero (t , template .InactivityTTLMillis )
222
+ require .Zero (t , template .FailureTTLMillis )
223
+ require .Zero (t , template .LockedTTLMillis )
224
+
225
225
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
226
226
ws := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
227
227
build := coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
228
228
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
229
229
ticker <- time .Now ()
230
230
stats := <- statCh
231
- // Expect no transitions since the field is unset on the template.
231
+ // Expect no transitions since the fields are unset on the template.
232
232
require .Len (t , stats .Transitions , 0 )
233
233
})
234
234
@@ -258,26 +258,33 @@ func TestWorkspaceAutobuild(t *testing.T) {
258
258
ProvisionPlan : echo .ProvisionComplete ,
259
259
ProvisionApply : echo .ProvisionComplete ,
260
260
})
261
+ // Create a template with a short inactivity ttl so we don't have to wait
262
+ // too long.
261
263
template := coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID , func (ctr * codersdk.CreateTemplateRequest ) {
262
264
ctr .InactivityTTLMillis = ptr.Ref [int64 ](inactiveTTL .Milliseconds ())
263
265
})
264
266
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
267
+
265
268
ws := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
266
269
build := coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
267
270
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
271
+
272
+ // Wait to trigger the inactivity threshold.
268
273
require .Eventually (t ,
269
274
func () bool {
270
275
return database .Now ().Sub (ws .LastUsedAt ) > inactiveTTL
271
276
},
272
277
testutil .IntervalMedium , testutil .IntervalFast )
273
278
ticker <- time .Now ()
274
279
stats := <- statCh
280
+
275
281
// Expect workspace to transition to stopped state for breaching
276
282
// failure TTL.
277
283
require .Len (t , stats .Transitions , 1 )
278
284
require .Equal (t , stats .Transitions [ws .ID ], database .WorkspaceTransitionStop )
279
- ws = coderdtest . MustWorkspace ( t , client , ws . ID )
285
+
280
286
// The workspace should be locked.
287
+ ws = coderdtest .MustWorkspace (t , client , ws .ID )
281
288
require .NotNil (t , ws .LockedAt )
282
289
lastUsedAt := ws .LastUsedAt
283
290
@@ -308,11 +315,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
308
315
})
309
316
)
310
317
user := coderdtest .CreateFirstUser (t , client )
311
- _ = coderdenttest .AddLicense (t , client , coderdenttest.LicenseOptions {
312
- Features : license.Features {
313
- codersdk .FeatureAdvancedTemplateScheduling : 1 ,
314
- },
315
- })
318
+ _ = coderdenttest .AddFullLicense (t , client )
316
319
version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
317
320
Parse : echo .ParseComplete ,
318
321
ProvisionPlan : echo .ProvisionComplete ,
@@ -331,6 +334,9 @@ func TestWorkspaceAutobuild(t *testing.T) {
331
334
require .Len (t , stats .Transitions , 0 )
332
335
})
333
336
337
+ // This is kind of a dumb test but it exists to offer some marginal
338
+ // confidence that bug in the auto-deletion logic doesn't delete running
339
+ // workspaces.
334
340
t .Run ("UnlockedWorkspacesNotDeleted" , func (t * testing.T ) {
335
341
t .Parallel ()
336
342
@@ -349,11 +355,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
349
355
})
350
356
)
351
357
user := coderdtest .CreateFirstUser (t , client )
352
- _ = coderdenttest .AddLicense (t , client , coderdenttest.LicenseOptions {
353
- Features : license.Features {
354
- codersdk .FeatureAdvancedTemplateScheduling : 1 ,
355
- },
356
- })
358
+ _ = coderdenttest .AddFullLicense (t , client )
357
359
version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
358
360
Parse : echo .ParseComplete ,
359
361
ProvisionPlan : echo .ProvisionComplete ,
@@ -365,6 +367,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
365
367
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
366
368
ws := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
367
369
build := coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
370
+ require .Nil (t , ws .LockedAt )
368
371
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
369
372
require .Eventually (t ,
370
373
func () bool {
@@ -378,6 +381,9 @@ func TestWorkspaceAutobuild(t *testing.T) {
378
381
require .Len (t , stats .Transitions , 0 )
379
382
})
380
383
384
+ // Assert that a stopped workspace that breaches the inactivity threshold
385
+ // does not trigger a build transition but is still placed in the
386
+ // lock state.
381
387
t .Run ("InactiveStoppedWorkspaceNoTransition" , func (t * testing.T ) {
382
388
t .Parallel ()
383
389
@@ -396,11 +402,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
396
402
})
397
403
)
398
404
user := coderdtest .CreateFirstUser (t , client )
399
- _ = coderdenttest .AddLicense (t , client , coderdenttest.LicenseOptions {
400
- Features : license.Features {
401
- codersdk .FeatureAdvancedTemplateScheduling : 1 ,
402
- },
403
- })
405
+ _ = coderdenttest .AddFullLicense (t , client )
404
406
version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
405
407
Parse : echo .ParseComplete ,
406
408
ProvisionPlan : echo .ProvisionComplete ,
@@ -410,6 +412,7 @@ func TestWorkspaceAutobuild(t *testing.T) {
410
412
ctr .InactivityTTLMillis = ptr.Ref [int64 ](inactiveTTL .Milliseconds ())
411
413
})
412
414
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
415
+
413
416
ws := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
414
417
build := coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
415
418
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
@@ -466,41 +469,50 @@ func TestWorkspaceAutobuild(t *testing.T) {
466
469
ctr .InactivityTTLMillis = ptr.Ref [int64 ](transitionTTL .Milliseconds ())
467
470
ctr .LockedTTLMillis = ptr.Ref [int64 ](transitionTTL .Milliseconds ())
468
471
})
469
-
470
472
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
473
+
471
474
ws := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
472
475
build := coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
473
476
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
477
+
474
478
require .Eventually (t ,
475
479
func () bool {
476
480
return database .Now ().Sub (ws .LastUsedAt ) > transitionTTL
477
481
},
478
482
testutil .IntervalMedium , testutil .IntervalFast )
483
+
479
484
ticker <- time .Now ()
480
485
stats := <- statCh
481
486
// Expect workspace to transition to stopped state for breaching
482
487
// inactive TTL.
483
488
require .Len (t , stats .Transitions , 1 )
484
489
require .Equal (t , stats .Transitions [ws .ID ], database .WorkspaceTransitionStop )
490
+
485
491
ws = coderdtest .MustWorkspace (t , client , ws .ID )
486
492
// The workspace should be locked.
487
493
require .NotNil (t , ws .LockedAt )
494
+
495
+ // Wait for the autobuilder to stop the workspace.
488
496
_ = coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
489
- // Wait for the workspace to breach the locked threshold.
497
+
498
+ // Wait to trigger our locked threshold.
490
499
require .Eventually (t ,
491
500
func () bool {
492
501
return database .Now ().Sub (* ws .LockedAt ) > transitionTTL
493
502
},
494
503
testutil .IntervalMedium , testutil .IntervalFast )
504
+
495
505
ticker <- time .Now ()
496
506
stats = <- statCh
497
507
require .Len (t , stats .Transitions , 1 )
498
508
// The workspace should be scheduled for deletion.
499
509
require .Equal (t , stats .Transitions [ws .ID ], database .WorkspaceTransitionDelete )
500
510
511
+ // Wait for the workspace to be deleted.
501
512
ws = coderdtest .MustWorkspace (t , client , ws .ID )
502
513
_ = coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
503
514
515
+ // Assert that the workspace is actually deleted.
504
516
_ , err := client .Workspace (testutil .Context (t , testutil .WaitShort ), ws .ID )
505
517
require .Error (t , err )
506
518
cerr , ok := codersdk .AsError (err )
@@ -575,11 +587,11 @@ func TestWorkspaceAutobuild(t *testing.T) {
575
587
576
588
ticker <- time .Now ()
577
589
stats = <- statCh
578
- // Expect no transitions since not enough time has elapsed.
579
590
require .Len (t , stats .Transitions , 1 )
580
591
require .Equal (t , database .WorkspaceTransitionDelete , stats .Transitions [ws .ID ])
581
592
})
582
593
594
+ // Assert that a locked workspace does not autostart.
583
595
t .Run ("LockedNoAutostart" , func (t * testing.T ) {
584
596
t .Parallel ()
585
597
@@ -621,12 +633,12 @@ func TestWorkspaceAutobuild(t *testing.T) {
621
633
622
634
// Assert that autostart works when the workspace isn't locked..
623
635
tickCh <- sched .Next (ws .LatestBuild .CreatedAt )
624
- // Then: the workspace should eventually be started
625
636
stats := <- statsCh
626
637
require .NoError (t , stats .Error )
627
638
require .Len (t , stats .Transitions , 1 )
628
639
require .Contains (t , stats .Transitions , ws .ID )
629
640
require .Equal (t , database .WorkspaceTransitionStart , stats .Transitions [ws .ID ])
641
+
630
642
ws = coderdtest .MustWorkspace (t , client , ws .ID )
631
643
coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
632
644
@@ -643,21 +655,21 @@ func TestWorkspaceAutobuild(t *testing.T) {
643
655
},
644
656
testutil .IntervalMedium , testutil .IntervalFast )
645
657
658
+ // We should see the workspace get stopped now.
646
659
tickCh <- time .Now ()
647
- // Then: the workspace should eventually be started
648
660
stats = <- statsCh
649
661
require .NoError (t , stats .Error )
650
662
require .Len (t , stats .Transitions , 1 )
651
663
require .Contains (t , stats .Transitions , ws .ID )
652
664
require .Equal (t , database .WorkspaceTransitionStop , stats .Transitions [ws .ID ])
665
+
666
+ // The workspace should be locked now.
653
667
ws = coderdtest .MustWorkspace (t , client , ws .ID )
654
668
coderdtest .AwaitWorkspaceBuildJob (t , client , ws .LatestBuild .ID )
655
- // The workspace should be locked now.
656
669
require .NotNil (t , ws .LockedAt )
657
670
658
671
// Assert that autostart is no longer triggered since workspace is locked.
659
672
tickCh <- sched .Next (ws .LatestBuild .CreatedAt )
660
- // Then: the workspace should eventually be started
661
673
stats = <- statsCh
662
674
require .Len (t , stats .Transitions , 0 )
663
675
})
0 commit comments