Skip to content

Commit 7358bf8

Browse files
committed
Merge branch 'main' of https://github.com/coder/coder into bq/19323
2 parents bddab45 + 427b23f commit 7358bf8

File tree

74 files changed

+2621
-1270
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+2621
-1270
lines changed

.coderabbit.yaml

Lines changed: 0 additions & 28 deletions
This file was deleted.

.github/pull_request_template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting.

.vscode/settings.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,5 @@
6060
"typos.config": ".github/workflows/typos.toml",
6161
"[markdown]": {
6262
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint"
63-
},
64-
"biome.configurationPath": "./site/biome.jsonc",
65-
"biome.lsp.bin": "./site/node_modules/.bin/biome"
63+
}
6664
}

cli/provisionerjobs_test.go

Lines changed: 52 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"testing"
99
"time"
1010

11-
"github.com/aws/smithy-go/ptr"
1211
"github.com/google/uuid"
1312
"github.com/stretchr/testify/assert"
1413
"github.com/stretchr/testify/require"
@@ -20,6 +19,7 @@ import (
2019
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2120
"github.com/coder/coder/v2/coderd/rbac"
2221
"github.com/coder/coder/v2/codersdk"
22+
"github.com/coder/coder/v2/provisionersdk"
2323
"github.com/coder/coder/v2/testutil"
2424
)
2525

@@ -36,67 +36,43 @@ func TestProvisionerJobs(t *testing.T) {
3636
templateAdminClient, templateAdmin := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgTemplateAdmin(owner.OrganizationID))
3737
memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
3838

39-
// Create initial resources with a running provisioner.
40-
firstProvisioner := coderdtest.NewTaggedProvisionerDaemon(t, coderdAPI, "default-provisioner", map[string]string{"owner": "", "scope": "organization"})
41-
t.Cleanup(func() { _ = firstProvisioner.Close() })
42-
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, completeWithAgent())
43-
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
44-
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) {
45-
req.AllowUserCancelWorkspaceJobs = ptr.Bool(true)
39+
// These CLI tests are related to provisioner job CRUD operations and as such
40+
// do not require the overhead of starting a provisioner. Other provisioner job
41+
// functionalities (acquisition etc.) are tested elsewhere.
42+
template := dbgen.Template(t, db, database.Template{
43+
OrganizationID: owner.OrganizationID,
44+
CreatedBy: owner.UserID,
45+
AllowUserCancelWorkspaceJobs: true,
46+
})
47+
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
48+
OrganizationID: owner.OrganizationID,
49+
CreatedBy: owner.UserID,
50+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
4651
})
47-
48-
// Stop the provisioner so it doesn't grab any more jobs.
49-
firstProvisioner.Close()
5052

