From 745c45c7794822ef075ba01ba77226da002be5f7 Mon Sep 17 00:00:00 2001 From: Matheus Pimenta Date: Wed, 15 Apr 2026 13:10:50 +0100 Subject: [PATCH] Introduce support for migrating API version Signed-off-by: Matheus Pimenta (cherry picked from commit b57e8230322bca334e2aa768296aa9a26f71ee13) --- internal/controller/kustomization_controller.go | 2 ++ internal/features/features.go | 15 +++++++++++++++ main.go | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/internal/controller/kustomization_controller.go b/internal/controller/kustomization_controller.go index 0714b32c..7b64dce4 100644 --- a/internal/controller/kustomization_controller.go +++ b/internal/controller/kustomization_controller.go @@ -120,6 +120,7 @@ type KustomizationReconciler struct { DirectSourceFetch bool FailFast bool GroupChangeLog bool + MigrateAPIVersion bool StrictSubstitutions bool } @@ -867,6 +868,7 @@ func (r *KustomizationReconciler) apply(ctx context.Context, fmt.Sprintf("%s/force", kustomizev1.GroupVersion.Group): kustomizev1.EnabledValue, } applyOpts.CustomStageKinds = r.CustomStageKinds + applyOpts.MigrateAPIVersion = r.MigrateAPIVersion fieldManagers := []ssa.FieldManager{ { diff --git a/internal/features/features.go b/internal/features/features.go index 56dee2e7..a1f7a5c1 100644 --- a/internal/features/features.go +++ b/internal/features/features.go @@ -55,6 +55,18 @@ const ( // immediate processing of the new revision. This can help avoid getting // stuck on failing deployments when fixes are available. CancelHealthCheckOnNewRevision = "CancelHealthCheckOnNewRevision" + + // MigrateAPIVersion controls whether the controller migrates the API + // version referenced by the managed fields entries of in-cluster objects + // to the API version of the applied objects when they differ. + // + // This works around a server-side apply dry-run failure that can occur + // after a CRD upgrade introduces a new optional field with a default + // value in a newer API version: the managed fields entry owned by the + // controller still references the old API version, and the API server + // reports the defaulted field as "field not declared in schema" when + // validating managed fields against the old version's schema. + MigrateAPIVersion = "MigrateAPIVersion" ) var features = map[string]bool{ @@ -88,6 +100,9 @@ var features = map[string]bool{ // DirectSourceFetch // opt-in from v1.8 controller.FeatureGateDirectSourceFetch: false, + // MigrateAPIVersion + // opt-in from v1.8.4 + MigrateAPIVersion: false, } func init() { diff --git a/main.go b/main.go index 2ea7f5ac..85310f13 100644 --- a/main.go +++ b/main.go @@ -303,6 +303,12 @@ func main() { os.Exit(1) } + migrateAPIVersion, err := features.Enabled(features.MigrateAPIVersion) + if err != nil { + setupLog.Error(err, "unable to check feature gate "+features.MigrateAPIVersion) + os.Exit(1) + } + var tokenCache *pkgcache.TokenCache if tokenCacheOptions.MaxSize > 0 { var err error @@ -357,6 +363,7 @@ func main() { KubeConfigOpts: kubeConfigOpts, Mapper: restMapper, Metrics: metricsH, + MigrateAPIVersion: migrateAPIVersion, NoCrossNamespaceRefs: aclOptions.NoCrossNamespaceRefs, NoRemoteBases: noRemoteBases, SOPSAgeSecret: sopsAgeSecret,