Repository navigation
fix(webhook): tolerate ClusterCreationPolicy CRD not installed - #110
Merged
atbagan merged 1 commit intoMay 30, 2026
Merged
Conversation
atbagan
deleted the
fix/controller-tolerate-missing-clustercreationpolicy-crd
branch
May 30, 2026 15:02
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What this changes
Adds an
apimeta.IsNoMatchErrorguard around theClusterCreationPolicyListlisting inTenantClusterValidator.validatePolicy(internal/webhook/tenantcluster_webhook.go:677). When the CRD is not installed in the API server, the admission webhook now treats the situation identically to "no policies installed" (empty-list path) instead of returning an internal error that denies the request.Four lines of production code plus one focused test case that uses a controller-runtime interceptor to inject the exact
apimeta.NoKindMatchErrorthe apiserver returns when the CRD is missing.Why
The
ClusterCreationPolicyCRD shipped inbutler-api v0.21.0and is distributed to clusters via thebutler-crdsHelm chart. butler-controller PR #105 (the same PR that introduced this validation path) bumped tov0.21.0and started referencingClusterCreationPolicyListon everyTenantClusterCREATE and UPDATE admission. Thebutler-crdschart was never updated to ship the new CRD; the chart's templates directory has 20 CRD YAMLs andclustercreationpolicy-crd.yamlis not among them.The result on butler-beta on 2026-05-29: every Flux Kustomization reconcile dry-runs every
TenantClusterinclusters/butler-beta. Each dry-run hits this webhook. The webhook callsClient.List(ctx, &ClusterCreationPolicyList{}). The apiserver returnsno matches for kind "ClusterCreationPolicy". The webhook returns the wrapped error. The dry-run is denied. The entire Kustomization apply fails. This blockedbutler-server v0.17.0from rolling out via the standing IUA-driven image patch. Full investigation in.secrets/butler-beta-vtenantcluster-2026-05-29.md.The validation logic at line 683 already short-circuits when
len(policies.Items) == 0(no policies installed means no enforcement). This change makes "CRD not installed" share that same code path. The semantic is the same. The implementation now matches.Verification
CGO_ENABLED=0 go vet ./...clean.go test ./internal/webhook/...pass including the newTestTCWebhook_ValidatePolicy_CRDMissing_TreatedAsNoPolicies. Diff is 63 insertions across two files.The fix was reasoned about against butler-beta on 2026-05-29 but verified live only via the equivalent kubectl-apply-of-the-CRD short-term unblock; the defensive code path here was not exercised against a running cluster because rolling a new controller image through GitOps requires Flux to be unwedged first, and Flux is currently being unwedged by the direct CRD apply.
Dependencies and merge order
Do not merge until the companion
butler-chartsPR lands. The chart-side fix adds the missing CRD to thebutler-crdschart. Once the chart is in good shape, this controller fix lands as durability hardening for the next cluster that takes a new controller before the chart upgrade.The two PRs together close the missed-migration gap from both sides: the chart so the CRD ships, the controller so a future similar gap degrades gracefully instead of wedging admission.
Not in scope
butler-crdschart to include this CRD. That is the companionbutler-chartsPR.butler-crdschart for other out-of-sync CRDs. Worth doing as part of the chart fix; flagged there.