Compare commits

...

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 323900adcc Rename changelog to 9898 and verify callers 2026-06-09 22:12:25 +00:00
copilot-swe-agent[bot] 317ffd069f Make ToSystemAffinity deterministic by sorting MatchLabels keys 2026-06-09 22:10:30 +00:00
copilot-swe-agent[bot] d6d9e4ee16 Initial plan 2026-06-09 22:06:02 +00:00
3 changed files with 55 additions and 1 deletions
+1
View File
@@ -0,0 +1 @@
Make ToSystemAffinity deterministic by sorting MatchLabels keys to avoid spurious affinity spec diffs and restarts
+15 -1
View File
@@ -20,6 +20,7 @@ import (
"fmt"
"io"
"os"
"sort"
"strings"
"time"
@@ -236,7 +237,20 @@ func CollectPodLogs(ctx context.Context, podGetter corev1client.CoreV1Interface,
func ToSystemAffinity(loadAffinity *LoadAffinity, volumeTopology *corev1api.NodeSelector) *corev1api.Affinity {
requirements := []corev1api.NodeSelectorRequirement{}
if loadAffinity != nil {
for k, v := range loadAffinity.NodeSelector.MatchLabels {
// MatchLabels is a map, so its iteration order is not deterministic.
// Sort the keys so the generated requirements (and therefore the
// resulting affinity) have a stable order. This output may be embedded
// into objects that are reconciled continuously (e.g. DaemonSet pod
// templates), where an order-only difference would be treated as a spec
// change and trigger unnecessary rollouts/restarts.
keys := make([]string, 0, len(loadAffinity.NodeSelector.MatchLabels))
for k := range loadAffinity.NodeSelector.MatchLabels {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := loadAffinity.NodeSelector.MatchLabels[k]
requirements = append(requirements, corev1api.NodeSelectorRequirement{
Key: k,
Values: []string{v},
+39
View File
@@ -834,6 +834,45 @@ func TestToSystemAffinity(t *testing.T) {
},
},
},
{
name: "with multiple match labels are sorted by key",
loadAffinity: &LoadAffinity{
NodeSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
"key-c": "value-c",
"key-a": "value-a",
"key-b": "value-b",
},
},
},
expected: &corev1api.Affinity{
NodeAffinity: &corev1api.NodeAffinity{
RequiredDuringSchedulingIgnoredDuringExecution: &corev1api.NodeSelector{
NodeSelectorTerms: []corev1api.NodeSelectorTerm{
{
MatchExpressions: []corev1api.NodeSelectorRequirement{
{
Key: "key-a",
Values: []string{"value-a"},
Operator: corev1api.NodeSelectorOpIn,
},
{
Key: "key-b",
Values: []string{"value-b"},
Operator: corev1api.NodeSelectorOpIn,
},
{
Key: "key-c",
Values: []string{"value-c"},
Operator: corev1api.NodeSelectorOpIn,
},
},
},
},
},
},
},
},
{
name: "with olume topology",
volumeTopology: &corev1api.NodeSelector{