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

Commit99c6f23

Browse files
SasSwartdannykoppingevgeniy-scherbina
authored
feat: add migrations and queries to support prebuilds (#16891)
Depends on#16916 _(change base to`main` once it is merged)_Closescoder/internal#514_This is one of several PRs to decompose the `dk/prebuilds` featurebranch into separate PRs to merge into `main`._---------Signed-off-by: Danny Kopping <dannykopping@gmail.com>Co-authored-by: Danny Kopping <dannykopping@gmail.com>Co-authored-by: evgeniy-scherbina <evgeniy.shcherbina.es@gmail.com>
1 parent4aa45a5 commit99c6f23

22 files changed

+2110
-59
lines changed

‎coderd/database/dbauthz/dbauthz.go

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"cdr.dev/slog"
2020

21+
"github.com/coder/coder/v2/coderd/prebuilds"
2122
"github.com/coder/coder/v2/coderd/rbac/policy"
2223
"github.com/coder/coder/v2/coderd/rbac/rolestore"
2324

@@ -361,6 +362,27 @@ var (
361362
}),
362363
Scope:rbac.ScopeAll,
363364
}.WithCachedASTValue()
365+
366+
subjectPrebuildsOrchestrator= rbac.Subject{
367+
FriendlyName:"Prebuilds Orchestrator",
368+
ID:prebuilds.SystemUserID.String(),
369+
Roles:rbac.Roles([]rbac.Role{
370+
{
371+
Identifier: rbac.RoleIdentifier{Name:"prebuilds-orchestrator"},
372+
DisplayName:"Coder",
373+
Site:rbac.Permissions(map[string][]policy.Action{
374+
// May use template, read template-related info, & insert template-related resources (preset prebuilds).
375+
rbac.ResourceTemplate.Type: {policy.ActionRead,policy.ActionUpdate,policy.ActionUse,policy.ActionViewInsights},
376+
// May CRUD workspaces, and start/stop them.
377+
rbac.ResourceWorkspace.Type: {
378+
policy.ActionCreate,policy.ActionDelete,policy.ActionRead,policy.ActionUpdate,
379+
policy.ActionWorkspaceStart,policy.ActionWorkspaceStop,
380+
},
381+
}),
382+
},
383+
}),
384+
Scope:rbac.ScopeAll,
385+
}.WithCachedASTValue()
364386
)
365387

366388
// AsProvisionerd returns a context with an actor that has permissions required
@@ -415,6 +437,12 @@ func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context {
415437
returncontext.WithValue(ctx,authContextKey{},subjectSystemReadProvisionerDaemons)
416438
}
417439

440+
// AsPrebuildsOrchestrator returns a context with an actor that has permissions
441+
// to read orchestrator workspace prebuilds.
442+
funcAsPrebuildsOrchestrator(ctx context.Context) context.Context {
443+
returncontext.WithValue(ctx,authContextKey{},subjectPrebuildsOrchestrator)
444+
}
445+
418446
varAsRemoveActor= rbac.Subject{
419447
ID:"remove-actor",
420448
}
@@ -1109,6 +1137,31 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data
11091137
returnq.db.BulkMarkNotificationMessagesSent(ctx,arg)
11101138
}
11111139

