Skip to content

Commit 81ba8d2

Browse files
SasSwartdannykopping
authored andcommitted
feat: add migrations and queries to support prebuilds
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
1 parent 8e491d8 commit 81ba8d2

20 files changed

+1174
-4
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 84 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

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

363385
// AsProvisionerd returns a context with an actor that has permissions required
@@ -412,6 +434,12 @@ func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context {
412434
return context.WithValue(ctx, authContextKey{}, subjectSystemReadProvisionerDaemons)
413435
}
414436

437+
// AsPrebuildsOrchestrator returns a context with an actor that has permissions
438+
// to read orchestrator workspace prebuilds.
439+
func AsPrebuildsOrchestrator(ctx context.Context) context.Context {
440+
return context.WithValue(ctx, authContextKey{}, subjectPrebuildsOrchestrator)
441+
}
442+
415443
var AsRemoveActor = rbac.Subject{
416444
ID: "remove-actor",
417445
}
@@ -1106,6 +1134,15 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data
11061134
return q.db.BulkMarkNotificationMessagesSent(ctx, arg)
11071135
}
11081136

1137+
func (q *querier) ClaimPrebuild(ctx context.Context, newOwnerID database.ClaimPrebuildParams) (database.ClaimPrebuildRow, error) {
1138+
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceWorkspace); err != nil {
1139+
return database.ClaimPrebuildRow{
1140+
ID: uuid.Nil,
1141+
}, err
1142+
}
1143+
return q.db.ClaimPrebuild(ctx, newOwnerID)
1144+
}
1145+
11091146
func (q *querier) CleanTailnetCoordinators(ctx context.Context) error {
11101147
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil {
11111148
return err
@@ -2020,6 +2057,20 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI
20202057
return q.db.GetParameterSchemasByJobID(ctx, jobID)
20212058
}
20222059

2060+
func (q *querier) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) {
2061+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2062+
return nil, err
2063+
}
2064+
return q.db.GetPrebuildMetrics(ctx)
2065+
}
2066+
2067+
func (q *querier) GetPrebuildsInProgress(ctx context.Context) ([]database.GetPrebuildsInProgressRow, error) {
2068+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2069+
return nil, err
2070+
}
2071+
return q.db.GetPrebuildsInProgress(ctx)
2072+
}
2073+
20232074
func (q *querier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceID uuid.UUID) (database.TemplateVersionPreset, error) {
20242075
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
20252076
return database.TemplateVersionPreset{}, err
@@ -2037,6 +2088,13 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te
20372088
return q.db.GetPresetParametersByTemplateVersionID(ctx, templateVersionID)
20382089
}
20392090

2091+
func (q *querier) GetPresetsBackoff(ctx context.Context, lookback time.Time) ([]database.GetPresetsBackoffRow, error) {
2092+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2093+
return nil, err
2094+
}
2095+
return q.db.GetPresetsBackoff(ctx, lookback)
2096+
}
2097+
20402098
func (q *querier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPreset, error) {
20412099
// An actor can read template version presets if they can read the related template version.
20422100
_, err := q.GetTemplateVersionByID(ctx, templateVersionID)
@@ -2088,13 +2146,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data
20882146
// can read the job.
20892147
_, err := q.GetWorkspaceBuildByJobID(ctx, id)
20902148
if err != nil {
2091-
return database.ProvisionerJob{}, err
2149+
return database.ProvisionerJob{}, xerrors.Errorf("fetch related workspace build: %w", err)
20922150
}
20932151
case database.ProvisionerJobTypeTemplateVersionDryRun, database.ProvisionerJobTypeTemplateVersionImport:
20942152
// Authorized call to get template version.
20952153
_, err := authorizedTemplateVersionFromJob(ctx, q, job)
20962154
if err != nil {
2097-
return database.ProvisionerJob{}, err
2155+
return database.ProvisionerJob{}, xerrors.Errorf("fetch related template version: %w", err)
20982156
}
20992157
default:
21002158
return database.ProvisionerJob{}, xerrors.Errorf("unknown job type: %q", job.Type)
@@ -2187,6 +2245,13 @@ func (q *querier) GetReplicasUpdatedAfter(ctx context.Context, updatedAt time.Ti
21872245
return q.db.GetReplicasUpdatedAfter(ctx, updatedAt)
21882246
}
21892247

2248+
func (q *querier) GetRunningPrebuilds(ctx context.Context) ([]database.GetRunningPrebuildsRow, error) {
2249+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2250+
return nil, err
2251+
}
2252+
return q.db.GetRunningPrebuilds(ctx)
2253+
}
2254+
21902255
func (q *querier) GetRuntimeConfig(ctx context.Context, key string) (string, error) {
21912256
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
21922257
return "", err
@@ -2311,6 +2376,16 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database
23112376
return q.db.GetTemplateParameterInsights(ctx, arg)
23122377
}
23132378

