From c0ae6aa8ba8fc5546dc17acdfe8019ad57958922 Mon Sep 17 00:00:00 2001 From: Gianluca Mardente Date: Tue, 6 Oct 2026 11:18:44 +0200 Subject: [PATCH 1/2] fix: Management cluster stale pass only removes resources it deployed When a Resources feature is deployed, the addon-controller also runs a cleanup pass against the management cluster (isMgmtCluster=true, with its own service account) for every GroupVersionKind the ClusterSummary has deployed, even when the ClusterProfile has no deploymentType: Local reference. In v1.13.0 that pass only considered resources carrying the clustersummary annotation of this very ClusterSummary, and that annotation was set on Local deploys only, so it could never touch anything but what this ClusterSummary had deployed locally. Since v1.14.0 (#1892) the annotation became a protective signal for both passes: a resource is skipped only when it is annotated for a different ClusterSummary, and a resource with no annotation falls through to the profile ownership check. That is right for the managed cluster pass, which has to detect resources deployed before the annotation existed, but it loosened the management cluster pass. A resource in the management cluster owned by a (Cluster)Profile with the same name, but deployed by someone else, is now considered stale and deleted. This happens when the management cluster is itself managed by another Sveltos instance deploying the same profile, or after a self-managed cluster was removed. The delete is typically forbidden for the addon-controller (for instance a Namespace, a PersistentVolume or an EventTrigger), so the failure repeats forever and, because the cleanup returns on the first error, the managed cluster pass and the rest of the post-processing never run: the feature stays in Provisioning. The management cluster pass requires again the clustersummary annotation of this ClusterSummary, as in v1.13.0. The managed cluster pass is unchanged. Co-Authored-By: Claude Sonnet 5.5 --- controllers/handlers_utils.go | 18 ++++-- controllers/handlers_utils_test.go | 99 ++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 5 deletions(-) diff --git a/controllers/handlers_utils.go b/controllers/handlers_utils.go index 9b35d464..c87c7c08 100644 --- a/controllers/handlers_utils.go +++ b/controllers/handlers_utils.go @@ -1206,16 +1206,24 @@ func processDeployedGVKs(ctx context.Context, isMgmtCluster bool, remoteConfig * continue } - // Only rely on the clustersummary annotation as a protective signal: skip a - // resource here when it is explicitly annotated for a *different* ClusterSummary - // (relevant when this ClusterSummary's remote cluster is the self-managed - // management cluster, and another ClusterSummary deployed there via + // The management cluster pass only removes what this very ClusterSummary deployed + // there via deploymentType: Local, so the resource must carry the clustersummary + // annotation of this ClusterSummary. That annotation has always been set on Local + // deploys. A resource without it was not deployed locally by this ClusterSummary: + // for instance, the management cluster can itself be a managed cluster of another + // Sveltos instance, which deployed resources owned by a (Cluster)Profile with the + // very same name. Those must never be removed here. + // + // The managed cluster pass is lenient: the annotation is only a protective signal. + // Skip a resource here when it is explicitly annotated for a *different* + // ClusterSummary (relevant when this ClusterSummary's remote cluster is the + // self-managed management cluster, and another ClusterSummary deployed there via // deploymentType: Local). A resource missing the annotation entirely predates it // being set on every deploy, and must still fall through to the normal // canDelete/isResourceOwner checks below, or upgraded ClusterSummaries would never // detect their own pre-existing resources as stale again. var skipAnnotationKey, skipAnnotationValue string - if _, ok := r.GetAnnotations()[clusterSummaryAnnotation]; ok { + if _, ok := r.GetAnnotations()[clusterSummaryAnnotation]; ok || isMgmtCluster { skipAnnotationKey = clusterSummaryAnnotation skipAnnotationValue = ownClusterSummaryValue } diff --git a/controllers/handlers_utils_test.go b/controllers/handlers_utils_test.go index a50b6796..d4842e26 100644 --- a/controllers/handlers_utils_test.go +++ b/controllers/handlers_utils_test.go @@ -1365,6 +1365,105 @@ var _ = Describe("HandlersUtils", func() { }, timeout, pollingInterval).Should(BeTrue()) }) + It(`undeployStaleResources in the management cluster only removes resources annotated for this ClusterSummary`, func() { + // The management cluster can itself be a managed cluster of another Sveltos instance. That + // instance deployed resources owned by a (Cluster)Profile with the same name as the one this + // ClusterSummary belongs to, but without the clustersummary annotation (for instance deployed + // by a release that did not set it on managed cluster deploys). The management cluster pass + // (isMgmtCluster=true) must not consider those stale: this ClusterSummary never deployed them. + newClusterRole := func(annotations map[string]string) *rbacv1.ClusterRole { + annotations[deployer.ReferenceKindAnnotation] = string(libsveltosv1beta1.ConfigMapReferencedResourceKind) + annotations[deployer.ReferenceNamespaceAnnotation] = randomString() + annotations[deployer.ReferenceNameAnnotation] = randomString() + + return &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: randomString(), + Labels: map[string]string{ + deployer.ReasonLabel: string(libsveltosv1beta1.FeatureResources), + }, + Annotations: annotations, + }, + } + } + + // Deployed by this ClusterSummary via deploymentType: Local + ownClusterRole := newClusterRole(map[string]string{ + controllers.ClusterSummaryAnnotation: controllers.GetClusterSummaryAnnotationValue(clusterSummary), + controllers.DeploymentTypeAnnotation: string(configv1beta1.DeploymentTypeLocal), + }) + // Deployed by a different ClusterSummary + otherClusterRole := newClusterRole(map[string]string{ + controllers.ClusterSummaryAnnotation: randomString(), + }) + // No clustersummary annotation at all + unannotatedClusterRole := newClusterRole(map[string]string{}) + + clusterRoles := []*rbacv1.ClusterRole{ownClusterRole, otherClusterRole, unannotatedClusterRole} + for _, clusterRole := range clusterRoles { + Expect(testEnv.Create(context.TODO(), clusterRole)).To(Succeed()) + Expect(waitForObject(ctx, testEnv.Client, clusterRole)).To(Succeed()) + } + + currentClusterProfile := &configv1beta1.ClusterProfile{} + Expect(testEnv.Get(context.TODO(), + types.NamespacedName{Name: clusterProfile.Name}, + currentClusterProfile)).To(Succeed()) + for _, clusterRole := range clusterRoles { + addOwnerReference(context.TODO(), testEnv.Client, clusterRole, currentClusterProfile) + } + + currentClusterSummary := &configv1beta1.ClusterSummary{} + Expect(testEnv.Get(context.TODO(), + types.NamespacedName{Namespace: clusterSummary.Namespace, Name: clusterSummary.Name}, + currentClusterSummary)).To(Succeed()) + currentClusterSummary.Status.FeatureSummaries = []configv1beta1.FeatureSummary{ + { + FeatureID: libsveltosv1beta1.FeatureResources, + Status: libsveltosv1beta1.FeatureStatusProvisioned, + }, + } + currentClusterSummary.Status.DeployedGVKs = []libsveltosv1beta1.FeatureDeploymentInfo{ + { + FeatureID: libsveltosv1beta1.FeatureResources, + DeployedGroupVersionKind: []string{ + testClusterRoleKindV1, + }, + }, + } + Expect(testEnv.Status().Update(context.TODO(), currentClusterSummary)).To(Succeed()) + + deployedGKVs := controllers.GetDeployedGroupVersionKinds(currentClusterSummary, libsveltosv1beta1.FeatureResources) + Expect(deployedGKVs).ToNot(BeEmpty()) + + // None of the ClusterRoles is in currentPolicies (nil): all are candidates for deletion + // were it not for the clustersummary annotation scoping. + _, err := controllers.UndeployStaleResources(context.TODO(), true, testEnv.Config, testEnv.Client, + libsveltosv1beta1.FeatureResources, currentClusterSummary, deployedGKVs, nil, + textlogger.NewLogger(textlogger.NewConfig())) + Expect(err).To(BeNil()) + + // What this ClusterSummary deployed locally and is not referenced anymore is removed + Eventually(func() bool { + currentClusterRole := &rbacv1.ClusterRole{} + err = testEnv.Get(context.TODO(), types.NamespacedName{Name: ownClusterRole.Name}, currentClusterRole) + return err != nil && apierrors.IsNotFound(err) + }, timeout, pollingInterval).Should(BeTrue()) + + // Anything not annotated for this ClusterSummary is never touched + Consistently(func() error { + for _, clusterRole := range []*rbacv1.ClusterRole{otherClusterRole, unannotatedClusterRole} { + currentClusterRole := &rbacv1.ClusterRole{} + if err := testEnv.Get(context.TODO(), types.NamespacedName{Name: clusterRole.Name}, + currentClusterRole); err != nil { + + return err + } + } + return nil + }, timeout, pollingInterval).Should(BeNil()) + }) + It("addExtraLabels adds extra labels on unstructured", func() { u := &unstructured.Unstructured{} extraLabels := map[string]string{ From 9f4dbe20fadc72afcdca9cbf605d24ded15f5be6 Mon Sep 17 00:00:00 2001 From: Gianluca Mardente Date: Fri, 9 Oct 2026 15:21:30 +0200 Subject: [PATCH 2/2] chore: management cluster stale pass ignores resources from a parent Sveltos instance Adds a unit test for undeployStaleResources in the management cluster pass (isMgmtCluster=true). The management cluster can itself be a managed cluster of a parent Sveltos instance. The test creates a resource that looks like it was deployed by that parent: deploymenttype: Remote, another cluster's clustersummary value, and the same owner-kind/owner-name as the local ClusterProfile. It checks that the resource is not removed, while a resource this ClusterSummary deployed with deploymenttype: Local and its own clustersummary value is removed. This PR also advances cluster-api to v1.14.3 --- Makefile | 2 +- controllers/handlers_utils_test.go | 84 ++++++++++++++++++++++++++++++ go.mod | 16 +++--- go.sum | 32 ++++++------ 4 files changed, 109 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index fc536085..63b5eb17 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,7 @@ KUBECTL := $(TOOLS_BIN_DIR)/kubectl GOVULNCHECK_VERSION := "v1.1.4" GOLANGCI_LINT_VERSION := "v2.13.2" -CLUSTERCTL_VERSION := v1.14.2 +CLUSTERCTL_VERSION := v1.14.3 KIND_VERSION := v0.32.0 KUSTOMIZE_VER := v5.8.0 diff --git a/controllers/handlers_utils_test.go b/controllers/handlers_utils_test.go index d4842e26..3e8a79bd 100644 --- a/controllers/handlers_utils_test.go +++ b/controllers/handlers_utils_test.go @@ -1464,6 +1464,90 @@ var _ = Describe("HandlersUtils", func() { }, timeout, pollingInterval).Should(BeNil()) }) + It(`undeployStaleResources in the management cluster does not remove resources deployed by a parent Sveltos instance`, func() { + // The management cluster can itself be a managed cluster of a parent Sveltos instance. The parent + // instance deployed a resource in this cluster (so deploymenttype is Remote and clustersummary is + // the identity of this cluster as seen by the parent). The (Cluster)Profile in the parent has the + // same name as the one this ClusterSummary belongs to, so the owner annotations match as well. + // The management cluster pass (isMgmtCluster=true) must not consider that resource stale, even + // though it has the reason label and is not part of currentPolicies. + newClusterRole := func(clusterSummaryValue, deploymentType string) *rbacv1.ClusterRole { + return &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: randomString(), + Labels: map[string]string{ + deployer.ReasonLabel: string(libsveltosv1beta1.FeatureResources), + }, + Annotations: map[string]string{ + deployer.ReferenceKindAnnotation: string(libsveltosv1beta1.ConfigMapReferencedResourceKind), + deployer.ReferenceNamespaceAnnotation: randomString(), + deployer.ReferenceNameAnnotation: randomString(), + deployer.OwnerKind: configv1beta1.ClusterProfileKind, + deployer.OwnerName: clusterProfile.Name, + controllers.ClusterSummaryAnnotation: clusterSummaryValue, + controllers.DeploymentTypeAnnotation: deploymentType, + }, + }, + } + } + + // Deployed by this ClusterSummary via deploymentType: Local + ownClusterRole := newClusterRole(controllers.GetClusterSummaryAnnotationValue(clusterSummary), + string(configv1beta1.DeploymentTypeLocal)) + // Deployed by the parent Sveltos instance + parentClusterRole := newClusterRole(fmt.Sprintf("capi-%s-%s", randomString(), randomString()), + string(configv1beta1.DeploymentTypeRemote)) + + clusterRoles := []*rbacv1.ClusterRole{ownClusterRole, parentClusterRole} + for _, clusterRole := range clusterRoles { + Expect(testEnv.Create(context.TODO(), clusterRole)).To(Succeed()) + Expect(waitForObject(ctx, testEnv.Client, clusterRole)).To(Succeed()) + } + + currentClusterSummary := &configv1beta1.ClusterSummary{} + Expect(testEnv.Get(context.TODO(), + types.NamespacedName{Namespace: clusterSummary.Namespace, Name: clusterSummary.Name}, + currentClusterSummary)).To(Succeed()) + currentClusterSummary.Status.FeatureSummaries = []configv1beta1.FeatureSummary{ + { + FeatureID: libsveltosv1beta1.FeatureResources, + Status: libsveltosv1beta1.FeatureStatusProvisioned, + }, + } + currentClusterSummary.Status.DeployedGVKs = []libsveltosv1beta1.FeatureDeploymentInfo{ + { + FeatureID: libsveltosv1beta1.FeatureResources, + DeployedGroupVersionKind: []string{ + testClusterRoleKindV1, + }, + }, + } + Expect(testEnv.Status().Update(context.TODO(), currentClusterSummary)).To(Succeed()) + + deployedGKVs := controllers.GetDeployedGroupVersionKinds(currentClusterSummary, libsveltosv1beta1.FeatureResources) + Expect(deployedGKVs).ToNot(BeEmpty()) + + // Neither ClusterRole is in currentPolicies (nil): both are candidates for deletion + // were it not for the deploymenttype and clustersummary annotations scoping. + _, err := controllers.UndeployStaleResources(context.TODO(), true, testEnv.Config, testEnv.Client, + libsveltosv1beta1.FeatureResources, currentClusterSummary, deployedGKVs, nil, + textlogger.NewLogger(textlogger.NewConfig())) + Expect(err).To(BeNil()) + + // What this ClusterSummary deployed locally and is not referenced anymore is removed + Eventually(func() bool { + currentClusterRole := &rbacv1.ClusterRole{} + err = testEnv.Get(context.TODO(), types.NamespacedName{Name: ownClusterRole.Name}, currentClusterRole) + return err != nil && apierrors.IsNotFound(err) + }, timeout, pollingInterval).Should(BeTrue()) + + // What the parent Sveltos instance deployed is never touched + Consistently(func() error { + currentClusterRole := &rbacv1.ClusterRole{} + return testEnv.Get(context.TODO(), types.NamespacedName{Name: parentClusterRole.Name}, currentClusterRole) + }, timeout, pollingInterval).Should(BeNil()) + }) + It("addExtraLabels adds extra labels on unstructured", func() { u := &unstructured.Unstructured{} extraLabels := map[string]string{ diff --git a/go.mod b/go.mod index 54f79701..f961ffa0 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.5.0 github.com/TwiN/go-color v1.4.1 github.com/dariubs/percent v1.0.0 - github.com/docker/cli v29.8.2+incompatible + github.com/docker/cli v29.9.0+incompatible github.com/fluxcd/pkg/apis/meta v1.32.0 github.com/fluxcd/pkg/http/fetch v0.26.0 github.com/fluxcd/pkg/tar v1.2.0 @@ -21,7 +21,7 @@ require ( github.com/opencontainers/image-spec v1.1.1 github.com/pkg/errors v0.9.1 github.com/projectsveltos/libsveltos v1.16.1-0.20261007133830-d623a1556939 - github.com/prometheus/client_golang v1.24.1 + github.com/prometheus/client_golang v1.25.0 github.com/sigstore/cosign/v3 v3.1.3 github.com/sigstore/sigstore v1.11.0 github.com/spf13/pflag v1.0.10 @@ -37,8 +37,8 @@ require ( k8s.io/klog/v2 v2.140.0 k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 oras.land/oras-go/v2 v2.6.2 - sigs.k8s.io/cluster-api v1.14.2 - sigs.k8s.io/cluster-api/api v1.14.2 + sigs.k8s.io/cluster-api v1.14.3 + sigs.k8s.io/cluster-api/api v1.14.3 sigs.k8s.io/controller-runtime v0.25.2 sigs.k8s.io/kustomize/api v0.21.2 sigs.k8s.io/kustomize/kyaml v0.21.2 @@ -190,7 +190,7 @@ require ( github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect github.com/jmoiron/sqlx v1.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.19.2 // indirect + github.com/klauspost/compress v1.20.1 // indirect github.com/klauspost/cpuid/v2 v2.2.10 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect @@ -225,9 +225,9 @@ require ( github.com/projectsveltos/lua-utils/glua-runes v0.0.0-20251212200258-2b3cdcb7c0f5 // indirect github.com/projectsveltos/lua-utils/glua-sprig v0.0.0-20251212200258-2b3cdcb7c0f5 // indirect github.com/projectsveltos/lua-utils/glua-strings v0.0.0-20251212200258-2b3cdcb7c0f5 // indirect - github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.70.1 // indirect - github.com/prometheus/procfs v0.21.1 // indirect + github.com/prometheus/client_model v0.6.3 // indirect + github.com/prometheus/common v0.72.0 // indirect + github.com/prometheus/procfs v0.22.0 // indirect github.com/redis/go-redis/extra/redisotel/v9 v9.5.3 // indirect github.com/rubenv/sql-migrate v1.8.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect diff --git a/go.sum b/go.sum index d0aacd59..00d966cb 100644 --- a/go.sum +++ b/go.sum @@ -248,8 +248,8 @@ github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5Qvfr github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v29.8.2+incompatible h1:2zgdFuoFst2T80oS42vhKGxkd0JRo305eIEKTsxR7pQ= -github.com/docker/cli v29.8.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.9.0+incompatible h1:Cw9x50ioSGgGwXJ4eO+hIBry/w3LLbyF8GPAEKz1fnE= +github.com/docker/cli v29.9.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= @@ -532,8 +532,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU= github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k= -github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8= -github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= +github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE= github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -653,17 +653,17 @@ github.com/projectsveltos/lua-utils/glua-sprig v0.0.0-20251212200258-2b3cdcb7c0f github.com/projectsveltos/lua-utils/glua-sprig v0.0.0-20251212200258-2b3cdcb7c0f5/go.mod h1:esi+znTJzieo7M60Ytx56vJZbWJ8WuJfVyRvOCOWs64= github.com/projectsveltos/lua-utils/glua-strings v0.0.0-20251212200258-2b3cdcb7c0f5 h1:ifNj1y4pqhSSDL0B5XfCPTnFy9ZjGTzStuOJu1jE9xs= github.com/projectsveltos/lua-utils/glua-strings v0.0.0-20251212200258-2b3cdcb7c0f5/go.mod h1:P/l817Avvelnzyb9YyMmnDYG3OabOyK8KuWF8s35kj0= -github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= -github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= +github.com/prometheus/client_golang v1.25.0 h1:cDtW1TcFsMi1RJc8khwCKB4VhzwV04aKqbYtNOXuiK0= +github.com/prometheus/client_golang v1.25.0/go.mod h1:j2X/4/kaQHLPnmyEU8zjmkndo1T317VpCIQEml8LTKk= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= -github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= -github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= +github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= +github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= +github.com/prometheus/common v0.72.0 h1:tAYsE+sPJxIncDAobm4H5aQjmox9ZxEIIqPbiffa8G4= +github.com/prometheus/common v0.72.0/go.mod h1:77NWqAQ2tXT7BIK40qjJdw5Acrsrg1TlHAnsQi3i6mk= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= -github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= -github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= +github.com/prometheus/procfs v0.22.0 h1:6q9+/JL9IKAPbCmBrv9n5O5Ty3NKnciV5X7YGw0oics= +github.com/prometheus/procfs v0.22.0/go.mod h1:CvmFr/GVhIjIvWJZW3tgkODBQMRIf0EyWMQLHCHab58= github.com/redis/go-redis/extra/rediscmd/v9 v9.5.3 h1:1/BDligzCa40GTllkDnY3Y5DTHuKCONbB2JcRyIfl20= github.com/redis/go-redis/extra/rediscmd/v9 v9.5.3/go.mod h1:3dZmcLn3Qw6FLlWASn1g4y+YO9ycEFUOM+bhBmzLVKQ= github.com/redis/go-redis/extra/redisotel/v9 v9.5.3 h1:kuvuJL/+MZIEdvtb/kTBRiRgYaOmx1l+lYJyVdrRUOs= @@ -1111,10 +1111,10 @@ oras.land/oras-go/v2 v2.6.2 h1:N04RXngAp1LJKTG6ifz3xHPipasEkWr+hFmInja5YKo= oras.land/oras-go/v2 v2.6.2/go.mod h1:PlTtg4JTDJkDe8yVHpM2wz7/YDc00GVas+i4jAW2TZ4= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.36.0 h1:/YpDJ4vReG7ZmzSpBGxduXgywWkJU9zHubgJG03MT+Y= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.36.0/go.mod h1:tJo1aepTXyR+8Xs3sUsGBDk4Ub2AM5dPAPKJx0mpm5c= -sigs.k8s.io/cluster-api v1.14.2 h1:o3GFNaeNFAOEEMpDPfhCK+2CjmV6gtQ8yLEcUwCg7bA= -sigs.k8s.io/cluster-api v1.14.2/go.mod h1:QGMq7dEyUsceFGBLIrnPDVmX2J316yfY20Woq1S9GuU= -sigs.k8s.io/cluster-api/api v1.14.2 h1:B0XWZGFrb4+R1pH2nApdR9d4tcQGIhpEquRxxf36fHg= -sigs.k8s.io/cluster-api/api v1.14.2/go.mod h1:LJ/5hdS9tqTBi9YqyLRnd1t53Sn/cXsa7rEVaY0bBms= +sigs.k8s.io/cluster-api v1.14.3 h1:xc2krMm7SfUV7/sVo3XcHwNz33fkYupy+iSD/W/TA/Q= +sigs.k8s.io/cluster-api v1.14.3/go.mod h1:NB3GmqTA/hlMaGDv01gt36/5k0DJ+ixGTJFHUe5Ib3Q= +sigs.k8s.io/cluster-api/api v1.14.3 h1:lTjHLULtlJHRXvroECdeiM2fXZOsvu93y+LYRjm/5II= +sigs.k8s.io/cluster-api/api v1.14.3/go.mod h1:LJ/5hdS9tqTBi9YqyLRnd1t53Sn/cXsa7rEVaY0bBms= sigs.k8s.io/controller-runtime v0.25.2 h1:bEkK3PVOIVK9X8QWLGVhJgmFc++47vfT6wakSzAOLsQ= sigs.k8s.io/controller-runtime v0.25.2/go.mod h1:4QqLdT6z/L6Olj8JJCtvztid4/fnIiYsfaTFScegctc= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=