From b60c5ab0a51be0190805e0b60493619f5e9097c2 Mon Sep 17 00:00:00 2001 From: Andrew Stucki Date: Thu, 23 Apr 2026 23:36:46 -0400 Subject: [PATCH] [release/v25.2.x] Backport deterministic sort --- .changes/unreleased/operator-Fixed-20260423-224719.yaml | 4 ++++ operator/internal/controller/redpanda/redpanda_controller.go | 5 +++++ 2 files changed, 9 insertions(+) create mode 100644 .changes/unreleased/operator-Fixed-20260423-224719.yaml diff --git a/.changes/unreleased/operator-Fixed-20260423-224719.yaml b/.changes/unreleased/operator-Fixed-20260423-224719.yaml new file mode 100644 index 000000000..47a906644 --- /dev/null +++ b/.changes/unreleased/operator-Fixed-20260423-224719.yaml @@ -0,0 +1,4 @@ +project: operator +kind: Fixed +body: Fixed an issue where in-use features from an enterprise cluster did not have deterministic sort order and could cause reconciliation storms due to status changes. +time: 2026-04-23T22:47:19.373877-04:00 diff --git a/operator/internal/controller/redpanda/redpanda_controller.go b/operator/internal/controller/redpanda/redpanda_controller.go index c6b3617aa..9ece4335e 100644 --- a/operator/internal/controller/redpanda/redpanda_controller.go +++ b/operator/internal/controller/redpanda/redpanda_controller.go @@ -14,6 +14,7 @@ import ( "bytes" "context" "fmt" + "sort" "strings" "time" @@ -638,6 +639,10 @@ func (r *RedpandaReconciler) reconcileLicense(ctx context.Context, state *cluste inUseFeatures = append(inUseFeatures, feature.Name) } } + // features.Features iterates a map under the hood; sort the + // resulting slice so repeated reconciles produce byte-identical + // status. + sort.Strings(inUseFeatures) status := &redpandav1alpha2.RedpandaLicenseStatus{ InUseFeatures: inUseFeatures,