mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(coderd/database): add task status and status view (#20235)
This change updates the `task_workspace_apps` table structure for improved linking to workspace builds and adds queries to manage tasks and a view to expose task status. Updates coder/internal#948 Supersedes coder/coder#20212 Supersedes coder/coder#19773
This commit is contained in:
@@ -2885,6 +2885,14 @@ func (q *querier) GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID)
|
||||
return q.db.GetTailnetTunnelPeerIDs(ctx, srcID)
|
||||
}
|
||||
|
||||
func (q *querier) GetTaskByID(ctx context.Context, id uuid.UUID) (database.Task, error) {
|
||||
return fetch(q.log, q.auth, q.db.GetTaskByID)(ctx, id)
|
||||
}
|
||||
|
||||
func (q *querier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.Task, error) {
|
||||
return fetch(q.log, q.auth, q.db.GetTaskByWorkspaceID)(ctx, workspaceID)
|
||||
}
|
||||
|
||||
func (q *querier) GetTelemetryItem(ctx context.Context, key string) (database.TelemetryItem, error) {
|
||||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
|
||||
return database.TelemetryItem{}, err
|
||||
@@ -4110,6 +4118,17 @@ func (q *querier) InsertReplica(ctx context.Context, arg database.InsertReplicaP
|
||||
return q.db.InsertReplica(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) InsertTask(ctx context.Context, arg database.InsertTaskParams) (database.TaskTable, error) {
|
||||
// Ensure the actor can access the specified template version (and thus its template).
|
||||
if _, err := q.GetTemplateVersionByID(ctx, arg.TemplateVersionID); err != nil {
|
||||
return database.TaskTable{}, err
|
||||
}
|
||||
|
||||
obj := rbac.ResourceTask.WithOwner(arg.OwnerID.String()).InOrg(arg.OrganizationID)
|
||||
|
||||
return insert(q.log, q.auth, obj, q.db.InsertTask)(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) InsertTelemetryItemIfNotExists(ctx context.Context, arg database.InsertTelemetryItemIfNotExistsParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
@@ -5668,6 +5687,18 @@ func (q *querier) UpsertTailnetTunnel(ctx context.Context, arg database.UpsertTa
|
||||
return q.db.UpsertTailnetTunnel(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertTaskWorkspaceApp(ctx context.Context, arg database.UpsertTaskWorkspaceAppParams) (database.TaskWorkspaceApp, error) {
|
||||
// Fetch the task to derive the RBAC object and authorize update on it.
|
||||
task, err := q.db.GetTaskByID(ctx, arg.TaskID)
|
||||
if err != nil {
|
||||
return database.TaskWorkspaceApp{}, err
|
||||
}
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, task); err != nil {
|
||||
return database.TaskWorkspaceApp{}, err
|
||||
}
|
||||
return q.db.UpsertTaskWorkspaceApp(ctx, arg)
|
||||
}
|
||||
|
||||
func (q *querier) UpsertTelemetryItem(ctx context.Context, arg database.UpsertTelemetryItemParams) error {
|
||||
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
|
||||
return err
|
||||
|
||||
@@ -2347,6 +2347,53 @@ func (s *MethodTestSuite) TestWorkspacePortSharing() {
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestTasks() {
|
||||
s.Run("GetTaskByID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
task := testutil.Fake(s.T(), faker, database.Task{})
|
||||
dbm.EXPECT().GetTaskByID(gomock.Any(), task.ID).Return(task, nil).AnyTimes()
|
||||
check.Args(task.ID).Asserts(task, policy.ActionRead).Returns(task)
|
||||
}))
|
||||
s.Run("InsertTask", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
tpl := testutil.Fake(s.T(), faker, database.Template{})
|
||||
tv := testutil.Fake(s.T(), faker, database.TemplateVersion{
|
||||
TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true},
|
||||
OrganizationID: tpl.OrganizationID,
|
||||
})
|
||||
|
||||
arg := testutil.Fake(s.T(), faker, database.InsertTaskParams{
|
||||
OrganizationID: tpl.OrganizationID,
|
||||
TemplateVersionID: tv.ID,
|
||||
})
|
||||
|
||||
dbm.EXPECT().GetTemplateVersionByID(gomock.Any(), tv.ID).Return(tv, nil).AnyTimes()
|
||||
dbm.EXPECT().GetTemplateByID(gomock.Any(), tpl.ID).Return(tpl, nil).AnyTimes()
|
||||
dbm.EXPECT().InsertTask(gomock.Any(), arg).Return(database.TaskTable{}, nil).AnyTimes()
|
||||
|
||||
check.Args(arg).Asserts(
|
||||
tpl, policy.ActionRead,
|
||||
rbac.ResourceTask.InOrg(arg.OrganizationID).WithOwner(arg.OwnerID.String()), policy.ActionCreate,
|
||||
).Returns(database.TaskTable{})
|
||||
}))
|
||||
s.Run("UpsertTaskWorkspaceApp", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
task := testutil.Fake(s.T(), faker, database.Task{})
|
||||
arg := database.UpsertTaskWorkspaceAppParams{
|
||||
TaskID: task.ID,
|
||||
WorkspaceBuildNumber: 1,
|
||||
}
|
||||
|
||||
dbm.EXPECT().GetTaskByID(gomock.Any(), task.ID).Return(task, nil).AnyTimes()
|
||||
dbm.EXPECT().UpsertTaskWorkspaceApp(gomock.Any(), arg).Return(database.TaskWorkspaceApp{}, nil).AnyTimes()
|
||||
|
||||
check.Args(arg).Asserts(task, policy.ActionUpdate).Returns(database.TaskWorkspaceApp{})
|
||||
}))
|
||||
s.Run("GetTaskByWorkspaceID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
task := testutil.Fake(s.T(), faker, database.Task{})
|
||||
task.WorkspaceID = uuid.NullUUID{UUID: uuid.New(), Valid: true}
|
||||
dbm.EXPECT().GetTaskByWorkspaceID(gomock.Any(), task.WorkspaceID.UUID).Return(task, nil).AnyTimes()
|
||||
check.Args(task.WorkspaceID.UUID).Asserts(task, policy.ActionRead).Returns(task)
|
||||
}))
|
||||
}
|
||||
|
||||
func (s *MethodTestSuite) TestProvisionerKeys() {
|
||||
s.Run("InsertProvisionerKey", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
|
||||
org := testutil.Fake(s.T(), faker, database.Organization{})
|
||||
|
||||
Reference in New Issue
Block a user