@@ -11,6 +11,7 @@ import (
11
11
"time"
12
12
13
13
gliderssh "github.com/gliderlabs/ssh"
14
+ "github.com/google/uuid"
14
15
"github.com/stretchr/testify/assert"
15
16
"github.com/stretchr/testify/require"
16
17
"golang.org/x/crypto/ssh"
@@ -346,3 +347,195 @@ func newAsyncCloser(ctx context.Context, t *testing.T) *asyncCloser {
346
347
started : make (chan struct {}),
347
348
}
348
349
}
350
+
351
+ func Test_getWorkspaceAgent (t * testing.T ) {
352
+ t .Parallel ()
353
+
354
+ createWorkspaceWithAgents := func (agents []codersdk.WorkspaceAgent ) codersdk.Workspace {
355
+ return codersdk.Workspace {
356
+ Name : "test-workspace" ,
357
+ LatestBuild : codersdk.WorkspaceBuild {
358
+ Resources : []codersdk.WorkspaceResource {
359
+ {
360
+ Agents : agents ,
361
+ },
362
+ },
363
+ },
364
+ }
365
+ }
366
+
367
+ createAgent := func (name string ) codersdk.WorkspaceAgent {
368
+ return codersdk.WorkspaceAgent {
369
+ ID : uuid .New (),
370
+ Name : name ,
371
+ ParentID : uuid.NullUUID {},
372
+ }
373
+ }
374
+
375
+ createSubAgent := func (name string , parentID uuid.UUID ) codersdk.WorkspaceAgent {
376
+ return codersdk.WorkspaceAgent {
377
+ ID : uuid .New (),
378
+ Name : name ,
379
+ ParentID : uuid.NullUUID {
380
+ UUID : parentID ,
381
+ Valid : true ,
382
+ },
383
+ }
384
+ }
385
+
386
+ t .Run ("SingleAgent_NoNameSpecified" , func (t * testing.T ) {
387
+ t .Parallel ()
388
+ agent := createAgent ("main" )
389
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent })
390
+
391
+ result , err := getWorkspaceAgent (workspace , "" )
392
+ require .NoError (t , err )
393
+ assert .Equal (t , agent .ID , result .ID )
394
+ assert .Equal (t , "main" , result .Name )
395
+ })
396
+
397
+ t .Run ("SingleSubAgent_NoNameSpecified" , func (t * testing.T ) {
398
+ t .Parallel ()
399
+ parentAgent := createAgent ("main" )
400
+ subAgent := createSubAgent ("devcontainer" , parentAgent .ID )
401
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {parentAgent , subAgent })
402
+
403
+ // Should prefer the sub-agent when no name is specified.
404
+ result , err := getWorkspaceAgent (workspace , "" )
405
+ require .NoError (t , err )
406
+ assert .Equal (t , subAgent .ID , result .ID )
407
+ assert .Equal (t , "devcontainer" , result .Name )
408
+ })
409
+
410
+ t .Run ("MultipleAgents_NoSubAgents_NoNameSpecified" , func (t * testing.T ) {
411
+ t .Parallel ()
412
+ agent1 := createAgent ("main1" )
413
+ agent2 := createAgent ("main2" )
414
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent1 , agent2 })
415
+
416
+ _ , err := getWorkspaceAgent (workspace , "" )
417
+ require .Error (t , err )
418
+ assert .Contains (t , err .Error (), "multiple agents found" )
419
+ assert .Contains (t , err .Error (), "available agents: [main1 main2]" )
420
+ })
421
+
422
+ t .Run ("MultipleSubAgents_NoNameSpecified" , func (t * testing.T ) {
423
+ t .Parallel ()
424
+ parentAgent := createAgent ("main" )
425
+ subAgent1 := createSubAgent ("devcontainer1" , parentAgent .ID )
426
+ subAgent2 := createSubAgent ("devcontainer2" , parentAgent .ID )
427
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {parentAgent , subAgent1 , subAgent2 })
428
+
429
+ _ , err := getWorkspaceAgent (workspace , "" )
430
+ require .Error (t , err )
431
+ assert .Contains (t , err .Error (), "multiple sub-agents found" )
432
+ assert .Contains (t , err .Error (), "available agents: [devcontainer1 devcontainer2 main]" )
433
+ })
434
+
435
+ t .Run ("AgentNameSpecified_Found_RegularAgent" , func (t * testing.T ) {
436
+ t .Parallel ()
437
+ agent1 := createAgent ("main1" )
438
+ agent2 := createAgent ("main2" )
439
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent1 , agent2 })
440
+
441
+ result , err := getWorkspaceAgent (workspace , "main1" )
442
+ require .NoError (t , err )
443
+ assert .Equal (t , agent1 .ID , result .ID )
444
+ assert .Equal (t , "main1" , result .Name )
445
+ })
446
+
447
+ t .Run ("AgentNameSpecified_Found_SubAgent" , func (t * testing.T ) {
448
+ t .Parallel ()
449
+ agent := createAgent ("main" )
450
+ subAgent := createSubAgent ("devcontainer" , agent .ID )
451
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent , subAgent })
452
+
453
+ result , err := getWorkspaceAgent (workspace , "devcontainer" )
454
+ require .NoError (t , err )
455
+ assert .Equal (t , subAgent .ID , result .ID )
456
+ assert .Equal (t , "devcontainer" , result .Name )
457
+ })
458
+
459
+ t .Run ("AgentNameSpecified_NotFound" , func (t * testing.T ) {
460
+ t .Parallel ()
461
+ agent1 := createAgent ("main1" )
462
+ agent2 := createAgent ("main2" )
463
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent1 , agent2 })
464
+
465
+ _ , err := getWorkspaceAgent (workspace , "nonexistent" )
466
+ require .Error (t , err )
467
+ assert .Contains (t , err .Error (), `agent not found by name "nonexistent"` )
468
+ assert .Contains (t , err .Error (), "available agents: [main1 main2]" )
469
+ })
470
+
471
+ t .Run ("NoAgents" , func (t * testing.T ) {
472
+ t .Parallel ()
473
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {})
474
+
475
+ _ , err := getWorkspaceAgent (workspace , "" )
476
+ require .Error (t , err )
477
+ assert .Contains (t , err .Error (), `workspace "test-workspace" has no agents` )
478
+ })
479
+
480
+ t .Run ("MixedAgents_SubAgentPreferred" , func (t * testing.T ) {
481
+ t .Parallel ()
482
+ agent := createAgent ("main" )
483
+ subAgent := createSubAgent ("devcontainer" , agent .ID )
484
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent , subAgent })
485
+
486
+ // When no name is specified and there's one sub-agent,
487
+ // it should be preferred.
488
+ result , err := getWorkspaceAgent (workspace , "" )
489
+ require .NoError (t , err )
490
+ assert .Equal (t , subAgent .ID , result .ID )
491
+ assert .Equal (t , "devcontainer" , result .Name )
492
+ })
493
+
494
+ t .Run ("MixedAgents_SpecificNameFound" , func (t * testing.T ) {
495
+ t .Parallel ()
496
+ agent := createAgent ("main" )
497
+ subAgent := createSubAgent ("devcontainer" , agent .ID )
498
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent , subAgent })
499
+
500
+ // Should be able to find regular agent by name.
501
+ result , err := getWorkspaceAgent (workspace , "main" )
502
+ require .NoError (t , err )
503
+ assert .Equal (t , agent .ID , result .ID )
504
+ assert .Equal (t , "main" , result .Name )
505
+
506
+ // Should be able to find sub-agent by name.
507
+ result , err = getWorkspaceAgent (workspace , "devcontainer" )
508
+ require .NoError (t , err )
509
+ assert .Equal (t , subAgent .ID , result .ID )
510
+ assert .Equal (t , "devcontainer" , result .Name )
511
+ })
512
+
513
+ t .Run ("AvailableAgentNames_SortedCorrectly" , func (t * testing.T ) {
514
+ t .Parallel ()
515
+ // Define agents in non-alphabetical order.
516
+ agent2 := createAgent ("zod" )
517
+ agent1 := createAgent ("clark" )
518
+ subAgent := createSubAgent ("krypton" , agent1 .ID )
519
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent2 , agent1 , subAgent })
520
+
521
+ _ , err := getWorkspaceAgent (workspace , "nonexistent" )
522
+ require .Error (t , err )
523
+ // Available agents should be sorted alphabetically.
524
+ assert .Contains (t , err .Error (), "available agents: [clark krypton zod]" )
525
+ })
526
+
527
+ t .Run ("MultipleAgentsAndSubAgents_NoNameSpecified" , func (t * testing.T ) {
528
+ t .Parallel ()
529
+ agent1 := createAgent ("main1" )
530
+ agent2 := createAgent ("main2" )
531
+ subAgent1 := createSubAgent ("dev1" , agent1 .ID )
532
+ subAgent2 := createSubAgent ("dev2" , agent1 .ID )
533
+ workspace := createWorkspaceWithAgents ([]codersdk.WorkspaceAgent {agent1 , agent2 , subAgent1 , subAgent2 })
534
+
535
+ // Should error because there are multiple sub-agents.
536
+ _ , err := getWorkspaceAgent (workspace , "" )
537
+ require .Error (t , err )
538
+ assert .Contains (t , err .Error (), "multiple sub-agents found" )
539
+ assert .Contains (t , err .Error (), "available agents: [dev1 dev2 main1 main2]" )
540
+ })
541
+ }
0 commit comments