diff --git a/cli/testdata/coder_provisioner_jobs_list_--help.golden b/cli/testdata/coder_provisioner_jobs_list_--help.golden
index 7a72605f0c288..f380a0334867c 100644
--- a/cli/testdata/coder_provisioner_jobs_list_--help.golden
+++ b/cli/testdata/coder_provisioner_jobs_list_--help.golden
@@ -11,7 +11,7 @@ OPTIONS:
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
- -c, --column [id|created at|started at|completed at|canceled at|error|error code|status|worker id|file id|tags|queue position|queue size|organization id|template version id|workspace build id|type|available workers|template version name|template id|template name|template display name|template icon|workspace id|workspace name|organization|queue] (default: created at,id,type,template display name,status,queue,tags)
+ -c, --column [id|created at|started at|completed at|canceled at|error|error code|status|worker id|worker name|file id|tags|queue position|queue size|organization id|template version id|workspace build id|type|available workers|template version name|template id|template name|template display name|template icon|workspace id|workspace name|organization|queue] (default: created at,id,type,template display name,status,queue,tags)
Columns to display in table output.
-l, --limit int, $CODER_PROVISIONER_JOB_LIST_LIMIT (default: 50)
diff --git a/cli/testdata/coder_provisioner_jobs_list_--output_json.golden b/cli/testdata/coder_provisioner_jobs_list_--output_json.golden
index d18e07121f653..e36723765b4df 100644
--- a/cli/testdata/coder_provisioner_jobs_list_--output_json.golden
+++ b/cli/testdata/coder_provisioner_jobs_list_--output_json.golden
@@ -6,6 +6,7 @@
"completed_at": "====[timestamp]=====",
"status": "succeeded",
"worker_id": "====[workspace build worker ID]=====",
+ "worker_name": "test-daemon",
"file_id": "=====[workspace build file ID]======",
"tags": {
"owner": "",
@@ -34,6 +35,7 @@
"completed_at": "====[timestamp]=====",
"status": "succeeded",
"worker_id": "====[workspace build worker ID]=====",
+ "worker_name": "test-daemon",
"file_id": "=====[workspace build file ID]======",
"tags": {
"owner": "",
diff --git a/cli/testdata/coder_provisioner_list.golden b/cli/testdata/coder_provisioner_list.golden
index 64941eebf5b89..92ac6e485e68f 100644
--- a/cli/testdata/coder_provisioner_list.golden
+++ b/cli/testdata/coder_provisioner_list.golden
@@ -1,2 +1,2 @@
-CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
-====[timestamp]===== ====[timestamp]===== built-in test v0.0.0-devel idle map[owner: scope:organization]
+CREATED AT LAST SEEN AT KEY NAME NAME VERSION STATUS TAGS
+====[timestamp]===== ====[timestamp]===== built-in test-daemon v0.0.0-devel idle map[owner: scope:organization]
diff --git a/cli/testdata/coder_provisioner_list_--output_json.golden b/cli/testdata/coder_provisioner_list_--output_json.golden
index e8b3637bdffa6..73dd35ff84266 100644
--- a/cli/testdata/coder_provisioner_list_--output_json.golden
+++ b/cli/testdata/coder_provisioner_list_--output_json.golden
@@ -5,7 +5,7 @@
"key_id": "00000000-0000-0000-0000-000000000001",
"created_at": "====[timestamp]=====",
"last_seen_at": "====[timestamp]=====",
- "name": "test",
+ "name": "test-daemon",
"version": "v0.0.0-devel",
"api_version": "1.6",
"provisioners": [
diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index d55582afbbe8b..075f33aeac02f 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -14618,6 +14618,9 @@ const docTemplate = `{
"worker_id": {
"type": "string",
"format": "uuid"
+ },
+ "worker_name": {
+ "type": "string"
}
}
},
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index 00f940737a1d6..e00ab22232483 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -13250,6 +13250,9 @@
"worker_id": {
"type": "string",
"format": "uuid"
+ },
+ "worker_name": {
+ "type": "string"
}
}
},
diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go
index a25f0576e76be..b395a2cf2afbe 100644
--- a/coderd/coderdtest/coderdtest.go
+++ b/coderd/coderdtest/coderdtest.go
@@ -96,6 +96,8 @@ import (
"github.com/coder/coder/v2/testutil"
)
+const defaultTestDaemonName = "test-daemon"
+
type Options struct {
// AccessURL denotes a custom access URL. By default we use the httptest
// server's URL. Setting this may result in unexpected behavior (especially
@@ -602,7 +604,7 @@ func NewWithAPI(t testing.TB, options *Options) (*codersdk.Client, io.Closer, *c
setHandler(rootHandler)
var provisionerCloser io.Closer = nopcloser{}
if options.IncludeProvisionerDaemon {
- provisionerCloser = NewTaggedProvisionerDaemon(t, coderAPI, "test", options.ProvisionerDaemonTags, coderd.MemoryProvisionerWithVersionOverride(options.ProvisionerDaemonVersion))
+ provisionerCloser = NewTaggedProvisionerDaemon(t, coderAPI, defaultTestDaemonName, options.ProvisionerDaemonTags, coderd.MemoryProvisionerWithVersionOverride(options.ProvisionerDaemonVersion))
}
client := codersdk.New(serverURL)
t.Cleanup(func() {
@@ -646,7 +648,7 @@ func (c *ProvisionerdCloser) Close() error {
// well with coderd testing. It registers the "echo" provisioner for
// quick testing.
func NewProvisionerDaemon(t testing.TB, coderAPI *coderd.API) io.Closer {
- return NewTaggedProvisionerDaemon(t, coderAPI, "test", nil)
+ return NewTaggedProvisionerDaemon(t, coderAPI, defaultTestDaemonName, nil)
}
func NewTaggedProvisionerDaemon(t testing.TB, coderAPI *coderd.API, name string, provisionerTags map[string]string, opts ...coderd.MemoryProvisionerDaemonOption) io.Closer {
diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go
index fc5a10cafc481..7dec84f8aaeb0 100644
--- a/coderd/database/dbmem/dbmem.go
+++ b/coderd/database/dbmem/dbmem.go
@@ -4848,6 +4848,13 @@ func (q *FakeQuerier) GetProvisionerJobsByOrganizationAndStatusWithQueuePosition
row.AvailableWorkers = append(row.AvailableWorkers, worker.ID)
}
}
+
+ // Add daemon name to provisioner job
+ for _, daemon := range q.provisionerDaemons {
+ if job.WorkerID.Valid && job.WorkerID.UUID == daemon.ID {
+ row.WorkerName = daemon.Name
+ }
+ }
rows = append(rows, row)
}
diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go
index ac08d72d0e493..fdb9252bf27ee 100644
--- a/coderd/database/queries.sql.go
+++ b/coderd/database/queries.sql.go
@@ -7730,7 +7730,9 @@ SELECT
COALESCE(t.display_name, '') AS template_display_name,
COALESCE(t.icon, '') AS template_icon,
w.id AS workspace_id,
- COALESCE(w.name, '') AS workspace_name
+ COALESCE(w.name, '') AS workspace_name,
+ -- Include the name of the provisioner_daemon associated to the job
+ COALESCE(pd.name, '') AS worker_name
FROM
provisioner_jobs pj
LEFT JOIN
@@ -7755,6 +7757,9 @@ LEFT JOIN
t.id = tv.template_id
AND t.organization_id = pj.organization_id
)
+LEFT JOIN
+ -- Join to get the daemon name corresponding to the job's worker_id
+ provisioner_daemons pd ON pd.id = pj.worker_id
WHERE
pj.organization_id = $1::uuid
AND (COALESCE(array_length($2::uuid[], 1), 0) = 0 OR pj.id = ANY($2::uuid[]))
@@ -7770,7 +7775,8 @@ GROUP BY
t.display_name,
t.icon,
w.id,
- w.name
+ w.name,
+ pd.name
ORDER BY
pj.created_at DESC
LIMIT
@@ -7797,6 +7803,7 @@ type GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow
TemplateIcon string `db:"template_icon" json:"template_icon"`
WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"`
WorkspaceName string `db:"workspace_name" json:"workspace_name"`
+ WorkerName string `db:"worker_name" json:"worker_name"`
}
func (q *sqlQuerier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
@@ -7844,6 +7851,7 @@ func (q *sqlQuerier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionA
&i.TemplateIcon,
&i.WorkspaceID,
&i.WorkspaceName,
+ &i.WorkerName,
); err != nil {
return nil, err
}
diff --git a/coderd/database/queries/provisionerjobs.sql b/coderd/database/queries/provisionerjobs.sql
index 2d544aedb9bd8..2ab7774e660b8 100644
--- a/coderd/database/queries/provisionerjobs.sql
+++ b/coderd/database/queries/provisionerjobs.sql
@@ -160,7 +160,9 @@ SELECT
COALESCE(t.display_name, '') AS template_display_name,
COALESCE(t.icon, '') AS template_icon,
w.id AS workspace_id,
- COALESCE(w.name, '') AS workspace_name
+ COALESCE(w.name, '') AS workspace_name,
+ -- Include the name of the provisioner_daemon associated to the job
+ COALESCE(pd.name, '') AS worker_name
FROM
provisioner_jobs pj
LEFT JOIN
@@ -185,6 +187,9 @@ LEFT JOIN
t.id = tv.template_id
AND t.organization_id = pj.organization_id
)
+LEFT JOIN
+ -- Join to get the daemon name corresponding to the job's worker_id
+ provisioner_daemons pd ON pd.id = pj.worker_id
WHERE
pj.organization_id = @organization_id::uuid
AND (COALESCE(array_length(@ids::uuid[], 1), 0) = 0 OR pj.id = ANY(@ids::uuid[]))
@@ -200,7 +205,8 @@ GROUP BY
t.display_name,
t.icon,
w.id,
- w.name
+ w.name,
+ pd.name
ORDER BY
pj.created_at DESC
LIMIT
diff --git a/coderd/provisionerjobs.go b/coderd/provisionerjobs.go
index 6d75227a14ccd..5a8a0a5126cc0 100644
--- a/coderd/provisionerjobs.go
+++ b/coderd/provisionerjobs.go
@@ -395,6 +395,7 @@ func convertProvisionerJobWithQueuePosition(pj database.GetProvisionerJobsByOrga
QueuePosition: pj.QueuePosition,
QueueSize: pj.QueueSize,
})
+ job.WorkerName = pj.WorkerName
job.AvailableWorkers = pj.AvailableWorkers
job.Metadata = codersdk.ProvisionerJobMetadata{
TemplateVersionName: pj.TemplateVersionName,
diff --git a/coderd/provisionerjobs_test.go b/coderd/provisionerjobs_test.go
index 6ec8959102fa5..98da3ae5584e6 100644
--- a/coderd/provisionerjobs_test.go
+++ b/coderd/provisionerjobs_test.go
@@ -27,162 +27,263 @@ import (
func TestProvisionerJobs(t *testing.T) {
t.Parallel()
- db, ps := dbtestutil.NewDB(t, dbtestutil.WithDumpOnFailure())
- client := coderdtest.New(t, &coderdtest.Options{
- IncludeProvisionerDaemon: true,
- Database: db,
- Pubsub: ps,
- })
- owner := coderdtest.CreateFirstUser(t, client)
- templateAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgTemplateAdmin(owner.OrganizationID))
- memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
-
- version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
- coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
- template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
-
- time.Sleep(1500 * time.Millisecond) // Ensure the workspace build job has a different timestamp for sorting.
- workspace := coderdtest.CreateWorkspace(t, client, template.ID)
- coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
-
- // Create a pending job.
- w := dbgen.Workspace(t, db, database.WorkspaceTable{
- OrganizationID: owner.OrganizationID,
- OwnerID: member.ID,
- TemplateID: template.ID,
- })
- wbID := uuid.New()
- job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{
- OrganizationID: w.OrganizationID,
- StartedAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
- Type: database.ProvisionerJobTypeWorkspaceBuild,
- Input: json.RawMessage(`{"workspace_build_id":"` + wbID.String() + `"}`),
- })
- dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
- ID: wbID,
- JobID: job.ID,
- WorkspaceID: w.ID,
- TemplateVersionID: version.ID,
- })
+ t.Run("ProvisionerJobs", func(t *testing.T) {
+ db, ps := dbtestutil.NewDB(t, dbtestutil.WithDumpOnFailure())
+ client := coderdtest.New(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: true,
+ Database: db,
+ Pubsub: ps,
+ })
+ owner := coderdtest.CreateFirstUser(t, client)
+ templateAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgTemplateAdmin(owner.OrganizationID))
+ memberClient, member := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
+
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
+
+ time.Sleep(1500 * time.Millisecond) // Ensure the workspace build job has a different timestamp for sorting.
+ workspace := coderdtest.CreateWorkspace(t, client, template.ID)
+ coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
- // Add more jobs than the default limit.
- for i := range 60 {
- dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{
+ // Create a pending job.
+ w := dbgen.Workspace(t, db, database.WorkspaceTable{
OrganizationID: owner.OrganizationID,
- Tags: database.StringMap{"count": strconv.Itoa(i)},
+ OwnerID: member.ID,
+ TemplateID: template.ID,
+ })
+ wbID := uuid.New()
+ job := dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{
+ OrganizationID: w.OrganizationID,
+ StartedAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
+ Type: database.ProvisionerJobTypeWorkspaceBuild,
+ Input: json.RawMessage(`{"workspace_build_id":"` + wbID.String() + `"}`),
+ })
+ dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
+ ID: wbID,
+ JobID: job.ID,
+ WorkspaceID: w.ID,
+ TemplateVersionID: version.ID,
})
- }
- t.Run("Single", func(t *testing.T) {
- t.Parallel()
- t.Run("Workspace", func(t *testing.T) {
+ // Add more jobs than the default limit.
+ for i := range 60 {
+ dbgen.ProvisionerJob(t, db, nil, database.ProvisionerJob{
+ OrganizationID: owner.OrganizationID,
+ Tags: database.StringMap{"count": strconv.Itoa(i)},
+ })
+ }
+
+ t.Run("Single", func(t *testing.T) {
t.Parallel()
- t.Run("OK", func(t *testing.T) {
+ t.Run("Workspace", func(t *testing.T) {
t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- // Note this calls the single job endpoint.
- job2, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, job.ID)
- require.NoError(t, err)
- require.Equal(t, job.ID, job2.ID)
-
- // Verify that job metadata is correct.
- assert.Equal(t, job2.Metadata, codersdk.ProvisionerJobMetadata{
- TemplateVersionName: version.Name,
- TemplateID: template.ID,
- TemplateName: template.Name,
- TemplateDisplayName: template.DisplayName,
- TemplateIcon: template.Icon,
- WorkspaceID: &w.ID,
- WorkspaceName: w.Name,
+ t.Run("OK", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ // Note this calls the single job endpoint.
+ job2, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, job.ID)
+ require.NoError(t, err)
+ require.Equal(t, job.ID, job2.ID)
+
+ // Verify that job metadata is correct.
+ assert.Equal(t, job2.Metadata, codersdk.ProvisionerJobMetadata{
+ TemplateVersionName: version.Name,
+ TemplateID: template.ID,
+ TemplateName: template.Name,
+ TemplateDisplayName: template.DisplayName,
+ TemplateIcon: template.Icon,
+ WorkspaceID: &w.ID,
+ WorkspaceName: w.Name,
+ })
})
})
- })
- t.Run("Template Import", func(t *testing.T) {
- t.Parallel()
- t.Run("OK", func(t *testing.T) {
+ t.Run("Template Import", func(t *testing.T) {
+ t.Parallel()
+ t.Run("OK", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ // Note this calls the single job endpoint.
+ job2, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, version.Job.ID)
+ require.NoError(t, err)
+ require.Equal(t, version.Job.ID, job2.ID)
+
+ // Verify that job metadata is correct.
+ assert.Equal(t, job2.Metadata, codersdk.ProvisionerJobMetadata{
+ TemplateVersionName: version.Name,
+ TemplateID: template.ID,
+ TemplateName: template.Name,
+ TemplateDisplayName: template.DisplayName,
+ TemplateIcon: template.Icon,
+ })
+ })
+ })
+ t.Run("Missing", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
// Note this calls the single job endpoint.
- job2, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, version.Job.ID)
- require.NoError(t, err)
- require.Equal(t, version.Job.ID, job2.ID)
-
- // Verify that job metadata is correct.
- assert.Equal(t, job2.Metadata, codersdk.ProvisionerJobMetadata{
- TemplateVersionName: version.Name,
- TemplateID: template.ID,
- TemplateName: template.Name,
- TemplateDisplayName: template.DisplayName,
- TemplateIcon: template.Icon,
- })
+ _, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, uuid.New())
+ require.Error(t, err)
})
})
- t.Run("Missing", func(t *testing.T) {
+
+ t.Run("Default limit", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitMedium)
- // Note this calls the single job endpoint.
- _, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, uuid.New())
- require.Error(t, err)
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
+ require.NoError(t, err)
+ require.Len(t, jobs, 50)
})
- })
- t.Run("Default limit", func(t *testing.T) {
- t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
- require.NoError(t, err)
- require.Len(t, jobs, 50)
- })
+ t.Run("IDs", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
+ IDs: []uuid.UUID{workspace.LatestBuild.Job.ID, version.Job.ID},
+ })
+ require.NoError(t, err)
+ require.Len(t, jobs, 2)
+ })
- t.Run("IDs", func(t *testing.T) {
- t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
- IDs: []uuid.UUID{workspace.LatestBuild.Job.ID, version.Job.ID},
+ t.Run("Status", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
+ Status: []codersdk.ProvisionerJobStatus{codersdk.ProvisionerJobRunning},
+ })
+ require.NoError(t, err)
+ require.Len(t, jobs, 1)
})
- require.NoError(t, err)
- require.Len(t, jobs, 2)
- })
- t.Run("Status", func(t *testing.T) {
- t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
- Status: []codersdk.ProvisionerJobStatus{codersdk.ProvisionerJobRunning},
+ t.Run("Tags", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
+ Tags: map[string]string{"count": "1"},
+ })
+ require.NoError(t, err)
+ require.Len(t, jobs, 1)
})
- require.NoError(t, err)
- require.Len(t, jobs, 1)
- })
- t.Run("Tags", func(t *testing.T) {
- t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
- Tags: map[string]string{"count": "1"},
+ t.Run("Limit", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
+ Limit: 1,
+ })
+ require.NoError(t, err)
+ require.Len(t, jobs, 1)
+ })
+
+ // For now, this is not allowed even though the member has created a
+ // workspace. Once member-level permissions for jobs are supported
+ // by RBAC, this test should be updated.
+ t.Run("MemberDenied", func(t *testing.T) {
+ t.Parallel()
+ ctx := testutil.Context(t, testutil.WaitMedium)
+ jobs, err := memberClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
+ require.Error(t, err)
+ require.Len(t, jobs, 0)
})
- require.NoError(t, err)
- require.Len(t, jobs, 1)
})
- t.Run("Limit", func(t *testing.T) {
+ // Ensures that when a provisioner job is in the succeeded state,
+ // the API response includes both worker_id and worker_name fields
+ t.Run("AssignedProvisionerJob", func(t *testing.T) {
t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, &codersdk.OrganizationProvisionerJobsOptions{
- Limit: 1,
+
+ db, ps := dbtestutil.NewDB(t, dbtestutil.WithDumpOnFailure())
+ client, _, coderdAPI := coderdtest.NewWithAPI(t, &coderdtest.Options{
+ IncludeProvisionerDaemon: false,
+ Database: db,
+ Pubsub: ps,
})
+ provisionerDaemonName := "provisioner_daemon_test"
+ provisionerDaemon := coderdtest.NewTaggedProvisionerDaemon(t, coderdAPI, provisionerDaemonName, map[string]string{"owner": "", "scope": "organization"})
+ owner := coderdtest.CreateFirstUser(t, client)
+ templateAdminClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgTemplateAdmin(owner.OrganizationID))
+
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
+ coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
+
+ workspace := coderdtest.CreateWorkspace(t, client, template.ID)
+ coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
+
+ // Stop the provisioner so it doesn't grab any more jobs
+ err := provisionerDaemon.Close()
require.NoError(t, err)
- require.Len(t, jobs, 1)
- })
- // For now, this is not allowed even though the member has created a
- // workspace. Once member-level permissions for jobs are supported
- // by RBAC, this test should be updated.
- t.Run("MemberDenied", func(t *testing.T) {
- t.Parallel()
- ctx := testutil.Context(t, testutil.WaitMedium)
- jobs, err := memberClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
- require.Error(t, err)
- require.Len(t, jobs, 0)
+ t.Run("List_IncludesWorkerIDAndName", func(t *testing.T) {
+ t.Parallel()
+
+ ctx := testutil.Context(t, testutil.WaitMedium)
+
+ // Get provisioner daemon responsible for executing the provisioner jobs
+ provisionerDaemons, err := db.GetProvisionerDaemons(ctx)
+ require.NoError(t, err)
+ require.Equal(t, 1, len(provisionerDaemons))
+ if assert.NotEmpty(t, provisionerDaemons) {
+ require.Equal(t, provisionerDaemonName, provisionerDaemons[0].Name)
+ }
+
+ // Get provisioner jobs
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
+ require.NoError(t, err)
+ require.Equal(t, 2, len(jobs))
+
+ for _, job := range jobs {
+ require.Equal(t, owner.OrganizationID, job.OrganizationID)
+ require.Equal(t, database.ProvisionerJobStatusSucceeded, database.ProvisionerJobStatus(job.Status))
+
+ // Guarantee that provisioner jobs contain the provisioner daemon ID and name
+ if assert.NotEmpty(t, provisionerDaemons) {
+ require.Equal(t, &provisionerDaemons[0].ID, job.WorkerID)
+ require.Equal(t, provisionerDaemonName, job.WorkerName)
+ }
+ }
+ })
+
+ t.Run("Get_IncludesWorkerIDAndName", func(t *testing.T) {
+ t.Parallel()
+
+ ctx := testutil.Context(t, testutil.WaitMedium)
+
+ // Get provisioner daemon responsible for executing the provisioner job
+ provisionerDaemons, err := db.GetProvisionerDaemons(ctx)
+ require.NoError(t, err)
+ require.Equal(t, 1, len(provisionerDaemons))
+ if assert.NotEmpty(t, provisionerDaemons) {
+ require.Equal(t, provisionerDaemonName, provisionerDaemons[0].Name)
+ }
+
+ // Get all provisioner jobs
+ jobs, err := templateAdminClient.OrganizationProvisionerJobs(ctx, owner.OrganizationID, nil)
+ require.NoError(t, err)
+ require.Equal(t, 2, len(jobs))
+
+ // Find workspace_build provisioner job ID
+ var workspaceProvisionerJobID uuid.UUID
+ for _, job := range jobs {
+ if job.Type == codersdk.ProvisionerJobTypeWorkspaceBuild {
+ workspaceProvisionerJobID = job.ID
+ }
+ }
+ require.NotNil(t, workspaceProvisionerJobID)
+
+ // Get workspace_build provisioner job by ID
+ workspaceProvisionerJob, err := templateAdminClient.OrganizationProvisionerJob(ctx, owner.OrganizationID, workspaceProvisionerJobID)
+ require.NoError(t, err)
+
+ require.Equal(t, owner.OrganizationID, workspaceProvisionerJob.OrganizationID)
+ require.Equal(t, database.ProvisionerJobStatusSucceeded, database.ProvisionerJobStatus(workspaceProvisionerJob.Status))
+
+ // Guarantee that provisioner job contains the provisioner daemon ID and name
+ if assert.NotEmpty(t, provisionerDaemons) {
+ require.Equal(t, &provisionerDaemons[0].ID, workspaceProvisionerJob.WorkerID)
+ require.Equal(t, provisionerDaemonName, workspaceProvisionerJob.WorkerName)
+ }
+ })
})
}
diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go
index 11345a115e07f..5fbda371b8f3f 100644
--- a/codersdk/provisionerdaemons.go
+++ b/codersdk/provisionerdaemons.go
@@ -178,6 +178,7 @@ type ProvisionerJob struct {
ErrorCode JobErrorCode `json:"error_code,omitempty" enums:"REQUIRED_TEMPLATE_VARIABLES" table:"error code"`
Status ProvisionerJobStatus `json:"status" enums:"pending,running,succeeded,canceling,canceled,failed" table:"status"`
WorkerID *uuid.UUID `json:"worker_id,omitempty" format:"uuid" table:"worker id"`
+ WorkerName string `json:"worker_name,omitempty" table:"worker name"`
FileID uuid.UUID `json:"file_id" format:"uuid" table:"file id"`
Tags map[string]string `json:"tags" table:"tags"`
QueuePosition int `json:"queue_position" table:"queue position"`
diff --git a/docs/reference/api/builds.md b/docs/reference/api/builds.md
index 8e88df96c1d29..00417c700cdfd 100644
--- a/docs/reference/api/builds.md
+++ b/docs/reference/api/builds.md
@@ -69,7 +69,8 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -302,7 +303,8 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1012,7 +1014,8 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1318,7 +1321,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1527,6 +1531,7 @@ Status Code **200**
| `»»» [any property]` | string | false | | |
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
| `»» worker_id` | string(uuid) | false | | |
+| `»» worker_name` | string | false | | |
| `» matched_provisioners` | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners) | false | | |
| `»» available` | integer | false | | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `»» count` | integer | false | | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags. |
@@ -1798,7 +1803,8 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
diff --git a/docs/reference/api/organizations.md b/docs/reference/api/organizations.md
index 8c49f33e31ce3..497e3f56d4e47 100644
--- a/docs/reference/api/organizations.md
+++ b/docs/reference/api/organizations.md
@@ -426,7 +426,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
}
]
```
@@ -473,6 +474,7 @@ Status Code **200**
| `»» [any property]` | string | false | | |
| `» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
| `» worker_id` | string(uuid) | false | | |
+| `» worker_name` | string | false | | |
#### Enumerated Values
@@ -551,7 +553,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisi
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
}
```
diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md
index aa704b0fe6a57..91f70950e989e 100644
--- a/docs/reference/api/schemas.md
+++ b/docs/reference/api/schemas.md
@@ -5518,7 +5518,8 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
}
```
@@ -5545,6 +5546,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
| » `[any property]` | string | false | | |
| `type` | [codersdk.ProvisionerJobType](#codersdkprovisionerjobtype) | false | | |
| `worker_id` | string | false | | |
+| `worker_name` | string | false | | |
#### Enumerated Values
@@ -7101,7 +7103,8 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -8241,7 +8244,8 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -9205,7 +9209,8 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -9928,7 +9933,8 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
diff --git a/docs/reference/api/templates.md b/docs/reference/api/templates.md
index c662118868656..09fc555c7d39c 100644
--- a/docs/reference/api/templates.md
+++ b/docs/reference/api/templates.md
@@ -489,7 +489,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -586,7 +587,8 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -707,7 +709,8 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1264,7 +1267,8 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1334,6 +1338,7 @@ Status Code **200**
| `»»» [any property]` | string | false | | |
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
| `»» worker_id` | string(uuid) | false | | |
+| `»» worker_name` | string | false | | |
| `» matched_provisioners` | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners) | false | | |
| `»» available` | integer | false | | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `»» count` | integer | false | | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags. |
@@ -1541,7 +1546,8 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1611,6 +1617,7 @@ Status Code **200**
| `»»» [any property]` | string | false | | |
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
| `»» worker_id` | string(uuid) | false | | |
+| `»» worker_name` | string | false | | |
| `» matched_provisioners` | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners) | false | | |
| `»» available` | integer | false | | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `»» count` | integer | false | | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags. |
@@ -1708,7 +1715,8 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1814,7 +1822,8 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -2010,7 +2019,8 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
}
```
@@ -2082,7 +2092,8 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
}
```
diff --git a/docs/reference/api/workspaces.md b/docs/reference/api/workspaces.md
index 8e25cd0bd58e6..49377ec14c6fd 100644
--- a/docs/reference/api/workspaces.md
+++ b/docs/reference/api/workspaces.md
@@ -124,7 +124,8 @@ of the template will be used.
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -405,7 +406,8 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -712,7 +714,8 @@ of the template will be used.
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -996,7 +999,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1261,7 +1265,8 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
@@ -1658,7 +1663,8 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
"property2": "string"
},
"type": "template_version_import",
- "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
+ "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
+ "worker_name": "string"
},
"matched_provisioners": {
"available": 0,
diff --git a/docs/reference/cli/provisioner_jobs_list.md b/docs/reference/cli/provisioner_jobs_list.md
index a7f2fa74384d2..07ad02f419bde 100644
--- a/docs/reference/cli/provisioner_jobs_list.md
+++ b/docs/reference/cli/provisioner_jobs_list.md
@@ -45,10 +45,10 @@ Select which organization (uuid or name) to use.
### -c, --column
-| | |
-|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Type | [id\|created at\|started at\|completed at\|canceled at\|error\|error code\|status\|worker id\|file id\|tags\|queue position\|queue size\|organization id\|template version id\|workspace build id\|type\|available workers\|template version name\|template id\|template name\|template display name\|template icon\|workspace id\|workspace name\|organization\|queue]
|
-| Default | created at,id,type,template display name,status,queue,tags
|
+| | |
+|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Type | [id\|created at\|started at\|completed at\|canceled at\|error\|error code\|status\|worker id\|worker name\|file id\|tags\|queue position\|queue size\|organization id\|template version id\|workspace build id\|type\|available workers\|template version name\|template id\|template name\|template display name\|template icon\|workspace id\|workspace name\|organization\|queue]
|
+| Default | created at,id,type,template display name,status,queue,tags
|
Columns to display in table output.
diff --git a/enterprise/cli/testdata/coder_provisioner_jobs_list_--help.golden b/enterprise/cli/testdata/coder_provisioner_jobs_list_--help.golden
index 7a72605f0c288..f380a0334867c 100644
--- a/enterprise/cli/testdata/coder_provisioner_jobs_list_--help.golden
+++ b/enterprise/cli/testdata/coder_provisioner_jobs_list_--help.golden
@@ -11,7 +11,7 @@ OPTIONS:
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
- -c, --column [id|created at|started at|completed at|canceled at|error|error code|status|worker id|file id|tags|queue position|queue size|organization id|template version id|workspace build id|type|available workers|template version name|template id|template name|template display name|template icon|workspace id|workspace name|organization|queue] (default: created at,id,type,template display name,status,queue,tags)
+ -c, --column [id|created at|started at|completed at|canceled at|error|error code|status|worker id|worker name|file id|tags|queue position|queue size|organization id|template version id|workspace build id|type|available workers|template version name|template id|template name|template display name|template icon|workspace id|workspace name|organization|queue] (default: created at,id,type,template display name,status,queue,tags)
Columns to display in table output.
-l, --limit int, $CODER_PROVISIONER_JOB_LIST_LIMIT (default: 50)
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index 897e5f9012a4f..68cf0940ad8e1 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -1925,6 +1925,7 @@ export interface ProvisionerJob {
readonly error_code?: JobErrorCode;
readonly status: ProvisionerJobStatus;
readonly worker_id?: string;
+ readonly worker_name?: string;
readonly file_id: string;
readonly tags: Record;
readonly queue_position: number;
diff --git a/site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/JobRow.tsx b/site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/JobRow.tsx
index e97749db3d6f4..2073f75ca3558 100644
--- a/site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/JobRow.tsx
+++ b/site/src/pages/OrganizationSettingsPage/OrganizationProvisionerJobsPage/JobRow.tsx
@@ -120,14 +120,16 @@ export const JobRow: FC = ({ job, defaultIsOpen = false }) => {
<>
Completed by provisioner:
- {job.worker_id}
-
+ {job.worker_name || "[removed]"}
+ {job.worker_name && (
+
+ )}
>
)}