1140+
func (q*querier)ClaimPrebuiltWorkspace(ctx context.Context,arg database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow,error) {
1141+
empty:= database.ClaimPrebuiltWorkspaceRow{}
1142+
1143+
preset,err:=q.db.GetPresetByID(ctx,arg.PresetID)
1144+
iferr!=nil {
1145+
returnempty,err
1146+
}
1147+
1148+
workspaceObject:=rbac.ResourceWorkspace.WithOwner(arg.NewUserID.String()).InOrg(preset.OrganizationID)
1149+
err=q.authorizeContext(ctx,policy.ActionCreate,workspaceObject.RBACObject())
1150+
iferr!=nil {
1151+
returnempty,err
1152+
}
1153+
1154+
tpl,err:=q.GetTemplateByID(ctx,preset.TemplateID.UUID)
1155+
iferr!=nil {
1156+
returnempty,xerrors.Errorf("verify template by id: %w",err)
1157+
}
1158+
iferr:=q.authorizeContext(ctx,policy.ActionUse,tpl);err!=nil {
1159+
returnempty,xerrors.Errorf("use template for workspace: %w",err)
1160+
}
1161+
1162+
returnq.db.ClaimPrebuiltWorkspace(ctx,arg)
1163+
}
1164+
11121165
func (q*querier)CleanTailnetCoordinators(ctx context.Context)error {
11131166
iferr:=q.authorizeContext(ctx,policy.ActionDelete,rbac.ResourceTailnetCoordinator);err!=nil {
11141167
returnerr
@@ -1130,6 +1183,13 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error {
11301183
returnq.db.CleanTailnetTunnels(ctx)
11311184
}
11321185

1186+
func (q*querier)CountInProgressPrebuilds(ctx context.Context) ([]database.CountInProgressPrebuildsRow,error) {
1187+
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceWorkspace.All());err!=nil {
1188+
returnnil,err
1189+
}
1190+
returnq.db.CountInProgressPrebuilds(ctx)
1191+
}
1192+
11331193
func (q*querier)CountUnreadInboxNotificationsByUserID(ctx context.Context,userID uuid.UUID) (int64,error) {
11341194
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceInboxNotification.WithOwner(userID.String()));err!=nil {
11351195
return0,err
@@ -2096,6 +2156,30 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
20962156
returnq.db.GetParameterSchemasByJobID(ctx,jobID)
20972157
}
20982158

2159+
func (q*querier)GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow,error) {
2160+
// GetPrebuildMetrics returns metrics related to prebuilt workspaces,
2161+
// such as the number of created and failed prebuilt workspaces.
2162+
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceWorkspace.All());err!=nil {
2163+
returnnil,err
2164+
}
2165+
returnq.db.GetPrebuildMetrics(ctx)
2166+
}
2167+
2168+
func (q*querier)GetPresetByID(ctx context.Context,presetID uuid.UUID) (database.GetPresetByIDRow,error) {
2169+
empty:= database.GetPresetByIDRow{}
2170+
2171+
preset,err:=q.db.GetPresetByID(ctx,presetID)
2172+
iferr!=nil {
2173+
returnempty,err
2174+
}
2175+
_,err=q.GetTemplateByID(ctx,preset.TemplateID.UUID)
2176+
iferr!=nil {
2177+
returnempty,err
2178+
}
2179+
2180+
returnpreset,nil
2181+
}
2182+
20992183
func (q*querier)GetPresetByWorkspaceBuildID(ctx context.Context,workspaceID uuid.UUID) (database.TemplateVersionPreset,error) {
21002184
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceTemplate);err!=nil {
21012185
return database.TemplateVersionPreset{},err
@@ -2113,6 +2197,14 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te
21132197
returnq.db.GetPresetParametersByTemplateVersionID(ctx,templateVersionID)
21142198
}
21152199

2200+
func (q*querier)GetPresetsBackoff(ctx context.Context,lookback time.Time) ([]database.GetPresetsBackoffRow,error) {
2201+
// GetPresetsBackoff returns a list of template version presets along with metadata such as the number of failed prebuilds.
2202+
iferr:=q.authorizeContext(ctx,policy.ActionViewInsights,rbac.ResourceTemplate.All());err!=nil {
2203+
returnnil,err
2204+
}
2205+
returnq.db.GetPresetsBackoff(ctx,lookback)
2206+
}
2207+
21162208
func (q*querier)GetPresetsByTemplateVersionID(ctx context.Context,templateVersionID uuid.UUID) ([]database.TemplateVersionPreset,error) {
21172209
// An actor can read template version presets if they can read the related template version.
21182210
_,err:=q.GetTemplateVersionByID(ctx,templateVersionID)
@@ -2164,13 +2256,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data
21642256
// can read the job.
21652257
_,err:=q.GetWorkspaceBuildByJobID(ctx,id)
21662258
iferr!=nil {
2167-
return database.ProvisionerJob{},err
2259+
return database.ProvisionerJob{},xerrors.Errorf("fetch related workspace build: %w",err)
21682260
}
21692261
casedatabase.ProvisionerJobTypeTemplateVersionDryRun,database.ProvisionerJobTypeTemplateVersionImport:
21702262
// Authorized call to get template version.
21712263
_,err:=authorizedTemplateVersionFromJob(ctx,q,job)
21722264
iferr!=nil {
2173-
return database.ProvisionerJob{},err
2265+
return database.ProvisionerJob{},xerrors.Errorf("fetch related template version: %w",err)
21742266
}
21752267
default:
21762268
return database.ProvisionerJob{},xerrors.Errorf("unknown job type: %q",job.Type)
@@ -2263,6 +2355,14 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
22632355
returnq.db.GetReplicasUpdatedAfter(ctx,updatedAt)
22642356
}
22652357

