Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/operator/controller/status/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package status
import (
"context"
"fmt"
"sort"
"strings"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -532,6 +533,7 @@ func isUpgrading(curVersions, oldVersions, newVersions map[string]string) (bool,
messages = append(messages, fmt.Sprintf("Upgrading %s to %q.", name, newVersion))
}
}
sort.Strings(messages)
return upgrading, messages
}

Expand Down
43 changes: 43 additions & 0 deletions pkg/operator/controller/status/controller_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package status

import (
"reflect"
"testing"
"time"

Expand Down Expand Up @@ -802,3 +803,45 @@ func TestComputeOperatorDegradedCondition(t *testing.T) {
}
}
}

// TestIsUpgradingMessageOrder verifies that isUpgrading returns messages in a
// stable, sorted order regardless of map iteration order. Non-deterministic
// message ordering caused a self-sustaining ClusterOperator write loop: each
// reconcile produced a different Message string, operatorStatusesEqual returned
// false, the ClusterOperator was written, the CO watch fired, and the cycle
// repeated indefinitely during upgrades.
func TestIsUpgradingMessageOrder(t *testing.T) {
// Two components upgrading simultaneously — map iteration order is random,
// so call isUpgrading many times and confirm the messages slice is always
// returned in the same sorted order.
curVersions := map[string]string{
OperatorVersionName: "v1",
CoreDNSVersionName: "dns-v1",
KubeRBACProxyName: "rbac-v1",
}
oldVersions := map[string]string{
OperatorVersionName: "v0",
CoreDNSVersionName: "dns-v0",
KubeRBACProxyName: "rbac-v0",
}
newVersions := map[string]string{
OperatorVersionName: "v2",
CoreDNSVersionName: "dns-v2",
KubeRBACProxyName: "rbac-v2",
}

var first []string
for i := 0; i < 100; i++ {
upgrading, messages := isUpgrading(curVersions, oldVersions, newVersions)
if !upgrading {
t.Fatal("expected upgrading=true")
}
if i == 0 {
first = messages
continue
}
if !reflect.DeepEqual(first, messages) {
t.Errorf("iteration %d: messages order changed\n first: %v\n current: %v", i, first, messages)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}
}