-
Notifications
You must be signed in to change notification settings - Fork 894
feat: cancel stuck pending jobs #17803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
0f51f35
2f3d606
4b252eb
ca49519
af994c2
3815727
b65f620
3c7c323
35df01f
8aa1ee2
4385933
96fee51
d8db119
5120fb1
8d4fa5a
18b809c
0fe1404
77be34e
4351529
c03bfa3
a15bd1c
5b9348f
91d2d32
767cb77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,10 +170,10 @@ var ( | |
Identifier: rbac.RoleIdentifier{Name: "provisionerd"}, | ||
DisplayName: "Provisioner Daemon", | ||
Site: rbac.Permissions(map[string][]policy.Action{ | ||
// TODO: Add ProvisionerJob resource type. | ||
rbac.ResourceFile.Type: {policy.ActionRead}, | ||
rbac.ResourceSystem.Type: {policy.WildcardSymbol}, | ||
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate}, | ||
rbac.ResourceProvisionerJobs.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionCreate}, | ||
rbac.ResourceFile.Type: {policy.ActionRead}, | ||
rbac.ResourceSystem.Type: {policy.WildcardSymbol}, | ||
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate}, | ||
// Unsure why provisionerd needs update and read personal | ||
rbac.ResourceUser.Type: {policy.ActionRead, policy.ActionReadPersonal, policy.ActionUpdatePersonal}, | ||
rbac.ResourceWorkspaceDormant.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStop}, | ||
|
@@ -219,19 +219,20 @@ var ( | |
Scope: rbac.ScopeAll, | ||
}.WithCachedASTValue() | ||
|
||
// See unhanger package. | ||
subjectHangDetector = rbac.Subject{ | ||
Type: rbac.SubjectTypeHangDetector, | ||
FriendlyName: "Hang Detector", | ||
// See reaper package. | ||
subjectJobReaper = rbac.Subject{ | ||
Type: rbac.SubjectTypeJobReaper, | ||
FriendlyName: "Job Reaper", | ||
ID: uuid.Nil.String(), | ||
Roles: rbac.Roles([]rbac.Role{ | ||
{ | ||
Identifier: rbac.RoleIdentifier{Name: "hangdetector"}, | ||
DisplayName: "Hang Detector Daemon", | ||
Identifier: rbac.RoleIdentifier{Name: "jobreaper"}, | ||
DisplayName: "Job Reaper Daemon", | ||
Site: rbac.Permissions(map[string][]policy.Action{ | ||
rbac.ResourceSystem.Type: {policy.WildcardSymbol}, | ||
rbac.ResourceTemplate.Type: {policy.ActionRead}, | ||
rbac.ResourceWorkspace.Type: {policy.ActionRead, policy.ActionUpdate}, | ||
rbac.ResourceSystem.Type: {policy.WildcardSymbol}, | ||
rbac.ResourceTemplate.Type: {policy.ActionRead}, | ||
rbac.ResourceWorkspace.Type: {policy.ActionRead, policy.ActionUpdate}, | ||
rbac.ResourceProvisionerJobs.Type: {policy.ActionRead, policy.ActionUpdate}, | ||
}), | ||
Org: map[string][]rbac.Permission{}, | ||
User: []rbac.Permission{}, | ||
|
@@ -346,6 +347,7 @@ var ( | |
rbac.ResourceNotificationTemplate.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, | ||
rbac.ResourceCryptoKey.Type: {policy.ActionCreate, policy.ActionUpdate, policy.ActionDelete}, | ||
rbac.ResourceFile.Type: {policy.ActionCreate, policy.ActionRead}, | ||
rbac.ResourceProvisionerJobs.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionCreate}, | ||
}), | ||
Org: map[string][]rbac.Permission{}, | ||
User: []rbac.Permission{}, | ||
|
@@ -407,10 +409,10 @@ func AsAutostart(ctx context.Context) context.Context { | |
return As(ctx, subjectAutostart) | ||
} | ||
|
||
// AsHangDetector returns a context with an actor that has permissions required | ||
// for unhanger.Detector to function. | ||
func AsHangDetector(ctx context.Context) context.Context { | ||
return As(ctx, subjectHangDetector) | ||
// AsJobReaper returns a context with an actor that has permissions required | ||
// for reaper.Detector to function. | ||
func AsJobReaper(ctx context.Context) context.Context { | ||
return As(ctx, subjectJobReaper) | ||
} | ||
|
||
// AsKeyRotator returns a context with an actor that has permissions required for rotating crypto keys. | ||
|
@@ -1085,11 +1087,10 @@ func (q *querier) AcquireNotificationMessages(ctx context.Context, arg database. | |
return q.db.AcquireNotificationMessages(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) AcquireProvisionerJob(ctx context.Context, arg database.AcquireProvisionerJobParams) (database.ProvisionerJob, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { | ||
// return database.ProvisionerJob{}, err | ||
// } | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
return database.ProvisionerJob{}, err | ||
} | ||
return q.db.AcquireProvisionerJob(ctx, arg) | ||
} | ||
|
||
|
@@ -1912,14 +1913,6 @@ func (q *querier) GetHealthSettings(ctx context.Context) (string, error) { | |
return q.db.GetHealthSettings(ctx) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) GetHungProvisionerJobs(ctx context.Context, hungSince time.Time) ([]database.ProvisionerJob, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { | ||
// return nil, err | ||
// } | ||
return q.db.GetHungProvisionerJobs(ctx, hungSince) | ||
} | ||
|
||
func (q *querier) GetInboxNotificationByID(ctx context.Context, id uuid.UUID) (database.InboxNotification, error) { | ||
return fetchWithAction(q.log, q.auth, policy.ActionRead, q.db.GetInboxNotificationByID)(ctx, id) | ||
} | ||
|
@@ -2307,6 +2300,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data | |
return job, nil | ||
} | ||
|
||
func (q *querier) GetProvisionerJobByIDForUpdate(ctx context.Context, id uuid.UUID) (database.ProvisionerJob, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs); err != nil { | ||
return database.ProvisionerJob{}, err | ||
} | ||
return q.db.GetProvisionerJobByIDForUpdate(ctx, id) | ||
} | ||
|
||
func (q *querier) GetProvisionerJobTimingsByJobID(ctx context.Context, jobID uuid.UUID) ([]database.ProvisionerJobTiming, error) { | ||
_, err := q.GetProvisionerJobByID(ctx, jobID) | ||
if err != nil { | ||
|
@@ -2315,31 +2315,47 @@ func (q *querier) GetProvisionerJobTimingsByJobID(ctx context.Context, jobID uui | |
return q.db.GetProvisionerJobTimingsByJobID(ctx, jobID) | ||
} | ||
|
||
// 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 | ||
// } | ||
return q.db.GetProvisionerJobsByIDs(ctx, ids) | ||
provisionerJobs, err := q.db.GetProvisionerJobsByIDs(ctx, ids) | ||
if err != nil { | ||
return nil, err | ||
} | ||
for _, job := range provisionerJobs { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs.InOrg(job.OrganizationID)); err != nil { | ||
return nil, err | ||
} | ||
} | ||
ibetitsmike marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return provisionerJobs, nil | ||
} | ||
|
||
// 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) { | ||
// if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs); err != nil { | ||
// return nil, err | ||
// } | ||
ibetitsmike marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return q.db.GetProvisionerJobsByIDsWithQueuePosition(ctx, ids) | ||
} | ||
|
||
func (q *querier) GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisioner(ctx context.Context, arg database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerParams) ([]database.GetProvisionerJobsByOrganizationAndStatusWithQueuePositionAndProvisionerRow, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs); err != nil { | ||
// return nil, err | ||
// } | ||
ibetitsmike marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 | ||
// } | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs); err != nil { | ||
return nil, err | ||
} | ||
return q.db.GetProvisionerJobsCreatedAfter(ctx, createdAt) | ||
} | ||
|
||
func (q *querier) GetProvisionerJobsToBeReaped(ctx context.Context, arg database.GetProvisionerJobsToBeReapedParams) ([]database.ProvisionerJob, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceProvisionerJobs); err != nil { | ||
return nil, err | ||
} | ||
return q.db.GetProvisionerJobsToBeReaped(ctx, arg) | ||
} | ||
|
||
func (q *querier) GetProvisionerKeyByHashedSecret(ctx context.Context, hashedSecret []byte) (database.ProvisionerKey, error) { | ||
return fetch(q.log, q.auth, q.db.GetProvisionerKeyByHashedSecret)(ctx, hashedSecret) | ||
} | ||
|
@@ -3524,27 +3540,28 @@ func (q *querier) InsertPresetParameters(ctx context.Context, arg database.Inser | |
return q.db.InsertPresetParameters(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { | ||
// return database.ProvisionerJob{}, err | ||
// TODO: Remove this once we have a proper rbac check for provisioner jobs. | ||
// Currently ProvisionerJobs are not associated with a user, so we can't | ||
// check for a user's permissions. We'd need to check for the associated workspace | ||
// and verify ownership through that. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment should probably mention all the ways a job could be made and what the permission check should look like. I think the following is correct:
I just don't want the comment to only say that workspace ownership needs to be checked, and for some poor soul to start working on this thinking it'll be simple when in reality it will probably be difficult. Likely should have a ticket created to track this too. You might want to add a comment here in the code with the ticket number after you create it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Left a simple description with link to the issue to not duplicate information. |
||
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceProvisionerJobs); err != nil { | ||
// return database.ProvisionerJob{}, err | ||
// } | ||
return q.db.InsertProvisionerJob(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) InsertProvisionerJobLogs(ctx context.Context, arg database.InsertProvisionerJobLogsParams) ([]database.ProvisionerJobLog, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { | ||
// return nil, err | ||
// if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
// return nil, err | ||
ibetitsmike marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// } | ||
return q.db.InsertProvisionerJobLogs(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) InsertProvisionerJobTimings(ctx context.Context, arg database.InsertProvisionerJobTimingsParams) ([]database.ProvisionerJobTiming, error) { | ||
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { | ||
// return nil, err | ||
// } | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
return nil, err | ||
} | ||
return q.db.InsertProvisionerJobTimings(ctx, arg) | ||
} | ||
|
||
|
@@ -4167,15 +4184,18 @@ func (q *querier) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg dat | |
return q.db.UpdateProvisionerDaemonLastSeenAt(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) UpdateProvisionerJobByID(ctx context.Context, arg database.UpdateProvisionerJobByIDParams) error { | ||
// if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { | ||
// return err | ||
// } | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
return err | ||
} | ||
return q.db.UpdateProvisionerJobByID(ctx, arg) | ||
} | ||
|
||
func (q *querier) UpdateProvisionerJobWithCancelByID(ctx context.Context, arg database.UpdateProvisionerJobWithCancelByIDParams) error { | ||
// if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
// return err | ||
// } | ||
ibetitsmike marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
job, err := q.db.GetProvisionerJobByID(ctx, arg.ID) | ||
if err != nil { | ||
return err | ||
|
@@ -4242,14 +4262,20 @@ func (q *querier) UpdateProvisionerJobWithCancelByID(ctx context.Context, arg da | |
return q.db.UpdateProvisionerJobWithCancelByID(ctx, arg) | ||
} | ||
|
||
// TODO: We need to create a ProvisionerJob resource type | ||
func (q *querier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, arg database.UpdateProvisionerJobWithCompleteByIDParams) error { | ||
// if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { | ||
// return err | ||
// } | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
return err | ||
} | ||
return q.db.UpdateProvisionerJobWithCompleteByID(ctx, arg) | ||
} | ||
|
||
func (q *querier) UpdateProvisionerJobWithCompleteWithStartedAtByID(ctx context.Context, arg database.UpdateProvisionerJobWithCompleteWithStartedAtByIDParams) error { | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerJobs); err != nil { | ||
return err | ||
} | ||
return q.db.UpdateProvisionerJobWithCompleteWithStartedAtByID(ctx, arg) | ||
} | ||
|
||
func (q *querier) UpdateReplica(ctx context.Context, arg database.UpdateReplicaParams) (database.Replica, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil { | ||
return database.Replica{}, err | ||
|
Uh oh!
There was an error while loading. Please reload this page.