From db48e06c5d19899fd7d1bea813a60e3daae6c953 Mon Sep 17 00:00:00 2001 From: Gianluca Mardente Date: Thu, 20 Aug 2026 18:54:07 +0200 Subject: [PATCH] bug: RemoteURL polling interval blocks drift-detection reconciliation When a PolicyRef or KustomizationRef uses `RemoteURL` with an `Interval`, a successful reconcile schedules a periodic re-fetch by both returning `reconcile.Result{RequeueAfter: interval}` and setting NextReconcileTime in the ClusterSummary Status. The latter suppresses *every* reconcile of that ClusterSummary until the cooldown expires. A drift-detection-triggered reconcile only resets FeatureSummary status and that reconciliation is skipped till we are past NextReconcileTime. So with `SyncMode: ContinuousWithDriftDetection` and a RemoteURL interval of 10 minutes for instance, a configuration drift would not be recovered till we are past NextReconcileTime. The `setNextReconcileTime` call was incorrect. When RemoteURL is used, only a new reconciliation needs to be scheduled (to check whether the content of the remote URL has changed). This PR fixes this issue by not setting the NextReconcileTime in this specific scenario. test/fv/remote_url_test.go now uses `ContinuousWithDriftDetection` and deletes a deployed resource mid-test to verify Sveltos redeploys it promptly, rather than only exercising `Continuous` sync mode. --- controllers/clustersummary_controller.go | 1 - test/fv/remote_url_test.go | 21 +++++++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/controllers/clustersummary_controller.go b/controllers/clustersummary_controller.go index c5772ab8..66fd782c 100644 --- a/controllers/clustersummary_controller.go +++ b/controllers/clustersummary_controller.go @@ -668,7 +668,6 @@ func (r *ClusterSummaryReconciler) proceedDeployingClusterSummary(ctx context.Co interval = kustomizeRefInterval } if interval > 0 { - r.setNextReconcileTime(clusterSummaryScope, interval) return reconcile.Result{RequeueAfter: interval}, nil } diff --git a/test/fv/remote_url_test.go b/test/fv/remote_url_test.go index 0df65ce3..ee29d8c3 100644 --- a/test/fv/remote_url_test.go +++ b/test/fv/remote_url_test.go @@ -46,12 +46,10 @@ var _ = Describe("Remote URL", func() { saName = "metrics-server" ) - // Extra Labels/Annotations are deprecated. Not supported in pull mode - // Do not run in PullMode. ExtraLabels/ExtraAnnotations are deprecated. So not implemented in pull mode. - It("Deploy the content of a remote URL", Label("FV", "EXTENDED"), func() { + It("Deploy the content of a remote URL", Label("FV", "PULLMODE", "EXTENDED"), func() { Byf("Create a ClusterProfile matching Cluster %s/%s", kindWorkloadCluster.GetNamespace(), kindWorkloadCluster.GetName()) clusterProfile := getClusterProfile(namePrefix, map[string]string{key: value}) - clusterProfile.Spec.SyncMode = configv1beta1.SyncModeContinuous + clusterProfile.Spec.SyncMode = configv1beta1.SyncModeContinuousWithDriftDetection Expect(k8sClient.Create(context.TODO(), clusterProfile)).To(Succeed()) verifyClusterProfileMatches(clusterProfile) @@ -125,6 +123,21 @@ var _ = Describe("Remote URL", func() { clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, libsveltosv1beta1.FeatureResources, policies, nil) + verifyDriftDetectionManagerDeployment(workloadClient) + + Byf("Deleting metric-server ServiceAccount %s/%s from the workload cluster", saNamespace, saName) + currentServiceAccount := &corev1.ServiceAccount{} + Expect(workloadClient.Get(context.TODO(), + types.NamespacedName{Namespace: saNamespace, Name: saName}, currentServiceAccount)).To(Succeed()) + Expect(workloadClient.Delete(context.TODO(), currentServiceAccount)).To(Succeed()) + + Byf("Verifying Sveltos redeploys metric-server ServiceAccount %s/%s after it is deleted", saNamespace, saName) + Eventually(func() error { + return workloadClient.Get(context.TODO(), + types.NamespacedName{Namespace: saNamespace, Name: saName}, + &corev1.ServiceAccount{}) + }, timeout, pollingInterval).Should(BeNil()) + Byf("Update ClusterProfile %s to not reference Remote URL", clusterProfile.Name) err = retry.RetryOnConflict(retry.DefaultRetry, func() error { Expect(k8sClient.Get(context.TODO(),