Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf941e78

Browse files
chore: add db query to retrieve workspaces & their agents (#14792)
Second PR for#14716.Adds a query that, given a user ID, returns all the workspaces they own, that can also be `ActionRead` by the requesting user.```type GetWorkspacesAndAgentsByOwnerIDRow struct {WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`WorkspaceName string `db:"workspace_name" json:"workspace_name"`JobStatus ProvisionerJobStatus `db:"job_status" json:"job_status"`Transition WorkspaceTransition `db:"transition" json:"transition"`Agents []AgentIDNamePair `db:"agents" json:"agents"`}``` `JobStatus` and `Transition` are set using the latest build/job of the workspace. Deleted workspaces are not included.
1 parent31506e6 commitf941e78

File tree

15 files changed

+551
-38
lines changed

15 files changed

+551
-38
lines changed

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,14 @@ func (q *querier) GetWorkspaces(ctx context.Context, arg database.GetWorkspacesP
27892789
returnq.db.GetAuthorizedWorkspaces(ctx,arg,prep)
27902790
}
27912791

2792+
func (q*querier)GetWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID) ([]database.GetWorkspacesAndAgentsByOwnerIDRow,error) {
2793+
prep,err:=prepareSQLFilter(ctx,q.auth,policy.ActionRead,rbac.ResourceWorkspace.Type)
2794+
iferr!=nil {
2795+
returnnil,xerrors.Errorf("(dev error) prepare sql filter: %w",err)
2796+
}
2797+
returnq.db.GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx,ownerID,prep)
2798+
}
2799+
27922800
func (q*querier)GetWorkspacesEligibleForTransition(ctx context.Context,now time.Time) ([]database.WorkspaceTable,error) {
27932801
returnq.db.GetWorkspacesEligibleForTransition(ctx,now)
27942802
}
@@ -4242,6 +4250,10 @@ func (q *querier) GetAuthorizedWorkspaces(ctx context.Context, arg database.GetW
42424250
returnq.GetWorkspaces(ctx,arg)
42434251
}
42444252

