Skip to content

Commit 0d729fd

Browse files
mjudeikisclaude
andauthored
fix(infrastructure): require CachedResource virtual storage for templates (never CRD fallback) (#338)
Templates must be served via the CachedResource virtual storage so they project into tenant workspaces. The bootstrap previously fell back to CRD storage when the CachedResource identityHash wasn't ready — an empty per-tenant CRD, so tenants saw no templates. Now all three bootstrap paths (operator reconcile, init container, legacy single-binary serve) FAIL and retry when the identityHash is missing, only registering the APIExport templates schema once virtual storage is ready. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent e6c5e32 commit 0d729fd

3 files changed

Lines changed: 24 additions & 15 deletions

File tree

providers/infrastructure/controller_manager.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@ func startControllerManager(ctx context.Context, config *rest.Config) error {
6161
if err := install.CRDs(ctx, config); err != nil {
6262
return fmt.Errorf("install CRDs: %w", err)
6363
}
64-
// Legacy single-binary path: CachedResource + EndpointSlice
65-
// before APIExport so we can use virtual storage for templates.
66-
// IdentityHash wait is best-effort; fall back to CRD storage
67-
// when it times out so the binary still boots in stub-only mode.
64+
// Legacy single-binary path: CachedResource + EndpointSlice before
65+
// APIExport so templates use virtual storage. Templates MUST be served
66+
// via virtual storage (to project into tenant workspaces) — never fall
67+
// back to CRD storage; fail so a restart retries until the identityHash
68+
// is ready.
6869
if err := install.PlatformCachedResources(ctx, config); err != nil {
6970
return fmt.Errorf("install CachedResources: %w", err)
7071
}
@@ -73,8 +74,10 @@ func startControllerManager(ctx context.Context, config *rest.Config) error {
7374
}
7475
hash, err := install.WaitForCachedResourceIdentity(ctx, config)
7576
if err != nil {
76-
log.Printf("controller manager: WARNING %v — using CRD storage for templates", err)
77-
hash = ""
77+
return fmt.Errorf("CachedResource identityHash not ready (templates require virtual storage): %w", err)
78+
}
79+
if hash == "" {
80+
return fmt.Errorf("CachedResource identityHash empty (templates require virtual storage)")
7881
}
7982
if err := install.PlatformSchemaInAPIExport(ctx, config, hash); err != nil {
8083
return fmt.Errorf("register platform schemas on APIExport: %w", err)

providers/infrastructure/init_cmd.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,15 @@ func runInitCmd(ctx context.Context) error {
121121
}
122122

123123
log.Printf("init: waiting for CachedResource identityHash")
124+
// Templates MUST use the CachedResource virtual storage (so they project into
125+
// tenant workspaces). Never fall back to CRD storage — fail so the init
126+
// container retries until the identityHash is ready.
124127
templatesIdentityHash, err := install.WaitForCachedResourceIdentity(ctx, adminConfig)
125128
if err != nil {
126-
// Non-fatal: fall back to CRD storage so a single missing hash
127-
// doesn't block boot. Operators can re-run init once the
128-
// CachedResource catches up.
129-
log.Printf("init: WARNING %v — falling back to CRD storage for templates", err)
130-
templatesIdentityHash = ""
129+
return fmt.Errorf("CachedResource identityHash not ready (templates require virtual storage): %w", err)
130+
}
131+
if templatesIdentityHash == "" {
132+
return fmt.Errorf("CachedResource identityHash empty (templates require virtual storage)")
131133
}
132134

133135
log.Printf("init: registering platform schemas on APIExport (templates storage=%s)", storageLabel(templatesIdentityHash))

providers/infrastructure/operator/bootstrap.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,16 @@ func Bootstrap(ctx context.Context, providerCfg *rest.Config, opts BootstrapOpti
7676
return fmt.Errorf("install APIExportEndpointSlice: %w", err)
7777
}
7878

79+
// Templates MUST be served via the CachedResource virtual storage so they
80+
// project into tenant workspaces. Never fall back to CRD storage (which is an
81+
// empty per-tenant CRD — tenants would see no templates). Fail instead and
82+
// let the reconcile retry until the CachedResource identityHash is ready.
7983
hash, err := install.WaitForCachedResourceIdentity(ctx, providerCfg)
8084
if err != nil {
81-
// Non-fatal: fall back to CRD storage this pass; a later reconcile
82-
// upgrades to virtual storage once the identityHash settles.
83-
log.Info("CachedResource identityHash not ready; using CRD storage for templates this pass", "err", err.Error())
84-
hash = ""
85+
return fmt.Errorf("CachedResource identityHash not ready (templates require virtual storage): %w", err)
86+
}
87+
if hash == "" {
88+
return fmt.Errorf("CachedResource identityHash empty (templates require virtual storage)")
8589
}
8690
if err := install.PlatformSchemaInAPIExport(ctx, providerCfg, hash); err != nil {
8791
return fmt.Errorf("register APIExport schemas: %w", err)

0 commit comments

Comments
 (0)