2379+
func (q *querier) GetTemplatePresetsWithPrebuilds(ctx context.Context, templateID uuid.NullUUID) ([]database.GetTemplatePresetsWithPrebuildsRow, error) {
2380+
// Although this fetches presets. It filters them by prebuilds and is only of use to the prebuild system.
2381+
// As such, we authorize this in line with other prebuild queries, not with other preset queries.
2382+
2383+
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil {
2384+
return nil, err
2385+
}
2386+
return q.db.GetTemplatePresetsWithPrebuilds(ctx, templateID)
2387+
}
2388+
23142389
func (q *querier) GetTemplateUsageStats(ctx context.Context, arg database.GetTemplateUsageStatsParams) ([]database.TemplateUsageStat, error) {
23152390
if err := q.authorizeTemplateInsights(ctx, arg.TemplateIDs); err != nil {
23162391
return nil, err
@@ -3235,6 +3310,13 @@ func (q *querier) InsertPresetParameters(ctx context.Context, arg database.Inser
32353310
return q.db.InsertPresetParameters(ctx, arg)
32363311
}
32373312

3313+
func (q *querier) InsertPresetPrebuild(ctx context.Context, arg database.InsertPresetPrebuildParams) (database.TemplateVersionPresetPrebuild, error) {
3314+
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
3315+
return database.TemplateVersionPresetPrebuild{}, err
3316+
}
3317+
return q.db.InsertPresetPrebuild(ctx, arg)
3318+
}
3319+
32383320
// TODO: We need to create a ProvisionerJob resource type
32393321
func (q *querier) InsertProvisionerJob(ctx context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
32403322
// if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -979,8 +979,8 @@ func (s *MethodTestSuite) TestOrganization() {
979979
})
980980

981981
check.Args(database.OrganizationMembersParams{
982-
OrganizationID: uuid.UUID{},
983-
UserID: uuid.UUID{},
982+
OrganizationID: o.ID,
983+
UserID: u.ID,
984984
}).Asserts(
985985
mem, policy.ActionRead,
986986
)
@@ -4642,6 +4642,65 @@ func (s *MethodTestSuite) TestNotifications() {
46424642
}))
46434643
}
46444644

