Skip to content

Commit 1cdc3e8

Browse files
johnstcnmafredri
andauthored
feat!: extract provisioner tags from coder_workspace_tags data source (coder#15578)
Relates to coder#15087 and coder#15427 - Extracts provisioner job tags from `coder_workspace_tags` on template version creation using `provisioner/terraform/tfparse` added in coder#15236 - Drops a WARN log in coderd if no matching provisioners found. - Also drops a warning message in the CLI if no provisioners are found. - To support both CLI and UI warnings, added a `codersdk.MatchedProvisioners` struct to the `TemplateVersion` response containing details of how many provisioners were around at the time of the insert. Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
1 parent 648cdd0 commit 1cdc3e8

11 files changed

+694
-95
lines changed

cli/templatepush.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cli
22

33
import (
44
"bufio"
5+
"encoding/json"
56
"errors"
67
"fmt"
78
"io"
@@ -415,6 +416,29 @@ func createValidTemplateVersion(inv *serpent.Invocation, args createValidTemplat
415416
if err != nil {
416417
return nil, err
417418
}
419+
var tagsJSON strings.Builder
420+
if err := json.NewEncoder(&tagsJSON).Encode(version.Job.Tags); err != nil {
421+
// Fall back to the less-pretty string representation.
422+
tagsJSON.Reset()
423+
_, _ = tagsJSON.WriteString(fmt.Sprintf("%v", version.Job.Tags))
424+
}
425+
if version.MatchedProvisioners.Count == 0 {
426+
cliui.Warnf(inv.Stderr, `No provisioners are available to handle the job!
427+
Please contact your deployment administrator for assistance.
428+
Details:
429+
Provisioner job ID : %s
430+
Requested tags : %s
431+
`, version.Job.ID, tagsJSON.String())
432+
} else if version.MatchedProvisioners.Available == 0 {
433+
cliui.Warnf(inv.Stderr, `All available provisioner daemons have been silent for a while.
434+
Your build will proceed once they become available.
435+
If this persists, please contact your deployment administrator for assistance.
436+
Details:
437+
Provisioner job ID : %s
438+
Requested tags : %s
439+
Most recently seen : %s
440+
`, version.Job.ID, strings.TrimSpace(tagsJSON.String()), version.MatchedProvisioners.MostRecentlySeen.Time)
441+
}
418442

419443
err = cliui.ProvisionerJob(inv.Context(), inv.Stdout, cliui.ProvisionerJobOptions{
420444
Fetch: func() (codersdk.ProvisionerJob, error) {

cli/templatepush_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"runtime"
99
"strings"
1010
"testing"
11+
"time"
1112

1213
"github.com/google/uuid"
1314
"github.com/stretchr/testify/assert"
@@ -16,9 +17,12 @@ import (
1617
"github.com/coder/coder/v2/cli/clitest"
1718
"github.com/coder/coder/v2/coderd/coderdtest"
1819
"github.com/coder/coder/v2/coderd/database"
20+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
1921
"github.com/coder/coder/v2/coderd/rbac"
2022
"github.com/coder/coder/v2/codersdk"
2123
"github.com/coder/coder/v2/provisioner/echo"
24+
"github.com/coder/coder/v2/provisioner/terraform/tfparse"
25+
"github.com/coder/coder/v2/provisionersdk"
2226
"github.com/coder/coder/v2/provisionersdk/proto"
2327
"github.com/coder/coder/v2/pty/ptytest"
2428
"github.com/coder/coder/v2/testutil"
@@ -406,6 +410,88 @@ func TestTemplatePush(t *testing.T) {
406410
t.Run("ProvisionerTags", func(t *testing.T) {
407411
t.Parallel()
408412

413+
t.Run("WorkspaceTagsTerraform", func(t *testing.T) {
414+
t.Parallel()
415+
ctx := testutil.Context(t, testutil.WaitShort)
416+
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
491+
492+
require.Contains(t, stderr.String(), "No provisioners are available to handle the job!")
493+
})
494+
409495
t.Run("ChangeTags", func(t *testing.T) {
410496
t.Parallel()
411497

coderd/apidoc/docs.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)