2358+
func (q*querier)GetRunningPrebuiltWorkspaces(ctx context.Context) ([]database.GetRunningPrebuiltWorkspacesRow,error) {
2359+
// This query returns only prebuilt workspaces, but we decided to require permissions for all workspaces.
2360+
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceWorkspace.All());err!=nil {
2361+
returnnil,err
2362+
}
2363+
returnq.db.GetRunningPrebuiltWorkspaces(ctx)
2364+
}
2365+
22662366
func (q*querier)GetRuntimeConfig(ctx context.Context,keystring) (string,error) {
22672367
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceSystem);err!=nil {
22682368
return"",err
@@ -2387,6 +2487,15 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database
23872487
returnq.db.GetTemplateParameterInsights(ctx,arg)
23882488
}
23892489

2490+
func (q*querier)GetTemplatePresetsWithPrebuilds(ctx context.Context,templateID uuid.NullUUID) ([]database.GetTemplatePresetsWithPrebuildsRow,error) {
2491+
// GetTemplatePresetsWithPrebuilds retrieves template versions with configured presets and prebuilds.
2492+
// Presets and prebuilds are part of the template, so if you can access templates - you can access them as well.
2493+
iferr:=q.authorizeContext(ctx,policy.ActionRead,rbac.ResourceTemplate.All());err!=nil {
2494+
returnnil,err
2495+
}
2496+
returnq.db.GetTemplatePresetsWithPrebuilds(ctx,templateID)
2497+
}
2498+
23902499
func (q*querier)GetTemplateUsageStats(ctx context.Context,arg database.GetTemplateUsageStatsParams) ([]database.TemplateUsageStat,error) {
23912500
iferr:=q.authorizeTemplateInsights(ctx,arg.TemplateIDs);err!=nil {
23922501
returnnil,err

‎coderd/database/dbauthz/dbauthz_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4838,6 +4838,96 @@ func (s *MethodTestSuite) TestNotifications() {
48384838
}))
48394839
}
48404840