4645+
func (s *MethodTestSuite) TestPrebuilds() {
4646+
s.Run("ClaimPrebuild", s.Subtest(func(db database.Store, check *expects) {
4647+
check.Args(database.ClaimPrebuildParams{}).
4648+
Asserts(rbac.ResourceWorkspace, policy.ActionUpdate).
4649+
ErrorsWithInMemDB(dbmem.ErrUnimplemented).
4650+
ErrorsWithPG(sql.ErrNoRows)
4651+
}))
4652+
s.Run("GetPrebuildMetrics", s.Subtest(func(_ database.Store, check *expects) {
4653+
check.Args().
4654+
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4655+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4656+
}))
4657+
s.Run("GetPrebuildsInProgress", s.Subtest(func(_ database.Store, check *expects) {
4658+
check.Args().
4659+
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4660+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4661+
}))
4662+
s.Run("GetPresetsBackoff", s.Subtest(func(_ database.Store, check *expects) {
4663+
check.Args(time.Time{}).
4664+
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4665+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4666+
}))
4667+
s.Run("GetRunningPrebuilds", s.Subtest(func(_ database.Store, check *expects) {
4668+
check.Args().
4669+
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4670+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4671+
}))
4672+
s.Run("GetTemplatePresetsWithPrebuilds", s.Subtest(func(db database.Store, check *expects) {
4673+
user := dbgen.User(s.T(), db, database.User{})
4674+
check.Args(uuid.NullUUID{UUID: user.ID, Valid: true}).
4675+
Asserts(rbac.ResourceTemplate, policy.ActionRead).
4676+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4677+
}))
4678+
s.Run("InsertPresetPrebuild", s.Subtest(func(db database.Store, check *expects) {
4679+
org := dbgen.Organization(s.T(), db, database.Organization{})
4680+
user := dbgen.User(s.T(), db, database.User{})
4681+
template := dbgen.Template(s.T(), db, database.Template{
4682+
CreatedBy: user.ID,
4683+
OrganizationID: org.ID,
4684+
})
4685+
templateVersion := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
4686+
TemplateID: uuid.NullUUID{UUID: template.ID, Valid: true},
4687+
OrganizationID: org.ID,
4688+
CreatedBy: user.ID,
4689+
})
4690+
preset := dbgen.Preset(s.T(), db, database.InsertPresetParams{
4691+
Name: coderdtest.RandomName(s.T()),
4692+
TemplateVersionID: templateVersion.ID,
4693+
})
4694+
check.Args(database.InsertPresetPrebuildParams{
4695+
ID: uuid.New(),
4696+
PresetID: preset.ID,
4697+
DesiredInstances: 1,
4698+
}).
4699+
Asserts(rbac.ResourceSystem, policy.ActionCreate).
4700+
ErrorsWithInMemDB(dbmem.ErrUnimplemented)
4701+
}))
4702+
}
4703+
46454704
func (s *MethodTestSuite) TestOAuth2ProviderApps() {
46464705
s.Run("GetOAuth2ProviderApps", s.Subtest(func(db database.Store, check *expects) {
46474706
apps := []database.OAuth2ProviderApp{

coderd/database/dbgen/dbgen.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,38 @@ func TelemetryItem(t testing.TB, db database.Store, seed database.TelemetryItem)
11581158
return item
11591159
}
11601160

1161+
func Preset(t testing.TB, db database.Store, seed database.InsertPresetParams) database.TemplateVersionPreset {
1162+
preset, err := db.InsertPreset(genCtx, database.InsertPresetParams{
1163+
TemplateVersionID: takeFirst(seed.TemplateVersionID, uuid.New()),
1164+
Name: takeFirst(seed.Name, testutil.GetRandomName(t)),
1165+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
1166+
})
1167+
require.NoError(t, err, "insert preset")
1168+
return preset
1169+
}
1170+
1171+
func PresetParameter(t testing.TB, db database.Store, seed database.InsertPresetParametersParams) []database.TemplateVersionPresetParameter {
1172+
parameters, err := db.InsertPresetParameters(genCtx, database.InsertPresetParametersParams{
1173+
TemplateVersionPresetID: takeFirst(seed.TemplateVersionPresetID, uuid.New()),
1174+
Names: takeFirstSlice(seed.Names, []string{testutil.GetRandomName(t)}),
1175+
Values: takeFirstSlice(seed.Values, []string{testutil.GetRandomName(t)}),
1176+
})
1177+
1178+
require.NoError(t, err, "insert preset parameters")
1179+
return parameters
1180+
}
1181+
1182+
func PresetPrebuild(t testing.TB, db database.Store, seed database.InsertPresetPrebuildParams) database.TemplateVersionPresetPrebuild {
1183+
prebuild, err := db.InsertPresetPrebuild(genCtx, database.InsertPresetPrebuildParams{
1184+
ID: takeFirst(seed.ID, uuid.New()),
1185+
PresetID: takeFirst(seed.PresetID, uuid.New()),
1186+
DesiredInstances: takeFirst(seed.DesiredInstances, 1),
1187+
InvalidateAfterSecs: 0,
1188+
})
1189+
require.NoError(t, err, "insert preset prebuild")
1190+
return prebuild
1191+
}
1192+
11611193
func provisionerJobTiming(t testing.TB, db database.Store, seed database.ProvisionerJobTiming) database.ProvisionerJobTiming {
11621194
timing, err := db.InsertProvisionerJobTimings(genCtx, database.InsertProvisionerJobTimingsParams{
11631195
JobID: takeFirst(seed.JobID, uuid.New()),

coderd/database/dbmem/dbmem.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,10 @@ func (*FakeQuerier) BulkMarkNotificationMessagesSent(_ context.Context, arg data
17141714
return int64(len(arg.IDs)), nil
17151715
}
17161716

1717+
func (*FakeQuerier) ClaimPrebuild(_ context.Context, _ database.ClaimPrebuildParams) (database.ClaimPrebuildRow, error) {
1718+
return database.ClaimPrebuildRow{}, ErrUnimplemented
1719+
}
1720+
17171721
func (*FakeQuerier) CleanTailnetCoordinators(_ context.Context) error {
17181722
return ErrUnimplemented
17191723
}
@@ -4023,6 +4027,14 @@ func (q *FakeQuerier) GetParameterSchemasByJobID(_ context.Context, jobID uuid.U
40234027
return parameters, nil
40244028
}
40254029

4030+
func (*FakeQuerier) GetPrebuildMetrics(_ context.Context) ([]database.GetPrebuildMetricsRow, error) {
4031+
return nil, ErrUnimplemented
4032+
}
4033+
4034+
func (*FakeQuerier) GetPrebuildsInProgress(_ context.Context) ([]database.GetPrebuildsInProgressRow, error) {
4035+
return nil, ErrUnimplemented
4036+
}
4037+
40264038
func (q *FakeQuerier) GetPresetByWorkspaceBuildID(_ context.Context, workspaceBuildID uuid.UUID) (database.TemplateVersionPreset, error) {
40274039
q.mutex.RLock()
40284040
defer q.mutex.RUnlock()
@@ -4065,6 +4077,10 @@ func (q *FakeQuerier) GetPresetParametersByTemplateVersionID(_ context.Context,
40654077
return parameters, nil
40664078
}
40674079

4080+
func (*FakeQuerier) GetPresetsBackoff(_ context.Context, _ time.Time) ([]database.GetPresetsBackoffRow, error) {
4081+
return nil, ErrUnimplemented
4082+
}
4083+
40684084
func (q *FakeQuerier) GetPresetsByTemplateVersionID(_ context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPreset, error) {
40694085
q.mutex.RLock()
40704086
defer q.mutex.RUnlock()
@@ -4728,6 +4744,10 @@ func (q *FakeQuerier) GetReplicasUpdatedAfter(_ context.Context, updatedAt time.
47284744
return replicas, nil
47294745
}
47304746

4747+
func (*FakeQuerier) GetRunningPrebuilds(_ context.Context) ([]database.GetRunningPrebuildsRow, error) {
4748+
return nil, ErrUnimplemented
4749+
}
4750+
47314751
func (q *FakeQuerier) GetRuntimeConfig(_ context.Context, key string) (string, error) {
47324752
q.mutex.Lock()
47334753
defer q.mutex.Unlock()
@@ -5767,6 +5787,10 @@ func (q *FakeQuerier) GetTemplateParameterInsights(ctx context.Context, arg data
57675787
return rows, nil
57685788
}
57695789

5790+
func (*FakeQuerier) GetTemplatePresetsWithPrebuilds(_ context.Context, _ uuid.NullUUID) ([]database.GetTemplatePresetsWithPrebuildsRow, error) {
5791+
return nil, ErrUnimplemented
5792+
}
5793+
57705794
func (q *FakeQuerier) GetTemplateUsageStats(_ context.Context, arg database.GetTemplateUsageStatsParams) ([]database.TemplateUsageStat, error) {
57715795
err := validateDatabaseType(arg)
57725796
if err != nil {
@@ -8542,6 +8566,15 @@ func (q *FakeQuerier) InsertPresetParameters(_ context.Context, arg database.Ins
85428566
return presetParameters, nil
85438567
}
85448568

8569+
func (*FakeQuerier) InsertPresetPrebuild(_ context.Context, arg database.InsertPresetPrebuildParams) (database.TemplateVersionPresetPrebuild, error) {
8570+
err := validateDatabaseType(arg)
8571+
if err != nil {
8572+
return database.TemplateVersionPresetPrebuild{}, err
8573+
}
8574+
8575+
return database.TemplateVersionPresetPrebuild{}, ErrUnimplemented
8576+
}
8577+
85458578
func (q *FakeQuerier) InsertProvisionerJob(_ context.Context, arg database.InsertProvisionerJobParams) (database.ProvisionerJob, error) {
85468579
if err := validateDatabaseType(arg); err != nil {
85478580
return database.ProvisionerJob{}, err

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy