-
Notifications
You must be signed in to change notification settings - Fork 874
feat: add migrations and queries to support prebuilds #16891
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 all commits
300e80f
b788237
8122595
bfb7c28
6639167
769ae1d
e7e9c27
3936047
8bdcafb
412d198
51773ec
23773c2
bc3ff44
baa3076
ed14fb3
3cc74fb
fc32154
d7b4ec4
e8b53f7
9df6554
ccc309e
ee1f16a
d040ddd
83a6722
cd70710
97cc4ff
4d59039
205d6af
e489e1b
1b29686
20470e4
7b9c8ce
e189a0b
692c0e5
f747db0
3166a42
aa6b490
bc4e7d2
f167b92
8fd34ab
7a8ec49
a64d661
c787cd2
bd38603
097f9c3
4cfdd6f
4a34d52
8d9cd45
f870d7e
18ad931
4667171
a26c094
6ed4121
2312f41
5150a5c
bff34ea
ef462b6
dc45165
9c8a352
eb80919
0b2bbee
3a97bf6
2eeb884
73f99e8
113e12b
217cae0
b0bf220
ff72a00
a007d4a
ea9c53b
66d44ed
29e121f
f64754f
7e02397
55d9827
866454b
4fa959a
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 |
---|---|---|
|
@@ -18,6 +18,7 @@ import ( | |
|
||
"cdr.dev/slog" | ||
|
||
"github.com/coder/coder/v2/coderd/prebuilds" | ||
"github.com/coder/coder/v2/coderd/rbac/policy" | ||
"github.com/coder/coder/v2/coderd/rbac/rolestore" | ||
|
||
|
@@ -361,6 +362,27 @@ var ( | |
}), | ||
Scope: rbac.ScopeAll, | ||
}.WithCachedASTValue() | ||
|
||
subjectPrebuildsOrchestrator = rbac.Subject{ | ||
FriendlyName: "Prebuilds Orchestrator", | ||
ID: prebuilds.SystemUserID.String(), | ||
Roles: rbac.Roles([]rbac.Role{ | ||
{ | ||
Identifier: rbac.RoleIdentifier{Name: "prebuilds-orchestrator"}, | ||
DisplayName: "Coder", | ||
Site: rbac.Permissions(map[string][]policy.Action{ | ||
// May use template, read template-related info, & insert template-related resources (preset prebuilds). | ||
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionUse, policy.ActionViewInsights}, | ||
// May CRUD workspaces, and start/stop them. | ||
rbac.ResourceWorkspace.Type: { | ||
policy.ActionCreate, policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, | ||
policy.ActionWorkspaceStart, policy.ActionWorkspaceStop, | ||
}, | ||
}), | ||
}, | ||
}), | ||
Scope: rbac.ScopeAll, | ||
}.WithCachedASTValue() | ||
) | ||
|
||
// AsProvisionerd returns a context with an actor that has permissions required | ||
|
@@ -415,6 +437,12 @@ func AsSystemReadProvisionerDaemons(ctx context.Context) context.Context { | |
return context.WithValue(ctx, authContextKey{}, subjectSystemReadProvisionerDaemons) | ||
} | ||
|
||
// AsPrebuildsOrchestrator returns a context with an actor that has permissions | ||
// to read orchestrator workspace prebuilds. | ||
func AsPrebuildsOrchestrator(ctx context.Context) context.Context { | ||
return context.WithValue(ctx, authContextKey{}, subjectPrebuildsOrchestrator) | ||
} | ||
|
||
var AsRemoveActor = rbac.Subject{ | ||
ID: "remove-actor", | ||
} | ||
|
@@ -1109,6 +1137,31 @@ func (q *querier) BulkMarkNotificationMessagesSent(ctx context.Context, arg data | |
return q.db.BulkMarkNotificationMessagesSent(ctx, arg) | ||
} | ||
|
||
func (q *querier) ClaimPrebuiltWorkspace(ctx context.Context, arg database.ClaimPrebuiltWorkspaceParams) (database.ClaimPrebuiltWorkspaceRow, error) { | ||
empty := database.ClaimPrebuiltWorkspaceRow{} | ||
|
||
preset, err := q.db.GetPresetByID(ctx, arg.PresetID) | ||
if err != nil { | ||
return empty, err | ||
} | ||
|
||
workspaceObject := rbac.ResourceWorkspace.WithOwner(arg.NewUserID.String()).InOrg(preset.OrganizationID) | ||
err = q.authorizeContext(ctx, policy.ActionCreate, workspaceObject.RBACObject()) | ||
if err != nil { | ||
return empty, err | ||
} | ||
|
||
tpl, err := q.GetTemplateByID(ctx, preset.TemplateID.UUID) | ||
if err != nil { | ||
return empty, xerrors.Errorf("verify template by id: %w", err) | ||
} | ||
if err := q.authorizeContext(ctx, policy.ActionUse, tpl); err != nil { | ||
return empty, xerrors.Errorf("use template for workspace: %w", err) | ||
} | ||
|
||
return q.db.ClaimPrebuiltWorkspace(ctx, arg) | ||
} | ||
|
||
func (q *querier) CleanTailnetCoordinators(ctx context.Context) error { | ||
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceTailnetCoordinator); err != nil { | ||
return err | ||
|
@@ -1130,6 +1183,13 @@ func (q *querier) CleanTailnetTunnels(ctx context.Context) error { | |
return q.db.CleanTailnetTunnels(ctx) | ||
} | ||
|
||
func (q *querier) CountInProgressPrebuilds(ctx context.Context) ([]database.CountInProgressPrebuildsRow, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspace.All()); err != nil { | ||
return nil, err | ||
} | ||
return q.db.CountInProgressPrebuilds(ctx) | ||
} | ||
Comment on lines
+1186
to
+1191
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. This query spans all organizations, and prebuilds are just workspaces 👍 |
||
|
||
func (q *querier) CountUnreadInboxNotificationsByUserID(ctx context.Context, userID uuid.UUID) (int64, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceInboxNotification.WithOwner(userID.String())); err != nil { | ||
return 0, err | ||
|
@@ -2096,6 +2156,30 @@ func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUI | |
return q.db.GetParameterSchemasByJobID(ctx, jobID) | ||
} | ||
|
||
func (q *querier) GetPrebuildMetrics(ctx context.Context) ([]database.GetPrebuildMetricsRow, error) { | ||
// GetPrebuildMetrics returns metrics related to prebuilt workspaces, | ||
// such as the number of created and failed prebuilt workspaces. | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspace.All()); err != nil { | ||
return nil, err | ||
} | ||
return q.db.GetPrebuildMetrics(ctx) | ||
} | ||
dannykopping marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func (q *querier) GetPresetByID(ctx context.Context, presetID uuid.UUID) (database.GetPresetByIDRow, error) { | ||
empty := database.GetPresetByIDRow{} | ||
|
||
preset, err := q.db.GetPresetByID(ctx, presetID) | ||
if err != nil { | ||
return empty, err | ||
} | ||
_, err = q.GetTemplateByID(ctx, preset.TemplateID.UUID) | ||
if err != nil { | ||
return empty, err | ||
} | ||
dannykopping marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return preset, nil | ||
} | ||
|
||
func (q *querier) GetPresetByWorkspaceBuildID(ctx context.Context, workspaceID uuid.UUID) (database.TemplateVersionPreset, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate); err != nil { | ||
return database.TemplateVersionPreset{}, err | ||
|
@@ -2113,6 +2197,14 @@ func (q *querier) GetPresetParametersByTemplateVersionID(ctx context.Context, te | |
return q.db.GetPresetParametersByTemplateVersionID(ctx, templateVersionID) | ||
} | ||
|
||
func (q *querier) GetPresetsBackoff(ctx context.Context, lookback time.Time) ([]database.GetPresetsBackoffRow, error) { | ||
// GetPresetsBackoff returns a list of template version presets along with metadata such as the number of failed prebuilds. | ||
if err := q.authorizeContext(ctx, policy.ActionViewInsights, rbac.ResourceTemplate.All()); err != nil { | ||
return nil, err | ||
} | ||
return q.db.GetPresetsBackoff(ctx, lookback) | ||
} | ||
Comment on lines
+2200
to
+2206
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. @spikecurtis we decided to just lump in the preset metrics with template insights. Since template insights are metrics related to a template, prebuild metrics metadata is essentially the same imo. |
||
|
||
func (q *querier) GetPresetsByTemplateVersionID(ctx context.Context, templateVersionID uuid.UUID) ([]database.TemplateVersionPreset, error) { | ||
// An actor can read template version presets if they can read the related template version. | ||
_, err := q.GetTemplateVersionByID(ctx, templateVersionID) | ||
|
@@ -2164,13 +2256,13 @@ func (q *querier) GetProvisionerJobByID(ctx context.Context, id uuid.UUID) (data | |
// can read the job. | ||
_, err := q.GetWorkspaceBuildByJobID(ctx, id) | ||
if err != nil { | ||
return database.ProvisionerJob{}, err | ||
return database.ProvisionerJob{}, xerrors.Errorf("fetch related workspace build: %w", err) | ||
SasSwart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
case database.ProvisionerJobTypeTemplateVersionDryRun, database.ProvisionerJobTypeTemplateVersionImport: | ||
// Authorized call to get template version. | ||
_, err := authorizedTemplateVersionFromJob(ctx, q, job) | ||
if err != nil { | ||
return database.ProvisionerJob{}, err | ||
return database.ProvisionerJob{}, xerrors.Errorf("fetch related template version: %w", err) | ||
} | ||
default: | ||
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 | |
return q.db.GetReplicasUpdatedAfter(ctx, updatedAt) | ||
} | ||
|
||
func (q *querier) GetRunningPrebuiltWorkspaces(ctx context.Context) ([]database.GetRunningPrebuiltWorkspacesRow, error) { | ||
// This query returns only prebuilt workspaces, but we decided to require permissions for all workspaces. | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspace.All()); err != nil { | ||
return nil, err | ||
} | ||
dannykopping marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return q.db.GetRunningPrebuiltWorkspaces(ctx) | ||
} | ||
|
||
func (q *querier) GetRuntimeConfig(ctx context.Context, key string) (string, error) { | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { | ||
return "", err | ||
|
@@ -2387,6 +2487,15 @@ func (q *querier) GetTemplateParameterInsights(ctx context.Context, arg database | |
return q.db.GetTemplateParameterInsights(ctx, arg) | ||
} | ||
|
||
func (q *querier) GetTemplatePresetsWithPrebuilds(ctx context.Context, templateID uuid.NullUUID) ([]database.GetTemplatePresetsWithPrebuildsRow, error) { | ||
// GetTemplatePresetsWithPrebuilds retrieves template versions with configured presets and prebuilds. | ||
// Presets and prebuilds are part of the template, so if you can access templates - you can access them as well. | ||
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceTemplate.All()); err != nil { | ||
return nil, err | ||
} | ||
return q.db.GetTemplatePresetsWithPrebuilds(ctx, templateID) | ||
} | ||
dannykopping marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func (q *querier) GetTemplateUsageStats(ctx context.Context, arg database.GetTemplateUsageStatsParams) ([]database.TemplateUsageStat, error) { | ||
if err := q.authorizeTemplateInsights(ctx, arg.TemplateIDs); err != nil { | ||
return nil, err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just leave a comment this should match
InsertWorkspace