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

Commit81da6be

Browse files
committed
Improvements & tests
Signed-off-by: Danny Kopping <dannykopping@gmail.com>
1 parent72b6c42 commit81da6be

File tree

8 files changed

+134
-59
lines changed

8 files changed

+134
-59
lines changed

‎cli/testdata/server-config.yaml.golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -693,10 +693,11 @@ workspace_prebuilds:
693693
# How often to reconcile workspace prebuilds state.
694694
# (default: 15s, type: duration)
695695
reconciliation_interval: 15s
696-
# Interval to increase reconciliation backoff by when unrecoverable errors occur.
696+
# Interval to increase reconciliation backoff by when prebuilds fail, after which
697+
# a retry attempt is made.
697698
# (default: 15s, type: duration)
698699
reconciliation_backoff_interval: 15s
699-
# Interval to look back to determine number of failedbuilds, which influences
700+
# Interval to look back to determine number of failedprebuilds, which influences
700701
# backoff.
701702
# (default: 1h0m0s, type: duration)
702703
reconciliation_backoff_lookback_period: 1h0m0s

‎coderd/coderd.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ func New(options *Options) *API {
597597
api.AppearanceFetcher.Store(&f)
598598
api.PortSharer.Store(&portsharing.DefaultPortSharer)
599599
api.PrebuildsClaimer.Store(&prebuilds.DefaultClaimer)
600+
api.PrebuildsReconciler.Store(&prebuilds.DefaultReconciler)
600601
buildInfo:= codersdk.BuildInfoResponse{
601602
ExternalURL:buildinfo.ExternalURL(),
602603
Version:buildinfo.Version(),
@@ -1568,10 +1569,11 @@ type API struct {
15681569
DERPMapper atomic.Pointer[func(derpMap*tailcfg.DERPMap)*tailcfg.DERPMap]
15691570
// AccessControlStore is a pointer to an atomic pointer since it is
15701571
// passed to dbauthz.
1571-
AccessControlStore*atomic.Pointer[dbauthz.AccessControlStore]
1572-
PortSharer atomic.Pointer[portsharing.PortSharer]
1573-
FileCache files.Cache
1574-
PrebuildsClaimer atomic.Pointer[prebuilds.Claimer]
1572+
AccessControlStore*atomic.Pointer[dbauthz.AccessControlStore]
1573+
PortSharer atomic.Pointer[portsharing.PortSharer]
1574+
FileCache files.Cache
1575+
PrebuildsClaimer atomic.Pointer[prebuilds.Claimer]
1576+
PrebuildsReconciler atomic.Pointer[prebuilds.ReconciliationOrchestrator]
15751577

15761578
UpdatesProvider tailnet.WorkspaceUpdatesProvider
15771579

@@ -1659,6 +1661,13 @@ func (api *API) Close() error {
16591661
_=api.AppSigningKeyCache.Close()
16601662
_=api.AppEncryptionKeyCache.Close()
16611663
_=api.UpdatesProvider.Close()
1664+
1665+
ifcurrent:=api.PrebuildsReconciler.Load();current!=nil {
1666+
ctx,giveUp:=context.WithTimeoutCause(context.Background(),time.Second*30,xerrors.New("gave up waiting for reconciler to stop"))
1667+
defergiveUp()
1668+
(*current).Stop(ctx,nil)
1669+
}
1670+
16621671
returnnil
16631672
}
16641673

‎coderd/prebuilds/api.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ package prebuilds
22

33
import (
44
"context"
5-
"errors"
65

76
"github.com/google/uuid"
7+
"golang.org/x/xerrors"
88

99
"github.com/coder/coder/v2/coderd/database"
1010
)
1111

12-
varErrNoClaimablePrebuiltWorkspaces=errors.New("no claimable prebuilt workspaces found")
12+
varErrNoClaimablePrebuiltWorkspaces=xerrors.New("no claimable prebuilt workspaces found")
1313

1414
// ReconciliationOrchestrator manages the lifecycle of prebuild reconciliation.
1515
// It runs a continuous loop to check and reconcile prebuild states, and can be stopped gracefully.

‎coderd/prebuilds/noop.go

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,25 @@ import (
1010

1111
typeNoopReconcilerstruct{}
1212

13-
funcNewNoopReconciler()*NoopReconciler {
14-
return&NoopReconciler{}
15-
}
16-
17-
func (NoopReconciler)RunLoop(context.Context) {}
18-
19-
func (NoopReconciler)Stop(context.Context,error) {}
20-
21-
func (NoopReconciler)ReconcileAll(context.Context)error {
22-
returnnil
23-
}
24-
13+
func (NoopReconciler)RunLoop(context.Context) {}
14+
func (NoopReconciler)Stop(context.Context,error) {}
15+
func (NoopReconciler)ReconcileAll(context.Context)error {returnnil }
2516
func (NoopReconciler)SnapshotState(context.Context, database.Store) (*GlobalSnapshot,error) {
2617
return&GlobalSnapshot{},nil
2718
}
28-
29-
func (NoopReconciler)ReconcilePreset(context.Context,PresetSnapshot)error {
30-
returnnil
31-
}
32-
19+
func (NoopReconciler)ReconcilePreset(context.Context,PresetSnapshot)error {returnnil }
3320
func (NoopReconciler)CalculateActions(context.Context,PresetSnapshot) (*ReconciliationActions,error) {
3421
return&ReconciliationActions{},nil
3522
}
3623

37-
var_ReconciliationOrchestrator=NoopReconciler{}
24+
varDefaultReconcilerReconciliationOrchestrator=NoopReconciler{}
3825

39-
typeAGPLPrebuildClaimerstruct{}
26+
typeNoopClaimerstruct{}
4027

41-
func (cAGPLPrebuildClaimer)Claim(context.Context, database.Store, uuid.UUID,string, uuid.UUID) (*uuid.UUID,error) {
28+
func (NoopClaimer)Claim(context.Context, database.Store, uuid.UUID,string, uuid.UUID) (*uuid.UUID,error) {
4229
// Not entitled to claim prebuilds in AGPL version.
4330
returnnil,ErrNoClaimablePrebuiltWorkspaces
4431
}
32+
func (NoopClaimer)Initiator() uuid.UUID {returnuuid.Nil }
4533

46-
func (cAGPLPrebuildClaimer)Initiator() uuid.UUID {
47-
returnuuid.Nil
48-
}
49-
50-
varDefaultClaimerClaimer=AGPLPrebuildClaimer{}
34+
varDefaultClaimerClaimer=NoopClaimer{}

‎codersdk/deployment.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,8 @@ type DeploymentValues struct {
396396
TermsOfServiceURL serpent.String`json:"terms_of_service_url,omitempty" typescript:",notnull"`
397397
NotificationsNotificationsConfig`json:"notifications,omitempty" typescript:",notnull"`
398398
AdditionalCSPPolicy serpent.StringArray`json:"additional_csp_policy,omitempty" typescript:",notnull"`
399-
PrebuildsPrebuildsConfig`json:"workspace_prebuilds,omitempty" typescript:",notnull"`
400399
WorkspaceHostnameSuffix serpent.String`json:"workspace_hostname_suffix,omitempty" typescript:",notnull"`
400+
PrebuildsPrebuildsConfig`json:"workspace_prebuilds,omitempty" typescript:",notnull"`
401401

402402
Config serpent.YAMLConfigPath`json:"config,omitempty" typescript:",notnull"`
403403
WriteConfig serpent.Bool`json:"write_config,omitempty" typescript:",notnull"`
@@ -3038,6 +3038,9 @@ Write out the current server config as YAML to stdout.`,
30383038
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration,"true"),
30393039
Hidden:true,// Hidden because most operators should not need to modify this.
30403040
},
3041+
// Push notifications.
3042+
3043+
// Workspace Prebuilds Options
30413044
{
30423045
Name:"Reconciliation Interval",
30433046
Description:"How often to reconcile workspace prebuilds state.",
@@ -3051,7 +3054,7 @@ Write out the current server config as YAML to stdout.`,
30513054
},
30523055
{
30533056
Name:"Reconciliation Backoff Interval",
3054-
Description:"Interval to increase reconciliation backoff by whenunrecoverable errors occur.",
3057+
Description:"Interval to increase reconciliation backoff by whenprebuilds fail, after which a retry attempt is made.",
30553058
Flag:"workspace-prebuilds-reconciliation-backoff-interval",
30563059
Env:"CODER_WORKSPACE_PREBUILDS_RECONCILIATION_BACKOFF_INTERVAL",
30573060
Value:&c.Prebuilds.ReconciliationBackoffInterval,
@@ -3063,7 +3066,7 @@ Write out the current server config as YAML to stdout.`,
30633066
},
30643067
{
30653068
Name:"Reconciliation Backoff Lookback Period",
3066-
Description:"Interval to look back to determine number of failedbuilds, which influences backoff.",
3069+
Description:"Interval to look back to determine number of failedprebuilds, which influences backoff.",
30673070
Flag:"workspace-prebuilds-reconciliation-backoff-lookback-period",
30683071
Env:"CODER_WORKSPACE_PREBUILDS_RECONCILIATION_BACKOFF_LOOKBACK_PERIOD",
30693072
Value:&c.Prebuilds.ReconciliationBackoffLookback,
@@ -3073,7 +3076,6 @@ Write out the current server config as YAML to stdout.`,
30733076
Annotations: serpent.Annotations{}.Mark(annotationFormatDuration,"true"),
30743077
Hidden:true,
30753078
},
3076-
// Push notifications.
30773079
}
30783080

30793081
returnopts
@@ -3298,9 +3300,9 @@ const (
32983300
ExperimentAutoFillParametersExperiment="auto-fill-parameters"// This should not be taken out of experiments until we have redesigned the feature.
32993301
ExperimentNotificationsExperiment="notifications"// Sends notifications via SMTP and webhooks following certain events.
33003302
ExperimentWorkspaceUsageExperiment="workspace-usage"// Enables the new workspace usage tracking.
3301-
ExperimentWorkspacePrebuildsExperiment="workspace-prebuilds"// Enables the new workspace prebuilds feature.
33023303
ExperimentWebPushExperiment="web-push"// Enables web push notifications through the browser.
33033304
ExperimentDynamicParametersExperiment="dynamic-parameters"// Enables dynamic parameters when creating a workspace.
3305+
ExperimentWorkspacePrebuildsExperiment="workspace-prebuilds"// Enables the new workspace prebuilds feature.
33043306
)
33053307

33063308
// ExperimentsSafe should include all experiments that are safe for

‎enterprise/coderd/coderd.go

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -632,8 +632,6 @@ type API struct {
632632

633633
licenseMetricsCollector*license.MetricsCollector
634634
tailnetService*tailnet.ClientService
635-
636-
PrebuildsReconciler agplprebuilds.ReconciliationOrchestrator
637635
}
638636

639637
// writeEntitlementWarningsHeader writes the entitlement warnings to the response header
@@ -665,12 +663,6 @@ func (api *API) Close() error {
665663
api.Options.CheckInactiveUsersCancelFunc()
666664
}
667665

668-
ifapi.PrebuildsReconciler!=nil {
669-
ctx,giveUp:=context.WithTimeoutCause(context.Background(),time.Second*30,xerrors.New("gave up waiting for reconciler to stop"))
670-
defergiveUp()
671-
api.PrebuildsReconciler.Stop(ctx,xerrors.New("api closed"))// TODO: determine root cause (requires changes up the stack, though).
672-
}
673-
674666
returnapi.AGPL.Close()
675667
}
676668

@@ -873,15 +865,15 @@ func (api *API) updateEntitlements(ctx context.Context) error {
873865
api.AGPL.PortSharer.Store(&ps)
874866
}
875867

876-
ifinitial,changed,enabled:=featureChanged(codersdk.FeatureWorkspacePrebuilds);shouldUpdate(initial,changed,enabled)||api.PrebuildsReconciler==nil{
868+
ifinitial,changed,enabled:=featureChanged(codersdk.FeatureWorkspacePrebuilds);shouldUpdate(initial,changed,enabled) {
877869
reconciler,claimer:=api.setupPrebuilds(enabled)
878-
ifapi.PrebuildsReconciler!=nil {
870+
ifcurrent:=api.AGPL.PrebuildsReconciler.Load();current!=nil {
879871
stopCtx,giveUp:=context.WithTimeoutCause(context.Background(),time.Second*30,xerrors.New("gave up waiting for reconciler to stop"))
880872
defergiveUp()
881-
api.PrebuildsReconciler.Stop(stopCtx,xerrors.New("entitlements change"))
873+
(*current).Stop(stopCtx,xerrors.New("entitlements change"))
882874
}
883875

884-
api.PrebuildsReconciler=reconciler
876+
api.AGPL.PrebuildsReconciler.Store(&reconciler)
885877
goreconciler.RunLoop(context.Background())
886878

887879
api.AGPL.PrebuildsClaimer.Store(&claimer)
@@ -1156,17 +1148,17 @@ func (api *API) Authorize(r *http.Request, action policy.Action, object rbac.Obj
11561148
returnapi.AGPL.HTTPAuth.Authorize(r,action,object)
11571149
}
11581150

1159-
func (api*API)setupPrebuilds(entitledbool) (agplprebuilds.ReconciliationOrchestrator, agplprebuilds.Claimer) {
1160-
enabled:=api.AGPL.Experiments.Enabled(codersdk.ExperimentWorkspacePrebuilds)
1161-
if!enabled||!entitled {
1151+
// nolint:revive // featureEnabled is a legit control flag.
1152+
func (api*API)setupPrebuilds(featureEnabledbool) (agplprebuilds.ReconciliationOrchestrator, agplprebuilds.Claimer) {
1153+
experimentEnabled:=api.AGPL.Experiments.Enabled(codersdk.ExperimentWorkspacePrebuilds)
1154+
if!experimentEnabled||!featureEnabled {
11621155
api.Logger.Debug(context.Background(),"prebuilds not enabled",
1163-
slog.F("experiment_enabled",enabled),slog.F("entitled",entitled))
1156+
slog.F("experiment_enabled",experimentEnabled),slog.F("feature_enabled",featureEnabled))
11641157

1165-
returnagplprebuilds.NewNoopReconciler(),agplprebuilds.DefaultClaimer
1158+
returnagplprebuilds.DefaultReconciler,agplprebuilds.DefaultClaimer
11661159
}
11671160

11681161
reconciler:=prebuilds.NewStoreReconciler(api.Database,api.Pubsub,api.DeploymentValues.Prebuilds,
11691162
api.Logger.Named("prebuilds"),quartz.NewReal())
1170-
11711163
returnreconciler, prebuilds.EnterpriseClaimer{}
11721164
}

‎enterprise/coderd/coderd_test.go

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,15 @@ import (
2828
"github.com/coder/coder/v2/agent"
2929
"github.com/coder/coder/v2/agent/agenttest"
3030
"github.com/coder/coder/v2/coderd/httpapi"
31+
agplprebuilds"github.com/coder/coder/v2/coderd/prebuilds"
3132
"github.com/coder/coder/v2/coderd/rbac/policy"
3233
"github.com/coder/coder/v2/coderd/util/ptr"
34+
"github.com/coder/coder/v2/enterprise/coderd/prebuilds"
3335
"github.com/coder/coder/v2/tailnet/tailnettest"
3436

37+
"github.com/coder/retry"
38+
"github.com/coder/serpent"
39+
3540
agplaudit"github.com/coder/coder/v2/coderd/audit"
3641
"github.com/coder/coder/v2/coderd/coderdtest"
3742
"github.com/coder/coder/v2/coderd/database"
@@ -50,8 +55,6 @@ import (
5055
"github.com/coder/coder/v2/enterprise/dbcrypt"
5156
"github.com/coder/coder/v2/enterprise/replicasync"
5257
"github.com/coder/coder/v2/testutil"
53-
"github.com/coder/retry"
54-
"github.com/coder/serpent"
5558
)
5659

5760
funcTestMain(m*testing.M) {
@@ -253,6 +256,90 @@ func TestEntitlements_HeaderWarnings(t *testing.T) {
253256
})
254257
}
255258

259+
funcTestEntitlements_Prebuilds(t*testing.T) {
260+
t.Parallel()
261+
262+
cases:= []struct {
263+
namestring
264+
experimentEnabledbool
265+
featureEnabledbool
266+
expectedEnabledbool
267+
}{
268+
{
269+
name:"Fully enabled",
270+
featureEnabled:true,
271+
experimentEnabled:true,
272+
expectedEnabled:true,
273+
},
274+
{
275+
name:"Feature disabled",
276+
featureEnabled:false,
277+
experimentEnabled:true,
278+
expectedEnabled:false,
279+
},
280+
{
281+
name:"Experiment disabled",
282+
featureEnabled:true,
283+
experimentEnabled:false,
284+
expectedEnabled:false,
285+
},
286+
{
287+
name:"Fully disabled",
288+
featureEnabled:false,
289+
experimentEnabled:false,
290+
expectedEnabled:false,
291+
},
292+
}
293+
294+
for_,tc:=rangecases {
295+
tc:=tc
296+
297+
t.Run(tc.name,func(t*testing.T) {
298+
t.Parallel()
299+
300+
varprebuildsEntitledint64
301+
iftc.featureEnabled {
302+
prebuildsEntitled=1
303+
}
304+
305+
_,_,api,_:=coderdenttest.NewWithAPI(t,&coderdenttest.Options{
306+
Options:&coderdtest.Options{
307+
DeploymentValues:coderdtest.DeploymentValues(t,func(values*codersdk.DeploymentValues) {
308+
iftc.experimentEnabled {
309+
values.Experiments= serpent.StringArray{string(codersdk.ExperimentWorkspacePrebuilds)}
310+
}
311+
}),
312+
},
313+
314+
EntitlementsUpdateInterval:time.Second,
315+
LicenseOptions:&coderdenttest.LicenseOptions{
316+
Features: license.Features{
317+
codersdk.FeatureWorkspacePrebuilds:prebuildsEntitled,
318+
},
319+
},
320+
})
321+
322+
// The entitlements will need to refresh before the reconciler is set.
323+
require.Eventually(t,func()bool {
324+
returnapi.AGPL.PrebuildsReconciler.Load()!=nil
325+
},testutil.WaitSuperLong,testutil.IntervalFast)
326+
327+
reconciler:=api.AGPL.PrebuildsReconciler.Load()
328+
claimer:=api.AGPL.PrebuildsClaimer.Load()
329+
require.NotNil(t,reconciler)
330+
require.NotNil(t,claimer)
331+
332+
iftc.expectedEnabled {
333+
require.IsType(t,&prebuilds.StoreReconciler{},*reconciler)
334+
require.IsType(t, prebuilds.EnterpriseClaimer{},*claimer)
335+
}else {
336+
require.Equal(t,&agplprebuilds.DefaultReconciler,reconciler)
337+
require.Equal(t,&agplprebuilds.DefaultClaimer,claimer)
338+
}
339+
})
340+
}
341+
}
342+
256343
funcTestAuditLogging(t*testing.T) {
257344
t.Parallel()
258345
t.Run("Enabled",func(t*testing.T) {

‎site/src/api/typesGenerated.ts

Lines changed: 1 addition & 1 deletion
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