From 54f67266bb3d53818b565bb6ed259fc6c48bc754 Mon Sep 17 00:00:00 2001 From: Jan Chaloupka Date: Wed, 5 May 2021 12:56:30 +0200 Subject: [PATCH] Define TolerationsEqual --- pkg/utils/predicates.go | 57 ++++++ pkg/utils/predicates_test.go | 337 +++++++++++++++++++++++++++++++++++ 2 files changed, 394 insertions(+) create mode 100644 pkg/utils/predicates_test.go diff --git a/pkg/utils/predicates.go b/pkg/utils/predicates.go index 126db7810..a705f4314 100644 --- a/pkg/utils/predicates.go +++ b/pkg/utils/predicates.go @@ -18,6 +18,7 @@ package utils import ( "fmt" + "sort" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/labels" @@ -107,3 +108,59 @@ func TolerationsTolerateTaintsWithFilter(tolerations []v1.Toleration, taints []v return true } + +// sort by (key, value, effect, operand) +func uniqueSortTolerations(srcTolerations []v1.Toleration) []v1.Toleration { + tolerations := append([]v1.Toleration{}, srcTolerations...) + + if len(tolerations) < 2 { + return tolerations + } + + sort.Slice(tolerations, func(i, j int) bool { + if tolerations[i].Key < tolerations[j].Key { + return true + } + if tolerations[i].Key > tolerations[j].Key { + return false + } + if tolerations[i].Value < tolerations[j].Value { + return true + } + if tolerations[i].Value > tolerations[j].Value { + return false + } + if tolerations[i].Effect < tolerations[j].Effect { + return true + } + if tolerations[i].Effect > tolerations[j].Effect { + return false + } + return tolerations[i].Operator < tolerations[j].Operator + }) + uniqueTolerations := []v1.Toleration{tolerations[0]} + idx := 0 + for _, t := range tolerations[1:] { + if t.MatchToleration(&uniqueTolerations[idx]) { + continue + } + idx++ + uniqueTolerations = append(uniqueTolerations, t) + } + return uniqueTolerations +} + +func TolerationsEqual(t1, t2 []v1.Toleration) bool { + t1Sorted := uniqueSortTolerations(t1) + t2Sorted := uniqueSortTolerations(t2) + l1Len := len(t1Sorted) + if l1Len != len(t2Sorted) { + return false + } + for i := 0; i < l1Len; i++ { + if !t1Sorted[i].MatchToleration(&t2Sorted[i]) { + return false + } + } + return true +} diff --git a/pkg/utils/predicates_test.go b/pkg/utils/predicates_test.go new file mode 100644 index 000000000..691da26ea --- /dev/null +++ b/pkg/utils/predicates_test.go @@ -0,0 +1,337 @@ +package utils + +import ( + "reflect" + "testing" + + v1 "k8s.io/api/core/v1" +) + +func TestUniqueSortTolerations(t *testing.T) { + tests := []struct { + name string + tolerations []v1.Toleration + expectedTolerations []v1.Toleration + }{ + { + name: "sort by key", + tolerations: []v1.Toleration{ + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key3", + Operator: v1.TolerationOpEqual, + Value: "value3", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + }, + expectedTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key3", + Operator: v1.TolerationOpEqual, + Value: "value3", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + { + name: "sort by value", + tolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value3", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + }, + expectedTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value3", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + { + name: "sort by effect", + tolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoExecute, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectPreferNoSchedule, + }, + }, + expectedTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoExecute, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectPreferNoSchedule, + }, + }, + }, + { + name: "sort unique", + tolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + expectedTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + resultTolerations := uniqueSortTolerations(test.tolerations) + if !reflect.DeepEqual(resultTolerations, test.expectedTolerations) { + t.Errorf("tolerations not sorted as expected, \n\tgot: %#v, \n\texpected: %#v", resultTolerations, test.expectedTolerations) + } + }) + } +} + +func TestTolerationsEqual(t *testing.T) { + tests := []struct { + name string + leftTolerations, rightTolerations []v1.Toleration + equal bool + }{ + { + name: "identical lists", + leftTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + rightTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + equal: true, + }, + { + name: "equal lists", + leftTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + rightTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + equal: true, + }, + { + name: "non-equal lists", + leftTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoSchedule, + }, + }, + rightTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoExecute, + }, + }, + equal: false, + }, + { + name: "different sizes lists", + leftTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + }, + rightTolerations: []v1.Toleration{ + { + Key: "key1", + Operator: v1.TolerationOpEqual, + Value: "value1", + Effect: v1.TaintEffectNoSchedule, + }, + { + Key: "key2", + Operator: v1.TolerationOpEqual, + Value: "value2", + Effect: v1.TaintEffectNoExecute, + }, + }, + equal: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + equal := TolerationsEqual(test.leftTolerations, test.rightTolerations) + if equal != test.equal { + t.Errorf("TolerationsEqual expected to be %v, got %v", test.equal, equal) + } + }) + } +}