4253+
func (q*querier)GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID,_ rbac.PreparedAuthorized) ([]database.GetWorkspacesAndAgentsByOwnerIDRow,error) {
4254+
returnq.GetWorkspacesAndAgentsByOwnerID(ctx,ownerID)
4255+
}
4256+
42454257
// GetAuthorizedUsers is not required for dbauthz since GetUsers is already
42464258
// authenticated.
42474259
func (q*querier)GetAuthorizedUsers(ctx context.Context,arg database.GetUsersParams,_ rbac.PreparedAuthorized) ([]database.GetUsersRow,error) {

‎coderd/database/dbauthz/dbauthz_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,24 @@ func (s *MethodTestSuite) TestWorkspace() {
14701470
// No asserts here because SQLFilter.
14711471
check.Args(database.GetWorkspacesParams{},emptyPreparedAuthorized{}).Asserts()
14721472
}))
1473+
s.Run("GetWorkspacesAndAgentsByOwnerID",s.Subtest(func(db database.Store,check*expects) {
1474+
ws:=dbgen.Workspace(s.T(),db, database.WorkspaceTable{})
1475+
build:=dbgen.WorkspaceBuild(s.T(),db, database.WorkspaceBuild{WorkspaceID:ws.ID,JobID:uuid.New()})
1476+
_=dbgen.ProvisionerJob(s.T(),db,nil, database.ProvisionerJob{ID:build.JobID,Type:database.ProvisionerJobTypeWorkspaceBuild})
1477+
res:=dbgen.WorkspaceResource(s.T(),db, database.WorkspaceResource{JobID:build.JobID})
1478+
_=dbgen.WorkspaceAgent(s.T(),db, database.WorkspaceAgent{ResourceID:res.ID})
1479+
// No asserts here because SQLFilter.
1480+
check.Args(ws.OwnerID).Asserts()
1481+
}))
1482+
s.Run("GetAuthorizedWorkspacesAndAgentsByOwnerID",s.Subtest(func(db database.Store,check*expects) {
1483+
ws:=dbgen.Workspace(s.T(),db, database.WorkspaceTable{})
1484+
build:=dbgen.WorkspaceBuild(s.T(),db, database.WorkspaceBuild{WorkspaceID:ws.ID,JobID:uuid.New()})
1485+
_=dbgen.ProvisionerJob(s.T(),db,nil, database.ProvisionerJob{ID:build.JobID,Type:database.ProvisionerJobTypeWorkspaceBuild})
1486+
res:=dbgen.WorkspaceResource(s.T(),db, database.WorkspaceResource{JobID:build.JobID})
1487+
_=dbgen.WorkspaceAgent(s.T(),db, database.WorkspaceAgent{ResourceID:res.ID})
1488+
// No asserts here because SQLFilter.
1489+
check.Args(ws.OwnerID,emptyPreparedAuthorized{}).Asserts()
1490+
}))
14731491
s.Run("GetLatestWorkspaceBuildByWorkspaceID",s.Subtest(func(db database.Store,check*expects) {
14741492
ws:=dbgen.Workspace(s.T(),db, database.WorkspaceTable{})
14751493
b:=dbgen.WorkspaceBuild(s.T(),db, database.WorkspaceBuild{WorkspaceID:ws.ID})

‎coderd/database/dbmem/dbmem.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6839,6 +6839,11 @@ func (q *FakeQuerier) GetWorkspaces(ctx context.Context, arg database.GetWorkspa
68396839
returnworkspaceRows,err
68406840
}
68416841

6842+
func (q*FakeQuerier)GetWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID) ([]database.GetWorkspacesAndAgentsByOwnerIDRow,error) {
6843+
// No auth filter.
6844+
returnq.GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx,ownerID,nil)
6845+
}
6846+
68426847
func (q*FakeQuerier)GetWorkspacesEligibleForTransition(ctx context.Context,now time.Time) ([]database.WorkspaceTable,error) {
68436848
q.mutex.RLock()
68446849
deferq.mutex.RUnlock()
@@ -11224,6 +11229,67 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
1122411229
returnq.convertToWorkspaceRowsNoLock(ctx,workspaces,int64(beforePageCount),arg.WithSummary),nil
1122511230
}
1122611231

11232+
func (q*FakeQuerier)GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID,prepared rbac.PreparedAuthorized) ([]database.GetWorkspacesAndAgentsByOwnerIDRow,error) {
11233+
q.mutex.RLock()
11234+
deferq.mutex.RUnlock()
11235+
11236+
ifprepared!=nil {
11237+
// Call this to match the same function calls as the SQL implementation.
11238+
_,err:=prepared.CompileToSQL(ctx,rbac.ConfigWithoutACL())
11239+
iferr!=nil {
11240+
returnnil,err
11241+
}
11242+
}
11243+
workspaces:=make([]database.WorkspaceTable,0)
11244+
for_,workspace:=rangeq.workspaces {
11245+
ifworkspace.OwnerID==ownerID&&!workspace.Deleted {
11246+
workspaces=append(workspaces,workspace)
11247+
}
11248+
}
11249+
11250+
out:=make([]database.GetWorkspacesAndAgentsByOwnerIDRow,0,len(workspaces))
11251+
for_,w:=rangeworkspaces {
11252+
// these always exist
11253+
build,err:=q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx,w.ID)
11254+
iferr!=nil {
11255+
returnnil,xerrors.Errorf("get latest build: %w",err)
11256+
}
11257+
11258+
job,err:=q.getProvisionerJobByIDNoLock(ctx,build.JobID)
11259+
iferr!=nil {
11260+
returnnil,xerrors.Errorf("get provisioner job: %w",err)
11261+
}
11262+
11263+
outAgents:=make([]database.AgentIDNamePair,0)
11264+
resources,err:=q.getWorkspaceResourcesByJobIDNoLock(ctx,job.ID)
11265+
iferr!=nil {
11266+
returnnil,xerrors.Errorf("get workspace resources: %w",err)
11267+
}
11268+
iflen(resources)>0 {
11269+
agents,err:=q.getWorkspaceAgentsByResourceIDsNoLock(ctx, []uuid.UUID{resources[0].ID})
11270+
iferr!=nil {
11271+
returnnil,xerrors.Errorf("get workspace agents: %w",err)
11272+
}
11273+
for_,a:=rangeagents {
11274+
outAgents=append(outAgents, database.AgentIDNamePair{
11275+
ID:a.ID,
11276+
Name:a.Name,
11277+
})
11278+
}
11279+
}
11280+
11281+
out=append(out, database.GetWorkspacesAndAgentsByOwnerIDRow{
11282+
ID:w.ID,
11283+
Name:w.Name,
11284+
JobStatus:job.JobStatus,
11285+
Transition:build.Transition,
11286+
Agents:outAgents,
11287+
})
11288+
}
11289+
11290+
returnout,nil
11291+
}
11292+
1122711293
func (q*FakeQuerier)GetAuthorizedUsers(ctx context.Context,arg database.GetUsersParams,prepared rbac.PreparedAuthorized) ([]database.GetUsersRow,error) {
1122811294
iferr:=validateDatabaseType(arg);err!=nil {
1122911295
returnnil,err

‎coderd/database/dbmetrics/querymetrics.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dbmock/dbmock.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎coderd/database/dump.sql

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROPTYPE agent_id_name_pair;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CREATETYPEagent_id_name_pairAS (
2+
id uuid,
3+
nametext
4+
);

‎coderd/database/modelqueries.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ func (q *sqlQuerier) GetTemplateGroupRoles(ctx context.Context, id uuid.UUID) ([
221221

222222
typeworkspaceQuerierinterface {
223223
GetAuthorizedWorkspaces(ctx context.Context,argGetWorkspacesParams,prepared rbac.PreparedAuthorized) ([]GetWorkspacesRow,error)
224+
GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID,prepared rbac.PreparedAuthorized) ([]GetWorkspacesAndAgentsByOwnerIDRow,error)
224225
}
225226

226227
// GetAuthorizedWorkspaces returns all workspaces that the user is authorized to access.
@@ -320,6 +321,49 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
320321
returnitems,nil
321322
}
322323

324+
func (q*sqlQuerier)GetAuthorizedWorkspacesAndAgentsByOwnerID(ctx context.Context,ownerID uuid.UUID,prepared rbac.PreparedAuthorized) ([]GetWorkspacesAndAgentsByOwnerIDRow,error) {
325+
authorizedFilter,err:=prepared.CompileToSQL(ctx,rbac.ConfigWorkspaces())
326+
iferr!=nil {
327+
returnnil,xerrors.Errorf("compile authorized filter: %w",err)
328+
}
329+
330+
// In order to properly use ORDER BY, OFFSET, and LIMIT, we need to inject the
331+
// authorizedFilter between the end of the where clause and those statements.
332+
filtered,err:=insertAuthorizedFilter(getWorkspacesAndAgentsByOwnerID,fmt.Sprintf(" AND %s",authorizedFilter))
333+
iferr!=nil {
334+
returnnil,xerrors.Errorf("insert authorized filter: %w",err)
335+
}
336+
337+
// The name comment is for metric tracking
338+
query:=fmt.Sprintf("-- name: GetAuthorizedWorkspacesAndAgentsByOwnerID :many\n%s",filtered)
339+
rows,err:=q.db.QueryContext(ctx,query,ownerID)
340+
iferr!=nil {
341+
returnnil,err
342+
}
343+
deferrows.Close()
344+
varitems []GetWorkspacesAndAgentsByOwnerIDRow
345+
forrows.Next() {
346+
variGetWorkspacesAndAgentsByOwnerIDRow
347+
iferr:=rows.Scan(
348+
&i.ID,
349+
&i.Name,
350+
&i.JobStatus,
351+
&i.Transition,
352+
pq.Array(&i.Agents),
353+
);err!=nil {
354+
returnnil,err
355+
}
356+
items=append(items,i)
357+
}
358+
iferr:=rows.Close();err!=nil {
359+
returnnil,err
360+
}
361+
iferr:=rows.Err();err!=nil {
362+
returnnil,err
363+
}
364+
returnitems,nil
365+
}
366+
323367
typeuserQuerierinterface {
324368
GetAuthorizedUsers(ctx context.Context,argGetUsersParams,prepared rbac.PreparedAuthorized) ([]GetUsersRow,error)
325369
}

‎coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp