@@ -10,6 +10,7 @@ import (
10
10
"github.com/stretchr/testify/require"
11
11
12
12
"github.com/coder/coder/v2/coderd/coderdtest"
13
+ "github.com/coder/coder/v2/coderd/database"
13
14
"github.com/coder/coder/v2/coderd/util/ptr"
14
15
"github.com/coder/coder/v2/codersdk"
15
16
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
@@ -31,12 +32,13 @@ func verifyQuota(ctx context.Context, t *testing.T, client *codersdk.Client, con
31
32
}
32
33
33
34
func TestWorkspaceQuota (t * testing.T ) {
34
- // TODO: refactor for new impl
35
-
36
35
t .Parallel ()
37
36
38
- t .Run ("BlocksBuild" , func (t * testing.T ) {
37
+ // This first test verifies the behavior of creating and deleting workspaces.
38
+ // It also tests multi-group quota stacking and the everyone group.
39
+ t .Run ("CreateDelete" , func (t * testing.T ) {
39
40
t .Parallel ()
41
+
40
42
ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
41
43
defer cancel ()
42
44
max := 1
@@ -49,8 +51,6 @@ func TestWorkspaceQuota(t *testing.T) {
49
51
},
50
52
})
51
53
coderdtest .NewProvisionerDaemon (t , api .AGPL )
52
- coderdtest .NewProvisionerDaemon (t , api .AGPL )
53
- coderdtest .NewProvisionerDaemon (t , api .AGPL )
54
54
55
55
verifyQuota (ctx , t , client , 0 , 0 )
56
56
@@ -157,4 +157,104 @@ func TestWorkspaceQuota(t *testing.T) {
157
157
verifyQuota (ctx , t , client , 4 , 4 )
158
158
require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
159
159
})
160
+
161
+ t .Run ("StartStop" , func (t * testing.T ) {
162
+ t .Parallel ()
163
+
164
+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitLong )
165
+ defer cancel ()
166
+ max := 1
167
+ client , _ , api , user := coderdenttest .NewWithAPI (t , & coderdenttest.Options {
168
+ UserWorkspaceQuota : max ,
169
+ LicenseOptions : & coderdenttest.LicenseOptions {
170
+ Features : license.Features {
171
+ codersdk .FeatureTemplateRBAC : 1 ,
172
+ },
173
+ },
174
+ })
175
+ coderdtest .NewProvisionerDaemon (t , api .AGPL )
176
+
177
+ verifyQuota (ctx , t , client , 0 , 0 )
178
+
179
+ // Patch the 'Everyone' group to verify its quota allowance is being accounted for.
180
+ _ , err := client .PatchGroup (ctx , user .OrganizationID , codersdk.PatchGroupRequest {
181
+ QuotaAllowance : ptr .Ref (4 ),
182
+ })
183
+ require .NoError (t , err )
184
+ verifyQuota (ctx , t , client , 0 , 4 )
185
+
186
+ stopResp := []* proto.Provision_Response {{
187
+ Type : & proto.Provision_Response_Complete {
188
+ Complete : & proto.Provision_Complete {
189
+ Resources : []* proto.Resource {{
190
+ Name : "example" ,
191
+ Type : "aws_instance" ,
192
+ DailyCost : 1 ,
193
+ }},
194
+ },
195
+ },
196
+ }}
197
+
198
+ startResp := []* proto.Provision_Response {{
199
+ Type : & proto.Provision_Response_Complete {
200
+ Complete : & proto.Provision_Complete {
201
+ Resources : []* proto.Resource {{
202
+ Name : "example" ,
203
+ Type : "aws_instance" ,
204
+ DailyCost : 2 ,
205
+ }},
206
+ },
207
+ },
208
+ }}
209
+
210
+ version := coderdtest .CreateTemplateVersion (t , client , user .OrganizationID , & echo.Responses {
211
+ Parse : echo .ParseComplete ,
212
+ ProvisionPlanMap : map [proto.WorkspaceTransition ][]* proto.Provision_Response {
213
+ proto .WorkspaceTransition_START : startResp ,
214
+ proto .WorkspaceTransition_STOP : stopResp ,
215
+ },
216
+ ProvisionApplyMap : map [proto.WorkspaceTransition ][]* proto.Provision_Response {
217
+ proto .WorkspaceTransition_START : startResp ,
218
+ proto .WorkspaceTransition_STOP : stopResp ,
219
+ },
220
+ })
221
+
222
+ coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
223
+ template := coderdtest .CreateTemplate (t , client , user .OrganizationID , version .ID )
224
+
225
+ // Spin up two workspaces.
226
+ var wg sync.WaitGroup
227
+ var workspaces []codersdk.Workspace
228
+ for i := 0 ; i < 2 ; i ++ {
229
+ workspace := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
230
+ workspaces = append (workspaces , workspace )
231
+ build := coderdtest .AwaitWorkspaceBuildJob (t , client , workspace .LatestBuild .ID )
232
+ assert .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
233
+ }
234
+ wg .Wait ()
235
+ verifyQuota (ctx , t , client , 4 , 4 )
236
+
237
+ // Next one must fail
238
+ workspace := coderdtest .CreateWorkspace (t , client , user .OrganizationID , template .ID )
239
+ build := coderdtest .AwaitWorkspaceBuildJob (t , client , workspace .LatestBuild .ID )
240
+ require .Contains (t , build .Job .Error , "quota" )
241
+
242
+ // Consumed shouldn't bump
243
+ verifyQuota (ctx , t , client , 4 , 4 )
244
+ require .Equal (t , codersdk .WorkspaceStatusFailed , build .Status )
245
+
246
+ build = coderdtest .CreateWorkspaceBuild (t , client , workspaces [0 ], database .WorkspaceTransitionStop )
247
+ build = coderdtest .AwaitWorkspaceBuildJob (t , client , build .ID )
248
+
249
+ // Quota goes down one
250
+ verifyQuota (ctx , t , client , 3 , 4 )
251
+ require .Equal (t , codersdk .WorkspaceStatusStopped , build .Status )
252
+
253
+ build = coderdtest .CreateWorkspaceBuild (t , client , workspaces [0 ], database .WorkspaceTransitionStart )
254
+ build = coderdtest .AwaitWorkspaceBuildJob (t , client , build .ID )
255
+
256
+ // Quota goes back up
257
+ verifyQuota (ctx , t , client , 4 , 4 )
258
+ require .Equal (t , codersdk .WorkspaceStatusRunning , build .Status )
259
+ })
160
260
}
0 commit comments