@@ -71,6 +71,7 @@ func (f *fakeContainerCLI) ExecAs(ctx context.Context, name, user string, args .
71
71
// fakeDevcontainerCLI implements the agentcontainers.DevcontainerCLI
72
72
// interface for testing.
73
73
type fakeDevcontainerCLI struct {
74
+ up func (workspaceFolder , configPath string ) (string , error )
74
75
upID string
75
76
upErr error
76
77
upErrC chan func () error // If set, send to return err, close to return upErr.
@@ -79,9 +80,14 @@ type fakeDevcontainerCLI struct {
79
80
readConfig agentcontainers.DevcontainerConfig
80
81
readConfigErr error
81
82
readConfigErrC chan func (envs []string ) error
83
+
84
+ configMap map [string ]agentcontainers.DevcontainerConfig // By config path
82
85
}
83
86
84
- func (f * fakeDevcontainerCLI ) Up (ctx context.Context , _ , _ string , _ ... agentcontainers.DevcontainerCLIUpOptions ) (string , error ) {
87
+ func (f * fakeDevcontainerCLI ) Up (ctx context.Context , workspaceFolder , configPath string , _ ... agentcontainers.DevcontainerCLIUpOptions ) (string , error ) {
88
+ if f .up != nil {
89
+ return f .up (workspaceFolder , configPath )
90
+ }
85
91
if f .upErrC != nil {
86
92
select {
87
93
case <- ctx .Done ():
@@ -109,7 +115,12 @@ func (f *fakeDevcontainerCLI) Exec(ctx context.Context, _, _ string, cmd string,
109
115
return f .execErr
110
116
}
111
117
112
- func (f * fakeDevcontainerCLI ) ReadConfig (ctx context.Context , _ , _ string , envs []string , _ ... agentcontainers.DevcontainerCLIReadConfigOptions ) (agentcontainers.DevcontainerConfig , error ) {
118
+ func (f * fakeDevcontainerCLI ) ReadConfig (ctx context.Context , _ , configPath string , envs []string , _ ... agentcontainers.DevcontainerCLIReadConfigOptions ) (agentcontainers.DevcontainerConfig , error ) {
119
+ if f .configMap != nil {
120
+ if v , found := f .configMap [configPath ]; found {
121
+ return v , f .readConfigErr
122
+ }
123
+ }
113
124
if f .readConfigErrC != nil {
114
125
select {
115
126
case <- ctx .Done ():
@@ -3576,193 +3587,112 @@ func TestDevcontainerDiscovery(t *testing.T) {
3576
3587
name string
3577
3588
agentDir string
3578
3589
fs map [string ]string
3590
+ configMap map [string ]agentcontainers.DevcontainerConfig
3579
3591
expectDevcontainerCount int
3580
- setupMocks func ( mDCCLI * acmock. MockDevcontainerCLI )
3592
+ expectUpCalledCount int
3581
3593
}{
3582
3594
{
3583
3595
name : "SingleEnabled" ,
3584
3596
agentDir : "/home/coder" ,
3585
3597
expectDevcontainerCount : 1 ,
3598
+ expectUpCalledCount : 1 ,
3586
3599
fs : map [string ]string {
3587
3600
"/home/coder/.git/HEAD" : "" ,
3588
3601
"/home/coder/.devcontainer/devcontainer.json" : "" ,
3589
3602
},
3590
- setupMocks : func (mDCCLI * acmock.MockDevcontainerCLI ) {
3591
- gomock .InOrder (
3592
- // Given: This dev container has auto start enabled.
3593
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3594
- "/home/coder" ,
3595
- "/home/coder/.devcontainer/devcontainer.json" ,
3596
- []string {},
3597
- ).Return (agentcontainers.DevcontainerConfig {
3598
- Configuration : agentcontainers.DevcontainerConfiguration {
3599
- Customizations : agentcontainers.DevcontainerCustomizations {
3600
- Coder : agentcontainers.CoderCustomization {
3601
- AutoStart : true ,
3602
- },
3603
+ configMap : map [string ]agentcontainers.DevcontainerConfig {
3604
+ "/home/coder/.devcontainer/devcontainer.json" : {
3605
+ Configuration : agentcontainers.DevcontainerConfiguration {
3606
+ Customizations : agentcontainers.DevcontainerCustomizations {
3607
+ Coder : agentcontainers.CoderCustomization {
3608
+ AutoStart : true ,
3603
3609
},
3604
3610
},
3605
- }, nil ),
3606
-
3607
- // Then: We expect it to be started.
3608
- mDCCLI .EXPECT ().Up (gomock .Any (),
3609
- "/home/coder" ,
3610
- "/home/coder/.devcontainer/devcontainer.json" ,
3611
- gomock .Any (),
3612
- ).Return ("" , nil ),
3613
- )
3611
+ },
3612
+ },
3614
3613
},
3615
3614
},
3616
3615
{
3617
3616
name : "SingleDisabled" ,
3618
3617
agentDir : "/home/coder" ,
3619
3618
expectDevcontainerCount : 1 ,
3619
+ expectUpCalledCount : 0 ,
3620
3620
fs : map [string ]string {
3621
3621
"/home/coder/.git/HEAD" : "" ,
3622
3622
"/home/coder/.devcontainer/devcontainer.json" : "" ,
3623
3623
},
3624
- setupMocks : func (mDCCLI * acmock.MockDevcontainerCLI ) {
3625
- gomock .InOrder (
3626
- // Given: This dev container has auto start disabled.
3627
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3628
- "/home/coder" ,
3629
- "/home/coder/.devcontainer/devcontainer.json" ,
3630
- []string {},
3631
- ).Return (agentcontainers.DevcontainerConfig {
3632
- Configuration : agentcontainers.DevcontainerConfiguration {
3633
- Customizations : agentcontainers.DevcontainerCustomizations {
3634
- Coder : agentcontainers.CoderCustomization {
3635
- AutoStart : false ,
3636
- },
3624
+ configMap : map [string ]agentcontainers.DevcontainerConfig {
3625
+ "/home/coder/.devcontainer/devcontainer.json" : {
3626
+ Configuration : agentcontainers.DevcontainerConfiguration {
3627
+ Customizations : agentcontainers.DevcontainerCustomizations {
3628
+ Coder : agentcontainers.CoderCustomization {
3629
+ AutoStart : false ,
3637
3630
},
3638
3631
},
3639
- }, nil ),
3640
-
3641
- // Then: We expect it to _not_ be started.
3642
- mDCCLI .EXPECT ().Up (gomock .Any (),
3643
- "/home/coder" ,
3644
- "/home/coder/.devcontainer/devcontainer.json" ,
3645
- gomock .Any (),
3646
- ).Return ("" , nil ).Times (0 ),
3647
- )
3632
+ },
3633
+ },
3648
3634
},
3649
3635
},
3650
3636
{
3651
3637
name : "OneEnabledOneDisabled" ,
3652
3638
agentDir : "/home/coder" ,
3653
3639
expectDevcontainerCount : 2 ,
3640
+ expectUpCalledCount : 1 ,
3654
3641
fs : map [string ]string {
3655
3642
"/home/coder/.git/HEAD" : "" ,
3656
3643
"/home/coder/.devcontainer/devcontainer.json" : "" ,
3657
3644
"/home/coder/project/.devcontainer.json" : "" ,
3658
3645
},
3659
- setupMocks : func (mDCCLI * acmock.MockDevcontainerCLI ) {
3660
- gomock .InOrder (
3661
- // Given: This dev container has auto start enabled.
3662
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3663
- "/home/coder" ,
3664
- "/home/coder/.devcontainer/devcontainer.json" ,
3665
- []string {},
3666
- ).Return (agentcontainers.DevcontainerConfig {
3667
- Configuration : agentcontainers.DevcontainerConfiguration {
3668
- Customizations : agentcontainers.DevcontainerCustomizations {
3669
- Coder : agentcontainers.CoderCustomization {
3670
- AutoStart : true ,
3671
- },
3646
+ configMap : map [string ]agentcontainers.DevcontainerConfig {
3647
+ "/home/coder/.devcontainer/devcontainer.json" : {
3648
+ Configuration : agentcontainers.DevcontainerConfiguration {
3649
+ Customizations : agentcontainers.DevcontainerCustomizations {
3650
+ Coder : agentcontainers.CoderCustomization {
3651
+ AutoStart : true ,
3672
3652
},
3673
3653
},
3674
- }, nil ),
3675
-
3676
- // Then: We expect it to be started.
3677
- mDCCLI .EXPECT ().Up (gomock .Any (),
3678
- "/home/coder" ,
3679
- "/home/coder/.devcontainer/devcontainer.json" ,
3680
- gomock .Any (),
3681
- ).Return ("" , nil ),
3682
- )
3683
-
3684
- gomock .InOrder (
3685
- // Given: This dev container has auto start disabled.
3686
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3687
- "/home/coder/project" ,
3688
- "/home/coder/project/.devcontainer.json" ,
3689
- []string {},
3690
- ).Return (agentcontainers.DevcontainerConfig {
3691
- Configuration : agentcontainers.DevcontainerConfiguration {
3692
- Customizations : agentcontainers.DevcontainerCustomizations {
3693
- Coder : agentcontainers.CoderCustomization {
3694
- AutoStart : false ,
3695
- },
3654
+ },
3655
+ },
3656
+ "/home/coder/project/.devcontainer.json" : {
3657
+ Configuration : agentcontainers.DevcontainerConfiguration {
3658
+ Customizations : agentcontainers.DevcontainerCustomizations {
3659
+ Coder : agentcontainers.CoderCustomization {
3660
+ AutoStart : false ,
3696
3661
},
3697
3662
},
3698
- }, nil ),
3699
-
3700
- // Then: We expect it to _not_ be started.
3701
- mDCCLI .EXPECT ().Up (gomock .Any (),
3702
- "/home/coder/project" ,
3703
- "/home/coder/project/.devcontainer.json" ,
3704
- gomock .Any (),
3705
- ).Return ("" , nil ).Times (0 ),
3706
- )
3663
+ },
3664
+ },
3707
3665
},
3708
3666
},
3709
3667
{
3710
3668
name : "MultipleEnabled" ,
3711
3669
agentDir : "/home/coder" ,
3712
3670
expectDevcontainerCount : 2 ,
3671
+ expectUpCalledCount : 2 ,
3713
3672
fs : map [string ]string {
3714
3673
"/home/coder/.git/HEAD" : "" ,
3715
3674
"/home/coder/.devcontainer/devcontainer.json" : "" ,
3716
3675
"/home/coder/project/.devcontainer.json" : "" ,
3717
3676
},
3718
- setupMocks : func (mDCCLI * acmock.MockDevcontainerCLI ) {
3719
- gomock .InOrder (
3720
- // Given: This dev container has auto start enabled.
3721
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3722
- "/home/coder" ,
3723
- "/home/coder/.devcontainer/devcontainer.json" ,
3724
- []string {},
3725
- ).Return (agentcontainers.DevcontainerConfig {
3726
- Configuration : agentcontainers.DevcontainerConfiguration {
3727
- Customizations : agentcontainers.DevcontainerCustomizations {
3728
- Coder : agentcontainers.CoderCustomization {
3729
- AutoStart : true ,
3730
- },
3677
+ configMap : map [string ]agentcontainers.DevcontainerConfig {
3678
+ "/home/coder/.devcontainer/devcontainer.json" : {
3679
+ Configuration : agentcontainers.DevcontainerConfiguration {
3680
+ Customizations : agentcontainers.DevcontainerCustomizations {
3681
+ Coder : agentcontainers.CoderCustomization {
3682
+ AutoStart : true ,
3731
3683
},
3732
3684
},
3733
- }, nil ),
3734
-
3735
- // Then: We expect it to be started.
3736
- mDCCLI .EXPECT ().Up (gomock .Any (),
3737
- "/home/coder" ,
3738
- "/home/coder/.devcontainer/devcontainer.json" ,
3739
- gomock .Any (),
3740
- ).Return ("" , nil ),
3741
- )
3742
-
3743
- gomock .InOrder (
3744
- // Given: This dev container has auto start enabled.
3745
- mDCCLI .EXPECT ().ReadConfig (gomock .Any (),
3746
- "/home/coder/project" ,
3747
- "/home/coder/project/.devcontainer.json" ,
3748
- []string {},
3749
- ).Return (agentcontainers.DevcontainerConfig {
3750
- Configuration : agentcontainers.DevcontainerConfiguration {
3751
- Customizations : agentcontainers.DevcontainerCustomizations {
3752
- Coder : agentcontainers.CoderCustomization {
3753
- AutoStart : true ,
3754
- },
3685
+ },
3686
+ },
3687
+ "/home/coder/project/.devcontainer.json" : {
3688
+ Configuration : agentcontainers.DevcontainerConfiguration {
3689
+ Customizations : agentcontainers.DevcontainerCustomizations {
3690
+ Coder : agentcontainers.CoderCustomization {
3691
+ AutoStart : true ,
3755
3692
},
3756
3693
},
3757
- }, nil ),
3758
-
3759
- // Then: We expect it to be started.
3760
- mDCCLI .EXPECT ().Up (gomock .Any (),
3761
- "/home/coder/project" ,
3762
- "/home/coder/project/.devcontainer.json" ,
3763
- gomock .Any (),
3764
- ).Return ("" , nil ),
3765
- )
3694
+ },
3695
+ },
3766
3696
},
3767
3697
},
3768
3698
}
@@ -3775,43 +3705,73 @@ func TestDevcontainerDiscovery(t *testing.T) {
3775
3705
ctx = testutil .Context (t , testutil .WaitShort )
3776
3706
logger = testutil .Logger (t )
3777
3707
mClock = quartz .NewMock (t )
3778
- mDCCLI = acmock .NewMockDevcontainerCLI (gomock .NewController (t ))
3708
+
3709
+ upCalledMu sync.Mutex
3710
+ upCalledFor = map [string ]bool {}
3711
+
3712
+ fCCLI = & fakeContainerCLI {}
3713
+ fDCCLI = & fakeDevcontainerCLI {
3714
+ configMap : tt .configMap ,
3715
+ up : func (_ , configPath string ) (string , error ) {
3716
+ upCalledMu .Lock ()
3717
+ upCalledFor [configPath ] = true
3718
+ upCalledMu .Unlock ()
3719
+ return "" , nil
3720
+ },
3721
+ }
3779
3722
3780
3723
r = chi .NewRouter ()
3781
3724
)
3782
3725
3783
- // Given: We setup our mocks. These mocks handle our expectations for these
3784
- // tests. If there are missing/unexpected mock calls, the test will fail.
3785
- tt .setupMocks (mDCCLI )
3786
-
3787
3726
api := agentcontainers .NewAPI (logger ,
3788
3727
agentcontainers .WithClock (mClock ),
3789
3728
agentcontainers .WithWatcher (watcher .NewNoop ()),
3790
3729
agentcontainers .WithFileSystem (initFS (t , tt .fs )),
3791
3730
agentcontainers .WithManifestInfo ("owner" , "workspace" , "parent-agent" , "/home/coder" ),
3792
- agentcontainers .WithContainerCLI (& fakeContainerCLI {} ),
3793
- agentcontainers .WithDevcontainerCLI (mDCCLI ),
3731
+ agentcontainers .WithContainerCLI (fCCLI ),
3732
+ agentcontainers .WithDevcontainerCLI (fDCCLI ),
3794
3733
agentcontainers .WithProjectDiscovery (true ),
3795
3734
agentcontainers .WithDiscoveryAutostart (true ),
3796
3735
)
3797
3736
api .Start ()
3798
- defer api .Close ()
3799
3737
r .Mount ("/" , api .Routes ())
3800
3738
3801
- // When: All expected dev containers have been found.
3739
+ // Given: We allow the discover routing to progress
3740
+ var got codersdk.WorkspaceAgentListContainersResponse
3802
3741
require .Eventuallyf (t , func () bool {
3803
3742
req := httptest .NewRequest (http .MethodGet , "/" , nil ).WithContext (ctx )
3804
3743
rec := httptest .NewRecorder ()
3805
3744
r .ServeHTTP (rec , req )
3806
3745
3807
- got : = codersdk.WorkspaceAgentListContainersResponse {}
3746
+ got = codersdk.WorkspaceAgentListContainersResponse {}
3808
3747
err := json .NewDecoder (rec .Body ).Decode (& got )
3809
3748
require .NoError (t , err )
3810
3749
3811
- return len (got .Devcontainers ) >= tt .expectDevcontainerCount
3750
+ upCalledMu .Lock ()
3751
+ upCalledCount := len (upCalledFor )
3752
+ upCalledMu .Unlock ()
3753
+
3754
+ return len (got .Devcontainers ) >= tt .expectDevcontainerCount && upCalledCount >= tt .expectUpCalledCount
3812
3755
}, testutil .WaitShort , testutil .IntervalFast , "dev containers never found" )
3813
3756
3814
- // Then: We expect the mock infra to not fail.
3757
+ // Close the API. We expect this not to fail because we should have finished
3758
+ // at this point.
3759
+ err := api .Close ()
3760
+ require .NoError (t , err )
3761
+
3762
+ // Then: We expect to find the expected devcontainers
3763
+ assert .Len (t , got .Devcontainers , tt .expectDevcontainerCount )
3764
+
3765
+ // And: We expect `up` to have been called the expected amount of times.
3766
+ assert .Len (t , upCalledFor , tt .expectUpCalledCount )
3767
+
3768
+ // And: `up` was called on the correct containers
3769
+ for configPath , config := range tt .configMap {
3770
+ autoStart := config .Configuration .Customizations .Coder .AutoStart
3771
+ wasUpCalled := upCalledFor [configPath ]
3772
+
3773
+ require .Equal (t , autoStart , wasUpCalled )
3774
+ }
3815
3775
})
3816
3776
}
3817
3777
0 commit comments