4841+
func (s*MethodTestSuite)TestPrebuilds() {
4842+
s.Run("ClaimPrebuiltWorkspace",s.Subtest(func(db database.Store,check*expects) {
4843+
org:=dbgen.Organization(s.T(),db, database.Organization{})
4844+
user:=dbgen.User(s.T(),db, database.User{})
4845+
template:=dbgen.Template(s.T(),db, database.Template{
4846+
OrganizationID:org.ID,
4847+
CreatedBy:user.ID,
4848+
})
4849+
templateVersion:=dbgen.TemplateVersion(s.T(),db, database.TemplateVersion{
4850+
TemplateID: uuid.NullUUID{
4851+
UUID:template.ID,
4852+
Valid:true,
4853+
},
4854+
OrganizationID:org.ID,
4855+
CreatedBy:user.ID,
4856+
})
4857+
preset:=dbgen.Preset(s.T(),db, database.InsertPresetParams{
4858+
TemplateVersionID:templateVersion.ID,
4859+
})
4860+
check.Args(database.ClaimPrebuiltWorkspaceParams{
4861+
NewUserID:user.ID,
4862+
NewName:"",
4863+
PresetID:preset.ID,
4864+
}).Asserts(
4865+
rbac.ResourceWorkspace.WithOwner(user.ID.String()).InOrg(org.ID),policy.ActionCreate,
4866+
template,policy.ActionRead,
4867+
template,policy.ActionUse,
4868+
).ErrorsWithInMemDB(dbmem.ErrUnimplemented).
4869+
ErrorsWithPG(sql.ErrNoRows)
4870+
}))
4871+
s.Run("GetPrebuildMetrics",s.Subtest(func(_ database.Store,check*expects) {
4872+
check.Args().
4873+
Asserts(rbac.ResourceWorkspace.All(),policy.ActionRead).
4874+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4875+
}))
4876+
s.Run("CountInProgressPrebuilds",s.Subtest(func(_ database.Store,check*expects) {
4877+
check.Args().
4878+
Asserts(rbac.ResourceWorkspace.All(),policy.ActionRead).
4879+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4880+
}))
4881+
s.Run("GetPresetsBackoff",s.Subtest(func(_ database.Store,check*expects) {
4882+
check.Args(time.Time{}).
4883+
Asserts(rbac.ResourceTemplate.All(),policy.ActionViewInsights).
4884+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4885+
}))
4886+
s.Run("GetRunningPrebuiltWorkspaces",s.Subtest(func(_ database.Store,check*expects) {
4887+
check.Args().
4888+
Asserts(rbac.ResourceWorkspace.All(),policy.ActionRead).
4889+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4890+
}))
4891+
s.Run("GetTemplatePresetsWithPrebuilds",s.Subtest(func(db database.Store,check*expects) {
4892+
user:=dbgen.User(s.T(),db, database.User{})
4893+
check.Args(uuid.NullUUID{UUID:user.ID,Valid:true}).
4894+
Asserts(rbac.ResourceTemplate.All(),policy.ActionRead).
4895+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4896+
}))
4897+
s.Run("GetPresetByID",s.Subtest(func(db database.Store,check*expects) {
4898+
org:=dbgen.Organization(s.T(),db, database.Organization{})
4899+
user:=dbgen.User(s.T(),db, database.User{})
4900+
template:=dbgen.Template(s.T(),db, database.Template{
4901+
OrganizationID:org.ID,
4902+
CreatedBy:user.ID,
4903+
})
4904+
templateVersion:=dbgen.TemplateVersion(s.T(),db, database.TemplateVersion{
4905+
TemplateID: uuid.NullUUID{
4906+
UUID:template.ID,
4907+
Valid:true,
4908+
},
4909+
OrganizationID:org.ID,
4910+
CreatedBy:user.ID,
4911+
})
4912+
preset:=dbgen.Preset(s.T(),db, database.InsertPresetParams{
4913+
TemplateVersionID:templateVersion.ID,
4914+
})
4915+
check.Args(preset.ID).
4916+
Asserts(template,policy.ActionRead).
4917+
Returns(database.GetPresetByIDRow{
4918+
ID:preset.ID,
4919+
TemplateVersionID:preset.TemplateVersionID,
4920+
Name:preset.Name,
4921+
CreatedAt:preset.CreatedAt,
4922+
TemplateID: uuid.NullUUID{
4923+
UUID:template.ID,
4924+
Valid:true,
4925+
},
4926+
OrganizationID:org.ID,
4927+
})
4928+
}))
4929+
}
4930+
48414931
func (s*MethodTestSuite)TestOAuth2ProviderApps() {
48424932
s.Run("GetOAuth2ProviderApps",s.Subtest(func(db database.Store,check*expects) {
48434933
apps:= []database.OAuth2ProviderApp{

‎coderd/database/dbgen/dbgen.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,29 @@ func TelemetryItem(t testing.TB, db database.Store, seed database.TelemetryItem)
11961196
returnitem
11971197
}
11981198

1199+
funcPreset(t testing.TB,db database.Store,seed database.InsertPresetParams) database.TemplateVersionPreset {
1200+
preset,err:=db.InsertPreset(genCtx, database.InsertPresetParams{
1201+
TemplateVersionID:takeFirst(seed.TemplateVersionID,uuid.New()),
1202+
Name:takeFirst(seed.Name,testutil.GetRandomName(t)),
1203+
CreatedAt:takeFirst(seed.CreatedAt,dbtime.Now()),
1204+
DesiredInstances:seed.DesiredInstances,
1205+
InvalidateAfterSecs:seed.InvalidateAfterSecs,
1206+
})
1207+
require.NoError(t,err,"insert preset")
1208+
returnpreset
1209+
}
1210+
1211+
funcPresetParameter(t testing.TB,db database.Store,seed database.InsertPresetParametersParams) []database.TemplateVersionPresetParameter {
1212+
parameters,err:=db.InsertPresetParameters(genCtx, database.InsertPresetParametersParams{
1213+
TemplateVersionPresetID:takeFirst(seed.TemplateVersionPresetID,uuid.New()),
1214+
Names:takeFirstSlice(seed.Names, []string{testutil.GetRandomName(t)}),
1215+
Values:takeFirstSlice(seed.Values, []string{testutil.GetRandomName(t)}),
1216+
})
1217+
1218+
require.NoError(t,err,"insert preset parameters")
1219+
returnparameters
1220+
}
1221+
11991222
funcprovisionerJobTiming(t testing.TB,db database.Store,seed database.ProvisionerJobTiming) database.ProvisionerJobTiming {
12001223
timing,err:=db.InsertProvisionerJobTimings(genCtx, database.InsertProvisionerJobTimingsParams{
12011224
JobID:takeFirst(seed.JobID,uuid.New()),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp