@@ -3,6 +3,7 @@ package agentcontainers
3
3
import (
4
4
"fmt"
5
5
"os"
6
+ "path/filepath"
6
7
"slices"
7
8
"strconv"
8
9
"strings"
@@ -11,6 +12,7 @@ import (
11
12
12
13
"go.uber.org/mock/gomock"
13
14
15
+ "github.com/google/go-cmp/cmp"
14
16
"github.com/google/uuid"
15
17
"github.com/ory/dockertest/v3"
16
18
"github.com/ory/dockertest/v3/docker"
@@ -412,6 +414,216 @@ func TestConvertDockerVolume(t *testing.T) {
412
414
}
413
415
}
414
416
417
+ // TestConvertDockerInspect tests the convertDockerInspect function using
418
+ // fixtures from ./testdata.
419
+ func TestConvertDockerInspect (t * testing.T ) {
420
+ t .Parallel ()
421
+
422
+ for _ ,tt := range []struct {
423
+ name string
424
+ expect []codersdk.WorkspaceAgentDevcontainer
425
+ expectWarns []string
426
+ expectError string
427
+ }{
428
+ {
429
+ name :"container_simple" ,
430
+ expect : []codersdk.WorkspaceAgentDevcontainer {
431
+ {
432
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,55 ,58 ,91280203 ,time .UTC ),
433
+ ID :"6b539b8c60f5230b8b0fde2502cd2332d31c0d526a3e6eb6eef1cc39439b3286" ,
434
+ FriendlyName :"eloquent_kowalevski" ,
435
+ Image :"debian:bookworm" ,
436
+ Labels :map [string ]string {},
437
+ Running :true ,
438
+ Status :"running" ,
439
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
440
+ Volumes :map [string ]string {},
441
+ },
442
+ },
443
+ },
444
+ {
445
+ name :"container_labels" ,
446
+ expect : []codersdk.WorkspaceAgentDevcontainer {
447
+ {
448
+ CreatedAt :time .Date (2025 ,3 ,11 ,20 ,3 ,28 ,71706536 ,time .UTC ),
449
+ ID :"bd8818e670230fc6f36145b21cf8d6d35580355662aa4d9fe5ae1b188a4c905f" ,
450
+ FriendlyName :"fervent_bardeen" ,
451
+ Image :"debian:bookworm" ,
452
+ Labels :map [string ]string {"baz" :"zap" ,"foo" :"bar" },
453
+ Running :true ,
454
+ Status :"running" ,
455
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
456
+ Volumes :map [string ]string {},
457
+ },
458
+ },
459
+ },
460
+ {
461
+ name :"container_binds" ,
462
+ expect : []codersdk.WorkspaceAgentDevcontainer {
463
+ {
464
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,58 ,43 ,522505027 ,time .UTC ),
465
+ ID :"fdc75ebefdc0243c0fce959e7685931691ac7aede278664a0e2c23af8a1e8d6a" ,
466
+ FriendlyName :"silly_beaver" ,
467
+ Image :"debian:bookworm" ,
468
+ Labels :map [string ]string {},
469
+ Running :true ,
470
+ Status :"running" ,
471
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
472
+ Volumes :map [string ]string {
473
+ "/tmp/test/a" :"/var/coder/a" ,
474
+ "/tmp/test/b" :"/var/coder/b" ,
475
+ },
476
+ },
477
+ },
478
+ },
479
+ {
480
+ name :"container_sameport" ,
481
+ expect : []codersdk.WorkspaceAgentDevcontainer {
482
+ {
483
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,56 ,34 ,842164541 ,time .UTC ),
484
+ ID :"4eac5ce199d27b2329d0ff0ce1a6fc595612ced48eba3669aadb6c57ebef3fa2" ,
485
+ FriendlyName :"modest_varahamihira" ,
486
+ Image :"debian:bookworm" ,
487
+ Labels :map [string ]string {},
488
+ Running :true ,
489
+ Status :"running" ,
490
+ Ports : []codersdk.WorkspaceAgentListeningPort {
491
+ {
492
+ Network :"tcp" ,
493
+ Port :12345 ,
494
+ },
495
+ },
496
+ Volumes :map [string ]string {},
497
+ },
498
+ },
499
+ },
500
+ {
501
+ name :"container_differentport" ,
502
+ expect : []codersdk.WorkspaceAgentDevcontainer {
503
+ {
504
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,57 ,8 ,862545133 ,time .UTC ),
505
+ ID :"3090de8b72b1224758a94a11b827c82ba2b09c45524f1263dc4a2d83e19625ea" ,
506
+ FriendlyName :"boring_ellis" ,
507
+ Image :"debian:bookworm" ,
508
+ Labels :map [string ]string {},
509
+ Running :true ,
510
+ Status :"running" ,
511
+ Ports : []codersdk.WorkspaceAgentListeningPort {
512
+ {
513
+ Network :"tcp" ,
514
+ Port :23456 ,
515
+ },
516
+ },
517
+ Volumes :map [string ]string {},
518
+ },
519
+ },
520
+ },
521
+ {
522
+ name :"container_volume" ,
523
+ expect : []codersdk.WorkspaceAgentDevcontainer {
524
+ {
525
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,59 ,42 ,39484134 ,time .UTC ),
526
+ ID :"b3688d98c007f53402a55e46d803f2f3ba9181d8e3f71a2eb19b392cf0377b4e" ,
527
+ FriendlyName :"upbeat_carver" ,
528
+ Image :"debian:bookworm" ,
529
+ Labels :map [string ]string {},
530
+ Running :true ,
531
+ Status :"running" ,
532
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
533
+ Volumes :map [string ]string {
534
+ "/var/lib/docker/volumes/testvol/_data" :"/testvol" ,
535
+ },
536
+ },
537
+ },
538
+ },
539
+ {
540
+ name :"devcontainer_simple" ,
541
+ expect : []codersdk.WorkspaceAgentDevcontainer {
542
+ {
543
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,1 ,5 ,751972661 ,time .UTC ),
544
+ ID :"0b2a9fcf5727d9562943ce47d445019f4520e37a2aa7c6d9346d01af4f4f9aed" ,
545
+ FriendlyName :"optimistic_hopper" ,
546
+ Image :"debian:bookworm" ,
547
+ Labels :map [string ]string {
548
+ "devcontainer.config_file" :"/home/coder/src/coder/coder/agent/agentcontainers/testdata/devcontainer_simple.json" ,
549
+ "devcontainer.metadata" :"[]" ,
550
+ },
551
+ Running :true ,
552
+ Status :"running" ,
553
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
554
+ Volumes :map [string ]string {},
555
+ },
556
+ },
557
+ },
558
+ {
559
+ name :"devcontainer_forwardport" ,
560
+ expect : []codersdk.WorkspaceAgentDevcontainer {
561
+ {
562
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,3 ,55 ,22053072 ,time .UTC ),
563
+ ID :"4a16af2293fb75dc827a6949a3905dd57ea28cc008823218ce24fab1cb66c067" ,
564
+ FriendlyName :"serene_khayyam" ,
565
+ Image :"debian:bookworm" ,
566
+ Labels :map [string ]string {
567
+ "devcontainer.config_file" :"/home/coder/src/coder/coder/agent/agentcontainers/testdata/devcontainer_forwardport.json" ,
568
+ "devcontainer.metadata" :"[]" ,
569
+ },
570
+ Running :true ,
571
+ Status :"running" ,
572
+ Ports : []codersdk.WorkspaceAgentListeningPort {},
573
+ Volumes :map [string ]string {},
574
+ },
575
+ },
576
+ },
577
+ {
578
+ name :"devcontainer_appport" ,
579
+ expect : []codersdk.WorkspaceAgentDevcontainer {
580
+ {
581
+ CreatedAt :time .Date (2025 ,3 ,11 ,17 ,2 ,42 ,613747761 ,time .UTC ),
582
+ ID :"52d23691f4b954d083f117358ea763e20f69af584e1c08f479c5752629ee0be3" ,
583
+ FriendlyName :"suspicious_margulis" ,
584
+ Image :"debian:bookworm" ,
585
+ Labels :map [string ]string {
586
+ "devcontainer.config_file" :"/home/coder/src/coder/coder/agent/agentcontainers/testdata/devcontainer_appport.json" ,
587
+ "devcontainer.metadata" :"[]" ,
588
+ },
589
+ Running :true ,
590
+ Status :"running" ,
591
+ Ports : []codersdk.WorkspaceAgentListeningPort {
592
+ {
593
+ Network :"tcp" ,
594
+ Port :8080 ,
595
+ },
596
+ },
597
+ Volumes :map [string ]string {},
598
+ },
599
+ },
600
+ },
601
+ } {
602
+ // nolint:paralleltest // variable recapture no longer required
603
+ t .Run (tt .name ,func (t * testing.T ) {
604
+ t .Parallel ()
605
+ bs ,err := os .ReadFile (filepath .Join ("testdata" ,tt .name + ".json" ))
606
+ require .NoError (t ,err ,"failed to read testdata file" )
607
+ actual ,warns ,err := convertDockerInspect (string (bs ))
608
+ if len (tt .expectWarns )> 0 {
609
+ assert .Len (t ,warns ,len (tt .expectWarns ),"expected warnings" )
610
+ for _ ,warn := range tt .expectWarns {
611
+ assert .Contains (t ,warns ,warn )
612
+ }
613
+ }
614
+ if tt .expectError != "" {
615
+ assert .Empty (t ,actual ,"expected no data" )
616
+ assert .ErrorContains (t ,err ,tt .expectError )
617
+ return
618
+ }
619
+ require .NoError (t ,err ,"expected no error" )
620
+ if diff := cmp .Diff (tt .expect ,actual );diff != "" {
621
+ t .Errorf ("unexpected diff (-want +got):\n %s" ,diff )
622
+ }
623
+ })
624
+ }
625
+ }
626
+
415
627
// TestDockerEnvInfoer tests the ability of EnvInfo to extract information from
416
628
// running containers. Containers are deleted after the test is complete.
417
629
// As this test creates containers, it is skipped by default.