From 596491c72935ad8445faa619497ea041abb72d82 Mon Sep 17 00:00:00 2001 From: Armand Picard Date: Fri, 8 Nov 2024 20:33:56 +0100 Subject: [PATCH 1/3] fix: Device Plugin daemonset keep restarting Define an ordering of the NodeSelectorRequirement in the daemonset to avoid the daemonset to be unstable when policies come in different order. Fixes #804 --- controllers/helper.go | 21 +++++++++++++++++++++ controllers/helper_test.go | 8 ++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/controllers/helper.go b/controllers/helper.go index 9ff735473..6114c3ddf 100644 --- a/controllers/helper.go +++ b/controllers/helper.go @@ -311,6 +311,27 @@ func nodeSelectorTermsForPolicyList(policies []sriovnetworkv1.SriovNetworkNodePo terms = append(terms, nodeSelector) } + // sorting is needed to keep the daemon spec stable. + // the policies can come in a random order + sort.Slice(terms, func(i, j int) bool { + expressionsA := terms[i].MatchExpressions + expressionsB := terms[j].MatchExpressions + if len(expressionsA) != len(expressionsB) { + return len(expressionsA) < len(expressionsB) + } + for k := range expressionsA { + expressionA := expressionsA[k] + expressionB := expressionsB[k] + if expressionA.Key != expressionB.Key { + return expressionA.Key < expressionB.Key + } + if expressionA.Values[0] != expressionB.Values[0] { + return expressionA.Values[0] != expressionB.Values[0] + } + } + return true + }) + return terms } diff --git a/controllers/helper_test.go b/controllers/helper_test.go index d998cf0da..87d57b054 100644 --- a/controllers/helper_test.go +++ b/controllers/helper_test.go @@ -64,8 +64,8 @@ func TestNodeSelectorMerge(t *testing.T) { MatchExpressions: []corev1.NodeSelectorRequirement{ { Operator: corev1.NodeSelectorOpIn, - Key: "foo", - Values: []string{"bar"}, + Key: "bb", + Values: []string{"cc"}, }, }, }, @@ -73,8 +73,8 @@ func TestNodeSelectorMerge(t *testing.T) { MatchExpressions: []corev1.NodeSelectorRequirement{ { Operator: corev1.NodeSelectorOpIn, - Key: "bb", - Values: []string{"cc"}, + Key: "foo", + Values: []string{"bar"}, }, }, }, From 5030cd2a1fce89f7e92e22de8d46551f36a55724 Mon Sep 17 00:00:00 2001 From: Armand Picard Date: Sun, 10 Nov 2024 19:49:06 +0100 Subject: [PATCH 2/3] Update controllers/helper.go Co-authored-by: Ido Heyvi --- controllers/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/helper.go b/controllers/helper.go index 6114c3ddf..4e4fd5d75 100644 --- a/controllers/helper.go +++ b/controllers/helper.go @@ -326,7 +326,7 @@ func nodeSelectorTermsForPolicyList(policies []sriovnetworkv1.SriovNetworkNodePo return expressionA.Key < expressionB.Key } if expressionA.Values[0] != expressionB.Values[0] { - return expressionA.Values[0] != expressionB.Values[0] + return expressionA.Values[0] < expressionB.Values[0] } } return true From 547a5feeff286d2dc666a6c66ec3969f623c11af Mon Sep 17 00:00:00 2001 From: Armand Picard Date: Sun, 10 Nov 2024 20:03:27 +0100 Subject: [PATCH 3/3] add: test case for ordering base on value --- controllers/helper_test.go | 55 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/controllers/helper_test.go b/controllers/helper_test.go index 87d57b054..eb6e402fb 100644 --- a/controllers/helper_test.go +++ b/controllers/helper_test.go @@ -148,6 +148,61 @@ func TestNodeSelectorMerge(t *testing.T) { }, expected: []corev1.NodeSelectorTerm{}, }, + { + tname: "testordersamekey", + policies: []sriovnetworkv1.SriovNetworkNodePolicy{ + { + Spec: sriovnetworkv1.SriovNetworkNodePolicySpec{ + NodeSelector: map[string]string{ + "env": "production", + }, + }, + }, + { + Spec: sriovnetworkv1.SriovNetworkNodePolicySpec{ + NodeSelector: map[string]string{ + "env": "staging", + }, + }, + }, + { + Spec: sriovnetworkv1.SriovNetworkNodePolicySpec{ + NodeSelector: map[string]string{ + "env": "dev", + }, + }, + }, + }, + expected: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Operator: corev1.NodeSelectorOpIn, + Key: "env", + Values: []string{"dev"}, + }, + }, + }, + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Operator: corev1.NodeSelectorOpIn, + Key: "env", + Values: []string{"production"}, + }, + }, + }, + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Operator: corev1.NodeSelectorOpIn, + Key: "env", + Values: []string{"staging"}, + }, + }, + }, + }, + }, } for _, tc := range table {