@@ -3,6 +3,7 @@ package cli_test
3
3
import (
4
4
"bytes"
5
5
"context"
6
+ "database/sql"
6
7
"os"
7
8
"path/filepath"
8
9
"runtime"
@@ -18,6 +19,7 @@ import (
18
19
"github.com/coder/coder/v2/coderd/coderdtest"
19
20
"github.com/coder/coder/v2/coderd/database"
20
21
"github.com/coder/coder/v2/coderd/database/dbtestutil"
22
+ "github.com/coder/coder/v2/coderd/database/dbtime"
21
23
"github.com/coder/coder/v2/coderd/rbac"
22
24
"github.com/coder/coder/v2/codersdk"
23
25
"github.com/coder/coder/v2/provisioner/echo"
@@ -412,84 +414,162 @@ func TestTemplatePush(t *testing.T) {
412
414
413
415
t .Run ("WorkspaceTagsTerraform" , func (t * testing.T ) {
414
416
t .Parallel ()
415
- ctx := testutil .Context (t , testutil .WaitShort )
416
417
417
- // Start an instance **without** a built-in provisioner.
418
- // We're not actually testing that the Terraform applies.
419
- // What we test is that a provisioner job is created with the expected
420
- // tags based on the __content__ of the Terraform.
421
- store , ps := dbtestutil .NewDB (t )
422
- client := coderdtest .New (t , & coderdtest.Options {
423
- Database : store ,
424
- Pubsub : ps ,
425
- })
426
-
427
- owner := coderdtest .CreateFirstUser (t , client )
428
- templateAdmin , _ := coderdtest .CreateAnotherUser (t , client , owner .OrganizationID , rbac .RoleTemplateAdmin ())
429
-
430
- // Create a tar file with some pre-defined content
431
- tarFile := testutil .CreateTar (t , map [string ]string {
432
- "main.tf" : `
433
- variable "a" {
434
- type = string
435
- default = "1"
436
- }
437
- data "coder_parameter" "b" {
438
- type = string
439
- default = "2"
440
- }
441
- resource "null_resource" "test" {}
442
- data "coder_workspace_tags" "tags" {
443
- tags = {
444
- "foo": "bar",
445
- "a": var.a,
446
- "b": data.coder_parameter.b.value,
447
- }
448
- }` ,
449
- })
450
-
451
- // Write the tar file to disk.
452
- tempDir := t .TempDir ()
453
- err := tfparse .WriteArchive (tarFile , "application/x-tar" , tempDir )
454
- require .NoError (t , err )
455
-
456
- // Run `coder templates push`
457
- templateName := strings .ReplaceAll (testutil .GetRandomName (t ), "_" , "-" )
458
- var stdout , stderr strings.Builder
459
- inv , root := clitest .New (t , "templates" , "push" , templateName , "-d" , tempDir , "--yes" )
460
- inv .Stdout = & stdout
461
- inv .Stderr = & stderr
462
- clitest .SetupConfig (t , templateAdmin , root )
463
-
464
- // Don't forget to clean up!
465
- cancelCtx , cancel := context .WithCancel (ctx )
466
- t .Cleanup (cancel )
467
- done := make (chan error )
468
- go func () {
469
- done <- inv .WithContext (cancelCtx ).Run ()
470
- }()
471
-
472
- // Assert that a provisioner job was created with the desired tags.
473
- wantTags := database .StringMap (provisionersdk .MutateTags (uuid .Nil , map [string ]string {
474
- "foo" : "bar" ,
475
- "a" : "1" ,
476
- "b" : "2" ,
477
- }))
478
- require .Eventually (t , func () bool {
479
- jobs , err := store .GetProvisionerJobsCreatedAfter (ctx , time.Time {})
480
- if ! assert .NoError (t , err ) {
481
- return false
482
- }
483
- if len (jobs ) == 0 {
484
- return false
485
- }
486
- return assert .EqualValues (t , wantTags , jobs [0 ].Tags )
487
- }, testutil .WaitShort , testutil .IntervalSlow )
488
-
489
- cancel ()
490
- <- done
418
+ tests := []struct {
419
+ name string
420
+ setupDaemon func (ctx context.Context , store database.Store , owner codersdk.CreateFirstUserResponse , tags database.StringMap , now time.Time ) error
421
+ expectOutput string
422
+ }{
423
+ {
424
+ name : "no provisioners available" ,
425
+ setupDaemon : func (_ context.Context , _ database.Store , _ codersdk.CreateFirstUserResponse , _ database.StringMap , _ time.Time ) error {
426
+ return nil
427
+ },
428
+ expectOutput : "there are no provisioners that accept the required tags" ,
429
+ },
430
+ {
431
+ name : "provisioner stale" ,
432
+ setupDaemon : func (ctx context.Context , store database.Store , owner codersdk.CreateFirstUserResponse , tags database.StringMap , now time.Time ) error {
433
+ pk , err := store .InsertProvisionerKey (ctx , database.InsertProvisionerKeyParams {
434
+ ID : uuid .New (),
435
+ CreatedAt : now ,
436
+ OrganizationID : owner .OrganizationID ,
437
+ Name : "test" ,
438
+ Tags : tags ,
439
+ HashedSecret : []byte ("secret" ),
440
+ })
441
+ if err != nil {
442
+ return err
443
+ }
444
+ oneHourAgo := now .Add (- time .Hour )
445
+ _ , err = store .UpsertProvisionerDaemon (ctx , database.UpsertProvisionerDaemonParams {
446
+ Provisioners : []database.ProvisionerType {database .ProvisionerTypeTerraform },
447
+ LastSeenAt : sql.NullTime {Time : oneHourAgo , Valid : true },
448
+ CreatedAt : oneHourAgo ,
449
+ Name : "test" ,
450
+ Tags : tags ,
451
+ OrganizationID : owner .OrganizationID ,
452
+ KeyID : pk .ID ,
453
+ })
454
+ return err
455
+ },
456
+ expectOutput : "Provisioners that accept the required tags have not responded for longer than expected" ,
457
+ },
458
+ {
459
+ name : "active provisioner" ,
460
+ setupDaemon : func (ctx context.Context , store database.Store , owner codersdk.CreateFirstUserResponse , tags database.StringMap , now time.Time ) error {
461
+ pk , err := store .InsertProvisionerKey (ctx , database.InsertProvisionerKeyParams {
462
+ ID : uuid .New (),
463
+ CreatedAt : now ,
464
+ OrganizationID : owner .OrganizationID ,
465
+ Name : "test" ,
466
+ Tags : tags ,
467
+ HashedSecret : []byte ("secret" ),
468
+ })
469
+ if err != nil {
470
+ return err
471
+ }
472
+ _ , err = store .UpsertProvisionerDaemon (ctx , database.UpsertProvisionerDaemonParams {
473
+ Provisioners : []database.ProvisionerType {database .ProvisionerTypeTerraform },
474
+ LastSeenAt : sql.NullTime {Time : now , Valid : true },
475
+ CreatedAt : now ,
476
+ Name : "test-active" ,
477
+ Tags : tags ,
478
+ OrganizationID : owner .OrganizationID ,
479
+ KeyID : pk .ID ,
480
+ })
481
+ return err
482
+ },
483
+ expectOutput : "" ,
484
+ },
485
+ }
491
486
492
- require .Contains (t , stderr .String (), "No provisioners are available to handle the job!" )
487
+ for _ , tt := range tests {
488
+ tt := tt
489
+ t .Run (tt .name , func (t * testing.T ) {
490
+ t .Parallel ()
491
+
492
+ // Start an instance **without** a built-in provisioner.
493
+ // We're not actually testing that the Terraform applies.
494
+ // What we test is that a provisioner job is created with the expected
495
+ // tags based on the __content__ of the Terraform.
496
+ store , ps := dbtestutil .NewDB (t )
497
+ client := coderdtest .New (t , & coderdtest.Options {
498
+ Database : store ,
499
+ Pubsub : ps ,
500
+ })
501
+
502
+ owner := coderdtest .CreateFirstUser (t , client )
503
+ templateAdmin , _ := coderdtest .CreateAnotherUser (t , client , owner .OrganizationID , rbac .RoleTemplateAdmin ())
504
+
505
+ // Create a tar file with some pre-defined content
506
+ tarFile := testutil .CreateTar (t , map [string ]string {
507
+ "main.tf" : `
508
+ variable "a" {
509
+ type = string
510
+ default = "1"
511
+ }
512
+ data "coder_parameter" "b" {
513
+ type = string
514
+ default = "2"
515
+ }
516
+ resource "null_resource" "test" {}
517
+ data "coder_workspace_tags" "tags" {
518
+ tags = {
519
+ "a": var.a,
520
+ "b": data.coder_parameter.b.value,
521
+ "test_name": "` + tt .name + `"
522
+ }
523
+ }` ,
524
+ })
525
+
526
+ // Write the tar file to disk.
527
+ tempDir := t .TempDir ()
528
+ err := tfparse .WriteArchive (tarFile , "application/x-tar" , tempDir )
529
+ require .NoError (t , err )
530
+
531
+ wantTags := database .StringMap (provisionersdk .MutateTags (uuid .Nil , map [string ]string {
532
+ "a" : "1" ,
533
+ "b" : "2" ,
534
+ "test_name" : tt .name ,
535
+ }))
536
+
537
+ templateName := strings .ReplaceAll (testutil .GetRandomName (t ), "_" , "-" )
538
+
539
+ inv , root := clitest .New (t , "templates" , "push" , templateName , "-d" , tempDir , "--yes" )
540
+ clitest .SetupConfig (t , templateAdmin , root )
541
+ pty := ptytest .New (t ).Attach (inv )
542
+
543
+ ctx := testutil .Context (t , testutil .WaitShort )
544
+ now := dbtime .Now ()
545
+ require .NoError (t , tt .setupDaemon (ctx , store , owner , wantTags , now ))
546
+
547
+ cancelCtx , cancel := context .WithCancel (ctx )
548
+ t .Cleanup (cancel )
549
+ done := make (chan error )
550
+ go func () {
551
+ done <- inv .WithContext (cancelCtx ).Run ()
552
+ }()
553
+
554
+ require .Eventually (t , func () bool {
555
+ jobs , err := store .GetProvisionerJobsCreatedAfter (ctx , time.Time {})
556
+ if ! assert .NoError (t , err ) {
557
+ return false
558
+ }
559
+ if len (jobs ) == 0 {
560
+ return false
561
+ }
562
+ return assert .EqualValues (t , wantTags , jobs [0 ].Tags )
563
+ }, testutil .WaitShort , testutil .IntervalFast )
564
+
565
+ if tt .expectOutput != "" {
566
+ pty .ExpectMatch (tt .expectOutput )
567
+ }
568
+
569
+ cancel ()
570
+ <- done
571
+ })
572
+ }
493
573
})
494
574
495
575
t .Run ("ChangeTags" , func (t * testing.T ) {
0 commit comments