@@ -3,6 +3,8 @@ package coderd_test
3
3
import (
4
4
"bytes"
5
5
"context"
6
+ "fmt"
7
+ "io"
6
8
"net/http"
7
9
"testing"
8
10
@@ -12,6 +14,7 @@ import (
12
14
13
15
"cdr.dev/slog"
14
16
"cdr.dev/slog/sloggers/slogtest"
17
+ "github.com/coder/coder/v2/apiversion"
15
18
"github.com/coder/coder/v2/buildinfo"
16
19
"github.com/coder/coder/v2/coderd/coderdtest"
17
20
"github.com/coder/coder/v2/coderd/database"
@@ -63,6 +66,108 @@ func TestProvisionerDaemonServe(t *testing.T) {
63
66
}
64
67
})
65
68
69
+ t .Run ("NoVersion" , func (t * testing.T ) {
70
+ t .Parallel ()
71
+ // In this test, we just send a HTTP request with minimal parameters to the provisionerdaemons
72
+ // endpoint. We do not pass the required machinery to start a websocket connection, so we expect a
73
+ // WebSocket protocol violation. This just means the pre-flight checks have passed though.
74
+
75
+ // Sending a HTTP request triggers an error log, which would otherwise fail the test.
76
+ logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
77
+ client , user := coderdenttest .New (t , & coderdenttest.Options {
78
+ LicenseOptions : & coderdenttest.LicenseOptions {
79
+ Features : license.Features {
80
+ codersdk .FeatureExternalProvisionerDaemons : 1 ,
81
+ },
82
+ },
83
+ ProvisionerDaemonPSK : "provisionersftw" ,
84
+ Options : & coderdtest.Options {
85
+ Logger : & logger ,
86
+ },
87
+ })
88
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
89
+ defer cancel ()
90
+
91
+ // Formulate the correct URL for provisionerd server.
92
+ srvURL , err := client .URL .Parse (fmt .Sprintf ("/api/v2/organizations/%s/provisionerdaemons/serve" , user .OrganizationID ))
93
+ require .NoError (t , err )
94
+ q := srvURL .Query ()
95
+ // Set required query parameters.
96
+ q .Add ("provisioner" , "echo" )
97
+ // Note: Explicitly not setting API version.
98
+ q .Add ("version" , "" )
99
+ srvURL .RawQuery = q .Encode ()
100
+
101
+ // Set PSK header for auth.
102
+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , srvURL .String (), nil )
103
+ require .NoError (t , err )
104
+ req .Header .Set (codersdk .ProvisionerDaemonPSK , "provisionersftw" )
105
+
106
+ // Do the request!
107
+ resp , err := client .HTTPClient .Do (req )
108
+ require .NoError (t , err )
109
+ defer resp .Body .Close ()
110
+ b , err := io .ReadAll (resp .Body )
111
+ require .NoError (t , err )
112
+ // The below means that provisionerd tried to serve us!
113
+ require .Contains (t , string (b ), "Internal error accepting websocket connection." )
114
+
115
+ daemons , err := client .ProvisionerDaemons (ctx ) //nolint:gocritic // Test assertion.
116
+ require .NoError (t , err )
117
+ if assert .Len (t , daemons , 1 ) {
118
+ assert .Equal (t , "1.0" , daemons [0 ].APIVersion ) // The whole point of this test is here.
119
+ }
120
+ })
121
+
122
+ t .Run ("OldVersion" , func (t * testing.T ) {
123
+ t .Parallel ()
124
+ // In this test, we just send a HTTP request with minimal parameters to the provisionerdaemons
125
+ // endpoint. We do not pass the required machinery to start a websocket connection, but we pass a
126
+ // version header that should cause provisionerd to refuse to serve us, so no websocket for you!
127
+
128
+ // Sending a HTTP request triggers an error log, which would otherwise fail the test.
129
+ logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
130
+ client , user := coderdenttest .New (t , & coderdenttest.Options {
131
+ LicenseOptions : & coderdenttest.LicenseOptions {
132
+ Features : license.Features {
133
+ codersdk .FeatureExternalProvisionerDaemons : 1 ,
134
+ },
135
+ },
136
+ ProvisionerDaemonPSK : "provisionersftw" ,
137
+ Options : & coderdtest.Options {
138
+ Logger : & logger ,
139
+ },
140
+ })
141
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
142
+ defer cancel ()
143
+
144
+ // Formulate the correct URL for provisionerd server.
145
+ srvURL , err := client .URL .Parse (fmt .Sprintf ("/api/v2/organizations/%s/provisionerdaemons/serve" , user .OrganizationID ))
146
+ require .NoError (t , err )
147
+ q := srvURL .Query ()
148
+ // Set required query parameters.
149
+ q .Add ("provisioner" , "echo" )
150
+
151
+ // Set a different (newer) version than the current.
152
+ v := apiversion .New (provisionersdk .CurrentMajor + 1 , provisionersdk .CurrentMinor + 1 )
153
+ q .Add ("version" , v .String ())
154
+ srvURL .RawQuery = q .Encode ()
155
+
156
+ // Set PSK header for auth.
157
+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , srvURL .String (), nil )
158
+ require .NoError (t , err )
159
+ req .Header .Set (codersdk .ProvisionerDaemonPSK , "provisionersftw" )
160
+
161
+ // Do the request!
162
+ resp , err := client .HTTPClient .Do (req )
163
+ require .NoError (t , err )
164
+ defer resp .Body .Close ()
165
+ b , err := io .ReadAll (resp .Body )
166
+ require .NoError (t , err )
167
+ // The below means that provisionerd tried to serve us, checked our api version, and said nope.
168
+ require .Contains (t , string (b ), "server is at version 1.0, behind requested major version 2.1" )
169
+ })
170
+
66
171
t .Run ("NoLicense" , func (t * testing.T ) {
67
172
t .Parallel ()
68
173
client , user := coderdenttest .New (t , & coderdenttest.Options {DontAddLicense : true })
0 commit comments