From 1e9e23c117492b28b6726a08738a1c26b625f402 Mon Sep 17 00:00:00 2001 From: steiler Date: Mon, 6 Jul 2026 12:14:18 +0200 Subject: [PATCH 1/2] fix: reset TargetForConfig condition on no-op reconcile When a target briefly drops and recovers but no intent hash changes, buildIntentInputs returns hasChanged=false and the reconciler returned early without calling SetConfigsTargetConditionForTarget. Any stale TargetForConfig=Failed condition written during the outage was never cleared, leaving all Config CRs permanently at Ready=False. Mirror the main-branch behaviour: always call SetConfigsTargetConditionForTarget(TargetForConfigReady) at the end of every successful reconcile, even when no transaction was needed. Fixes 22-Srl-Update-Replace CI failures where srl3 briefly lost its dsctx at 07:14:41, setting configs to Ready=False, which were never restored because subsequent reconciles detected no hash change and skipped the condition-reset call. Co-authored-by: Cursor --- pkg/reconcilers/targetconfig/reconciler.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/reconcilers/targetconfig/reconciler.go b/pkg/reconcilers/targetconfig/reconciler.go index 94f6bc31..f5a19f0d 100644 --- a/pkg/reconcilers/targetconfig/reconciler.go +++ b/pkg/reconcilers/targetconfig/reconciler.go @@ -239,6 +239,17 @@ func (r *reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu if !hasChanged { log.Info("Transact skip, nothing to update") + // Still reset TargetForConfig to Ready so any stale Failed condition + // (set when the target was briefly not-ready) is cleared. Without this + // the overall Config Ready condition stays False permanently whenever a + // target drops and recovers but no intent change is detected. + if err := r.cfgMgr.SetConfigsTargetConditionForTarget( + ctx, targetOrig, + configv1alpha1.TargetForConfigReady("target ready"), + ); err != nil { + return ctrl.Result{}, + errors.Wrap(r.handleError(ctx, targetOrig, "cannot update config status", err), errUpdateStatus) + } return ctrl.Result{}, nil } From f3bbd8ee3c9791ce5239013ef17ea77ba888ae21 Mon Sep 17 00:00:00 2001 From: steiler Date: Mon, 6 Jul 2026 15:18:26 +0200 Subject: [PATCH 2/2] fix(configresolver): clear stale Resolver=False after same-content secret re-creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a referenced secret is deleted, the configresolver sets Resolver=False and preserves the last-good SensitiveConfig. If the secret is re-created with identical content, detectChange returns noChange=true because all hashes still match — causing the reconciler to exit early without ever clearing the stale failure condition. The Config would remain non-Ready permanently. Fix: before early-exiting on noChange, check whether the current Resolver condition is False. If it is, call handleSuccess to clear it — the secret is clearly available now (hashes matched), so the stored failure is no longer valid. Fixes TC5 in the 04-sensitive integration test suite. Co-authored-by: Cursor --- pkg/reconcilers/configresolver/reconciler.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/reconcilers/configresolver/reconciler.go b/pkg/reconcilers/configresolver/reconciler.go index 362fe294..a1227e70 100644 --- a/pkg/reconcilers/configresolver/reconciler.go +++ b/pkg/reconcilers/configresolver/reconciler.go @@ -240,6 +240,17 @@ func (r *reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu // ── No change ───────────────────────────────────────────────────────────── if change.noChange() { + // Even when content is identical to the stored SensitiveConfig, clear a + // stale Resolver=False condition. This occurs when a secret is deleted + // (which sets Resolver=False and preserves the last-good SC), then + // re-created with the same content: detectChange returns noChange=true + // because all hashes still match, but the failure condition from the + // deletion window must be cleared so the Config can become Ready again. + resolverC := cfgOrig.GetCondition(configv1alpha1.ConditionTypeResolver) + if resolverC.Status != "" && !resolverC.IsTrue() { + log.Info("no content change but stale Resolver=False detected — clearing condition") + return ctrl.Result{}, errors.Wrap(r.handleSuccess(ctx, cfgOrig), errUpdateStatus) + } log.Debug("no change detected, skipping") return ctrl.Result{}, nil }