From 84231e573fe34fe9116a5a109829193e6e531be6 Mon Sep 17 00:00:00 2001 From: "Y@&h" <121890726+yp969803@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:15:33 +0530 Subject: [PATCH] add finalizer syncer for Thanos Ruler (#8060) --- pkg/thanos/operator.go | 30 ++++++++++++++--- test/e2e/main_test.go | 51 +++++++++++++++-------------- test/e2e/status_subresource_test.go | 34 +++++++++++++++++++ test/framework/prometheus_rule.go | 2 +- 4 files changed, 86 insertions(+), 31 deletions(-) diff --git a/pkg/thanos/operator.go b/pkg/thanos/operator.go index eb63cb806..cd0f42f8c 100644 --- a/pkg/thanos/operator.go +++ b/pkg/thanos/operator.go @@ -89,6 +89,8 @@ type Operator struct { config Config configResourcesStatusEnabled bool + + finalizerSyncer *operator.FinalizerSyncer } // Config defines the operator's parameters for the Thanos controller. @@ -159,11 +161,16 @@ func New(ctx context.Context, restConfig *rest.Config, c operator.Config, logger Labels: c.Labels, LocalHost: c.LocalHost, }, + finalizerSyncer: operator.NewNoopFinalizerSyncer(), } for _, opt := range options { opt(o) } + if o.configResourcesStatusEnabled { + o.finalizerSyncer = operator.NewFinalizerSyncer(mdClient, monitoringv1.SchemeGroupVersion.WithResource(monitoringv1.ThanosRulerName)) + } + o.cmapInfs, err = informers.NewInformersForResource( informers.NewMetadataInformerFactory( c.Namespaces.ThanosRulerAllowList, @@ -476,16 +483,29 @@ func (o *Operator) sync(ctx context.Context, key string) error { return nil } - // Check if the Thanos instance is marked for deletion. - if o.rr.DeletionInProgress(tr) { - return nil - } - if tr.Spec.Paused { return nil } logger := o.logger.With("key", key) + + finalizerAdded, err := o.finalizerSyncer.Sync(ctx, tr, o.rr.DeletionInProgress(tr), func() error { return nil }) + if err != nil { + return err + } + + if finalizerAdded { + // Since the object has been updated, let's trigger another sync. + o.rr.EnqueueForReconciliation(tr) + return nil + } + + // Check if the Thanos instance is marked for deletion. + if o.rr.DeletionInProgress(tr) { + o.reconciliations.ForgetObject(key) + return nil + } + logger.Info("sync thanos-ruler") if err := operator.CheckStorageClass(ctx, o.canReadStorageClass, o.kclient, tr.Spec.Storage); err != nil { diff --git a/test/e2e/main_test.go b/test/e2e/main_test.go index 130c788db..670af6b32 100644 --- a/test/e2e/main_test.go +++ b/test/e2e/main_test.go @@ -428,31 +428,32 @@ const ( func TestGatedFeatures(t *testing.T) { skipFeatureGatedTests(t) testFuncs := map[string]func(t *testing.T){ - "CreatePrometheusAgentDaemonSet": testCreatePrometheusAgentDaemonSet, - "PromAgentDaemonSetResourceUpdate": testPromAgentDaemonSetResourceUpdate, - "PromAgentReconcileDaemonSetResourceUpdate": testPromAgentReconcileDaemonSetResourceUpdate, - "PromAgentReconcileDaemonSetResourceDelete": testPromAgentReconcileDaemonSetResourceDelete, - "PrometheusAgentDaemonSetSelectPodMonitor": testPrometheusAgentDaemonSetSelectPodMonitor, - "PrometheusRetentionPolicies": testPrometheusRetentionPolicies, - "FinalizerWhenStatusForConfigResourcesEnabled": testFinalizerWhenStatusForConfigResourcesEnabled, - "PrometheusAgentDaemonSetCELValidations": testPrometheusAgentDaemonSetCELValidations, - "ServiceMonitorStatusSubresource": testServiceMonitorStatusSubresource, - "ServiceMonitorStatusWithMultipleWorkloads": testServiceMonitorStatusWithMultipleWorkloads, - "GarbageCollectionOfServiceMonitorBinding": testGarbageCollectionOfServiceMonitorBinding, - "RmServiceMonitorBindingDuringWorkloadDelete": testRmServiceMonitorBindingDuringWorkloadDelete, - "PodMonitorStatusSubresource": testPodMonitorStatusSubresource, - "GarbageCollectionOfPodMonitorBinding": testGarbageCollectionOfPodMonitorBinding, - "RmPodMonitorBindingDuringWorkloadDelete": testRmPodMonitorBindingDuringWorkloadDelete, - "ProbeStatusSubresource": testProbeStatusSubresource, - "GarbageCollectionOfProbeBinding": testGarbageCollectionOfProbeBinding, - "RmProbeBindingDuringWorkloadDelete": testRmProbeBindingDuringWorkloadDelete, - "ScrapeConfigStatusSubresource": testScrapeConfigStatusSubresource, - "GarbageCollectionOfScrapeConfigBinding": testGarbageCollectionOfScrapeConfigBinding, - "RmScrapeConfigBindingDuringWorkloadDelete": testRmScrapeConfigBindingDuringWorkloadDelete, - "PrometheusRuleStatusSubresource": testPrometheusRuleStatusSubresource, - "FinalizerForPromAgentWhenStatusForConfigResEnabled": testFinalizerForPromAgentWhenStatusForConfigResEnabled, - "GarbageCollectionOfPrometheusRuleBinding": testGarbageCollectionOfPrometheusRuleBinding, - "RmPrometheusRuleBindingDuringWorkloadDelete": testRmPrometheusRuleBindingDuringWorkloadDelete, + "CreatePrometheusAgentDaemonSet": testCreatePrometheusAgentDaemonSet, + "PromAgentDaemonSetResourceUpdate": testPromAgentDaemonSetResourceUpdate, + "PromAgentReconcileDaemonSetResourceUpdate": testPromAgentReconcileDaemonSetResourceUpdate, + "PromAgentReconcileDaemonSetResourceDelete": testPromAgentReconcileDaemonSetResourceDelete, + "PrometheusAgentDaemonSetSelectPodMonitor": testPrometheusAgentDaemonSetSelectPodMonitor, + "PrometheusRetentionPolicies": testPrometheusRetentionPolicies, + "FinalizerWhenStatusForConfigResourcesEnabled": testFinalizerWhenStatusForConfigResourcesEnabled, + "PrometheusAgentDaemonSetCELValidations": testPrometheusAgentDaemonSetCELValidations, + "ServiceMonitorStatusSubresource": testServiceMonitorStatusSubresource, + "ServiceMonitorStatusWithMultipleWorkloads": testServiceMonitorStatusWithMultipleWorkloads, + "GarbageCollectionOfServiceMonitorBinding": testGarbageCollectionOfServiceMonitorBinding, + "RmServiceMonitorBindingDuringWorkloadDelete": testRmServiceMonitorBindingDuringWorkloadDelete, + "PodMonitorStatusSubresource": testPodMonitorStatusSubresource, + "GarbageCollectionOfPodMonitorBinding": testGarbageCollectionOfPodMonitorBinding, + "RmPodMonitorBindingDuringWorkloadDelete": testRmPodMonitorBindingDuringWorkloadDelete, + "ProbeStatusSubresource": testProbeStatusSubresource, + "GarbageCollectionOfProbeBinding": testGarbageCollectionOfProbeBinding, + "RmProbeBindingDuringWorkloadDelete": testRmProbeBindingDuringWorkloadDelete, + "ScrapeConfigStatusSubresource": testScrapeConfigStatusSubresource, + "GarbageCollectionOfScrapeConfigBinding": testGarbageCollectionOfScrapeConfigBinding, + "RmScrapeConfigBindingDuringWorkloadDelete": testRmScrapeConfigBindingDuringWorkloadDelete, + "PrometheusRuleStatusSubresource": testPrometheusRuleStatusSubresource, + "FinalizerForPromAgentWhenStatusForConfigResEnabled": testFinalizerForPromAgentWhenStatusForConfigResEnabled, + "GarbageCollectionOfPrometheusRuleBinding": testGarbageCollectionOfPrometheusRuleBinding, + "RmPrometheusRuleBindingDuringWorkloadDelete": testRmPrometheusRuleBindingDuringWorkloadDelete, + "FinalizerForThanosRulerWhenStatusForConfigResEnabled": testFinalizerForThanosRulerWhenStatusForConfigResEnabled, } for name, f := range testFuncs { diff --git a/test/e2e/status_subresource_test.go b/test/e2e/status_subresource_test.go index d52333722..478dc3a2f 100644 --- a/test/e2e/status_subresource_test.go +++ b/test/e2e/status_subresource_test.go @@ -1053,3 +1053,37 @@ func testRmPrometheusRuleBindingDuringWorkloadDelete(t *testing.T) { _, err = framework.WaitForRuleWorkloadBindingCleanup(ctx, pr1, p, monitoringv1.PrometheusName, 1*time.Minute) require.NoError(t, err) } + +// testFinalizerForThanosRulerWhenStatusForConfigResEnabled tests the adding/removing of status-cleanup finalizer for ThanosRuler when StatusForConfigurationResourcesFeature is enabled. +func testFinalizerForThanosRulerWhenStatusForConfigResEnabled(t *testing.T) { + t.Parallel() + ctx := context.Background() + testCtx := framework.NewTestCtx(t) + defer testCtx.Cleanup(t) + + ns := framework.CreateNamespace(ctx, t, testCtx) + framework.SetupPrometheusRBAC(ctx, t, testCtx, ns) + _, err := framework.CreateOrUpdatePrometheusOperatorWithOpts( + ctx, testFramework.PrometheusOperatorOpts{ + Namespace: ns, + AllowedNamespaces: []string{ns}, + EnabledFeatureGates: []operator.FeatureGateName{operator.StatusForConfigurationResourcesFeature}, + }, + ) + require.NoError(t, err) + + name := "tr-status-finalizer" + + tr := framework.MakeBasicThanosRuler(name, 1, name) + _, err = framework.CreateThanosRulerAndWaitUntilReady(ctx, ns, tr) + require.NoError(t, err) + + ruler, err := framework.MonClientV1.ThanosRulers(ns).Get(ctx, name, v1.GetOptions{}) + require.NoError(t, err) + + finalizers := ruler.GetFinalizers() + require.NotEmpty(t, finalizers) + + err = framework.DeleteThanosRulerAndWaitUntilGone(ctx, ns, name) + require.NoError(t, err) +} diff --git a/test/framework/prometheus_rule.go b/test/framework/prometheus_rule.go index 790aea5c5..f6da5144b 100644 --- a/test/framework/prometheus_rule.go +++ b/test/framework/prometheus_rule.go @@ -197,7 +197,7 @@ func (f *Framework) WaitForRuleWorkloadBindingCleanup(ctx context.Context, pm *m resource, timeout, ); err != nil { - return nil, fmt.Errorf("podMonitor status %v/%v failed to reach expected condition: %w", pm.Namespace, pm.Name, err) + return nil, fmt.Errorf("prometheusRule status %v/%v failed to reach expected condition: %w", pm.Namespace, pm.Name, err) } return current, nil }