From 28424eb3127852a16d9244ef097e688ecd10c966 Mon Sep 17 00:00:00 2001 From: AlinsRan Date: Thu, 20 Aug 2026 15:33:55 +0800 Subject: [PATCH] fix: do not warn about managed clusters that meet the minimum Kubernetes version Managed distributions report a version like v1.31.0-eks-a737599 or v1.31.0-gke.1000000. ParseSemantic reads the vendor tag as a prerelease and semver sorts a prerelease below the same release, so a cluster running exactly the minimum was reported as not meeting it. Compare against the release components unless the suffix is a real prerelease (alpha/beta/rc), which still sorts below the release it precedes. Signed-off-by: AlinsRan --- internal/manager/run.go | 23 +++++++++++ internal/manager/run_version_test.go | 59 ++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 internal/manager/run_version_test.go diff --git a/internal/manager/run.go b/internal/manager/run.go index fb245b6a..4d3d7464 100644 --- a/internal/manager/run.go +++ b/internal/manager/run.go @@ -20,7 +20,9 @@ package manager import ( "context" "crypto/tls" + "fmt" "os" + "strings" "github.com/go-logr/logr" networkingv1beta1 "k8s.io/api/networking/v1beta1" @@ -333,6 +335,7 @@ func checkK8sVersion(mgr ctrl.Manager, logger logr.Logger) { logger.Info("failed to parse server version", "error", err) return } + currentVersion = releaseVersion(currentVersion) if !currentVersion.AtLeast(minV) { logger.Info("WARNING: Kubernetes cluster version does not meet minimum requirement", @@ -341,3 +344,23 @@ func checkK8sVersion(mgr ctrl.Manager, logger logr.Logger) { ) } } + +// releaseVersion drops a distribution suffix so it does not read as a +// prerelease. Managed clusters report versions like v1.31.0-eks-a737599 or +// v1.32.1-gke.1000000, and semver sorts a prerelease below the same release, +// so an EKS cluster running exactly the minimum would otherwise be reported as +// too old. Only alpha/beta/rc are real prereleases; anything else is a vendor +// tag and does not make the cluster older than its release. +func releaseVersion(v *version.Version) *version.Version { + pre := v.PreRelease() + if pre == "" { + return v + } + for _, prefix := range []string{"alpha", "beta", "rc"} { + if strings.HasPrefix(pre, prefix) { + return v + } + } + // WithPreRelease("") is a no-op, so rebuild from the release components. + return version.MustParseSemantic(fmt.Sprintf("%d.%d.%d", v.Major(), v.Minor(), v.Patch())) +} diff --git a/internal/manager/run_version_test.go b/internal/manager/run_version_test.go new file mode 100644 index 00000000..26d25a34 --- /dev/null +++ b/internal/manager/run_version_test.go @@ -0,0 +1,59 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package manager + +import ( + "testing" + + "k8s.io/apimachinery/pkg/util/version" +) + +func TestReleaseVersionAtLeast(t *testing.T) { + minV := version.MustParseSemantic("1.31.0") + + for _, tc := range []struct { + gitVersion string + wantAtLeast bool + }{ + // Managed distributions tag the release; that is not a prerelease. + {"v1.31.0-eks-a737599", true}, + {"v1.31.0-gke.1000000", true}, + {"v1.31.0+rke2r1", true}, + {"v1.30.5-eks-a737599", false}, + + // Real prereleases of the minimum still sort below it. + {"v1.31.0-alpha.1", false}, + {"v1.31.0-beta.0", false}, + {"v1.31.0-rc.1", false}, + + {"v1.31.0", true}, + {"v1.32.1", true}, + {"v1.30.0", false}, + } { + t.Run(tc.gitVersion, func(t *testing.T) { + parsed, err := version.ParseSemantic(tc.gitVersion) + if err != nil { + t.Fatalf("parsing %q: %v", tc.gitVersion, err) + } + if got := releaseVersion(parsed).AtLeast(minV); got != tc.wantAtLeast { + t.Errorf("releaseVersion(%q).AtLeast(%s) = %v, want %v", + tc.gitVersion, minV, got, tc.wantAtLeast) + } + }) + } +}