9
9
"time"
10
10
11
11
"github.com/google/uuid"
12
+ "github.com/sqlc-dev/pqtype"
12
13
"github.com/stretchr/testify/assert"
13
14
"github.com/stretchr/testify/require"
14
15
"go.uber.org/goleak"
@@ -18,6 +19,8 @@ import (
18
19
"cdr.dev/slog/sloggers/slogtest"
19
20
"github.com/coder/coder/v2/coderd/database"
20
21
"github.com/coder/coder/v2/coderd/database/dbmem"
22
+ "github.com/coder/coder/v2/coderd/database/dbtestutil"
23
+ "github.com/coder/coder/v2/coderd/database/dbtime"
21
24
"github.com/coder/coder/v2/coderd/database/provisionerjobs"
22
25
"github.com/coder/coder/v2/coderd/database/pubsub"
23
26
"github.com/coder/coder/v2/coderd/provisionerdserver"
@@ -315,6 +318,133 @@ func TestAcquirer_UnblockOnCancel(t *testing.T) {
315
318
require .Equal (t ,jobID ,job .ID )
316
319
}
317
320
321
+ func TestAcquirer_MatchTags (t * testing.T ) {
322
+ t .Parallel ()
323
+ if testing .Short () {
324
+ t .Skip ("skipping this test due to -short" )
325
+ }
326
+
327
+ someID := uuid .NewString ()
328
+ someOtherID := uuid .NewString ()
329
+
330
+ for _ ,tt := range []struct {
331
+ name string
332
+ provisionerJobTags map [string ]string
333
+ acquireJobTags map [string ]string
334
+ expectAcquire bool
335
+ }{
336
+ {
337
+ name :"untagged provisioner and untagged job" ,
338
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
339
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
340
+ expectAcquire :true ,
341
+ },
342
+ {
343
+ name :"untagged provisioner and tagged job" ,
344
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
345
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
346
+ expectAcquire :false ,
347
+ },
348
+ {
349
+ name :"tagged provisioner and untagged job" ,
350
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
351
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
352
+ expectAcquire :false ,
353
+ },
354
+ {
355
+ name :"tagged provisioner and tagged job" ,
356
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
357
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
358
+ expectAcquire :true ,
359
+ },
360
+ {
361
+ name :"tagged provisioner and double-tagged job" ,
362
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" ,"baz" :"zap" },
363
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
364
+ expectAcquire :false ,
365
+ },
366
+ {
367
+ name :"double-tagged provisioner and tagged job" ,
368
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" },
369
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" ,"baz" :"zap" },
370
+ expectAcquire :true ,
371
+ },
372
+ {
373
+ name :"double-tagged provisioner and double-tagged job" ,
374
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" ,"baz" :"zap" },
375
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" ,"foo" :"bar" ,"baz" :"zap" },
376
+ expectAcquire :true ,
377
+ },
378
+ {
379
+ name :"owner-scoped provisioner and untagged job" ,
380
+ provisionerJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
381
+ acquireJobTags :map [string ]string {"scope" :"owner" ,"owner" :someID },
382
+ expectAcquire :false ,
383
+ },
384
+ {
385
+ name :"owner-scoped provisioner and owner-scoped job" ,
386
+ provisionerJobTags :map [string ]string {"scope" :"owner" ,"owner" :someID },
387
+ acquireJobTags :map [string ]string {"scope" :"owner" ,"owner" :someID },
388
+ expectAcquire :true ,
389
+ },
390
+ {
391
+ name :"owner-scoped provisioner and different owner-scoped job" ,
392
+ provisionerJobTags :map [string ]string {"scope" :"owner" ,"owner" :someOtherID },
393
+ acquireJobTags :map [string ]string {"scope" :"owner" ,"owner" :someID },
394
+ expectAcquire :false ,
395
+ },
396
+ {
397
+ name :"org-scoped provisioner and owner-scoped job" ,
398
+ provisionerJobTags :map [string ]string {"scope" :"owner" ,"owner" :someID },
399
+ acquireJobTags :map [string ]string {"scope" :"organization" ,"owner" :"" },
400
+ expectAcquire :false ,
401
+ },
402
+ } {
403
+ tt := tt
404
+ t .Run (tt .name ,func (t * testing.T ) {
405
+ t .Parallel ()
406
+
407
+ ctx := testutil .Context (t ,testutil .WaitShort / 2 )
408
+ // NOTE: explicitly not using fake store for this test.
409
+ db ,ps := dbtestutil .NewDB (t )
410
+ log := slogtest .Make (t ,nil ).Leveled (slog .LevelDebug )
411
+ org ,err := db .InsertOrganization (ctx , database.InsertOrganizationParams {
412
+ ID :uuid .New (),
413
+ Name :"test org" ,
414
+ Description :"the organization of testing" ,
415
+ CreatedAt :dbtime .Now (),
416
+ UpdatedAt :dbtime .Now (),
417
+ })
418
+ require .NoError (t ,err )
419
+ pj ,err := db .InsertProvisionerJob (ctx , database.InsertProvisionerJobParams {
420
+ ID :uuid .New (),
421
+ CreatedAt :dbtime .Now (),
422
+ UpdatedAt :dbtime .Now (),
423
+ OrganizationID :org .ID ,
424
+ InitiatorID :uuid .New (),
425
+ Provisioner :database .ProvisionerTypeEcho ,
426
+ StorageMethod :database .ProvisionerStorageMethodFile ,
427
+ FileID :uuid .New (),
428
+ Type :database .ProvisionerJobTypeWorkspaceBuild ,
429
+ Input : []byte ("{}" ),
430
+ Tags :tt .provisionerJobTags ,
431
+ TraceMetadata : pqtype.NullRawMessage {},
432
+ })
433
+ require .NoError (t ,err )
434
+ ptypes := []database.ProvisionerType {database .ProvisionerTypeEcho }
435
+ acq := provisionerdserver .NewAcquirer (ctx ,log ,db ,ps )
436
+ aj ,err := acq .AcquireJob (ctx ,uuid .New (),ptypes ,tt .acquireJobTags )
437
+ if tt .expectAcquire {
438
+ assert .NoError (t ,err )
439
+ assert .Equal (t ,pj .ID ,aj .ID )
440
+ }else {
441
+ assert .Empty (t ,aj ,"should not have acquired job" )
442
+ assert .ErrorIs (t ,err ,context .DeadlineExceeded ,"should have timed out" )
443
+ }
444
+ })
445
+ }
446
+ }
447
+
318
448
func postJob (t * testing.T ,ps pubsub.Pubsub ,pt database.ProvisionerType ,tags provisionerdserver.Tags ) {
319
449
t .Helper ()
320
450
msg ,err := json .Marshal (provisionerjobs.JobPosting {