This repository was archived by the owner on Aug 5, 2026. It is now read-only.
fix(dynamic): invalidate discovery cache on CustomResourceDefinition events - #2
Merged
Merged
Conversation
…events The RESTMapper is a DeferredDiscoveryRESTMapper backed by a MemCache discovery client, built once at startup and never refreshed. CRDs (or new CRD versions) registered after the cache warms are therefore invisible to RESTMapping/IsNamespaced — and, for the installer umbrella, to the `inst.crdExists` Pass-B gate — until the controller is restarted. This is the stale-CRD-discovery-cache class that forces a manual cdc restart on every umbrella version bump / component CRD roll. Add WatchCRDsAndInvalidate: a dynamic informer on CustomResourceDefinition that calls mapper.Reset() on add/update/delete (debounced/coalesced, and skipping resync no-ops). Reset() invalidates the MemCache and drops the delegate, so the next lookup re-discovers from the live cluster — no restart needed. Wired into main after the mapper is built; non-fatal so the controller still runs (IsNamespaced keeps its reactive reset). Complements krateoplatformops#183 (reactive Reset on IsNamespaced miss) with a proactive refresh that also covers the render-time crdExists lookup. Note: the cdc ServiceAccount needs get;list;watch on customresourcedefinitions.apiextensions.k8s.io (already required for the crdExists lookup). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndow Self-review follow-ups: - WaitForCacheSync + log so a missing/denied CRD watch (RBAC) is visible instead of silently degrading to the reactive-only reset. - Add a startup Info log confirming the watch is active. - Rename crdInvalidateDebounce -> crdInvalidateWindow and correct the comment: it is a fixed coalescing window from the first event (a throttle that bounds staleness), not an extending debounce. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The composition-dynamic-controller renders compositions using a
DeferredDiscoveryRESTMapperbacked by a MemCache discovery client (internal/tools/dynamic/dynamic.go). It is built once at startup and never refreshed, and there is no CRD watch to invalidate it.So any CRD — or a new version of an existing CRD — registered after the cache warms is invisible to
RESTMapping/IsNamespaced, and (for the Krateo installer umbrella) to theinst.crdExistsPass-B gate: those Compositions silently never emit, even though the CompositionDefinitions are Ready and a server-side dry-run of the same chart renders them fine. The only workaround today is a manual controller restart on every umbrella version bump / component-CRD roll.Change
Add
WatchCRDsAndInvalidate(crdwatch.go): a dynamic informer onCustomResourceDefinitionthat callsmapper.Reset()on add/update/delete.Reset()(client-go v0.35.3) invalidates the MemCache and drops the delegate, so the next lookup re-discovers from the live cluster.resourceVersion).mainright after the mapper is built; non-fatal — if the watch can’t start, the controller still runs andIsNamespacedkeeps its reactive reset.Complements krateoplatformops#183 (reactive
Reset()on anIsNamespacedmiss) with a proactive refresh that also covers the render-timecrdExistslookup, removing the manual-restart nudge.Tests
go build ./...,go vet, andgo test ./internal/tools/dynamic/pass; addedTestWatchCRDsAndInvalidate_NoResetIsNoopfor the static-mapper no-op branch.RBAC
The cdc ServiceAccount needs
get;list;watchoncustomresourcedefinitions.apiextensions.k8s.io(already required for thecrdExistslookup).🤖 Generated with Claude Code