@@ -21,6 +21,7 @@ import (
21
21
"github.com/coder/coder/v2/coderd/database/dbgen"
22
22
"github.com/coder/coder/v2/coderd/database/dbtestutil"
23
23
"github.com/coder/coder/v2/coderd/database/dbtime"
24
+ "github.com/coder/coder/v2/coderd/rbac"
24
25
"github.com/coder/coder/v2/coderd/util/ptr"
25
26
"github.com/coder/coder/v2/codersdk"
26
27
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
@@ -31,9 +32,13 @@ import (
31
32
)
32
33
33
34
func verifyQuota (ctx context.Context , t * testing.T , client * codersdk.Client , organizationID string , consumed , total int ) {
35
+ verifyQuotaUser (ctx , t , client , organizationID , codersdk .Me , consumed , total )
36
+ }
37
+
38
+ func verifyQuotaUser (ctx context.Context , t * testing.T , client * codersdk.Client , organizationID string , user string , consumed , total int ) {
34
39
t .Helper ()
35
40
36
- got , err := client .WorkspaceQuota (ctx , organizationID , codersdk . Me )
41
+ got , err := client .WorkspaceQuota (ctx , organizationID , user )
37
42
require .NoError (t , err )
38
43
require .EqualValues (t , codersdk.WorkspaceQuota {
39
44
Budget : total ,
@@ -43,7 +48,7 @@ func verifyQuota(ctx context.Context, t *testing.T, client *codersdk.Client, org
43
48
// Remove this check when the deprecated endpoint is removed.
44
49
// This just makes sure the deprecated endpoint is still working
45
50
// as intended. It will only work for the default organization.
46
- deprecatedGot , err := deprecatedQuotaEndpoint (ctx , client , codersdk . Me )
51
+ deprecatedGot , err := deprecatedQuotaEndpoint (ctx , client , user )
47
52
require .NoError (t , err , "deprecated endpoint" )
48
53
// Only continue to check if the values differ
49
54
if deprecatedGot .Budget != got .Budget || deprecatedGot .CreditsConsumed != got .CreditsConsumed {
@@ -300,6 +305,95 @@ func TestWorkspaceQuota(t *testing.T) {
300
305
verifyQuota (ctx , t , owner , first .OrganizationID .String (), 0 , 30 )
301
306
verifyQuota (ctx , t , owner , second .ID .String (), 0 , 15 )
302
307
})
308
+
309
+ // ManyWorkspaces uses dbfake and dbgen to insert a scenario into the db.
310
+ t .Run ("ManyWorkspaces" , func (t * testing.T ) {
311
+ t .Parallel ()
312
+
313
+ owner , db , first := coderdenttest .NewWithDatabase (t , & coderdenttest.Options {
314
+ LicenseOptions : & coderdenttest.LicenseOptions {
315
+ Features : license.Features {
316
+ codersdk .FeatureTemplateRBAC : 1 ,
317
+ codersdk .FeatureMultipleOrganizations : 1 ,
318
+ },
319
+ },
320
+ })
321
+ client , _ := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .RoleOwner ())
322
+
323
+ // Prepopulate database. Use dbfake as it is quicker and
324
+ // easier than the api.
325
+ ctx := testutil .Context (t , testutil .WaitLong )
326
+
327
+ user := dbgen .User (t , db , database.User {})
328
+ noise := dbgen .User (t , db , database.User {})
329
+
330
+ second := dbfake .Organization (t , db ).
331
+ Members (user , noise ).
332
+ EveryoneAllowance (10 ).
333
+ Group (database.Group {
334
+ QuotaAllowance : 25 ,
335
+ }, user , noise ).
336
+ Group (database.Group {
337
+ QuotaAllowance : 30 ,
338
+ }, noise ).
339
+ Do ()
340
+
341
+ third := dbfake .Organization (t , db ).
342
+ Members (noise ).
343
+ EveryoneAllowance (7 ).
344
+ Do ()
345
+
346
+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), user .ID .String (), 0 , 35 )
347
+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), noise .ID .String (), 0 , 65 )
348
+
349
+ // Workspaces owned by the user
350
+ consumed := 0
351
+ for i := 0 ; i < 2 ; i ++ {
352
+ const cost = 5
353
+ dbfake .WorkspaceBuild (t , db ,
354
+ database.WorkspaceTable {
355
+ OwnerID : user .ID ,
356
+ OrganizationID : second .Org .ID ,
357
+ }).
358
+ Seed (database.WorkspaceBuild {
359
+ DailyCost : cost ,
360
+ }).Do ()
361
+ consumed += cost
362
+ }
363
+
364
+ // Add some noise
365
+ // Workspace by the user in the third org
366
+ dbfake .WorkspaceBuild (t , db ,
367
+ database.WorkspaceTable {
368
+ OwnerID : user .ID ,
369
+ OrganizationID : third .Org .ID ,
370
+ }).
371
+ Seed (database.WorkspaceBuild {
372
+ DailyCost : 10 ,
373
+ }).Do ()
374
+
375
+ // Workspace by another user in third org
376
+ dbfake .WorkspaceBuild (t , db ,
377
+ database.WorkspaceTable {
378
+ OwnerID : noise .ID ,
379
+ OrganizationID : third .Org .ID ,
380
+ }).
381
+ Seed (database.WorkspaceBuild {
382
+ DailyCost : 10 ,
383
+ }).Do ()
384
+
385
+ // Workspace by another user in second org
386
+ dbfake .WorkspaceBuild (t , db ,
387
+ database.WorkspaceTable {
388
+ OwnerID : noise .ID ,
389
+ OrganizationID : second .Org .ID ,
390
+ }).
391
+ Seed (database.WorkspaceBuild {
392
+ DailyCost : 10 ,
393
+ }).Do ()
394
+
395
+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), user .ID .String (), consumed , 35 )
396
+ })
303
397
}
304
398
305
399
// nolint:paralleltest,tparallel // Tests must run serially
0 commit comments