mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat(coderd): add endpoint to list provisioner jobs (#16029)
Closes #15190 Updates #15084
This commit is contained in:
committed by
GitHub
parent
0e8ef09415
commit
3864c7e3b0
+6
-1
@@ -43,7 +43,12 @@
|
||||
"scope": "organization"
|
||||
},
|
||||
"queue_position": 0,
|
||||
"queue_size": 0
|
||||
"queue_size": 0,
|
||||
"organization_id": "===========[first org ID]===========",
|
||||
"input": {
|
||||
"workspace_build_id": "========[workspace build ID]========"
|
||||
},
|
||||
"type": "workspace_build"
|
||||
},
|
||||
"reason": "initiator",
|
||||
"resources": [],
|
||||
|
||||
Generated
+113
@@ -3025,6 +3025,71 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/provisionerjobs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Organizations"
|
||||
],
|
||||
"summary": "Get provisioner jobs",
|
||||
"operationId": "get-provisioner-jobs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page limit",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"pending",
|
||||
"running",
|
||||
"succeeded",
|
||||
"canceling",
|
||||
"canceled",
|
||||
"failed",
|
||||
"unknown",
|
||||
"pending",
|
||||
"running",
|
||||
"succeeded",
|
||||
"canceling",
|
||||
"canceled",
|
||||
"failed"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Filter results by status",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJob"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/provisionerkeys": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -12561,6 +12626,13 @@ const docTemplate = `{
|
||||
"codersdk.ProvisionerJob": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"available_workers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"canceled_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
@@ -12594,6 +12666,13 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"input": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJobInput"
|
||||
},
|
||||
"organization_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"queue_position": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -12625,12 +12704,31 @@ const docTemplate = `{
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJobType"
|
||||
},
|
||||
"worker_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ProvisionerJobInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"template_version_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"workspace_build_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ProvisionerJobLog": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -12687,6 +12785,19 @@ const docTemplate = `{
|
||||
"ProvisionerJobUnknown"
|
||||
]
|
||||
},
|
||||
"codersdk.ProvisionerJobType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"template_version_import",
|
||||
"workspace_build",
|
||||
"template_version_dry_run"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ProvisionerJobTypeTemplateVersionImport",
|
||||
"ProvisionerJobTypeWorkspaceBuild",
|
||||
"ProvisionerJobTypeTemplateVersionDryRun"
|
||||
]
|
||||
},
|
||||
"codersdk.ProvisionerKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -12900,6 +13011,7 @@ const docTemplate = `{
|
||||
"organization",
|
||||
"organization_member",
|
||||
"provisioner_daemon",
|
||||
"provisioner_jobs",
|
||||
"provisioner_keys",
|
||||
"replicas",
|
||||
"system",
|
||||
@@ -12934,6 +13046,7 @@ const docTemplate = `{
|
||||
"ResourceOrganization",
|
||||
"ResourceOrganizationMember",
|
||||
"ResourceProvisionerDaemon",
|
||||
"ResourceProvisionerJobs",
|
||||
"ResourceProvisionerKeys",
|
||||
"ResourceReplicas",
|
||||
"ResourceSystem",
|
||||
|
||||
Generated
+109
@@ -2657,6 +2657,67 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/provisionerjobs": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"CoderSessionToken": []
|
||||
}
|
||||
],
|
||||
"produces": ["application/json"],
|
||||
"tags": ["Organizations"],
|
||||
"summary": "Get provisioner jobs",
|
||||
"operationId": "get-provisioner-jobs",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Organization ID",
|
||||
"name": "organization",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "Page limit",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"pending",
|
||||
"running",
|
||||
"succeeded",
|
||||
"canceling",
|
||||
"canceled",
|
||||
"failed",
|
||||
"unknown",
|
||||
"pending",
|
||||
"running",
|
||||
"succeeded",
|
||||
"canceling",
|
||||
"canceled",
|
||||
"failed"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Filter results by status",
|
||||
"name": "status",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJob"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/organizations/{organization}/provisionerkeys": {
|
||||
"get": {
|
||||
"security": [
|
||||
@@ -11334,6 +11395,13 @@
|
||||
"codersdk.ProvisionerJob": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"available_workers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
},
|
||||
"canceled_at": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
@@ -11365,6 +11433,13 @@
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"input": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJobInput"
|
||||
},
|
||||
"organization_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"queue_position": {
|
||||
"type": "integer"
|
||||
},
|
||||
@@ -11396,12 +11471,31 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/codersdk.ProvisionerJobType"
|
||||
},
|
||||
"worker_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ProvisionerJobInput": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"error": {
|
||||
"type": "string"
|
||||
},
|
||||
"template_version_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
},
|
||||
"workspace_build_id": {
|
||||
"type": "string",
|
||||
"format": "uuid"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.ProvisionerJobLog": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -11452,6 +11546,19 @@
|
||||
"ProvisionerJobUnknown"
|
||||
]
|
||||
},
|
||||
"codersdk.ProvisionerJobType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"template_version_import",
|
||||
"workspace_build",
|
||||
"template_version_dry_run"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ProvisionerJobTypeTemplateVersionImport",
|
||||
"ProvisionerJobTypeWorkspaceBuild",
|
||||
"ProvisionerJobTypeTemplateVersionDryRun"
|
||||
]
|
||||
},
|
||||
"codersdk.ProvisionerKey": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -11647,6 +11754,7 @@
|
||||
"organization",
|
||||
"organization_member",
|
||||
"provisioner_daemon",
|
||||
"provisioner_jobs",
|
||||
"provisioner_keys",
|
||||
"replicas",
|
||||
"system",
|
||||
@@ -11681,6 +11789,7 @@
|
||||
"ResourceOrganization",
|
||||
"ResourceOrganizationMember",
|
||||
"ResourceProvisionerDaemon",
|
||||
"ResourceProvisionerJobs",
|
||||
"ResourceProvisionerKeys",
|
||||
"ResourceReplicas",
|
||||
"ResourceSystem",
|
||||
|
||||
@@ -1010,6 +1010,9 @@ func New(options *Options) *API {
|
||||
r.Route("/provisionerdaemons", func(r chi.Router) {
|
||||
r.Get("/", api.provisionerDaemons)
|
||||
})
|
||||
r.Route("/provisionerjobs", func(r chi.Router) {
|
||||
r.Get("/", api.provisionerJobs)
|
||||
})
|
||||
})
|
||||
})
|
||||
r.Route("/templates", func(r chi.Router) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@@ -48,7 +47,11 @@ type NotAuthorizedError struct {
|
||||
var _ httpapiconstraints.IsUnauthorizedError = (*NotAuthorizedError)(nil)
|
||||
|
||||
func (e NotAuthorizedError) Error() string {
|
||||
return fmt.Sprintf("unauthorized: %s", e.Err.Error())
|
||||
var detail string
|
||||
if e.Err != nil {
|
||||
detail = ": " + e.Err.Error()
|
||||
}
|
||||
return "unauthorized" + detail
|
||||
}
|
||||
|
||||
// IsUnauthorized implements the IsUnauthorized interface.
|
||||
@@ -1975,7 +1978,7 @@ func (q *querier) GetProvisionerJobTimingsByJobID(ctx context.Context, jobID uui
|
||||
return q.db.GetProvisionerJobTimingsByJobID(ctx, jobID)
|
||||
}
|
||||
|
||||
// TODO: we need to add a provisioner job resource
|
||||
// TODO: We have a ProvisionerJobs resource, but it hasn't been checked for this use-case.
|
||||
func (q *querier) GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]database.ProvisionerJob, error) {
|
||||
// if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
// return nil, err
|
||||
@@ -1983,12 +1986,16 @@ func (q *querier) GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID)
|
||||
return q.db.GetProvisionerJobsByIDs(ctx, ids)
|
||||
}
|
||||
|
||||
// TODO: we need to add a provisioner job resource
|
||||
// TODO: We have a ProvisionerJobs resource, but it hasn't been checked for this use-case.
|
||||
func (q *querier) GetProvisionerJobsByIDsWithQueuePosition(ctx context.Context, ids []uuid.UUID) ([]database.GetProvisionerJobsByIDsWithQueuePositionRow, error) {
|
||||
return q.db.GetProvisionerJobsByIDsWithQueuePosition(ctx, ids)
|
||||
}
|
||||
|
||||
// TODO: We need to create a ProvisionerJob resource type
|
||||
func (q *querier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
|
||||
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner)(ctx, arg)
|
||||
}
|
||||
|
||||
// TODO: We have a ProvisionerJobs resource, but it hasn't been checked for this use-case.
|
||||
func (q *querier) GetProvisionerJobsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ProvisionerJob, error) {
|
||||
// if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
// return nil, err
|
||||
|
||||
@@ -3258,6 +3258,38 @@ func (s *MethodTestSuite) TestExtraMethods() {
|
||||
LastSeenAt: sql.NullTime{Time: dbtime.Now(), Valid: true},
|
||||
}).Asserts(rbac.ResourceProvisionerDaemon, policy.ActionUpdate)
|
||||
}))
|
||||
s.Run("GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner", s.Subtest(func(db database.Store, check *expects) {
|
||||
org := dbgen.Organization(s.T(), db, database.Organization{})
|
||||
user := dbgen.User(s.T(), db, database.User{})
|
||||
tags := database.StringMap(map[string]string{
|
||||
provisionersdk.TagScope: provisionersdk.ScopeOrganization,
|
||||
})
|
||||
t := dbgen.Template(s.T(), db, database.Template{OrganizationID: org.ID, CreatedBy: user.ID})
|
||||
tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{OrganizationID: org.ID, CreatedBy: user.ID, TemplateID: uuid.NullUUID{UUID: t.ID, Valid: true}})
|
||||
j1 := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
|
||||
OrganizationID: org.ID,
|
||||
Type: database.ProvisionerJobTypeTemplateVersionImport,
|
||||
Input: []byte(`{"template_version_id":"` + tv.ID.String() + `"}`),
|
||||
Tags: tags,
|
||||
})
|
||||
w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{OrganizationID: org.ID, OwnerID: user.ID, TemplateID: t.ID})
|
||||
wbID := uuid.New()
|
||||
j2 := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
|
||||
OrganizationID: org.ID,
|
||||
Type: database.ProvisionerJobTypeWorkspaceBuild,
|
||||
Input: []byte(`{"workspace_build_id":"` + wbID.String() + `"}`),
|
||||
Tags: tags,
|
||||
})
|
||||
dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{ID: wbID, WorkspaceID: w.ID, TemplateVersionID: tv.ID, JobID: j2.ID})
|
||||
|
||||
ds, err := db.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(context.Background(), database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams{
|
||||
OrganizationID: uuid.NullUUID{Valid: true, UUID: org.ID},
|
||||
})
|
||||
s.NoError(err, "get provisioner jobs by org")
|
||||
check.Args(database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams{
|
||||
OrganizationID: uuid.NullUUID{Valid: true, UUID: org.ID},
|
||||
}).Asserts(j1, policy.ActionRead, j2, policy.ActionRead).Returns(ds)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestTailnetFunctions() {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -249,12 +250,18 @@ func WorkspaceAgentScriptTiming(t testing.TB, db database.Store, orig database.W
|
||||
func Workspace(t testing.TB, db database.Store, orig database.WorkspaceTable) database.WorkspaceTable {
|
||||
t.Helper()
|
||||
|
||||
var defOrgID uuid.UUID
|
||||
if orig.OrganizationID == uuid.Nil {
|
||||
defOrg, _ := db.GetDefaultOrganization(genCtx)
|
||||
defOrgID = defOrg.ID
|
||||
}
|
||||
|
||||
workspace, err := db.InsertWorkspace(genCtx, database.InsertWorkspaceParams{
|
||||
ID: takeFirst(orig.ID, uuid.New()),
|
||||
OwnerID: takeFirst(orig.OwnerID, uuid.New()),
|
||||
CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()),
|
||||
UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()),
|
||||
OrganizationID: takeFirst(orig.OrganizationID, uuid.New()),
|
||||
OrganizationID: takeFirst(orig.OrganizationID, defOrgID, uuid.New()),
|
||||
TemplateID: takeFirst(orig.TemplateID, uuid.New()),
|
||||
LastUsedAt: takeFirst(orig.LastUsedAt, dbtime.Now()),
|
||||
Name: takeFirst(orig.Name, testutil.GetRandomName(t)),
|
||||
@@ -557,13 +564,15 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
}
|
||||
|
||||
jobID := takeFirst(orig.ID, uuid.New())
|
||||
|
||||
// Always set some tags to prevent Acquire from grabbing jobs it should not.
|
||||
tags := maps.Clone(orig.Tags)
|
||||
if !orig.StartedAt.Time.IsZero() {
|
||||
if orig.Tags == nil {
|
||||
orig.Tags = make(database.StringMap)
|
||||
if tags == nil {
|
||||
tags = make(database.StringMap)
|
||||
}
|
||||
// Make sure when we acquire the job, we only get this one.
|
||||
orig.Tags[jobID.String()] = "true"
|
||||
tags[jobID.String()] = "true"
|
||||
}
|
||||
|
||||
job, err := db.InsertProvisionerJob(genCtx, database.InsertProvisionerJobParams{
|
||||
@@ -577,7 +586,7 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
FileID: takeFirst(orig.FileID, uuid.New()),
|
||||
Type: takeFirst(orig.Type, database.ProvisionerJobTypeWorkspaceBuild),
|
||||
Input: takeFirstSlice(orig.Input, []byte("{}")),
|
||||
Tags: orig.Tags,
|
||||
Tags: tags,
|
||||
TraceMetadata: pqtype.NullRawMessage{},
|
||||
})
|
||||
require.NoError(t, err, "insert job")
|
||||
@@ -589,9 +598,9 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
job, err = db.AcquireProvisionerJob(genCtx, database.AcquireProvisionerJobParams{
|
||||
StartedAt: orig.StartedAt,
|
||||
OrganizationID: job.OrganizationID,
|
||||
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
|
||||
ProvisionerTags: must(json.Marshal(orig.Tags)),
|
||||
WorkerID: uuid.NullUUID{},
|
||||
Types: []database.ProvisionerType{job.Provisioner},
|
||||
ProvisionerTags: must(json.Marshal(tags)),
|
||||
WorkerID: takeFirst(orig.WorkerID, uuid.NullUUID{}),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// There is no easy way to make sure we acquire the correct job.
|
||||
@@ -599,7 +608,7 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
}
|
||||
|
||||
if !orig.CompletedAt.Time.IsZero() || orig.Error.String != "" {
|
||||
err := db.UpdateProvisionerJobWithCompleteByID(genCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
|
||||
err = db.UpdateProvisionerJobWithCompleteByID(genCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
|
||||
ID: jobID,
|
||||
UpdatedAt: job.UpdatedAt,
|
||||
CompletedAt: orig.CompletedAt,
|
||||
@@ -609,7 +618,7 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
require.NoError(t, err)
|
||||
}
|
||||
if !orig.CanceledAt.Time.IsZero() {
|
||||
err := db.UpdateProvisionerJobWithCancelByID(genCtx, database.UpdateProvisionerJobWithCancelByIDParams{
|
||||
err = db.UpdateProvisionerJobWithCancelByID(genCtx, database.UpdateProvisionerJobWithCancelByIDParams{
|
||||
ID: jobID,
|
||||
CanceledAt: orig.CanceledAt,
|
||||
CompletedAt: orig.CompletedAt,
|
||||
@@ -618,7 +627,7 @@ func ProvisionerJob(t testing.TB, db database.Store, ps pubsub.Pubsub, orig data
|
||||
}
|
||||
|
||||
job, err = db.GetProvisionerJobByID(genCtx, jobID)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, err, "get job: %s", jobID.String())
|
||||
|
||||
return job
|
||||
}
|
||||
|
||||
+205
-83
@@ -1130,6 +1130,96 @@ func getOwnerFromTags(tags map[string]string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) getProvisionerJobsByIDsWithQueuePositionLocked(_ context.Context, ids []uuid.UUID) ([]database.GetProvisionerJobsByIDsWithQueuePositionRow, error) {
|
||||
// WITH pending_jobs AS (
|
||||
// SELECT
|
||||
// id, created_at
|
||||
// FROM
|
||||
// provisioner_jobs
|
||||
// WHERE
|
||||
// started_at IS NULL
|
||||
// AND
|
||||
// canceled_at IS NULL
|
||||
// AND
|
||||
// completed_at IS NULL
|
||||
// AND
|
||||
// error IS NULL
|
||||
// ),
|
||||
type pendingJobRow struct {
|
||||
ID uuid.UUID
|
||||
CreatedAt time.Time
|
||||
}
|
||||
pendingJobs := make([]pendingJobRow, 0)
|
||||
for _, job := range q.provisionerJobs {
|
||||
if job.StartedAt.Valid ||
|
||||
job.CanceledAt.Valid ||
|
||||
job.CompletedAt.Valid ||
|
||||
job.Error.Valid {
|
||||
continue
|
||||
}
|
||||
pendingJobs = append(pendingJobs, pendingJobRow{
|
||||
ID: job.ID,
|
||||
CreatedAt: job.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
// queue_position AS (
|
||||
// SELECT
|
||||
// id,
|
||||
// ROW_NUMBER() OVER (ORDER BY created_at ASC) AS queue_position
|
||||
// FROM
|
||||
// pending_jobs
|
||||
// ),
|
||||
slices.SortFunc(pendingJobs, func(a, b pendingJobRow) int {
|
||||
c := a.CreatedAt.Compare(b.CreatedAt)
|
||||
return c
|
||||
})
|
||||
|
||||
queuePosition := make(map[uuid.UUID]int64)
|
||||
for idx, pj := range pendingJobs {
|
||||
queuePosition[pj.ID] = int64(idx + 1)
|
||||
}
|
||||
|
||||
// queue_size AS (
|
||||
// SELECT COUNT(*) AS count FROM pending_jobs
|
||||
// ),
|
||||
queueSize := len(pendingJobs)
|
||||
|
||||
// SELECT
|
||||
// sqlc.embed(pj),
|
||||
// COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
// COALESCE(qs.count, 0) AS queue_size
|
||||
// FROM
|
||||
// provisioner_jobs pj
|
||||
// LEFT JOIN
|
||||
// queue_position qp ON pj.id = qp.id
|
||||
// LEFT JOIN
|
||||
// queue_size qs ON TRUE
|
||||
// WHERE
|
||||
// pj.id IN (...)
|
||||
jobs := make([]database.GetProvisionerJobsByIDsWithQueuePositionRow, 0)
|
||||
for _, job := range q.provisionerJobs {
|
||||
if ids != nil && !slices.Contains(ids, job.ID) {
|
||||
continue
|
||||
}
|
||||
// clone the Tags before appending, since maps are reference types and
|
||||
// we don't want the caller to be able to mutate the map we have inside
|
||||
// dbmem!
|
||||
job.Tags = maps.Clone(job.Tags)
|
||||
job := database.GetProvisionerJobsByIDsWithQueuePositionRow{
|
||||
// sqlc.embed(pj),
|
||||
ProvisionerJob: job,
|
||||
// COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
QueuePosition: queuePosition[job.ID],
|
||||
// COALESCE(qs.count, 0) AS queue_size
|
||||
QueueSize: int64(queueSize),
|
||||
}
|
||||
jobs = append(jobs, job)
|
||||
}
|
||||
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
func (*FakeQuerier) AcquireLock(_ context.Context, _ int64) error {
|
||||
return xerrors.New("AcquireLock must only be called within a transaction")
|
||||
}
|
||||
@@ -3901,97 +3991,129 @@ func (q *FakeQuerier) GetProvisionerJobsByIDs(_ context.Context, ids []uuid.UUID
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetProvisionerJobsByIDsWithQueuePosition(_ context.Context, ids []uuid.UUID) ([]database.GetProvisionerJobsByIDsWithQueuePositionRow, error) {
|
||||
func (q *FakeQuerier) GetProvisionerJobsByIDsWithQueuePosition(ctx context.Context, ids []uuid.UUID) ([]database.GetProvisionerJobsByIDsWithQueuePositionRow, error) {
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
// WITH pending_jobs AS (
|
||||
// SELECT
|
||||
// id, created_at
|
||||
// FROM
|
||||
// provisioner_jobs
|
||||
// WHERE
|
||||
// started_at IS NULL
|
||||
// AND
|
||||
// canceled_at IS NULL
|
||||
// AND
|
||||
// completed_at IS NULL
|
||||
// AND
|
||||
// error IS NULL
|
||||
// ),
|
||||
type pendingJobRow struct {
|
||||
ID uuid.UUID
|
||||
CreatedAt time.Time
|
||||
if ids == nil {
|
||||
ids = []uuid.UUID{}
|
||||
}
|
||||
pendingJobs := make([]pendingJobRow, 0)
|
||||
for _, job := range q.provisionerJobs {
|
||||
if job.StartedAt.Valid ||
|
||||
job.CanceledAt.Valid ||
|
||||
job.CompletedAt.Valid ||
|
||||
job.Error.Valid {
|
||||
continue
|
||||
}
|
||||
pendingJobs = append(pendingJobs, pendingJobRow{
|
||||
ID: job.ID,
|
||||
CreatedAt: job.CreatedAt,
|
||||
})
|
||||
return q.getProvisionerJobsByIDsWithQueuePositionLocked(ctx, ids)
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
|
||||
err := validateDatabaseType(arg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// queue_position AS (
|
||||
// SELECT
|
||||
// id,
|
||||
// ROW_NUMBER() OVER (ORDER BY created_at ASC) AS queue_position
|
||||
// FROM
|
||||
// pending_jobs
|
||||
// ),
|
||||
slices.SortFunc(pendingJobs, func(a, b pendingJobRow) int {
|
||||
c := a.CreatedAt.Compare(b.CreatedAt)
|
||||
return c
|
||||
q.mutex.RLock()
|
||||
defer q.mutex.RUnlock()
|
||||
|
||||
/*
|
||||
-- name: GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner :many
|
||||
WITH pending_jobs AS (
|
||||
SELECT
|
||||
id, created_at
|
||||
FROM
|
||||
provisioner_jobs
|
||||
WHERE
|
||||
started_at IS NULL
|
||||
AND
|
||||
canceled_at IS NULL
|
||||
AND
|
||||
completed_at IS NULL
|
||||
AND
|
||||
error IS NULL
|
||||
),
|
||||
queue_position AS (
|
||||
SELECT
|
||||
id,
|
||||
ROW_NUMBER() OVER (ORDER BY created_at ASC) AS queue_position
|
||||
FROM
|
||||
pending_jobs
|
||||
),
|
||||
queue_size AS (
|
||||
SELECT COUNT(*) AS count FROM pending_jobs
|
||||
)
|
||||
SELECT
|
||||
sqlc.embed(pj),
|
||||
COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
COALESCE(qs.count, 0) AS queue_size,
|
||||
array_agg(DISTINCT pd.id) FILTER (WHERE pd.id IS NOT NULL)::uuid[] AS available_workers
|
||||
FROM
|
||||
provisioner_jobs pj
|
||||
LEFT JOIN
|
||||
queue_position qp ON qp.id = pj.id
|
||||
LEFT JOIN
|
||||
queue_size qs ON TRUE
|
||||
LEFT JOIN
|
||||
provisioner_daemons pd ON (
|
||||
-- See AcquireProvisionerJob.
|
||||
pj.started_at IS NULL
|
||||
AND pj.organization_id = pd.organization_id
|
||||
AND pj.provisioner = ANY(pd.provisioners)
|
||||
AND provisioner_tagset_contains(pd.tags, pj.tags)
|
||||
)
|
||||
WHERE
|
||||
(sqlc.narg('organization_id')::uuid IS NULL OR pj.organization_id = @organization_id)
|
||||
AND (COALESCE(array_length(@status::provisioner_job_status[], 1), 1) > 0 OR pj.job_status = ANY(@status::provisioner_job_status[]))
|
||||
GROUP BY
|
||||
pj.id,
|
||||
qp.queue_position,
|
||||
qs.count
|
||||
ORDER BY
|
||||
pj.created_at DESC
|
||||
LIMIT
|
||||
sqlc.narg('limit')::int;
|
||||
*/
|
||||
rowsWithQueuePosition, err := q.getProvisionerJobsByIDsWithQueuePositionLocked(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var rows []database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow
|
||||
for _, rowQP := range rowsWithQueuePosition {
|
||||
job := rowQP.ProvisionerJob
|
||||
|
||||
if arg.OrganizationID.Valid && job.OrganizationID != arg.OrganizationID.UUID {
|
||||
continue
|
||||
}
|
||||
if len(arg.Status) > 0 && !slices.Contains(arg.Status, job.JobStatus) {
|
||||
continue
|
||||
}
|
||||
|
||||
row := database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow{
|
||||
ProvisionerJob: rowQP.ProvisionerJob,
|
||||
QueuePosition: rowQP.QueuePosition,
|
||||
QueueSize: rowQP.QueueSize,
|
||||
}
|
||||
if row.QueuePosition > 0 {
|
||||
var availableWorkers []database.ProvisionerDaemon
|
||||
for _, daemon := range q.provisionerDaemons {
|
||||
if daemon.OrganizationID == job.OrganizationID &&
|
||||
slices.Contains(daemon.Provisioners, job.Provisioner) &&
|
||||
tagsSubset(job.Tags, daemon.Tags) {
|
||||
availableWorkers = append(availableWorkers, daemon)
|
||||
}
|
||||
}
|
||||
slices.SortFunc(availableWorkers, func(a, b database.ProvisionerDaemon) int {
|
||||
return a.CreatedAt.Compare(b.CreatedAt)
|
||||
})
|
||||
for _, worker := range availableWorkers {
|
||||
row.AvailableWorkers = append(row.AvailableWorkers, worker.ID)
|
||||
}
|
||||
}
|
||||
rows = append(rows, row)
|
||||
}
|
||||
|
||||
slices.SortFunc(rows, func(a, b database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow) int {
|
||||
return b.ProvisionerJob.CreatedAt.Compare(a.ProvisionerJob.CreatedAt)
|
||||
})
|
||||
|
||||
queuePosition := make(map[uuid.UUID]int64)
|
||||
for idx, pj := range pendingJobs {
|
||||
queuePosition[pj.ID] = int64(idx + 1)
|
||||
if arg.Limit.Valid && arg.Limit.Int32 > 0 && len(rows) > int(arg.Limit.Int32) {
|
||||
rows = rows[:arg.Limit.Int32]
|
||||
}
|
||||
|
||||
// queue_size AS (
|
||||
// SELECT COUNT(*) AS count FROM pending_jobs
|
||||
// ),
|
||||
queueSize := len(pendingJobs)
|
||||
|
||||
// SELECT
|
||||
// sqlc.embed(pj),
|
||||
// COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
// COALESCE(qs.count, 0) AS queue_size
|
||||
// FROM
|
||||
// provisioner_jobs pj
|
||||
// LEFT JOIN
|
||||
// queue_position qp ON pj.id = qp.id
|
||||
// LEFT JOIN
|
||||
// queue_size qs ON TRUE
|
||||
// WHERE
|
||||
// pj.id IN (...)
|
||||
jobs := make([]database.GetProvisionerJobsByIDsWithQueuePositionRow, 0)
|
||||
for _, job := range q.provisionerJobs {
|
||||
if !slices.Contains(ids, job.ID) {
|
||||
continue
|
||||
}
|
||||
// clone the Tags before appending, since maps are reference types and
|
||||
// we don't want the caller to be able to mutate the map we have inside
|
||||
// dbmem!
|
||||
job.Tags = maps.Clone(job.Tags)
|
||||
job := database.GetProvisionerJobsByIDsWithQueuePositionRow{
|
||||
// sqlc.embed(pj),
|
||||
ProvisionerJob: job,
|
||||
// COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
QueuePosition: queuePosition[job.ID],
|
||||
// COALESCE(qs.count, 0) AS queue_size
|
||||
QueueSize: int64(queueSize),
|
||||
}
|
||||
jobs = append(jobs, job)
|
||||
}
|
||||
|
||||
return jobs, nil
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
func (q *FakeQuerier) GetProvisionerJobsCreatedAfter(_ context.Context, after time.Time) ([]database.ProvisionerJob, error) {
|
||||
|
||||
@@ -1022,6 +1022,13 @@ func (m queryMetricsStore) GetProvisionerJobsByIDsWithQueuePosition(ctx context.
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
|
||||
start := time.Now()
|
||||
r0, r1 := m.s.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx, arg)
|
||||
m.queryLatencies.WithLabelValues("GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner").Observe(time.Since(start).Seconds())
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
func (m queryMetricsStore) GetProvisionerJobsCreatedAfter(ctx context.Context, createdAt time.Time) ([]database.ProvisionerJob, error) {
|
||||
start := time.Now()
|
||||
jobs, err := m.s.GetProvisionerJobsCreatedAfter(ctx, createdAt)
|
||||
|
||||
@@ -2105,6 +2105,21 @@ func (mr *MockStoreMockRecorder) GetProvisionerJobsByIDsWithQueuePosition(arg0,
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProvisionerJobsByIDsWithQueuePosition", reflect.TypeOf((*MockStore)(nil).GetProvisionerJobsByIDsWithQueuePosition), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner mocks base method.
|
||||
func (m *MockStore) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(arg0 context.Context, arg1 database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner", arg0, arg1)
|
||||
ret0, _ := ret[0].([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner indicates an expected call of GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner.
|
||||
func (mr *MockStoreMockRecorder) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner", reflect.TypeOf((*MockStore)(nil).GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetProvisionerJobsCreatedAfter mocks base method.
|
||||
func (m *MockStore) GetProvisionerJobsCreatedAfter(arg0 context.Context, arg1 time.Time) ([]database.ProvisionerJob, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
||||
@@ -458,6 +458,18 @@ func (g Group) IsEveryone() bool {
|
||||
return g.ID == g.OrganizationID
|
||||
}
|
||||
|
||||
func (p ProvisionerJob) RBACObject() rbac.Object {
|
||||
switch p.Type {
|
||||
// Only acceptable for known job types at this time because template
|
||||
// admins may not be allowed to view new types.
|
||||
case ProvisionerJobTypeTemplateVersionImport, ProvisionerJobTypeTemplateVersionDryRun, ProvisionerJobTypeWorkspaceBuild:
|
||||
return rbac.ResourceProvisionerJobs.InOrg(p.OrganizationID)
|
||||
|
||||
default:
|
||||
panic("developer error: unknown provisioner job type " + string(p.Type))
|
||||
}
|
||||
}
|
||||
|
||||
func (p ProvisionerJob) Finished() bool {
|
||||
return p.CanceledAt.Valid || p.CompletedAt.Valid
|
||||
}
|
||||
@@ -511,3 +523,7 @@ func (k CryptoKey) CanVerify(now time.Time) bool {
|
||||
isBeforeDeletion := !k.DeletesAt.Valid || now.Before(k.DeletesAt.Time)
|
||||
return hasSecret && isBeforeDeletion
|
||||
}
|
||||
|
||||
func (r GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow) RBACObject() rbac.Object {
|
||||
return r.ProvisionerJob.RBACObject()
|
||||
}
|
||||
|
||||
@@ -208,6 +208,7 @@ type sqlcQuerier interface {
|
||||
GetProvisionerJobTimingsByJobID(ctx context.Context, jobID uuid.UUID) ([]ProvisionerJobTiming, error)
|
||||
GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUID) ([]ProvisionerJob, error)
|
||||
GetProvisionerJobsByIDsWithQueuePosition(ctx context.Context, ids []uuid.UUID) ([]GetProvisionerJobsByIDsWithQueuePositionRow, error)
|
||||
GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error)
|
||||
GetProvisionerJobsCreatedAfter(ctx context.Context, createdAt time.Time) ([]ProvisionerJob, error)
|
||||
GetProvisionerKeyByHashedSecret(ctx context.Context, hashedSecret []byte) (ProvisionerKey, error)
|
||||
GetProvisionerKeyByID(ctx context.Context, id uuid.UUID) (ProvisionerKey, error)
|
||||
|
||||
@@ -6222,6 +6222,128 @@ func (q *sqlQuerier) GetProvisionerJobsByIDsWithQueuePosition(ctx context.Contex
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner = `-- name: GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner :many
|
||||
WITH pending_jobs AS (
|
||||
SELECT
|
||||
id, created_at
|
||||
FROM
|
||||
provisioner_jobs
|
||||
WHERE
|
||||
started_at IS NULL
|
||||
AND
|
||||
canceled_at IS NULL
|
||||
AND
|
||||
completed_at IS NULL
|
||||
AND
|
||||
error IS NULL
|
||||
),
|
||||
queue_position AS (
|
||||
SELECT
|
||||
id,
|
||||
ROW_NUMBER() OVER (ORDER BY created_at ASC) AS queue_position
|
||||
FROM
|
||||
pending_jobs
|
||||
),
|
||||
queue_size AS (
|
||||
SELECT COUNT(*) AS count FROM pending_jobs
|
||||
)
|
||||
SELECT
|
||||
pj.id, pj.created_at, pj.updated_at, pj.started_at, pj.canceled_at, pj.completed_at, pj.error, pj.organization_id, pj.initiator_id, pj.provisioner, pj.storage_method, pj.type, pj.input, pj.worker_id, pj.file_id, pj.tags, pj.error_code, pj.trace_metadata, pj.job_status,
|
||||
COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
COALESCE(qs.count, 0) AS queue_size,
|
||||
-- Use subquery to utilize ORDER BY in array_agg since it cannot be
|
||||
-- combined with FILTER.
|
||||
(
|
||||
SELECT
|
||||
-- Order for stable output.
|
||||
array_agg(pd.id ORDER BY pd.created_at ASC)::uuid[]
|
||||
FROM
|
||||
provisioner_daemons pd
|
||||
WHERE
|
||||
-- See AcquireProvisionerJob.
|
||||
pj.started_at IS NULL
|
||||
AND pj.organization_id = pd.organization_id
|
||||
AND pj.provisioner = ANY(pd.provisioners)
|
||||
AND provisioner_tagset_contains(pd.tags, pj.tags)
|
||||
) AS available_workers
|
||||
FROM
|
||||
provisioner_jobs pj
|
||||
LEFT JOIN
|
||||
queue_position qp ON qp.id = pj.id
|
||||
LEFT JOIN
|
||||
queue_size qs ON TRUE
|
||||
WHERE
|
||||
($1::uuid IS NULL OR pj.organization_id = $1)
|
||||
AND (COALESCE(array_length($2::provisioner_job_status[], 1), 0) = 0 OR pj.job_status = ANY($2::provisioner_job_status[]))
|
||||
GROUP BY
|
||||
pj.id,
|
||||
qp.queue_position,
|
||||
qs.count
|
||||
ORDER BY
|
||||
pj.created_at DESC
|
||||
LIMIT
|
||||
$3::int
|
||||
`
|
||||
|
||||
type GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams struct {
|
||||
OrganizationID uuid.NullUUID `db:"organization_id" json:"organization_id"`
|
||||
Status []ProvisionerJobStatus `db:"status" json:"status"`
|
||||
Limit sql.NullInt32 `db:"limit" json:"limit"`
|
||||
}
|
||||
|
||||
type GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow struct {
|
||||
ProvisionerJob ProvisionerJob `db:"provisioner_job" json:"provisioner_job"`
|
||||
QueuePosition int64 `db:"queue_position" json:"queue_position"`
|
||||
QueueSize int64 `db:"queue_size" json:"queue_size"`
|
||||
AvailableWorkers []uuid.UUID `db:"available_workers" json:"available_workers"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner, arg.OrganizationID, pq.Array(arg.Status), arg.Limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow
|
||||
for rows.Next() {
|
||||
var i GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow
|
||||
if err := rows.Scan(
|
||||
&i.ProvisionerJob.ID,
|
||||
&i.ProvisionerJob.CreatedAt,
|
||||
&i.ProvisionerJob.UpdatedAt,
|
||||
&i.ProvisionerJob.StartedAt,
|
||||
&i.ProvisionerJob.CanceledAt,
|
||||
&i.ProvisionerJob.CompletedAt,
|
||||
&i.ProvisionerJob.Error,
|
||||
&i.ProvisionerJob.OrganizationID,
|
||||
&i.ProvisionerJob.InitiatorID,
|
||||
&i.ProvisionerJob.Provisioner,
|
||||
&i.ProvisionerJob.StorageMethod,
|
||||
&i.ProvisionerJob.Type,
|
||||
&i.ProvisionerJob.Input,
|
||||
&i.ProvisionerJob.WorkerID,
|
||||
&i.ProvisionerJob.FileID,
|
||||
&i.ProvisionerJob.Tags,
|
||||
&i.ProvisionerJob.ErrorCode,
|
||||
&i.ProvisionerJob.TraceMetadata,
|
||||
&i.ProvisionerJob.JobStatus,
|
||||
&i.QueuePosition,
|
||||
&i.QueueSize,
|
||||
pq.Array(&i.AvailableWorkers),
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getProvisionerJobsCreatedAfter = `-- name: GetProvisionerJobsCreatedAfter :many
|
||||
SELECT id, created_at, updated_at, started_at, canceled_at, completed_at, error, organization_id, initiator_id, provisioner, storage_method, type, input, worker_id, file_id, tags, error_code, trace_metadata, job_status FROM provisioner_jobs WHERE created_at > $1
|
||||
`
|
||||
|
||||
@@ -87,6 +87,68 @@ LEFT JOIN
|
||||
WHERE
|
||||
pj.id = ANY(@ids :: uuid [ ]);
|
||||
|
||||
-- name: GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner :many
|
||||
WITH pending_jobs AS (
|
||||
SELECT
|
||||
id, created_at
|
||||
FROM
|
||||
provisioner_jobs
|
||||
WHERE
|
||||
started_at IS NULL
|
||||
AND
|
||||
canceled_at IS NULL
|
||||
AND
|
||||
completed_at IS NULL
|
||||
AND
|
||||
error IS NULL
|
||||
),
|
||||
queue_position AS (
|
||||
SELECT
|
||||
id,
|
||||
ROW_NUMBER() OVER (ORDER BY created_at ASC) AS queue_position
|
||||
FROM
|
||||
pending_jobs
|
||||
),
|
||||
queue_size AS (
|
||||
SELECT COUNT(*) AS count FROM pending_jobs
|
||||
)
|
||||
SELECT
|
||||
sqlc.embed(pj),
|
||||
COALESCE(qp.queue_position, 0) AS queue_position,
|
||||
COALESCE(qs.count, 0) AS queue_size,
|
||||
-- Use subquery to utilize ORDER BY in array_agg since it cannot be
|
||||
-- combined with FILTER.
|
||||
(
|
||||
SELECT
|
||||
-- Order for stable output.
|
||||
array_agg(pd.id ORDER BY pd.created_at ASC)::uuid[]
|
||||
FROM
|
||||
provisioner_daemons pd
|
||||
WHERE
|
||||
-- See AcquireProvisionerJob.
|
||||
pj.started_at IS NULL
|
||||
AND pj.organization_id = pd.organization_id
|
||||
AND pj.provisioner = ANY(pd.provisioners)
|
||||
AND provisioner_tagset_contains(pd.tags, pj.tags)
|
||||
) AS available_workers
|
||||
FROM
|
||||
provisioner_jobs pj
|
||||
LEFT JOIN
|
||||
queue_position qp ON qp.id = pj.id
|
||||
LEFT JOIN
|
||||
queue_size qs ON TRUE
|
||||
WHERE
|
||||
(sqlc.narg('organization_id')::uuid IS NULL OR pj.organization_id = @organization_id)
|
||||
AND (COALESCE(array_length(@status::provisioner_job_status[], 1), 0) = 0 OR pj.job_status = ANY(@status::provisioner_job_status[]))
|
||||
GROUP BY
|
||||
pj.id,
|
||||
qp.queue_position,
|
||||
qs.count
|
||||
ORDER BY
|
||||
pj.created_at DESC
|
||||
LIMIT
|
||||
sqlc.narg('limit')::int;
|
||||
|
||||
-- name: GetProvisionerJobsCreatedAfter :many
|
||||
SELECT * FROM provisioner_jobs WHERE created_at > $1;
|
||||
|
||||
|
||||
@@ -19,12 +19,78 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/database/dbauthz"
|
||||
"github.com/coder/coder/v2/coderd/database/pubsub"
|
||||
"github.com/coder/coder/v2/coderd/httpapi"
|
||||
"github.com/coder/coder/v2/coderd/httpmw"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/coderd/rbac/policy"
|
||||
"github.com/coder/coder/v2/coderd/util/slice"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/codersdk/wsjson"
|
||||
"github.com/coder/coder/v2/provisionersdk"
|
||||
"github.com/coder/websocket"
|
||||
)
|
||||
|
||||
// @Summary Get provisioner jobs
|
||||
// @ID get-provisioner-jobs
|
||||
// @Security CoderSessionToken
|
||||
// @Produce json
|
||||
// @Tags Organizations
|
||||
// @Param organization path string true "Organization ID" format(uuid)
|
||||
// @Param limit query int false "Page limit"
|
||||
// @Param status query codersdk.ProvisionerJobStatus false "Filter results by status" enums(pending,running,succeeded,canceling,canceled,failed)
|
||||
// @Success 200 {array} codersdk.ProvisionerJob
|
||||
// @Router /organizations/{organization}/provisionerjobs [get]
|
||||
func (api *API) provisionerJobs(rw http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
org := httpmw.OrganizationParam(r)
|
||||
|
||||
// For now, only owners and template admins can access provisioner jobs.
|
||||
if !api.Authorize(r, policy.ActionRead, rbac.ResourceProvisionerJobs.InOrg(org.ID)) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
|
||||
qp := r.URL.Query()
|
||||
p := httpapi.NewQueryParamParser()
|
||||
limit := p.PositiveInt32(qp, 0, "limit")
|
||||
status := p.Strings(qp, nil, "status")
|
||||
p.ErrorExcessParams(qp)
|
||||
if len(p.Errors) > 0 {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid query parameters.",
|
||||
Validations: p.Errors,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
jobs, err := api.Database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx, database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams{
|
||||
OrganizationID: uuid.NullUUID{UUID: org.ID, Valid: true},
|
||||
Status: slice.StringEnums[database.ProvisionerJobStatus](status),
|
||||
Limit: sql.NullInt32{Int32: limit, Valid: limit > 0},
|
||||
})
|
||||
if err != nil {
|
||||
if httpapi.Is404Error(err) {
|
||||
httpapi.ResourceNotFound(rw)
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error fetching provisioner jobs.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.List(jobs, func(dbJob database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow) codersdk.ProvisionerJob {
|
||||
job := convertProvisionerJob(database.GetProvisionerJobsByIDsWithQueuePositionRow{
|
||||
ProvisionerJob: dbJob.ProvisionerJob,
|
||||
QueuePosition: dbJob.QueuePosition,
|
||||
QueueSize: dbJob.QueueSize,
|
||||
})
|
||||
job.AvailableWorkers = dbJob.AvailableWorkers
|
||||
return job
|
||||
}))
|
||||
}
|
||||
|
||||
// Returns provisioner logs based on query parameters.
|
||||
// The intended usage for a client to stream all logs (with JS API):
|
||||
// GET /logs
|
||||
@@ -236,14 +302,16 @@ func convertProvisionerJobLog(provisionerJobLog database.ProvisionerJobLog) code
|
||||
func convertProvisionerJob(pj database.GetProvisionerJobsByIDsWithQueuePositionRow) codersdk.ProvisionerJob {
|
||||
provisionerJob := pj.ProvisionerJob
|
||||
job := codersdk.ProvisionerJob{
|
||||
ID: provisionerJob.ID,
|
||||
CreatedAt: provisionerJob.CreatedAt,
|
||||
Error: provisionerJob.Error.String,
|
||||
ErrorCode: codersdk.JobErrorCode(provisionerJob.ErrorCode.String),
|
||||
FileID: provisionerJob.FileID,
|
||||
Tags: provisionerJob.Tags,
|
||||
QueuePosition: int(pj.QueuePosition),
|
||||
QueueSize: int(pj.QueueSize),
|
||||
ID: provisionerJob.ID,
|
||||
OrganizationID: provisionerJob.OrganizationID,
|
||||
CreatedAt: provisionerJob.CreatedAt,
|
||||
Type: codersdk.ProvisionerJobType(provisionerJob.Type),
|
||||
Error: provisionerJob.Error.String,
|
||||
ErrorCode: codersdk.JobErrorCode(provisionerJob.ErrorCode.String),
|
||||
FileID: provisionerJob.FileID,
|
||||
Tags: provisionerJob.Tags,
|
||||
QueuePosition: int(pj.QueuePosition),
|
||||
QueueSize: int(pj.QueueSize),
|
||||
}
|
||||
// Applying values optional to the struct.
|
||||
if provisionerJob.StartedAt.Valid {
|
||||
@@ -260,6 +328,13 @@ func convertProvisionerJob(pj database.GetProvisionerJobsByIDsWithQueuePositionR
|
||||
}
|
||||
job.Status = codersdk.ProvisionerJobStatus(pj.ProvisionerJob.JobStatus)
|
||||
|
||||
// Only unmarshal input if it exists, this should only be zero in testing.
|
||||
if len(provisionerJob.Input) > 0 {
|
||||
if err := json.Unmarshal(provisionerJob.Input, &job.Input); err != nil {
|
||||
job.Input.Error = xerrors.Errorf("decode input %s: %w", provisionerJob.Input, err).Error()
|
||||
}
|
||||
}
|
||||
|
||||
return job
|
||||
}
|
||||
|
||||
|
||||
@@ -2,16 +2,107 @@ package coderd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/coder/coder/v2/coderd/coderdtest"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/dbgen"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtestutil"
|
||||
"github.com/coder/coder/v2/coderd/database/dbtime"
|
||||
"github.com/coder/coder/v2/coderd/rbac"
|
||||
"github.com/coder/coder/v2/codersdk"
|
||||
"github.com/coder/coder/v2/provisioner/echo"
|
||||
"github.com/coder/coder/v2/provisionersdk/proto"
|
||||
"github.com/coder/coder/v2/testutil"
|
||||
)
|
||||
|
||||
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("All", 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, 3)
|
||||
})
|
||||
|
||||
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)
|
||||
})
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProvisionerJobLogs(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("StreamAfterComplete", func(t *testing.T) {
|
||||
|
||||
@@ -214,6 +214,13 @@ var (
|
||||
Type: "provisioner_daemon",
|
||||
}
|
||||
|
||||
// ResourceProvisionerJobs
|
||||
// Valid Actions
|
||||
// - "ActionRead" :: read provisioner jobs
|
||||
ResourceProvisionerJobs = Object{
|
||||
Type: "provisioner_jobs",
|
||||
}
|
||||
|
||||
// ResourceProvisionerKeys
|
||||
// Valid Actions
|
||||
// - "ActionCreate" :: create a provisioner key
|
||||
@@ -338,6 +345,7 @@ func AllResources() []Objecter {
|
||||
ResourceOrganization,
|
||||
ResourceOrganizationMember,
|
||||
ResourceProvisionerDaemon,
|
||||
ResourceProvisionerJobs,
|
||||
ResourceProvisionerKeys,
|
||||
ResourceReplicas,
|
||||
ResourceSystem,
|
||||
|
||||
@@ -169,6 +169,11 @@ var RBACPermissions = map[string]PermissionDefinition{
|
||||
ActionDelete: actDef("delete a provisioner daemon"),
|
||||
},
|
||||
},
|
||||
"provisioner_jobs": {
|
||||
Actions: map[Action]ActionDefinition{
|
||||
ActionRead: actDef("read provisioner jobs"),
|
||||
},
|
||||
},
|
||||
"provisioner_keys": {
|
||||
Actions: map[Action]ActionDefinition{
|
||||
ActionCreate: actDef("create a provisioner key"),
|
||||
|
||||
@@ -483,6 +483,7 @@ func ReloadBuiltinRoles(opts *RoleOptions) {
|
||||
ResourceOrganizationMember.Type: {policy.ActionRead},
|
||||
ResourceGroup.Type: {policy.ActionRead},
|
||||
ResourceGroupMember.Type: {policy.ActionRead},
|
||||
ResourceProvisionerJobs.Type: {policy.ActionRead},
|
||||
}),
|
||||
},
|
||||
User: []Permission{},
|
||||
|
||||
@@ -564,6 +564,15 @@ func TestRolePermissions(t *testing.T) {
|
||||
false: {setOtherOrg, memberMe, orgMemberMe, userAdmin, templateAdmin, orgTemplateAdmin, orgUserAdmin, orgAuditor},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "ProvisionerJobs",
|
||||
Actions: []policy.Action{policy.ActionRead},
|
||||
Resource: rbac.ResourceProvisionerJobs.InOrg(orgID),
|
||||
AuthorizeMap: map[bool][]hasAuthSubjects{
|
||||
true: {owner, orgTemplateAdmin, orgAdmin},
|
||||
false: {setOtherOrg, memberMe, orgMemberMe, templateAdmin, userAdmin, orgUserAdmin, orgAuditor},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "System",
|
||||
Actions: crud,
|
||||
|
||||
@@ -13,6 +13,17 @@ func ToStrings[T ~string](a []T) []string {
|
||||
return tmp
|
||||
}
|
||||
|
||||
func StringEnums[E ~string](a []string) []E {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
tmp := make([]E, 0, len(a))
|
||||
for _, v := range a {
|
||||
tmp = append(tmp, E(v))
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// Omit creates a new slice with the arguments omitted from the list.
|
||||
func Omit[T comparable](a []T, omits ...T) []T {
|
||||
tmp := make([]T, 0, len(a))
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -343,6 +344,47 @@ func (c *Client) OrganizationProvisionerDaemons(ctx context.Context, organizatio
|
||||
return daemons, json.NewDecoder(res.Body).Decode(&daemons)
|
||||
}
|
||||
|
||||
type OrganizationProvisionerJobsOptions struct {
|
||||
Limit int
|
||||
Status []ProvisionerJobStatus
|
||||
}
|
||||
|
||||
func (c *Client) OrganizationProvisionerJobs(ctx context.Context, organizationID uuid.UUID, opts *OrganizationProvisionerJobsOptions) ([]ProvisionerJob, error) {
|
||||
qp := url.Values{}
|
||||
if opts != nil {
|
||||
if opts.Limit > 0 {
|
||||
qp.Add("limit", strconv.Itoa(opts.Limit))
|
||||
}
|
||||
if len(opts.Status) > 0 {
|
||||
qp.Add("status", joinSlice(opts.Status))
|
||||
}
|
||||
}
|
||||
|
||||
res, err := c.Request(ctx, http.MethodGet,
|
||||
fmt.Sprintf("/api/v2/organizations/%s/provisionerjobs?%s", organizationID.String(), qp.Encode()),
|
||||
nil,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("make request: %w", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, ReadBodyAsError(res)
|
||||
}
|
||||
|
||||
var jobs []ProvisionerJob
|
||||
return jobs, json.NewDecoder(res.Body).Decode(&jobs)
|
||||
}
|
||||
|
||||
func joinSlice[T ~string](s []T) string {
|
||||
var ss []string
|
||||
for _, v := range s {
|
||||
ss = append(ss, string(v))
|
||||
}
|
||||
return strings.Join(ss, ",")
|
||||
}
|
||||
|
||||
// CreateTemplateVersion processes source-code and optionally associates the version with a template.
|
||||
// Executing without a template is useful for validating source-code.
|
||||
func (c *Client) CreateTemplateVersion(ctx context.Context, organizationID uuid.UUID, req CreateTemplateVersionRequest) (TemplateVersion, error) {
|
||||
|
||||
@@ -112,6 +112,34 @@ const (
|
||||
ProvisionerJobUnknown ProvisionerJobStatus = "unknown"
|
||||
)
|
||||
|
||||
func ProvisionerJobStatusEnums() []ProvisionerJobStatus {
|
||||
return []ProvisionerJobStatus{
|
||||
ProvisionerJobPending,
|
||||
ProvisionerJobRunning,
|
||||
ProvisionerJobSucceeded,
|
||||
ProvisionerJobCanceling,
|
||||
ProvisionerJobCanceled,
|
||||
ProvisionerJobFailed,
|
||||
ProvisionerJobUnknown,
|
||||
}
|
||||
}
|
||||
|
||||
// ProvisionerJobInput represents the input for the job.
|
||||
type ProvisionerJobInput struct {
|
||||
TemplateVersionID *uuid.UUID `json:"template_version_id,omitempty" format:"uuid" table:"template version id"`
|
||||
WorkspaceBuildID *uuid.UUID `json:"workspace_build_id,omitempty" format:"uuid" table:"workspace build id"`
|
||||
Error string `json:"error,omitempty" table:"-"`
|
||||
}
|
||||
|
||||
// ProvisionerJobType represents the type of job.
|
||||
type ProvisionerJobType string
|
||||
|
||||
const (
|
||||
ProvisionerJobTypeTemplateVersionImport ProvisionerJobType = "template_version_import"
|
||||
ProvisionerJobTypeWorkspaceBuild ProvisionerJobType = "workspace_build"
|
||||
ProvisionerJobTypeTemplateVersionDryRun ProvisionerJobType = "template_version_dry_run"
|
||||
)
|
||||
|
||||
// JobErrorCode defines the error code returned by job runner.
|
||||
type JobErrorCode string
|
||||
|
||||
@@ -127,19 +155,23 @@ func JobIsMissingParameterErrorCode(code JobErrorCode) bool {
|
||||
|
||||
// ProvisionerJob describes the job executed by the provisioning daemon.
|
||||
type ProvisionerJob struct {
|
||||
ID uuid.UUID `json:"id" format:"uuid"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty" format:"date-time"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty" format:"date-time"`
|
||||
CanceledAt *time.Time `json:"canceled_at,omitempty" format:"date-time"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ErrorCode JobErrorCode `json:"error_code,omitempty" enums:"REQUIRED_TEMPLATE_VARIABLES"`
|
||||
Status ProvisionerJobStatus `json:"status" enums:"pending,running,succeeded,canceling,canceled,failed"`
|
||||
WorkerID *uuid.UUID `json:"worker_id,omitempty" format:"uuid"`
|
||||
FileID uuid.UUID `json:"file_id" format:"uuid"`
|
||||
Tags map[string]string `json:"tags"`
|
||||
QueuePosition int `json:"queue_position"`
|
||||
QueueSize int `json:"queue_size"`
|
||||
ID uuid.UUID `json:"id" format:"uuid" table:"id"`
|
||||
CreatedAt time.Time `json:"created_at" format:"date-time" table:"created at,default_sort"`
|
||||
StartedAt *time.Time `json:"started_at,omitempty" format:"date-time" table:"started at"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty" format:"date-time" table:"completed at"`
|
||||
CanceledAt *time.Time `json:"canceled_at,omitempty" format:"date-time" table:"canceled at"`
|
||||
Error string `json:"error,omitempty" table:"error"`
|
||||
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"`
|
||||
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"`
|
||||
QueueSize int `json:"queue_size" table:"queue size"`
|
||||
OrganizationID uuid.UUID `json:"organization_id" format:"uuid" table:"organization id"`
|
||||
Input ProvisionerJobInput `json:"input" table:"input,recursive_inline"`
|
||||
Type ProvisionerJobType `json:"type" table:"type"`
|
||||
AvailableWorkers []uuid.UUID `json:"available_workers,omitempty" format:"uuid" table:"available workers"`
|
||||
}
|
||||
|
||||
// ProvisionerJobLog represents the provisioner log entry annotated with source and level.
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
ResourceOrganization RBACResource = "organization"
|
||||
ResourceOrganizationMember RBACResource = "organization_member"
|
||||
ResourceProvisionerDaemon RBACResource = "provisioner_daemon"
|
||||
ResourceProvisionerJobs RBACResource = "provisioner_jobs"
|
||||
ResourceProvisionerKeys RBACResource = "provisioner_keys"
|
||||
ResourceReplicas RBACResource = "replicas"
|
||||
ResourceSystem RBACResource = "system"
|
||||
@@ -82,6 +83,7 @@ var RBACResourceActions = map[RBACResource][]RBACAction{
|
||||
ResourceOrganization: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
ResourceOrganizationMember: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
ResourceProvisionerDaemon: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
ResourceProvisionerJobs: {ActionRead},
|
||||
ResourceProvisionerKeys: {ActionCreate, ActionDelete, ActionRead},
|
||||
ResourceReplicas: {ActionRead},
|
||||
ResourceSystem: {ActionCreate, ActionDelete, ActionRead, ActionUpdate},
|
||||
|
||||
Generated
+60
@@ -35,6 +35,9 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -42,6 +45,12 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -50,6 +59,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -230,6 +240,9 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -237,6 +250,12 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -245,6 +264,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -867,6 +887,9 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -874,6 +897,12 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -882,6 +911,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1135,6 +1165,9 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1142,6 +1175,12 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1150,6 +1189,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1311,6 +1351,7 @@ Status Code **200**
|
||||
| `» initiator_id` | string(uuid) | false | | |
|
||||
| `» initiator_name` | string | false | | |
|
||||
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
|
||||
| `»» available_workers` | array | false | | |
|
||||
| `»» canceled_at` | string(date-time) | false | | |
|
||||
| `»» completed_at` | string(date-time) | false | | |
|
||||
| `»» created_at` | string(date-time) | false | | |
|
||||
@@ -1318,12 +1359,18 @@ Status Code **200**
|
||||
| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `»» file_id` | string(uuid) | false | | |
|
||||
| `»» id` | string(uuid) | false | | |
|
||||
| `»» input` | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput) | false | | |
|
||||
| `»»» error` | string | false | | |
|
||||
| `»»» template_version_id` | string(uuid) | false | | |
|
||||
| `»»» workspace_build_id` | string(uuid) | false | | |
|
||||
| `»» organization_id` | string(uuid) | false | | |
|
||||
| `»» queue_position` | integer | false | | |
|
||||
| `»» queue_size` | integer | false | | |
|
||||
| `»» started_at` | string(date-time) | false | | |
|
||||
| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `»» tags` | object | false | | |
|
||||
| `»»» [any property]` | string | false | | |
|
||||
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
|
||||
| `»» worker_id` | string(uuid) | 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. |
|
||||
@@ -1438,6 +1485,9 @@ Status Code **200**
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
| `type` | `template_version_import` |
|
||||
| `type` | `workspace_build` |
|
||||
| `type` | `template_version_dry_run` |
|
||||
| `reason` | `initiator` |
|
||||
| `reason` | `autostart` |
|
||||
| `reason` | `autostop` |
|
||||
@@ -1540,6 +1590,9 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1547,6 +1600,12 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1555,6 +1614,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
|
||||
Generated
+5
@@ -202,6 +202,7 @@ Status Code **200**
|
||||
| `resource_type` | `organization` |
|
||||
| `resource_type` | `organization_member` |
|
||||
| `resource_type` | `provisioner_daemon` |
|
||||
| `resource_type` | `provisioner_jobs` |
|
||||
| `resource_type` | `provisioner_keys` |
|
||||
| `resource_type` | `replicas` |
|
||||
| `resource_type` | `system` |
|
||||
@@ -363,6 +364,7 @@ Status Code **200**
|
||||
| `resource_type` | `organization` |
|
||||
| `resource_type` | `organization_member` |
|
||||
| `resource_type` | `provisioner_daemon` |
|
||||
| `resource_type` | `provisioner_jobs` |
|
||||
| `resource_type` | `provisioner_keys` |
|
||||
| `resource_type` | `replicas` |
|
||||
| `resource_type` | `system` |
|
||||
@@ -524,6 +526,7 @@ Status Code **200**
|
||||
| `resource_type` | `organization` |
|
||||
| `resource_type` | `organization_member` |
|
||||
| `resource_type` | `provisioner_daemon` |
|
||||
| `resource_type` | `provisioner_jobs` |
|
||||
| `resource_type` | `provisioner_keys` |
|
||||
| `resource_type` | `replicas` |
|
||||
| `resource_type` | `system` |
|
||||
@@ -654,6 +657,7 @@ Status Code **200**
|
||||
| `resource_type` | `organization` |
|
||||
| `resource_type` | `organization_member` |
|
||||
| `resource_type` | `provisioner_daemon` |
|
||||
| `resource_type` | `provisioner_jobs` |
|
||||
| `resource_type` | `provisioner_keys` |
|
||||
| `resource_type` | `replicas` |
|
||||
| `resource_type` | `system` |
|
||||
@@ -916,6 +920,7 @@ Status Code **200**
|
||||
| `resource_type` | `organization` |
|
||||
| `resource_type` | `organization_member` |
|
||||
| `resource_type` | `provisioner_daemon` |
|
||||
| `resource_type` | `provisioner_jobs` |
|
||||
| `resource_type` | `provisioner_keys` |
|
||||
| `resource_type` | `replicas` |
|
||||
| `resource_type` | `system` |
|
||||
|
||||
Generated
+128
@@ -343,3 +343,131 @@ curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization} \
|
||||
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.Organization](schemas.md#codersdkorganization) |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
## Get provisioner jobs
|
||||
|
||||
### Code samples
|
||||
|
||||
```shell
|
||||
# Example request using curl
|
||||
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerjobs \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Coder-Session-Token: API_KEY'
|
||||
```
|
||||
|
||||
`GET /organizations/{organization}/provisionerjobs`
|
||||
|
||||
### Parameters
|
||||
|
||||
| Name | In | Type | Required | Description |
|
||||
|----------------|-------|--------------|----------|--------------------------|
|
||||
| `organization` | path | string(uuid) | true | Organization ID |
|
||||
| `limit` | query | integer | false | Page limit |
|
||||
| `status` | query | string | false | Filter results by status |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------------|
|
||||
| `status` | `pending` |
|
||||
| `status` | `running` |
|
||||
| `status` | `succeeded` |
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
| `status` | `unknown` |
|
||||
| `status` | `pending` |
|
||||
| `status` | `running` |
|
||||
| `status` | `succeeded` |
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
|
||||
### Example responses
|
||||
|
||||
> 200 Response
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
"error": "string",
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
"status": "pending",
|
||||
"tags": {
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
||||
| Status | Meaning | Description | Schema |
|
||||
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------|
|
||||
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) |
|
||||
|
||||
<h3 id="get-provisioner-jobs-responseschema">Response Schema</h3>
|
||||
|
||||
Status Code **200**
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------------|--------------------------------------------------------------------------|----------|--------------|-------------|
|
||||
| `[array item]` | array | false | | |
|
||||
| `» available_workers` | array | false | | |
|
||||
| `» canceled_at` | string(date-time) | false | | |
|
||||
| `» completed_at` | string(date-time) | false | | |
|
||||
| `» created_at` | string(date-time) | false | | |
|
||||
| `» error` | string | false | | |
|
||||
| `» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `» file_id` | string(uuid) | false | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» input` | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput) | false | | |
|
||||
| `»» error` | string | false | | |
|
||||
| `»» template_version_id` | string(uuid) | false | | |
|
||||
| `»» workspace_build_id` | string(uuid) | false | | |
|
||||
| `» organization_id` | string(uuid) | false | | |
|
||||
| `» queue_position` | integer | false | | |
|
||||
| `» queue_size` | integer | false | | |
|
||||
| `» started_at` | string(date-time) | false | | |
|
||||
| `» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `» tags` | object | false | | |
|
||||
| `»» [any property]` | string | false | | |
|
||||
| `» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
|
||||
| `» worker_id` | string(uuid) | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
| Property | Value |
|
||||
|--------------|-------------------------------|
|
||||
| `error_code` | `REQUIRED_TEMPLATE_VARIABLES` |
|
||||
| `status` | `pending` |
|
||||
| `status` | `running` |
|
||||
| `status` | `succeeded` |
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
| `type` | `template_version_import` |
|
||||
| `type` | `workspace_build` |
|
||||
| `type` | `template_version_dry_run` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
Generated
+105
-16
@@ -4446,6 +4446,9 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
|
||||
```json
|
||||
{
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -4453,6 +4456,12 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -4461,28 +4470,33 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------|----------------------------------------------------------------|----------|--------------|-------------|
|
||||
| `canceled_at` | string | false | | |
|
||||
| `completed_at` | string | false | | |
|
||||
| `created_at` | string | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `error_code` | [codersdk.JobErrorCode](#codersdkjoberrorcode) | false | | |
|
||||
| `file_id` | string | false | | |
|
||||
| `id` | string | false | | |
|
||||
| `queue_position` | integer | false | | |
|
||||
| `queue_size` | integer | false | | |
|
||||
| `started_at` | string | false | | |
|
||||
| `status` | [codersdk.ProvisionerJobStatus](#codersdkprovisionerjobstatus) | false | | |
|
||||
| `tags` | object | false | | |
|
||||
| » `[any property]` | string | false | | |
|
||||
| `worker_id` | string | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|---------------------|----------------------------------------------------------------|----------|--------------|-------------|
|
||||
| `available_workers` | array of string | false | | |
|
||||
| `canceled_at` | string | false | | |
|
||||
| `completed_at` | string | false | | |
|
||||
| `created_at` | string | false | | |
|
||||
| `error` | string | false | | |
|
||||
| `error_code` | [codersdk.JobErrorCode](#codersdkjoberrorcode) | false | | |
|
||||
| `file_id` | string | false | | |
|
||||
| `id` | string | false | | |
|
||||
| `input` | [codersdk.ProvisionerJobInput](#codersdkprovisionerjobinput) | false | | |
|
||||
| `organization_id` | string | false | | |
|
||||
| `queue_position` | integer | false | | |
|
||||
| `queue_size` | integer | false | | |
|
||||
| `started_at` | string | false | | |
|
||||
| `status` | [codersdk.ProvisionerJobStatus](#codersdkprovisionerjobstatus) | false | | |
|
||||
| `tags` | object | false | | |
|
||||
| » `[any property]` | string | false | | |
|
||||
| `type` | [codersdk.ProvisionerJobType](#codersdkprovisionerjobtype) | false | | |
|
||||
| `worker_id` | string | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
@@ -4496,6 +4510,24 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
|
||||
## codersdk.ProvisionerJobInput
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
}
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|-----------------------|--------|----------|--------------|-------------|
|
||||
| `error` | string | false | | |
|
||||
| `template_version_id` | string | false | | |
|
||||
| `workspace_build_id` | string | false | | |
|
||||
|
||||
## codersdk.ProvisionerJobLog
|
||||
|
||||
```json
|
||||
@@ -4550,6 +4582,22 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
| `failed` |
|
||||
| `unknown` |
|
||||
|
||||
## codersdk.ProvisionerJobType
|
||||
|
||||
```json
|
||||
"template_version_import"
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
| Value |
|
||||
|----------------------------|
|
||||
| `template_version_import` |
|
||||
| `workspace_build` |
|
||||
| `template_version_dry_run` |
|
||||
|
||||
## codersdk.ProvisionerKey
|
||||
|
||||
```json
|
||||
@@ -4827,6 +4875,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith
|
||||
| `organization` |
|
||||
| `organization_member` |
|
||||
| `provisioner_daemon` |
|
||||
| `provisioner_jobs` |
|
||||
| `provisioner_keys` |
|
||||
| `replicas` |
|
||||
| `system` |
|
||||
@@ -5895,6 +5944,9 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -5902,6 +5954,12 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -5910,6 +5968,7 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -6950,6 +7009,9 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -6957,6 +7019,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -6965,6 +7033,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -7682,6 +7751,9 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -7689,6 +7761,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -7697,6 +7775,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -8336,6 +8415,9 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -8343,6 +8425,12 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -8351,6 +8439,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
|
||||
Generated
+182
-72
@@ -447,6 +447,9 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -454,6 +457,12 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -462,6 +471,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -525,6 +535,9 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -532,6 +545,12 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -540,6 +559,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -627,6 +647,9 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -634,6 +657,12 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -642,6 +671,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1157,6 +1187,9 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1164,6 +1197,12 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1172,6 +1211,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1202,42 +1242,49 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
|
||||
|
||||
Status Code **200**
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------------|--------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `[array item]` | array | false | | |
|
||||
| `» archived` | boolean | false | | |
|
||||
| `» created_at` | string(date-time) | false | | |
|
||||
| `» created_by` | [codersdk.MinimalUser](schemas.md#codersdkminimaluser) | false | | |
|
||||
| `»» avatar_url` | string(uri) | false | | |
|
||||
| `»» id` | string(uuid) | true | | |
|
||||
| `»» username` | string | true | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
|
||||
| `»» canceled_at` | string(date-time) | false | | |
|
||||
| `»» completed_at` | string(date-time) | false | | |
|
||||
| `»» created_at` | string(date-time) | false | | |
|
||||
| `»» error` | string | false | | |
|
||||
| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `»» file_id` | string(uuid) | false | | |
|
||||
| `»» id` | string(uuid) | false | | |
|
||||
| `»» queue_position` | integer | false | | |
|
||||
| `»» queue_size` | integer | false | | |
|
||||
| `»» started_at` | string(date-time) | false | | |
|
||||
| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `»» tags` | object | false | | |
|
||||
| `»»» [any property]` | string | false | | |
|
||||
| `»» worker_id` | string(uuid) | 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. |
|
||||
| `»» most_recently_seen` | string(date-time) | false | | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null. |
|
||||
| `» message` | string | false | | |
|
||||
| `» name` | string | false | | |
|
||||
| `» organization_id` | string(uuid) | false | | |
|
||||
| `» readme` | string | false | | |
|
||||
| `» template_id` | string(uuid) | false | | |
|
||||
| `» updated_at` | string(date-time) | false | | |
|
||||
| `» warnings` | array | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|---------------------------|--------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `[array item]` | array | false | | |
|
||||
| `» archived` | boolean | false | | |
|
||||
| `» created_at` | string(date-time) | false | | |
|
||||
| `» created_by` | [codersdk.MinimalUser](schemas.md#codersdkminimaluser) | false | | |
|
||||
| `»» avatar_url` | string(uri) | false | | |
|
||||
| `»» id` | string(uuid) | true | | |
|
||||
| `»» username` | string | true | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
|
||||
| `»» available_workers` | array | false | | |
|
||||
| `»» canceled_at` | string(date-time) | false | | |
|
||||
| `»» completed_at` | string(date-time) | false | | |
|
||||
| `»» created_at` | string(date-time) | false | | |
|
||||
| `»» error` | string | false | | |
|
||||
| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `»» file_id` | string(uuid) | false | | |
|
||||
| `»» id` | string(uuid) | false | | |
|
||||
| `»» input` | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput) | false | | |
|
||||
| `»»» error` | string | false | | |
|
||||
| `»»» template_version_id` | string(uuid) | false | | |
|
||||
| `»»» workspace_build_id` | string(uuid) | false | | |
|
||||
| `»» organization_id` | string(uuid) | false | | |
|
||||
| `»» queue_position` | integer | false | | |
|
||||
| `»» queue_size` | integer | false | | |
|
||||
| `»» started_at` | string(date-time) | false | | |
|
||||
| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `»» tags` | object | false | | |
|
||||
| `»»» [any property]` | string | false | | |
|
||||
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
|
||||
| `»» worker_id` | string(uuid) | 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. |
|
||||
| `»» most_recently_seen` | string(date-time) | false | | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null. |
|
||||
| `» message` | string | false | | |
|
||||
| `» name` | string | false | | |
|
||||
| `» organization_id` | string(uuid) | false | | |
|
||||
| `» readme` | string | false | | |
|
||||
| `» template_id` | string(uuid) | false | | |
|
||||
| `» updated_at` | string(date-time) | false | | |
|
||||
| `» warnings` | array | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
@@ -1250,6 +1297,9 @@ Status Code **200**
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
| `type` | `template_version_import` |
|
||||
| `type` | `workspace_build` |
|
||||
| `type` | `template_version_dry_run` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
@@ -1397,6 +1447,9 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1404,6 +1457,12 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1412,6 +1471,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1442,42 +1502,49 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ
|
||||
|
||||
Status Code **200**
|
||||
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|--------------------------|--------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `[array item]` | array | false | | |
|
||||
| `» archived` | boolean | false | | |
|
||||
| `» created_at` | string(date-time) | false | | |
|
||||
| `» created_by` | [codersdk.MinimalUser](schemas.md#codersdkminimaluser) | false | | |
|
||||
| `»» avatar_url` | string(uri) | false | | |
|
||||
| `»» id` | string(uuid) | true | | |
|
||||
| `»» username` | string | true | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
|
||||
| `»» canceled_at` | string(date-time) | false | | |
|
||||
| `»» completed_at` | string(date-time) | false | | |
|
||||
| `»» created_at` | string(date-time) | false | | |
|
||||
| `»» error` | string | false | | |
|
||||
| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `»» file_id` | string(uuid) | false | | |
|
||||
| `»» id` | string(uuid) | false | | |
|
||||
| `»» queue_position` | integer | false | | |
|
||||
| `»» queue_size` | integer | false | | |
|
||||
| `»» started_at` | string(date-time) | false | | |
|
||||
| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `»» tags` | object | false | | |
|
||||
| `»»» [any property]` | string | false | | |
|
||||
| `»» worker_id` | string(uuid) | 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. |
|
||||
| `»» most_recently_seen` | string(date-time) | false | | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null. |
|
||||
| `» message` | string | false | | |
|
||||
| `» name` | string | false | | |
|
||||
| `» organization_id` | string(uuid) | false | | |
|
||||
| `» readme` | string | false | | |
|
||||
| `» template_id` | string(uuid) | false | | |
|
||||
| `» updated_at` | string(date-time) | false | | |
|
||||
| `» warnings` | array | false | | |
|
||||
| Name | Type | Required | Restrictions | Description |
|
||||
|---------------------------|--------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `[array item]` | array | false | | |
|
||||
| `» archived` | boolean | false | | |
|
||||
| `» created_at` | string(date-time) | false | | |
|
||||
| `» created_by` | [codersdk.MinimalUser](schemas.md#codersdkminimaluser) | false | | |
|
||||
| `»» avatar_url` | string(uri) | false | | |
|
||||
| `»» id` | string(uuid) | true | | |
|
||||
| `»» username` | string | true | | |
|
||||
| `» id` | string(uuid) | false | | |
|
||||
| `» job` | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) | false | | |
|
||||
| `»» available_workers` | array | false | | |
|
||||
| `»» canceled_at` | string(date-time) | false | | |
|
||||
| `»» completed_at` | string(date-time) | false | | |
|
||||
| `»» created_at` | string(date-time) | false | | |
|
||||
| `»» error` | string | false | | |
|
||||
| `»» error_code` | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode) | false | | |
|
||||
| `»» file_id` | string(uuid) | false | | |
|
||||
| `»» id` | string(uuid) | false | | |
|
||||
| `»» input` | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput) | false | | |
|
||||
| `»»» error` | string | false | | |
|
||||
| `»»» template_version_id` | string(uuid) | false | | |
|
||||
| `»»» workspace_build_id` | string(uuid) | false | | |
|
||||
| `»» organization_id` | string(uuid) | false | | |
|
||||
| `»» queue_position` | integer | false | | |
|
||||
| `»» queue_size` | integer | false | | |
|
||||
| `»» started_at` | string(date-time) | false | | |
|
||||
| `»» status` | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus) | false | | |
|
||||
| `»» tags` | object | false | | |
|
||||
| `»»» [any property]` | string | false | | |
|
||||
| `»» type` | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype) | false | | |
|
||||
| `»» worker_id` | string(uuid) | 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. |
|
||||
| `»» most_recently_seen` | string(date-time) | false | | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null. |
|
||||
| `» message` | string | false | | |
|
||||
| `» name` | string | false | | |
|
||||
| `» organization_id` | string(uuid) | false | | |
|
||||
| `» readme` | string | false | | |
|
||||
| `» template_id` | string(uuid) | false | | |
|
||||
| `» updated_at` | string(date-time) | false | | |
|
||||
| `» warnings` | array | false | | |
|
||||
|
||||
#### Enumerated Values
|
||||
|
||||
@@ -1490,6 +1557,9 @@ Status Code **200**
|
||||
| `status` | `canceling` |
|
||||
| `status` | `canceled` |
|
||||
| `status` | `failed` |
|
||||
| `type` | `template_version_import` |
|
||||
| `type` | `workspace_build` |
|
||||
| `type` | `template_version_dry_run` |
|
||||
|
||||
To perform this operation, you must be authenticated. [Learn more](authentication.md).
|
||||
|
||||
@@ -1527,6 +1597,9 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1534,6 +1607,12 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1542,6 +1621,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1614,6 +1694,9 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
|
||||
},
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1621,6 +1704,12 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1629,6 +1718,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1791,6 +1881,9 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/
|
||||
|
||||
```json
|
||||
{
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1798,6 +1891,12 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1806,6 +1905,7 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
}
|
||||
```
|
||||
@@ -1844,6 +1944,9 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d
|
||||
|
||||
```json
|
||||
{
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1851,6 +1954,12 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1859,6 +1968,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
}
|
||||
```
|
||||
|
||||
Generated
+60
@@ -76,6 +76,9 @@ of the template will be used.
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -83,6 +86,12 @@ of the template will be used.
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -91,6 +100,7 @@ of the template will be used.
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -307,6 +317,9 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -314,6 +327,12 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -322,6 +341,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -562,6 +582,9 @@ of the template will be used.
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -569,6 +592,12 @@ of the template will be used.
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -577,6 +606,7 @@ of the template will be used.
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -796,6 +826,9 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -803,6 +836,12 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -811,6 +850,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1024,6 +1064,9 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1031,6 +1074,12 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1039,6 +1088,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
@@ -1371,6 +1421,9 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
|
||||
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
|
||||
"initiator_name": "string",
|
||||
"job": {
|
||||
"available_workers": [
|
||||
"497f6eca-6276-4993-bfeb-53cbbbba6f08"
|
||||
],
|
||||
"canceled_at": "2019-08-24T14:15:22Z",
|
||||
"completed_at": "2019-08-24T14:15:22Z",
|
||||
"created_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1378,6 +1431,12 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
|
||||
"error_code": "REQUIRED_TEMPLATE_VARIABLES",
|
||||
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
|
||||
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
|
||||
"input": {
|
||||
"error": "string",
|
||||
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
|
||||
"workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
|
||||
},
|
||||
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
|
||||
"queue_position": 0,
|
||||
"queue_size": 0,
|
||||
"started_at": "2019-08-24T14:15:22Z",
|
||||
@@ -1386,6 +1445,7 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
|
||||
"property1": "string",
|
||||
"property2": "string"
|
||||
},
|
||||
"type": "template_version_import",
|
||||
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
|
||||
},
|
||||
"matched_provisioners": {
|
||||
|
||||
@@ -119,6 +119,9 @@ export const RBACResourceActions: Partial<
|
||||
read: "read provisioner daemon",
|
||||
update: "update a provisioner daemon",
|
||||
},
|
||||
provisioner_jobs: {
|
||||
read: "read provisioner jobs",
|
||||
},
|
||||
provisioner_keys: {
|
||||
create: "create a provisioner key",
|
||||
delete: "delete a provisioner key",
|
||||
|
||||
Generated
+31
@@ -1428,6 +1428,12 @@ export interface OrganizationMemberWithUserData extends OrganizationMember {
|
||||
readonly global_roles: readonly SlimRole[];
|
||||
}
|
||||
|
||||
// From codersdk/organizations.go
|
||||
export interface OrganizationProvisionerJobsOptions {
|
||||
readonly Limit: number;
|
||||
readonly Status: readonly ProvisionerJobStatus[];
|
||||
}
|
||||
|
||||
// From codersdk/idpsync.go
|
||||
export interface OrganizationSyncSettings {
|
||||
readonly field: string;
|
||||
@@ -1585,6 +1591,17 @@ export interface ProvisionerJob {
|
||||
readonly tags: Record<string, string>;
|
||||
readonly queue_position: number;
|
||||
readonly queue_size: number;
|
||||
readonly organization_id: string;
|
||||
readonly input: ProvisionerJobInput;
|
||||
readonly type: ProvisionerJobType;
|
||||
readonly available_workers?: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/provisionerdaemons.go
|
||||
export interface ProvisionerJobInput {
|
||||
readonly template_version_id?: string;
|
||||
readonly workspace_build_id?: string;
|
||||
readonly error?: string;
|
||||
}
|
||||
|
||||
// From codersdk/provisionerdaemons.go
|
||||
@@ -1617,6 +1634,18 @@ export const ProvisionerJobStatuses: ProvisionerJobStatus[] = [
|
||||
"unknown",
|
||||
];
|
||||
|
||||
// From codersdk/provisionerdaemons.go
|
||||
export type ProvisionerJobType =
|
||||
| "template_version_dry_run"
|
||||
| "template_version_import"
|
||||
| "workspace_build";
|
||||
|
||||
export const ProvisionerJobTypes: ProvisionerJobType[] = [
|
||||
"template_version_dry_run",
|
||||
"template_version_import",
|
||||
"workspace_build",
|
||||
];
|
||||
|
||||
// From codersdk/provisionerdaemons.go
|
||||
export interface ProvisionerKey {
|
||||
readonly id: string;
|
||||
@@ -1767,6 +1796,7 @@ export type RBACResource =
|
||||
| "organization"
|
||||
| "organization_member"
|
||||
| "provisioner_daemon"
|
||||
| "provisioner_jobs"
|
||||
| "provisioner_keys"
|
||||
| "replicas"
|
||||
| "system"
|
||||
@@ -1801,6 +1831,7 @@ export const RBACResources: RBACResource[] = [
|
||||
"organization",
|
||||
"organization_member",
|
||||
"provisioner_daemon",
|
||||
"provisioner_jobs",
|
||||
"provisioner_keys",
|
||||
"replicas",
|
||||
"system",
|
||||
|
||||
@@ -655,6 +655,11 @@ export const MockProvisionerJob: TypesGen.ProvisionerJob = {
|
||||
},
|
||||
queue_position: 0,
|
||||
queue_size: 0,
|
||||
input: {
|
||||
template_version_id: "test-template-version", // MockTemplateVersion.id
|
||||
},
|
||||
organization_id: MockOrganization.id,
|
||||
type: "template_version_dry_run",
|
||||
};
|
||||
|
||||
export const MockFailedProvisionerJob: TypesGen.ProvisionerJob = {
|
||||
|
||||
Reference in New Issue
Block a user