mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
feat: add prebuilds configuration & bootstrapping (#17527)
Closes https://github.com/coder/internal/issues/508 --------- Signed-off-by: Danny Kopping <dannykopping@gmail.com> Co-authored-by: Cian Johnston <cian@coder.com>
This commit is contained in:
27
coderd/apidoc/docs.go
generated
27
coderd/apidoc/docs.go
generated
@ -11926,6 +11926,9 @@ const docTemplate = `{
|
||||
"workspace_hostname_suffix": {
|
||||
"type": "string"
|
||||
},
|
||||
"workspace_prebuilds": {
|
||||
"$ref": "#/definitions/codersdk.PrebuildsConfig"
|
||||
},
|
||||
"write_config": {
|
||||
"type": "boolean"
|
||||
}
|
||||
@ -12005,7 +12008,8 @@ const docTemplate = `{
|
||||
"notifications",
|
||||
"workspace-usage",
|
||||
"web-push",
|
||||
"dynamic-parameters"
|
||||
"dynamic-parameters",
|
||||
"workspace-prebuilds"
|
||||
],
|
||||
"x-enum-comments": {
|
||||
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
|
||||
@ -12013,6 +12017,7 @@ const docTemplate = `{
|
||||
"ExperimentExample": "This isn't used for anything.",
|
||||
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
|
||||
"ExperimentWebPush": "Enables web push notifications through the browser.",
|
||||
"ExperimentWorkspacePrebuilds": "Enables the new workspace prebuilds feature.",
|
||||
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
|
||||
},
|
||||
"x-enum-varnames": [
|
||||
@ -12021,7 +12026,8 @@ const docTemplate = `{
|
||||
"ExperimentNotifications",
|
||||
"ExperimentWorkspaceUsage",
|
||||
"ExperimentWebPush",
|
||||
"ExperimentDynamicParameters"
|
||||
"ExperimentDynamicParameters",
|
||||
"ExperimentWorkspacePrebuilds"
|
||||
]
|
||||
},
|
||||
"codersdk.ExternalAuth": {
|
||||
@ -13654,6 +13660,23 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.PrebuildsConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reconciliation_backoff_interval": {
|
||||
"description": "ReconciliationBackoffInterval specifies the amount of time to increase the backoff interval\nwhen errors occur during reconciliation.",
|
||||
"type": "integer"
|
||||
},
|
||||
"reconciliation_backoff_lookback": {
|
||||
"description": "ReconciliationBackoffLookback determines the time window to look back when calculating\nthe number of failed prebuilds, which influences the backoff strategy.",
|
||||
"type": "integer"
|
||||
},
|
||||
"reconciliation_interval": {
|
||||
"description": "ReconciliationInterval defines how often the workspace prebuilds state should be reconciled.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.Preset": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
27
coderd/apidoc/swagger.json
generated
27
coderd/apidoc/swagger.json
generated
@ -10684,6 +10684,9 @@
|
||||
"workspace_hostname_suffix": {
|
||||
"type": "string"
|
||||
},
|
||||
"workspace_prebuilds": {
|
||||
"$ref": "#/definitions/codersdk.PrebuildsConfig"
|
||||
},
|
||||
"write_config": {
|
||||
"type": "boolean"
|
||||
}
|
||||
@ -10759,7 +10762,8 @@
|
||||
"notifications",
|
||||
"workspace-usage",
|
||||
"web-push",
|
||||
"dynamic-parameters"
|
||||
"dynamic-parameters",
|
||||
"workspace-prebuilds"
|
||||
],
|
||||
"x-enum-comments": {
|
||||
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
|
||||
@ -10767,6 +10771,7 @@
|
||||
"ExperimentExample": "This isn't used for anything.",
|
||||
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
|
||||
"ExperimentWebPush": "Enables web push notifications through the browser.",
|
||||
"ExperimentWorkspacePrebuilds": "Enables the new workspace prebuilds feature.",
|
||||
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
|
||||
},
|
||||
"x-enum-varnames": [
|
||||
@ -10775,7 +10780,8 @@
|
||||
"ExperimentNotifications",
|
||||
"ExperimentWorkspaceUsage",
|
||||
"ExperimentWebPush",
|
||||
"ExperimentDynamicParameters"
|
||||
"ExperimentDynamicParameters",
|
||||
"ExperimentWorkspacePrebuilds"
|
||||
]
|
||||
},
|
||||
"codersdk.ExternalAuth": {
|
||||
@ -12346,6 +12352,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.PrebuildsConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"reconciliation_backoff_interval": {
|
||||
"description": "ReconciliationBackoffInterval specifies the amount of time to increase the backoff interval\nwhen errors occur during reconciliation.",
|
||||
"type": "integer"
|
||||
},
|
||||
"reconciliation_backoff_lookback": {
|
||||
"description": "ReconciliationBackoffLookback determines the time window to look back when calculating\nthe number of failed prebuilds, which influences the backoff strategy.",
|
||||
"type": "integer"
|
||||
},
|
||||
"reconciliation_interval": {
|
||||
"description": "ReconciliationInterval defines how often the workspace prebuilds state should be reconciled.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"codersdk.Preset": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -597,6 +597,7 @@ func New(options *Options) *API {
|
||||
api.AppearanceFetcher.Store(&f)
|
||||
api.PortSharer.Store(&portsharing.DefaultPortSharer)
|
||||
api.PrebuildsClaimer.Store(&prebuilds.DefaultClaimer)
|
||||
api.PrebuildsReconciler.Store(&prebuilds.DefaultReconciler)
|
||||
buildInfo := codersdk.BuildInfoResponse{
|
||||
ExternalURL: buildinfo.ExternalURL(),
|
||||
Version: buildinfo.Version(),
|
||||
@ -1568,10 +1569,11 @@ type API struct {
|
||||
DERPMapper atomic.Pointer[func(derpMap *tailcfg.DERPMap) *tailcfg.DERPMap]
|
||||
// AccessControlStore is a pointer to an atomic pointer since it is
|
||||
// passed to dbauthz.
|
||||
AccessControlStore *atomic.Pointer[dbauthz.AccessControlStore]
|
||||
PortSharer atomic.Pointer[portsharing.PortSharer]
|
||||
FileCache files.Cache
|
||||
PrebuildsClaimer atomic.Pointer[prebuilds.Claimer]
|
||||
AccessControlStore *atomic.Pointer[dbauthz.AccessControlStore]
|
||||
PortSharer atomic.Pointer[portsharing.PortSharer]
|
||||
FileCache files.Cache
|
||||
PrebuildsClaimer atomic.Pointer[prebuilds.Claimer]
|
||||
PrebuildsReconciler atomic.Pointer[prebuilds.ReconciliationOrchestrator]
|
||||
|
||||
UpdatesProvider tailnet.WorkspaceUpdatesProvider
|
||||
|
||||
@ -1659,6 +1661,13 @@ func (api *API) Close() error {
|
||||
_ = api.AppSigningKeyCache.Close()
|
||||
_ = api.AppEncryptionKeyCache.Close()
|
||||
_ = api.UpdatesProvider.Close()
|
||||
|
||||
if current := api.PrebuildsReconciler.Load(); current != nil {
|
||||
ctx, giveUp := context.WithTimeoutCause(context.Background(), time.Second*30, xerrors.New("gave up waiting for reconciler to stop before shutdown"))
|
||||
defer giveUp()
|
||||
(*current).Stop(ctx, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,10 +14,10 @@ var ErrNoClaimablePrebuiltWorkspaces = xerrors.New("no claimable prebuilt worksp
|
||||
type ReconciliationOrchestrator interface {
|
||||
Reconciler
|
||||
|
||||
// RunLoop starts a continuous reconciliation loop that periodically calls ReconcileAll
|
||||
// Run starts a continuous reconciliation loop that periodically calls ReconcileAll
|
||||
// to ensure all prebuilds are in their desired states. The loop runs until the context
|
||||
// is canceled or Stop is called.
|
||||
RunLoop(ctx context.Context)
|
||||
Run(ctx context.Context)
|
||||
|
||||
// Stop gracefully shuts down the orchestrator with the given cause.
|
||||
// The cause is used for logging and error reporting.
|
||||
|
@ -10,41 +10,28 @@ import (
|
||||
|
||||
type NoopReconciler struct{}
|
||||
|
||||
func NewNoopReconciler() *NoopReconciler {
|
||||
return &NoopReconciler{}
|
||||
}
|
||||
|
||||
func (NoopReconciler) RunLoop(context.Context) {}
|
||||
|
||||
func (NoopReconciler) Stop(context.Context, error) {}
|
||||
|
||||
func (NoopReconciler) ReconcileAll(context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NoopReconciler) Run(context.Context) {}
|
||||
func (NoopReconciler) Stop(context.Context, error) {}
|
||||
func (NoopReconciler) ReconcileAll(context.Context) error { return nil }
|
||||
func (NoopReconciler) SnapshotState(context.Context, database.Store) (*GlobalSnapshot, error) {
|
||||
return &GlobalSnapshot{}, nil
|
||||
}
|
||||
|
||||
func (NoopReconciler) ReconcilePreset(context.Context, PresetSnapshot) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (NoopReconciler) ReconcilePreset(context.Context, PresetSnapshot) error { return nil }
|
||||
func (NoopReconciler) CalculateActions(context.Context, PresetSnapshot) (*ReconciliationActions, error) {
|
||||
return &ReconciliationActions{}, nil
|
||||
}
|
||||
|
||||
var _ ReconciliationOrchestrator = NoopReconciler{}
|
||||
var DefaultReconciler ReconciliationOrchestrator = NoopReconciler{}
|
||||
|
||||
type AGPLPrebuildClaimer struct{}
|
||||
type NoopClaimer struct{}
|
||||
|
||||
func (AGPLPrebuildClaimer) Claim(context.Context, uuid.UUID, string, uuid.UUID) (*uuid.UUID, error) {
|
||||
func (NoopClaimer) Claim(context.Context, uuid.UUID, string, uuid.UUID) (*uuid.UUID, error) {
|
||||
// Not entitled to claim prebuilds in AGPL version.
|
||||
return nil, ErrNoClaimablePrebuiltWorkspaces
|
||||
}
|
||||
|
||||
func (AGPLPrebuildClaimer) Initiator() uuid.UUID {
|
||||
func (NoopClaimer) Initiator() uuid.UUID {
|
||||
return uuid.Nil
|
||||
}
|
||||
|
||||
var DefaultClaimer Claimer = AGPLPrebuildClaimer{}
|
||||
var DefaultClaimer Claimer = NoopClaimer{}
|
||||
|
Reference in New Issue
Block a user