mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 13:29:11 +01:00
Merge pull request #1795 from ingvagabund/podantiaffinity-unit-test
refactor(TestPodAntiAffinity): inline object creation
This commit is contained in:
@@ -33,84 +33,75 @@ import (
|
||||
"sigs.k8s.io/descheduler/test"
|
||||
)
|
||||
|
||||
func TestPodAntiAffinity(t *testing.T) {
|
||||
node1 := test.BuildTestNode("n1", 2000, 3000, 10, func(node *v1.Node) {
|
||||
node.ObjectMeta.Labels = map[string]string{
|
||||
"region": "main-region",
|
||||
}
|
||||
})
|
||||
node2 := test.BuildTestNode("n2", 2000, 3000, 10, func(node *v1.Node) {
|
||||
node.ObjectMeta.Labels = map[string]string{
|
||||
"datacenter": "east",
|
||||
}
|
||||
})
|
||||
node3 := test.BuildTestNode("n3", 2000, 3000, 10, func(node *v1.Node) {
|
||||
node.Spec = v1.NodeSpec{
|
||||
Unschedulable: true,
|
||||
}
|
||||
})
|
||||
node4 := test.BuildTestNode("n4", 2, 2, 1, nil)
|
||||
node5 := test.BuildTestNode("n5", 200, 3000, 10, func(node *v1.Node) {
|
||||
node.ObjectMeta.Labels = map[string]string{
|
||||
"region": "main-region",
|
||||
}
|
||||
})
|
||||
const (
|
||||
nodeName1 = "n1"
|
||||
nodeName2 = "n2"
|
||||
nodeName3 = "n3"
|
||||
nodeName4 = "n4"
|
||||
nodeName5 = "n5"
|
||||
)
|
||||
|
||||
p1 := test.BuildTestPod("p1", 100, 0, node1.Name, nil)
|
||||
p2 := test.BuildTestPod("p2", 100, 0, node1.Name, nil)
|
||||
p3 := test.BuildTestPod("p3", 100, 0, node1.Name, nil)
|
||||
p4 := test.BuildTestPod("p4", 100, 0, node1.Name, nil)
|
||||
p5 := test.BuildTestPod("p5", 100, 0, node1.Name, nil)
|
||||
p6 := test.BuildTestPod("p6", 100, 0, node1.Name, nil)
|
||||
p7 := test.BuildTestPod("p7", 100, 0, node1.Name, nil)
|
||||
p8 := test.BuildTestPod("p8", 100, 0, node1.Name, nil)
|
||||
p9 := test.BuildTestPod("p9", 100, 0, node1.Name, nil)
|
||||
p10 := test.BuildTestPod("p10", 100, 0, node1.Name, nil)
|
||||
p11 := test.BuildTestPod("p11", 100, 0, node5.Name, nil)
|
||||
p9.DeletionTimestamp = &metav1.Time{}
|
||||
p10.DeletionTimestamp = &metav1.Time{}
|
||||
func buildTestNode(name string, apply func(*v1.Node)) *v1.Node {
|
||||
return test.BuildTestNode(name, 2000, 3000, 10, apply)
|
||||
}
|
||||
|
||||
criticalPriority := utils.SystemCriticalPriority
|
||||
nonEvictablePod := test.BuildTestPod("non-evict", 100, 0, node1.Name, func(pod *v1.Pod) {
|
||||
pod.Spec.Priority = &criticalPriority
|
||||
})
|
||||
p2.Labels = map[string]string{"foo": "bar"}
|
||||
p5.Labels = map[string]string{"foo": "bar"}
|
||||
p6.Labels = map[string]string{"foo": "bar"}
|
||||
p7.Labels = map[string]string{"foo1": "bar1"}
|
||||
p11.Labels = map[string]string{"foo": "bar"}
|
||||
nonEvictablePod.Labels = map[string]string{"foo": "bar"}
|
||||
test.SetNormalOwnerRef(p1)
|
||||
test.SetNormalOwnerRef(p2)
|
||||
test.SetNormalOwnerRef(p3)
|
||||
test.SetNormalOwnerRef(p4)
|
||||
test.SetNormalOwnerRef(p5)
|
||||
test.SetNormalOwnerRef(p6)
|
||||
test.SetNormalOwnerRef(p7)
|
||||
test.SetNormalOwnerRef(p9)
|
||||
test.SetNormalOwnerRef(p10)
|
||||
test.SetNormalOwnerRef(p11)
|
||||
|
||||
// set pod anti affinity
|
||||
test.SetPodAntiAffinity(p1, "foo", "bar")
|
||||
test.SetPodAntiAffinity(p3, "foo", "bar")
|
||||
test.SetPodAntiAffinity(p4, "foo", "bar")
|
||||
test.SetPodAntiAffinity(p5, "foo1", "bar1")
|
||||
test.SetPodAntiAffinity(p6, "foo1", "bar1")
|
||||
test.SetPodAntiAffinity(p7, "foo", "bar")
|
||||
test.SetPodAntiAffinity(p9, "foo", "bar")
|
||||
test.SetPodAntiAffinity(p10, "foo", "bar")
|
||||
|
||||
// set pod priority
|
||||
test.SetPodPriority(p5, 100)
|
||||
test.SetPodPriority(p6, 50)
|
||||
test.SetPodPriority(p7, 0)
|
||||
|
||||
// Set pod node selectors
|
||||
p8.Spec.NodeSelector = map[string]string{
|
||||
"datacenter": "west",
|
||||
func setNodeMainRegionLabel(node *v1.Node) {
|
||||
node.ObjectMeta.Labels = map[string]string{
|
||||
"region": "main-region",
|
||||
}
|
||||
}
|
||||
|
||||
func buildTestNode1() *v1.Node {
|
||||
return buildTestNode(nodeName1, setNodeMainRegionLabel)
|
||||
}
|
||||
|
||||
func buildTestPod(name, nodeName string, apply func(*v1.Pod)) *v1.Pod {
|
||||
return test.BuildTestPod(name, 100, 0, nodeName, apply)
|
||||
}
|
||||
|
||||
func buildTestPodForNode1(name string, apply func(*v1.Pod)) *v1.Pod {
|
||||
return buildTestPod(name, nodeName1, apply)
|
||||
}
|
||||
|
||||
func setPodAntiAffinityFooBar(pod *v1.Pod) {
|
||||
test.SetPodAntiAffinity(pod, "foo", "bar")
|
||||
}
|
||||
|
||||
func setPodAntiAffinityFoo1Bar1(pod *v1.Pod) {
|
||||
test.SetPodAntiAffinity(pod, "foo1", "bar1")
|
||||
}
|
||||
|
||||
func setLabelsFooBar(pod *v1.Pod) {
|
||||
pod.Labels = map[string]string{"foo": "bar"}
|
||||
}
|
||||
|
||||
func setLabelsFoo1Bar1(pod *v1.Pod) {
|
||||
pod.Labels = map[string]string{"foo1": "bar1"}
|
||||
}
|
||||
|
||||
func buildTestPodWithAntiAffinityForNode1(name string) *v1.Pod {
|
||||
return buildTestPodForNode1(name, func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setPodAntiAffinityFooBar(pod)
|
||||
})
|
||||
}
|
||||
|
||||
func buildTestPodP2ForNode1() *v1.Pod {
|
||||
return buildTestPodForNode1("p2", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setLabelsFooBar(pod)
|
||||
})
|
||||
}
|
||||
|
||||
func buildTestPodNonEvictableForNode1() *v1.Pod {
|
||||
criticalPriority := utils.SystemCriticalPriority
|
||||
return buildTestPodForNode1("non-evict", func(pod *v1.Pod) {
|
||||
pod.Spec.Priority = &criticalPriority
|
||||
setLabelsFooBar(pod)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPodAntiAffinity(t *testing.T) {
|
||||
var uint1 uint = 1
|
||||
var uint3 uint = 3
|
||||
|
||||
@@ -125,87 +116,204 @@ func TestPodAntiAffinity(t *testing.T) {
|
||||
nodes []*v1.Node
|
||||
}{
|
||||
{
|
||||
description: "Maximum pods to evict - 0",
|
||||
pods: []*v1.Pod{p1, p2, p3, p4},
|
||||
nodes: []*v1.Node{node1},
|
||||
description: "Maximum pods to evict - 0",
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodP2ForNode1(),
|
||||
buildTestPodWithAntiAffinityForNode1("p3"),
|
||||
buildTestPodWithAntiAffinityForNode1("p4"),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 3,
|
||||
},
|
||||
{
|
||||
description: "Maximum pods to evict - 3",
|
||||
maxPodsToEvictPerNode: &uint3,
|
||||
pods: []*v1.Pod{p1, p2, p3, p4},
|
||||
nodes: []*v1.Node{node1},
|
||||
description: "Maximum pods to evict - 3",
|
||||
maxPodsToEvictPerNode: &uint3,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodP2ForNode1(),
|
||||
buildTestPodWithAntiAffinityForNode1("p3"),
|
||||
buildTestPodWithAntiAffinityForNode1("p4"),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 3,
|
||||
},
|
||||
{
|
||||
description: "Maximum pods to evict (maxPodsToEvictPerNamespace=3) - 3",
|
||||
maxNoOfPodsToEvictPerNamespace: &uint3,
|
||||
pods: []*v1.Pod{p1, p2, p3, p4},
|
||||
nodes: []*v1.Node{node1},
|
||||
expectedEvictedPodCount: 3,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodP2ForNode1(),
|
||||
buildTestPodWithAntiAffinityForNode1("p3"),
|
||||
buildTestPodWithAntiAffinityForNode1("p4"),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 3,
|
||||
},
|
||||
{
|
||||
description: "Maximum pods to evict (maxNoOfPodsToEvictTotal)",
|
||||
maxNoOfPodsToEvictPerNamespace: &uint3,
|
||||
maxNoOfPodsToEvictTotal: &uint1,
|
||||
pods: []*v1.Pod{p1, p2, p3, p4},
|
||||
nodes: []*v1.Node{node1},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Evict only 1 pod after sorting",
|
||||
pods: []*v1.Pod{p5, p6, p7},
|
||||
nodes: []*v1.Node{node1},
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodP2ForNode1(),
|
||||
buildTestPodWithAntiAffinityForNode1("p3"),
|
||||
buildTestPodWithAntiAffinityForNode1("p4"),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Evicts pod that conflicts with critical pod (but does not evict critical pod)",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{p1, nonEvictablePod},
|
||||
nodes: []*v1.Node{node1},
|
||||
description: "Evict only 1 pod after sorting",
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p5", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setLabelsFooBar(pod)
|
||||
setPodAntiAffinityFoo1Bar1(pod)
|
||||
test.SetPodPriority(pod, 100)
|
||||
}),
|
||||
buildTestPodForNode1("p6", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setLabelsFooBar(pod)
|
||||
setPodAntiAffinityFoo1Bar1(pod)
|
||||
test.SetPodPriority(pod, 50)
|
||||
}),
|
||||
buildTestPodForNode1("p7", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setLabelsFoo1Bar1(pod)
|
||||
setPodAntiAffinityFooBar(pod)
|
||||
test.SetPodPriority(pod, 0)
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Evicts pod that conflicts with critical pod (but does not evict critical pod)",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{p1, nonEvictablePod},
|
||||
nodes: []*v1.Node{node1},
|
||||
description: "Evicts pod that conflicts with critical pod (but does not evict critical pod)",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodNonEvictableForNode1(),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Won't evict pods because node selectors don't match available nodes",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{p8, nonEvictablePod},
|
||||
nodes: []*v1.Node{node1, node2},
|
||||
description: "Evicts pod that conflicts with critical pod (but does not evict critical pod)",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodNonEvictableForNode1(),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 1,
|
||||
},
|
||||
{
|
||||
description: "Won't evict pods because node selectors don't match available nodes",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p8", func(pod *v1.Pod) {
|
||||
pod.Spec.NodeSelector = map[string]string{
|
||||
"datacenter": "west",
|
||||
}
|
||||
}),
|
||||
buildTestPodNonEvictableForNode1(),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
buildTestNode(nodeName2, func(node *v1.Node) {
|
||||
node.ObjectMeta.Labels = map[string]string{
|
||||
"datacenter": "east",
|
||||
}
|
||||
}),
|
||||
},
|
||||
expectedEvictedPodCount: 0,
|
||||
nodeFit: true,
|
||||
},
|
||||
{
|
||||
description: "Won't evict pods because only other node is not schedulable",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{p8, nonEvictablePod},
|
||||
nodes: []*v1.Node{node1, node3},
|
||||
description: "Won't evict pods because only other node is not schedulable",
|
||||
maxPodsToEvictPerNode: &uint1,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p8", func(pod *v1.Pod) {
|
||||
pod.Spec.NodeSelector = map[string]string{
|
||||
"datacenter": "west",
|
||||
}
|
||||
}),
|
||||
buildTestPodNonEvictableForNode1(),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
buildTestNode(nodeName3, func(node *v1.Node) {
|
||||
node.Spec = v1.NodeSpec{
|
||||
Unschedulable: true,
|
||||
}
|
||||
}),
|
||||
},
|
||||
expectedEvictedPodCount: 0,
|
||||
nodeFit: true,
|
||||
},
|
||||
{
|
||||
description: "No pod to evicted since all pod terminating",
|
||||
pods: []*v1.Pod{p9, p10},
|
||||
nodes: []*v1.Node{node1},
|
||||
description: "No pod to evicted since all pod terminating",
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodForNode1("p9", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setPodAntiAffinityFooBar(pod)
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
buildTestPodForNode1("p10", func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setPodAntiAffinityFooBar(pod)
|
||||
pod.DeletionTimestamp = &metav1.Time{}
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
},
|
||||
expectedEvictedPodCount: 0,
|
||||
},
|
||||
{
|
||||
description: "Won't evict pods because only other node doesn't have enough resources",
|
||||
maxPodsToEvictPerNode: &uint3,
|
||||
pods: []*v1.Pod{p1, p2, p3, p4},
|
||||
nodes: []*v1.Node{node1, node4},
|
||||
description: "Won't evict pods because only other node doesn't have enough resources",
|
||||
maxPodsToEvictPerNode: &uint3,
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPodP2ForNode1(),
|
||||
buildTestPodWithAntiAffinityForNode1("p3"),
|
||||
buildTestPodWithAntiAffinityForNode1("p4"),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
test.BuildTestNode(nodeName4, 2, 2, 1, nil),
|
||||
},
|
||||
expectedEvictedPodCount: 0,
|
||||
nodeFit: true,
|
||||
},
|
||||
{
|
||||
description: "Evict pod violating anti-affinity among different node (all pods have anti-affinity)",
|
||||
pods: []*v1.Pod{p1, p11},
|
||||
nodes: []*v1.Node{node1, node5},
|
||||
description: "Evict pod violating anti-affinity among different node (all pods have anti-affinity)",
|
||||
pods: []*v1.Pod{
|
||||
buildTestPodWithAntiAffinityForNode1("p1"),
|
||||
buildTestPod("p11", nodeName5, func(pod *v1.Pod) {
|
||||
test.SetNormalOwnerRef(pod)
|
||||
setLabelsFooBar(pod)
|
||||
}),
|
||||
},
|
||||
nodes: []*v1.Node{
|
||||
buildTestNode1(),
|
||||
test.BuildTestNode(nodeName5, 200, 3000, 10, setNodeMainRegionLabel),
|
||||
},
|
||||
expectedEvictedPodCount: 1,
|
||||
nodeFit: false,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user