mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-28 14:41:10 +01:00
Define NodeSelectorsEqual predicate
This commit is contained in:
@@ -335,3 +335,606 @@ func TestTolerationsEqual(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUniqueSortNodeSelectorRequirements(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
requirements []v1.NodeSelectorRequirement
|
||||
expectedRequirements []v1.NodeSelectorRequirement
|
||||
}{
|
||||
{
|
||||
name: "Identical requirements",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sorted requirements",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sort values",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sort by key",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k3",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k3",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sort by operator",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpExists,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpGt,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpExists,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpGt,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sort by values",
|
||||
requirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v6", "v5"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v4", "v1"},
|
||||
},
|
||||
},
|
||||
expectedRequirements: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v4"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v5", "v6"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
resultRequirements := uniqueSortNodeSelectorRequirements(test.requirements)
|
||||
if !reflect.DeepEqual(resultRequirements, test.expectedRequirements) {
|
||||
t.Errorf("Requirements not sorted as expected, \n\tgot: %#v, \n\texpected: %#v", resultRequirements, test.expectedRequirements)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUniqueSortNodeSelectorTerms(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
terms []v1.NodeSelectorTerm
|
||||
expectedTerms []v1.NodeSelectorTerm
|
||||
}{
|
||||
{
|
||||
name: "Identical terms",
|
||||
terms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
MatchFields: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
MatchFields: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sorted terms",
|
||||
terms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
MatchFields: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
MatchFields: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Sort terms",
|
||||
terms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v3", "v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v3"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Unique sort terms",
|
||||
terms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v2", "v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
resultTerms := uniqueSortNodeSelectorTerms(test.terms)
|
||||
if !reflect.DeepEqual(resultTerms, test.expectedTerms) {
|
||||
t.Errorf("Terms not sorted as expected, \n\tgot: %#v, \n\texpected: %#v", resultTerms, test.expectedTerms)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodeSelectorTermsEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
leftSelector, rightSelector v1.NodeSelector
|
||||
equal bool
|
||||
}{
|
||||
{
|
||||
name: "identical selectors",
|
||||
leftSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rightSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
equal: true,
|
||||
},
|
||||
{
|
||||
name: "equal selectors",
|
||||
leftSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rightSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
equal: true,
|
||||
},
|
||||
{
|
||||
name: "non-equal selectors in values",
|
||||
leftSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rightSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
equal: false,
|
||||
},
|
||||
{
|
||||
name: "non-equal selectors in keys",
|
||||
leftSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k3",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
rightSelector: v1.NodeSelector{
|
||||
NodeSelectorTerms: []v1.NodeSelectorTerm{
|
||||
{
|
||||
MatchExpressions: []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: "k1",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
{
|
||||
Key: "k2",
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{"v1", "v2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
equal: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
equal := NodeSelectorsEqual(&test.leftSelector, &test.rightSelector)
|
||||
if equal != test.equal {
|
||||
t.Errorf("NodeSelectorsEqual expected to be %v, got %v", test.equal, equal)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user