5153
t.Run("Cancel", func(t *testing.T) {
5254
t.Parallel()
5355

54-
// Set up test helpers.
55-
type jobInput struct {
56-
WorkspaceBuildID string `json:"workspace_build_id,omitempty"`
57-
TemplateVersionID string `json:"template_version_id,omitempty"`
58-
DryRun bool `json:"dry_run,omitempty"`
59-
}
60-
prepareJob := func(t *testing.T, input jobInput) database.ProvisionerJob {
56+
// Test helper to create a provisioner job of a given type with a given input.
57+
prepareJob := func(t *testing.T, jobType database.ProvisionerJobType, input json.RawMessage) database.ProvisionerJob {
6158
t.Helper()
62-
63-
inputBytes, err := json.Marshal(input)
64-
require.NoError(t, err)
65-
66-
var typ database.ProvisionerJobType
67-
switch {
68-
case input.WorkspaceBuildID != "":
69-
typ = database.ProvisionerJobTypeWorkspaceBuild
70-
case input.TemplateVersionID != "":
71-
if input.DryRun {
72-
typ = database.ProvisionerJobTypeTemplateVersionDryRun
73-
} else {
74-
typ = database.ProvisionerJobTypeTemplateVersionImport
75-
}
76-
default:
77-
t.Fatal("invalid input")
78-
}
79-
80-
var (
81-
tags = database.StringMap{"owner": "", "scope": "organization", "foo": uuid.New().String()}
82-
_ = dbgen.ProvisionerDaemon(t, db, database.ProvisionerDaemon{Tags: tags})
83-
job = dbgen.ProvisionerJob(t, db, coderdAPI.Pubsub, database.ProvisionerJob{
84-
InitiatorID: member.ID,
85-
Input: json.RawMessage(inputBytes),
86-
Type: typ,
87-
Tags: tags,
88-
StartedAt: sql.NullTime{Time: coderdAPI.Clock.Now().Add(-time.Minute), Valid: true},
89-
})
90-
)
91-
return job
59+
return dbgen.ProvisionerJob(t, db, coderdAPI.Pubsub, database.ProvisionerJob{
60+
InitiatorID: member.ID,
61+
Input: input,
62+
Type: jobType,
63+
StartedAt: sql.NullTime{Time: coderdAPI.Clock.Now().Add(-time.Minute), Valid: true},
64+
Tags: database.StringMap{provisionersdk.TagOwner: "", provisionersdk.TagScope: provisionersdk.ScopeOrganization, "foo": uuid.NewString()},
65+
})
9266
}
9367

68+
// Test helper to create a workspace build job with a predefined input.
9469
prepareWorkspaceBuildJob := func(t *testing.T) database.ProvisionerJob {
9570
t.Helper()
9671
var (
97-
wbID = uuid.New()
98-
job = prepareJob(t, jobInput{WorkspaceBuildID: wbID.String()})
99-
w = dbgen.Workspace(t, db, database.WorkspaceTable{
72+
wbID = uuid.New()
73+
input, _ = json.Marshal(map[string]string{"workspace_build_id": wbID.String()})
74+
job = prepareJob(t, database.ProvisionerJobTypeWorkspaceBuild, input)
75+
w = dbgen.Workspace(t, db, database.WorkspaceTable{
10076
OrganizationID: owner.OrganizationID,
10177
OwnerID: member.ID,
10278
TemplateID: template.ID,
@@ -112,12 +88,14 @@ func TestProvisionerJobs(t *testing.T) {
11288
return job
11389
}
11490

115-
prepareTemplateVersionImportJobBuilder := func(t *testing.T, dryRun bool) database.ProvisionerJob {
91+
// Test helper to create a template version import job with a predefined input.
92+
prepareTemplateVersionImportJob := func(t *testing.T) database.ProvisionerJob {
11693
t.Helper()
11794
var (
118-
tvID = uuid.New()
119-
job = prepareJob(t, jobInput{TemplateVersionID: tvID.String(), DryRun: dryRun})
120-
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{
95+
tvID = uuid.New()
96+
input, _ = json.Marshal(map[string]string{"template_version_id": tvID.String()})
97+
job = prepareJob(t, database.ProvisionerJobTypeTemplateVersionImport, input)
98+
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{
12199
OrganizationID: owner.OrganizationID,
122100
CreatedBy: templateAdmin.ID,
123101
ID: tvID,
@@ -127,11 +105,26 @@ func TestProvisionerJobs(t *testing.T) {
127105
)
128106
return job
129107
}
130-
prepareTemplateVersionImportJob := func(t *testing.T) database.ProvisionerJob {
131-
return prepareTemplateVersionImportJobBuilder(t, false)
132-
}
108+
109+
// Test helper to create a template version import dry run job with a predefined input.
133110
prepareTemplateVersionImportJobDryRun := func(t *testing.T) database.ProvisionerJob {
134-
return prepareTemplateVersionImportJobBuilder(t, true)
111+
t.Helper()
112+
var (
113+
tvID = uuid.New()
114+
input, _ = json.Marshal(map[string]interface{}{
115+
"template_version_id": tvID.String(),
116+
"dry_run": true,
117+
})
118+
job = prepareJob(t, database.ProvisionerJobTypeTemplateVersionDryRun, input)
119+
_ = dbgen.TemplateVersion(t, db, database.TemplateVersion{
120+
OrganizationID: owner.OrganizationID,
121+
CreatedBy: templateAdmin.ID,
122+
ID: tvID,
123+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
124+
JobID: job.ID,
125+
})
126+
)
127+
return job
135128
}
136129

137130
// Run the cancellation test suite.

cli/provisioners.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package cli
22

33
import (
44
"fmt"
5+
"time"
56

67
"golang.org/x/xerrors"
78

89
"github.com/coder/coder/v2/cli/cliui"
10+
"github.com/coder/coder/v2/coderd/util/slice"
911
"github.com/coder/coder/v2/codersdk"
1012
"github.com/coder/serpent"
1113
)
@@ -39,7 +41,10 @@ func (r *RootCmd) provisionerList() *serpent.Command {
3941
cliui.TableFormat([]provisionerDaemonRow{}, []string{"created at", "last seen at", "key name", "name", "version", "status", "tags"}),
4042
cliui.JSONFormat(),
4143
)
42-
limit int64
44+
limit int64
45+
offline bool
46+
status []string
47+
maxAge time.Duration
4348
)
4449

4550
cmd := &serpent.Command{
@@ -59,7 +64,10 @@ func (r *RootCmd) provisionerList() *serpent.Command {
5964
}
6065

6166
daemons, err := client.OrganizationProvisionerDaemons(ctx, org.ID, &codersdk.OrganizationProvisionerDaemonsOptions{
62-
Limit: int(limit),
67+
Limit: int(limit),
68+
Offline: offline,
69+
Status: slice.StringEnums[codersdk.ProvisionerDaemonStatus](status),
70+
MaxAge: maxAge,
6371
})
6472
if err != nil {
6573
return xerrors.Errorf("list provisioner daemons: %w", err)
@@ -98,6 +106,27 @@ func (r *RootCmd) provisionerList() *serpent.Command {
98106
Default: "50",
99107
Value: serpent.Int64Of(&limit),
100108
},
109+
{
110+
Flag: "show-offline",
111+
FlagShorthand: "f",
112+
Env: "CODER_PROVISIONER_SHOW_OFFLINE",
113+
Description: "Show offline provisioners.",
114+
Value: serpent.BoolOf(&offline),
115+
},
116+
{
117+
Flag: "status",
118+
FlagShorthand: "s",
119+
Env: "CODER_PROVISIONER_LIST_STATUS",
120+
Description: "Filter by provisioner status.",
121+
Value: serpent.EnumArrayOf(&status, slice.ToStrings(codersdk.ProvisionerDaemonStatusEnums())...),
122+
},
123+
{
124+
Flag: "max-age",
125+
FlagShorthand: "m",
126+
Env: "CODER_PROVISIONER_LIST_MAX_AGE",
127+
Description: "Filter provisioners by maximum age.",
128+
Value: serpent.DurationOf(&maxAge),
129+
},
101130
}...)
102131

103132
orgContext.AttachOptions(cmd)

cli/provisioners_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,74 @@ func TestProvisioners_Golden(t *testing.T) {
197197
clitest.TestGoldenFile(t, t.Name(), got.Bytes(), replace)
198198
})
199199

200+
t.Run("list with offline provisioner daemons", func(t *testing.T) {
201+
t.Parallel()
202+
203+
var got bytes.Buffer
204+
inv, root := clitest.New(t,
205+
"provisioners",
206+
"list",
207+
"--show-offline",
208+
)
209+
inv.Stdout = &got
210+
clitest.SetupConfig(t, templateAdminClient, root)
211+
err := inv.Run()
212+
require.NoError(t, err)
213+
214+
clitest.TestGoldenFile(t, t.Name(), got.Bytes(), replace)
215+
})
216+
217+
t.Run("list provisioner daemons by status", func(t *testing.T) {
218+
t.Parallel()
219+
220+
var got bytes.Buffer
221+
inv, root := clitest.New(t,
222+
"provisioners",
223+
"list",
224+
"--status=idle,offline,busy",
225+
)
226+
inv.Stdout = &got
227+
clitest.SetupConfig(t, templateAdminClient, root)
228+
err := inv.Run()
229+
require.NoError(t, err)
230+
231+
clitest.TestGoldenFile(t, t.Name(), got.Bytes(), replace)
232+
})
233+
234+
t.Run("list provisioner daemons without offline", func(t *testing.T) {
235+
t.Parallel()
236+
237+
var got bytes.Buffer
238+
inv, root := clitest.New(t,
239+
"provisioners",
240+
"list",
241+
"--status=idle,busy",
242+
)
243+
inv.Stdout = &got
244+
clitest.SetupConfig(t, templateAdminClient, root)
245+
err := inv.Run()
246+
require.NoError(t, err)
247+
248+
clitest.TestGoldenFile(t, t.Name(), got.Bytes(), replace)
249+
})
250+
251+
t.Run("list provisioner daemons by max age", func(t *testing.T) {
252+
t.Parallel()
253+
254+
var got bytes.Buffer
255+
inv, root := clitest.New(t,
256+
"provisioners",
257+
"list",
258+
"--max-age=1h",
259+
)
260+
inv.Stdout = &got
261+
clitest.SetupConfig(t, templateAdminClient, root)
262+
err := inv.Run()
263+
require.NoError(t, err)
264+
265+
clitest.TestGoldenFile(t, t.Name(), got.Bytes(), replace)
266+
})
267+
200268
// Test jobs list with template admin as members are currently
201269
// unable to access provisioner jobs. In the future (with RBAC
202270
// changes), we may allow them to view _their_ jobs.
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
ID CREATED AT LAST SEEN AT NAME VERSION TAGS KEY NAME STATUS CURRENT JOB ID CURRENT JOB STATUS PREVIOUS JOB ID PREVIOUS JOB STATUS ORGANIZATION
2-
00000000-0000-0000-aaaa-000000000000 ====[timestamp]===== ====[timestamp]===== default-provisioner v0.0.0-devel map[owner: scope:organization] built-in idle <nil> <nil> 00000000-0000-0000-bbbb-000000000001 succeeded Coder
3-
00000000-0000-0000-aaaa-000000000001 ====[timestamp]===== ====[timestamp]===== provisioner-1 v0.0.0 map[foo:bar owner: scope:organization] built-in busy 00000000-0000-0000-bbbb-000000000002 running <nil> <nil> Coder
4-
00000000-0000-0000-aaaa-000000000002 ====[timestamp]===== ====[timestamp]===== provisioner-2 v0.0.0 map[owner: scope:organization] built-in offline <nil> <nil> 00000000-0000-0000-bbbb-000000000003 succeeded Coder
5-
00000000-0000-0000-aaaa-000000000003 ====[timestamp]===== ====[timestamp]===== provisioner-3 v0.0.0 map[owner: scope:organization] built-in idle <nil> <nil> <nil> <nil> Coder
1+
ID CREATED AT LAST SEEN AT NAME VERSION TAGS KEY NAME STATUS CURRENT JOB ID CURRENT JOB STATUS PREVIOUS JOB ID PREVIOUS JOB STATUS ORGANIZATION
2+
00000000-0000-0000-aaaa-000000000000 ====[timestamp]===== ====[timestamp]===== default-provisioner v0.0.0-devel map[owner: scope:organization] built-in idle <nil> <nil> 00000000-0000-0000-bbbb-000000000001 succeeded Coder
3+
00000000-0000-0000-aaaa-000000000001 ====[timestamp]===== ====[timestamp]===== provisioner-1 v0.0.0 map[foo:bar owner: scope:organization] built-in busy 00000000-0000-0000-bbbb-000000000002 running <nil> <nil> Coder
4+
00000000-0000-0000-aaaa-000000000003 ====[timestamp]===== ====[timestamp]===== provisioner-3 v0.0.0 map[owner: scope:organization] built-in idle <nil> <nil> <nil> <nil> Coder
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
2+
====[timestamp]===== ====[timestamp]===== built-in default-provisioner v0.0.0-devel idle map[owner: scope:organization]
3+
====[timestamp]===== ====[timestamp]===== built-in provisioner-1 v0.0.0 busy map[foo:bar owner: scope:organization]
4+
====[timestamp]===== ====[timestamp]===== built-in provisioner-3 v0.0.0 idle map[owner: scope:organization]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
2+
====[timestamp]===== ====[timestamp]===== built-in default-provisioner v0.0.0-devel idle map[owner: scope:organization]
3+
====[timestamp]===== ====[timestamp]===== built-in provisioner-1 v0.0.0 busy map[foo:bar owner: scope:organization]
4+
====[timestamp]===== ====[timestamp]===== built-in provisioner-2 v0.0.0 offline map[owner: scope:organization]
5+
====[timestamp]===== ====[timestamp]===== built-in provisioner-3 v0.0.0 idle map[owner: scope:organization]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
2+
====[timestamp]===== ====[timestamp]===== built-in default-provisioner v0.0.0-devel idle map[owner: scope:organization]
3+
====[timestamp]===== ====[timestamp]===== built-in provisioner-1 v0.0.0 busy map[foo:bar owner: scope:organization]
4+
====[timestamp]===== ====[timestamp]===== built-in provisioner-3 v0.0.0 idle map[owner: scope:organization]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy