cleanup: move scheduler plugin tests to use PodWrapper

Move scheduler plugin unit tests use testing PodWrapper
where applicable to reduce duplicating pod creation
code and shorten number of lines.

Signed-off-by: Yibo Zhuang <yibzhuang@gmail.com>
This commit is contained in:
Yibo Zhuang 2022-05-05 10:48:55 -07:00
parent fd08d47d8b
commit bc8f3198d5
18 changed files with 862 additions and 2830 deletions

View File

@ -28,12 +28,11 @@ import (
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
clienttesting "k8s.io/client-go/testing" clienttesting "k8s.io/client-go/testing"
frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime" frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestDefaultBinder(t *testing.T) { func TestDefaultBinder(t *testing.T) {
testPod := &v1.Pod{ testPod := st.MakePod().Name("foo").Namespace("ns").Obj()
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "ns"},
}
testNode := "foohost.kubernetes.mydomain.com" testNode := "foohost.kubernetes.mydomain.com"
tests := []struct { tests := []struct {
name string name string

View File

@ -26,6 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestGetPodServices(t *testing.T) { func TestGetPodServices(t *testing.T) {
@ -48,16 +49,11 @@ func TestGetPodServices(t *testing.T) {
} }
var pods []*v1.Pod var pods []*v1.Pod
for i := 0; i < 5; i++ { for i := 0; i < 5; i++ {
pod := &v1.Pod{ pod := st.MakePod().Name(fmt.Sprintf("test-pod-%d", i)).
ObjectMeta: metav1.ObjectMeta{ Namespace("test").
Namespace: "test", Label("app", fmt.Sprintf("test-%d", i)).
Name: fmt.Sprintf("test-pod-%d", i), Label("label", fmt.Sprintf("label-%d", i)).
Labels: map[string]string{ Obj()
"app": fmt.Sprintf("test-%d", i),
"label": fmt.Sprintf("label-%d", i),
},
},
}
pods = append(pods, pod) pods = append(pods, pod)
} }

View File

@ -240,8 +240,8 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: gcr.io/250:latest 250MB // Image: gcr.io/250:latest 250MB
// Score: 100 * (250M/2 - 23M)/(1000M * 2 - 23M) = 5 // Score: 100 * (250M/2 - 23M)/(1000M * 2 - 23M) = 5
pod: &v1.Pod{Spec: test40250}, pod: &v1.Pod{Spec: test40250},
nodes: []*v1.Node{makeImageNode("machine1", node403002000), makeImageNode("machine2", node25010)}, nodes: []*v1.Node{makeImageNode("node1", node403002000), makeImageNode("node2", node25010)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 5}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 5}},
name: "two images spread on two nodes, prefer the larger image one", name: "two images spread on two nodes, prefer the larger image one",
}, },
{ {
@ -255,8 +255,8 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: not present // Image: not present
// Score: 0 // Score: 0
pod: &v1.Pod{Spec: test40300}, pod: &v1.Pod{Spec: test40300},
nodes: []*v1.Node{makeImageNode("machine1", node403002000), makeImageNode("machine2", node25010)}, nodes: []*v1.Node{makeImageNode("node1", node403002000), makeImageNode("node2", node25010)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 7}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 7}, {Name: "node2", Score: 0}},
name: "two images on one node, prefer this node", name: "two images on one node, prefer this node",
}, },
{ {
@ -270,8 +270,8 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: gcr.io/10:latest 10MB // Image: gcr.io/10:latest 10MB
// Score: 0 (10M/2 < 23M, min-threshold) // Score: 0 (10M/2 < 23M, min-threshold)
pod: &v1.Pod{Spec: testMinMax}, pod: &v1.Pod{Spec: testMinMax},
nodes: []*v1.Node{makeImageNode("machine1", node400030), makeImageNode("machine2", node25010)}, nodes: []*v1.Node{makeImageNode("node1", node400030), makeImageNode("node2", node25010)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
name: "if exceed limit, use limit", name: "if exceed limit, use limit",
}, },
{ {
@ -289,8 +289,8 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: // Image:
// Score: 0 // Score: 0
pod: &v1.Pod{Spec: testMinMax}, pod: &v1.Pod{Spec: testMinMax},
nodes: []*v1.Node{makeImageNode("machine1", node400030), makeImageNode("machine2", node25010), makeImageNode("machine3", nodeWithNoImages)}, nodes: []*v1.Node{makeImageNode("node1", node400030), makeImageNode("node2", node25010), makeImageNode("node3", nodeWithNoImages)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 66}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 66}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
name: "if exceed limit, use limit (with node which has no images present)", name: "if exceed limit, use limit (with node which has no images present)",
}, },
{ {
@ -308,9 +308,9 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: // Image:
// Score: 0 // Score: 0
pod: &v1.Pod{Spec: test300600900}, pod: &v1.Pod{Spec: test300600900},
nodes: []*v1.Node{makeImageNode("machine1", node60040900), makeImageNode("machine2", node300600900), makeImageNode("machine3", nodeWithNoImages)}, nodes: []*v1.Node{makeImageNode("node1", node60040900), makeImageNode("node2", node300600900), makeImageNode("node3", nodeWithNoImages)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 32}, {Name: "machine2", Score: 36}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 32}, {Name: "node2", Score: 36}, {Name: "node3", Score: 0}},
name: "pod with multiple large images, machine2 is preferred", name: "pod with multiple large images, node2 is preferred",
}, },
{ {
// Pod: gcr.io/30 gcr.io/40 // Pod: gcr.io/30 gcr.io/40
@ -323,8 +323,8 @@ func TestImageLocalityPriority(t *testing.T) {
// Image: 100 * (30M - 23M) / (1000M * 2 - 23M) = 0 // Image: 100 * (30M - 23M) / (1000M * 2 - 23M) = 0
// Score: 0 // Score: 0
pod: &v1.Pod{Spec: test3040}, pod: &v1.Pod{Spec: test3040},
nodes: []*v1.Node{makeImageNode("machine1", node203040), makeImageNode("machine2", node400030)}, nodes: []*v1.Node{makeImageNode("node1", node203040), makeImageNode("node2", node400030)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 1}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 1}, {Name: "node2", Score: 0}},
name: "pod with multiple small images", name: "pod with multiple small images",
}, },
} }

View File

@ -22,7 +22,7 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config"
@ -377,52 +377,52 @@ func TestPreferredAffinity(t *testing.T) {
wantStatus *framework.Status wantStatus *framework.Status
}{ }{
{ {
name: "all machines are same priority as Affinity is nil", name: "all nodes are same priority as Affinity is nil",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
// the node(machine1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score // the node(node1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score
// the node(machine3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score // the node(node3) that don't have the label {"region": "whatever the value is"} (mismatch the topology key) but that have existing pods that match the labelSelector get low score
// the node(machine2) that have the label {"region": "China"} (match the topology key) but that have existing pods that mismatch the labelSelector get low score // the node(node2) that have the label {"region": "China"} (match the topology key) but that have existing pods that mismatch the labelSelector get low score
{ {
name: "Affinity: pod that matches topology key & pods in nodes will get high score comparing to others" + name: "Affinity: pod that matches topology key & pods in nodes will get high score comparing to others" +
"which doesn't match either pods in nodes or in topology key", "which doesn't match either pods in nodes or in topology key",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
// the node1(machine1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score // the node1(node1) that have the label {"region": "China"} (match the topology key) and that have existing pods that match the labelSelector get high score
// the node2(machine2) that have the label {"region": "China"}, match the topology key and have the same label value with node1, get the same high score with node1 // the node2(node2) that have the label {"region": "China"}, match the topology key and have the same label value with node1, get the same high score with node1
// the node3(machine3) that have the label {"region": "India"}, match the topology key but have a different label value, don't have existing pods that match the labelSelector, // the node3(node3) that have the label {"region": "India"}, match the topology key but have a different label value, don't have existing pods that match the labelSelector,
// get a low score. // get a low score.
{ {
name: "All the nodes that have the same topology key & label value with one of them has an existing pod that match the affinity rules, have the same score", name: "All the nodes that have the same topology key & label value with one of them has an existing pod that match the affinity rules, have the same score",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegion}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChinaAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChinaAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
// there are 2 regions, say regionChina(machine1,machine3,machine4) and regionIndia(machine2,machine5), both regions have nodes that match the preference. // there are 2 regions, say regionChina(node1,node3,node4) and regionIndia(node2,node5), both regions have nodes that match the preference.
// But there are more nodes(actually more existing pods) in regionChina that match the preference than regionIndia. // But there are more nodes(actually more existing pods) in regionChina that match the preference than regionIndia.
// Then, nodes in regionChina get higher score than nodes in regionIndia, and all the nodes in regionChina should get a same score(high score), // Then, nodes in regionChina get higher score than nodes in regionIndia, and all the nodes in regionChina should get a same score(high score),
// while all the nodes in regionIndia should get another same score(low score). // while all the nodes in regionIndia should get another same score(low score).
@ -430,37 +430,37 @@ func TestPreferredAffinity(t *testing.T) {
name: "Affinity: nodes in one region has more matching pods comparing to other region, so the region which has more matches will get high score", name: "Affinity: nodes in one region has more matching pods comparing to other region, so the region which has more matches will get high score",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine4"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node4"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine5"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node5"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine4", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node4", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node5", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: framework.MaxNodeScore}, {Name: "machine4", Score: framework.MaxNodeScore}, {Name: "machine5", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: framework.MaxNodeScore}, {Name: "node4", Score: framework.MaxNodeScore}, {Name: "node5", Score: 0}},
}, },
// Test with the different operators and values for pod affinity scheduling preference, including some match failures. // Test with the different operators and values for pod affinity scheduling preference, including some match failures.
{ {
name: "Affinity: different Label operators and values for pod affinity scheduling preference, including some match failures ", name: "Affinity: different Label operators and values for pod affinity scheduling preference, including some match failures ",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: affinity3}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: affinity3}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 20}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 20}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
// Test the symmetry cases for affinity, the difference between affinity and symmetry is not the pod wants to run together with some existing pods, // Test the symmetry cases for affinity, the difference between affinity and symmetry is not the pod wants to run together with some existing pods,
// but the existing pods have the inter pod affinity preference while the pod to schedule satisfy the preference. // but the existing pods have the inter pod affinity preference while the pod to schedule satisfy the preference.
@ -468,57 +468,57 @@ func TestPreferredAffinity(t *testing.T) {
name: "Affinity symmetry: considered only the preferredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", name: "Affinity symmetry: considered only the preferredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: stayWithS1InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: stayWithS1InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
{ {
name: "Affinity symmetry with namespace selector", name: "Affinity symmetry with namespace selector",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "AntiAffinity symmetry with namespace selector", name: "AntiAffinity symmetry with namespace selector",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: stayWithS2InRegion}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: framework.MaxNodeScore}},
}, },
{ {
name: "Affinity symmetry: considered RequiredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry", name: "Affinity symmetry: considered RequiredDuringSchedulingIgnoredDuringExecution in pod affinity symmetry",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardAffinity}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardAffinity}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardAffinity}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardAffinity}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
// The pod to schedule prefer to stay away from some existing pods at node level using the pod anti affinity. // The pod to schedule prefer to stay away from some existing pods at node level using the pod anti affinity.
@ -531,94 +531,94 @@ func TestPreferredAffinity(t *testing.T) {
name: "Anti Affinity: pod that does not match existing pods in node will get high score ", name: "Anti Affinity: pod that does not match existing pods in node will get high score ",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChina}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
{ {
name: "Anti Affinity: pod that does not match topology key & match the pods in nodes will get higher score comparing to others ", name: "Anti Affinity: pod that does not match topology key & match the pods in nodes will get higher score comparing to others ",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChina}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
{ {
name: "Anti Affinity: one node has more matching pods comparing to other node, so the node which has more unmatches will get high score", name: "Anti Affinity: one node has more matching pods comparing to other node, so the node which has more unmatches will get high score",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
// Test the symmetry cases for anti affinity // Test the symmetry cases for anti affinity
{ {
name: "Anti Affinity symmetry: the existing pods in node which has anti affinity match will get high score", name: "Anti Affinity symmetry: the existing pods in node which has anti affinity match will get high score",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: awayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: awayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: awayFromS1InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelAzAz2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelAzAz2}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
// Test both affinity and anti-affinity // Test both affinity and anti-affinity
{ {
name: "Affinity and Anti Affinity: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity", name: "Affinity and Anti Affinity: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelAzAz1}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
}, },
// Combined cases considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels (they are in the same RC/service), // Combined cases considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels (they are in the same RC/service),
// the pod prefer to run together with its brother pods in the same region, but wants to stay away from them at node level, // the pod prefer to run together with its brother pods in the same region, but wants to stay away from them at node level,
// so that all the pods of a RC/service can stay in a same region but trying to separate with each other // so that all the pods of a RC/service can stay in a same region but trying to separate with each other
// machine-1,machine-3,machine-4 are in ChinaRegion others machine-2,machine-5 are in IndiaRegion // node-1,node-3,node-4 are in ChinaRegion others node-2,node-5 are in IndiaRegion
{ {
name: "Affinity and Anti Affinity: considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels", name: "Affinity and Anti Affinity: considering both affinity and anti-affinity, the pod to schedule and existing pods have the same labels",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node3"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine4"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node4"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine5"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node5"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChinaAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChinaAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine4", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node4", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node5", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: framework.MaxNodeScore}, {Name: "machine4", Score: framework.MaxNodeScore}, {Name: "machine5", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: framework.MaxNodeScore}, {Name: "node4", Score: framework.MaxNodeScore}, {Name: "node5", Score: 0}},
}, },
// Consider Affinity, Anti Affinity and symmetry together. // Consider Affinity, Anti Affinity and symmetry together.
// for Affinity, the weights are: 8, 0, 0, 0 // for Affinity, the weights are: 8, 0, 0, 0
@ -629,18 +629,18 @@ func TestPreferredAffinity(t *testing.T) {
name: "Affinity and Anti Affinity and symmetry: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity & symmetry", name: "Affinity and Anti Affinity and symmetry: considered only preferredDuringSchedulingIgnoredDuringExecution in both pod affinity & anti affinity & symmetry",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: stayWithS1InRegionAwayFromS2InAz}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS2}},
{Spec: v1.PodSpec{NodeName: "machine3", Affinity: stayWithS1InRegionAwayFromS2InAz}}, {Spec: v1.PodSpec{NodeName: "node3", Affinity: stayWithS1InRegionAwayFromS2InAz}},
{Spec: v1.PodSpec{NodeName: "machine4", Affinity: awayFromS1InAz}}, {Spec: v1.PodSpec{NodeName: "node4", Affinity: awayFromS1InAz}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelAzAz1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine4", Labels: labelAzAz2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node4", Labels: labelAzAz2}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: framework.MaxNodeScore}, {Name: "machine4", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: framework.MaxNodeScore}, {Name: "node4", Score: 0}},
}, },
// Cover https://github.com/kubernetes/kubernetes/issues/82796 which panics upon: // Cover https://github.com/kubernetes/kubernetes/issues/82796 which panics upon:
// 1. Some nodes in a topology don't have pods with affinity, but other nodes in the same topology have. // 1. Some nodes in a topology don't have pods with affinity, but other nodes in the same topology have.
@ -649,22 +649,22 @@ func TestPreferredAffinity(t *testing.T) {
name: "Avoid panic when partial nodes in a topology don't have pods with affinity", name: "Avoid panic when partial nodes in a topology don't have pods with affinity",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: ""}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: stayWithS1InRegionAwayFromS2InAz}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: stayWithS1InRegionAwayFromS2InAz}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChina}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
}, },
{ {
name: "invalid Affinity fails PreScore", name: "invalid Affinity fails PreScore",
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: invalidAffinityLabels}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: invalidAffinityLabels}},
wantStatus: framework.NewStatus(framework.Error, `Invalid value: "{{.bad-value.}}"`), wantStatus: framework.NewStatus(framework.Error, `Invalid value: "{{.bad-value.}}"`),
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChina}},
}, },
}, },
{ {
@ -672,69 +672,69 @@ func TestPreferredAffinity(t *testing.T) {
pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: invalidAntiAffinityLabels}}, pod: &v1.Pod{Spec: v1.PodSpec{NodeName: "", Affinity: invalidAntiAffinityLabels}},
wantStatus: framework.NewStatus(framework.Error, `Invalid value: "{{.bad-value.}}"`), wantStatus: framework.NewStatus(framework.Error, `Invalid value: "{{.bad-value.}}"`),
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgChina}},
}, },
}, },
{ {
name: "Affinity with pods matching NamespaceSelector", name: "Affinity with pods matching NamespaceSelector",
pod: &v1.Pod{Spec: v1.PodSpec{Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
}, },
{ {
name: "Affinity with pods matching both NamespaceSelector and Namespaces fields", name: "Affinity with pods matching both NamespaceSelector and Namespaces fields",
pod: &v1.Pod{Spec: v1.PodSpec{Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{Affinity: affinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
}, },
{ {
name: "Affinity with pods matching NamespaceSelector", name: "Affinity with pods matching NamespaceSelector",
pod: &v1.Pod{Spec: v1.PodSpec{Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
{ {
name: "Affinity with pods matching both NamespaceSelector and Namespaces fields", name: "Affinity with pods matching both NamespaceSelector and Namespaces fields",
pod: &v1.Pod{Spec: v1.PodSpec{Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, pod: &v1.Pod{Spec: v1.PodSpec{Affinity: antiAffinityNamespaceSelector}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node1"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelSecurityS1}},
{Spec: v1.PodSpec{NodeName: "machine2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}}, {Spec: v1.PodSpec{NodeName: "node2"}, ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team1", Labels: podLabelSecurityS1}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: framework.MaxNodeScore}},
}, },
} }
for _, test := range tests { for _, test := range tests {
@ -826,76 +826,76 @@ func TestPreferredAffinityWithHardPodAffinitySymmetricWeight(t *testing.T) {
name: "with default weight", name: "with default weight",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardPodAffinity}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardPodAffinity}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
{ {
name: "with zero weight", name: "with zero weight",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: podLabelServiceS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardPodAffinity}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardPodAffinity}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
hardPodAffinityWeight: 0, hardPodAffinityWeight: 0,
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "with no matching namespace", name: "with no matching namespace",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelServiceS1}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team2", Labels: podLabelServiceS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardPodAffinity}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardPodAffinity}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "with matching NamespaceSelector", name: "with matching NamespaceSelector",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelServiceS1}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam1.team1", Labels: podLabelServiceS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardPodAffinity}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardPodAffinity}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
{ {
name: "with matching Namespaces", name: "with matching Namespaces",
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelServiceS1}}, pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: "subteam2.team2", Labels: podLabelServiceS1}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: v1.PodSpec{NodeName: "machine1", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node1", Affinity: hardPodAffinity}},
{Spec: v1.PodSpec{NodeName: "machine2", Affinity: hardPodAffinity}}, {Spec: v1.PodSpec{NodeName: "node2", Affinity: hardPodAffinity}},
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: labelRgChina}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: labelRgChina}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: labelRgIndia}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: labelRgIndia}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: labelAzAz1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: labelAzAz1}},
}, },
hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight, hardPodAffinityWeight: v1.DefaultHardPodAffinitySymmetricWeight,
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}, {Name: "node3", Score: 0}},
}, },
} }
for _, test := range tests { for _, test := range tests {

View File

@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
"k8s.io/kubernetes/pkg/scheduler/framework/runtime" "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
"k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/internal/cache"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
// TODO: Add test case for RequiredDuringSchedulingRequiredDuringExecution after it's implemented. // TODO: Add test case for RequiredDuringSchedulingRequiredDuringExecution after it's implemented.
@ -49,37 +50,25 @@ func TestNodeAffinity(t *testing.T) {
}, },
{ {
name: "missing labels", name: "missing labels",
pod: &v1.Pod{ pod: st.MakePod().NodeSelector(map[string]string{
Spec: v1.PodSpec{ "foo": "bar",
NodeSelector: map[string]string{ }).Obj(),
"foo": "bar",
},
},
},
wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonPod), wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReasonPod),
}, },
{ {
name: "same labels", name: "same labels",
pod: &v1.Pod{ pod: st.MakePod().NodeSelector(map[string]string{
Spec: v1.PodSpec{ "foo": "bar",
NodeSelector: map[string]string{ }).Obj(),
"foo": "bar",
},
},
},
labels: map[string]string{ labels: map[string]string{
"foo": "bar", "foo": "bar",
}, },
}, },
{ {
name: "node labels are superset", name: "node labels are superset",
pod: &v1.Pod{ pod: st.MakePod().NodeSelector(map[string]string{
Spec: v1.PodSpec{ "foo": "bar",
NodeSelector: map[string]string{ }).Obj(),
"foo": "bar",
},
},
},
labels: map[string]string{ labels: map[string]string{
"foo": "bar", "foo": "bar",
"baz": "blah", "baz": "blah",
@ -87,14 +76,10 @@ func TestNodeAffinity(t *testing.T) {
}, },
{ {
name: "node labels are subset", name: "node labels are subset",
pod: &v1.Pod{ pod: st.MakePod().NodeSelector(map[string]string{
Spec: v1.PodSpec{ "foo": "bar",
NodeSelector: map[string]string{ "baz": "blah",
"foo": "bar", }).Obj(),
"baz": "blah",
},
},
},
labels: map[string]string{ labels: map[string]string{
"foo": "bar", "foo": "bar",
}, },
@ -1029,69 +1014,69 @@ func TestNodeAffinityPriority(t *testing.T) {
disablePreScore bool disablePreScore bool
}{ }{
{ {
name: "all machines are same priority as NodeAffinity is nil", name: "all nodes are same priority as NodeAffinity is nil",
pod: &v1.Pod{ pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{}, Annotations: map[string]string{},
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: label3}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "no machine matches preferred scheduling requirements in NodeAffinity of pod so all machines' priority is zero", name: "no node matches preferred scheduling requirements in NodeAffinity of pod so all nodes' priority is zero",
pod: &v1.Pod{ pod: &v1.Pod{
Spec: v1.PodSpec{ Spec: v1.PodSpec{
Affinity: affinity1, Affinity: affinity1,
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label4}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label4}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: label3}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "only machine1 matches the preferred scheduling requirements of pod", name: "only node1 matches the preferred scheduling requirements of pod",
pod: &v1.Pod{ pod: &v1.Pod{
Spec: v1.PodSpec{ Spec: v1.PodSpec{
Affinity: affinity1, Affinity: affinity1,
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label3}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: label3}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}, {Name: "machine3", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}, {Name: "node3", Score: 0}},
}, },
{ {
name: "all machines matches the preferred scheduling requirements of pod but with different priorities ", name: "all nodes matches the preferred scheduling requirements of pod but with different priorities ",
pod: &v1.Pod{ pod: &v1.Pod{
Spec: v1.PodSpec{ Spec: v1.PodSpec{
Affinity: affinity2, Affinity: affinity2,
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: label5}}, {ObjectMeta: metav1.ObjectMeta{Name: "node5", Labels: label5}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 18}, {Name: "machine5", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 36}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 18}, {Name: "node5", Score: framework.MaxNodeScore}, {Name: "node2", Score: 36}},
}, },
{ {
name: "added affinity", name: "added affinity",
pod: &v1.Pod{}, pod: &v1.Pod{},
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
args: config.NodeAffinityArgs{ args: config.NodeAffinityArgs{
AddedAffinity: affinity1.NodeAffinity, AddedAffinity: affinity1.NodeAffinity,
}, },
@ -1104,11 +1089,11 @@ func TestNodeAffinityPriority(t *testing.T) {
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine3", Labels: label5}}, {ObjectMeta: metav1.ObjectMeta{Name: "node3", Labels: label5}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 40}, {Name: "machine2", Score: 60}, {Name: "machine3", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 40}, {Name: "node2", Score: 60}, {Name: "node3", Score: framework.MaxNodeScore}},
args: config.NodeAffinityArgs{ args: config.NodeAffinityArgs{
AddedAffinity: &v1.NodeAffinity{ AddedAffinity: &v1.NodeAffinity{
PreferredDuringSchedulingIgnoredDuringExecution: []v1.PreferredSchedulingTerm{ PreferredDuringSchedulingIgnoredDuringExecution: []v1.PreferredSchedulingTerm{
@ -1136,11 +1121,11 @@ func TestNodeAffinityPriority(t *testing.T) {
}, },
}, },
nodes: []*v1.Node{ nodes: []*v1.Node{
{ObjectMeta: metav1.ObjectMeta{Name: "machine1", Labels: label1}}, {ObjectMeta: metav1.ObjectMeta{Name: "node1", Labels: label1}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine5", Labels: label5}}, {ObjectMeta: metav1.ObjectMeta{Name: "node5", Labels: label5}},
{ObjectMeta: metav1.ObjectMeta{Name: "machine2", Labels: label2}}, {ObjectMeta: metav1.ObjectMeta{Name: "node2", Labels: label2}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 18}, {Name: "machine5", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 36}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 18}, {Name: "node5", Score: framework.MaxNodeScore}, {Name: "node2", Score: 36}},
disablePreScore: true, disablePreScore: true,
}, },
} }

View File

@ -22,8 +22,8 @@ import (
"testing" "testing"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestNodeName(t *testing.T) { func TestNodeName(t *testing.T) {
@ -39,29 +39,13 @@ func TestNodeName(t *testing.T) {
name: "no host specified", name: "no host specified",
}, },
{ {
pod: &v1.Pod{ pod: st.MakePod().Node("foo").Obj(),
Spec: v1.PodSpec{ node: st.MakeNode().Name("foo").Obj(),
NodeName: "foo",
},
},
node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
},
name: "host matches", name: "host matches",
}, },
{ {
pod: &v1.Pod{ pod: st.MakePod().Node("bar").Obj(),
Spec: v1.PodSpec{ node: st.MakeNode().Name("foo").Obj(),
NodeName: "bar",
},
},
node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
},
name: "host doesn't match", name: "host doesn't match",
wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReason), wantStatus: framework.NewStatus(framework.UnschedulableAndUnresolvable, ErrReason),
}, },

View File

@ -27,6 +27,7 @@ import (
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func newPod(host string, hostPortInfos ...string) *v1.Pod { func newPod(host string, hostPortInfos ...string) *v1.Pod {
@ -41,16 +42,7 @@ func newPod(host string, hostPortInfos ...string) *v1.Pod {
Protocol: v1.Protocol(splited[0]), Protocol: v1.Protocol(splited[0]),
}) })
} }
return &v1.Pod{ return st.MakePod().Node(host).ContainerPort(networkPorts).Obj()
Spec: v1.PodSpec{
NodeName: host,
Containers: []v1.Container{
{
Ports: networkPorts,
},
},
},
}
} }
func TestNodePorts(t *testing.T) { func TestNodePorts(t *testing.T) {
@ -184,66 +176,42 @@ func TestGetContainerPorts(t *testing.T) {
expected []*v1.ContainerPort expected []*v1.ContainerPort
}{ }{
{ {
pod1: &v1.Pod{ pod1: st.MakePod().ContainerPort([]v1.ContainerPort{
Spec: v1.PodSpec{ {
Containers: []v1.Container{ ContainerPort: 8001,
{ Protocol: v1.ProtocolTCP,
Ports: []v1.ContainerPort{
{
ContainerPort: 8001,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8002,
Protocol: v1.ProtocolTCP,
},
},
},
{
Ports: []v1.ContainerPort{
{
ContainerPort: 8003,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8004,
Protocol: v1.ProtocolTCP,
},
},
},
},
}, },
}, {
pod2: &v1.Pod{ ContainerPort: 8002,
Spec: v1.PodSpec{ Protocol: v1.ProtocolTCP,
Containers: []v1.Container{ }}).ContainerPort([]v1.ContainerPort{
{ {
Ports: []v1.ContainerPort{ ContainerPort: 8003,
{ Protocol: v1.ProtocolTCP,
ContainerPort: 8011,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8012,
Protocol: v1.ProtocolTCP,
},
},
},
{
Ports: []v1.ContainerPort{
{
ContainerPort: 8013,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8014,
Protocol: v1.ProtocolTCP,
},
},
},
},
}, },
}, {
ContainerPort: 8004,
Protocol: v1.ProtocolTCP,
},
}).Obj(),
pod2: st.MakePod().ContainerPort([]v1.ContainerPort{
{
ContainerPort: 8011,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8012,
Protocol: v1.ProtocolTCP,
}}).ContainerPort([]v1.ContainerPort{
{
ContainerPort: 8013,
Protocol: v1.ProtocolTCP,
},
{
ContainerPort: 8014,
Protocol: v1.ProtocolTCP,
},
}).Obj(),
expected: []*v1.ContainerPort{ expected: []*v1.ContainerPort{
{ {
ContainerPort: 8001, ContainerPort: 8001,

View File

@ -29,6 +29,7 @@ import (
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
"k8s.io/kubernetes/pkg/scheduler/framework/runtime" "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
"k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/internal/cache"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestNodeResourcesBalancedAllocation(t *testing.T) { func TestNodeResourcesBalancedAllocation(t *testing.T) {
@ -52,7 +53,7 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
}, },
}, },
}, },
NodeName: "machine1", NodeName: "node1",
} }
labels1 := map[string]string{ labels1 := map[string]string{
"foo": "bar", "foo": "bar",
@ -62,17 +63,8 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
"bar": "foo", "bar": "foo",
"baz": "blah", "baz": "blah",
} }
machine1Spec := v1.PodSpec{
NodeName: "machine1",
}
machine2Spec := v1.PodSpec{
NodeName: "machine2",
}
noResources := v1.PodSpec{
Containers: []v1.Container{},
}
cpuOnly := v1.PodSpec{ cpuOnly := v1.PodSpec{
NodeName: "machine1", NodeName: "node1",
Containers: []v1.Container{ Containers: []v1.Container{
{ {
Resources: v1.ResourceRequirements{ Resources: v1.ResourceRequirements{
@ -93,9 +85,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
}, },
} }
cpuOnly2 := cpuOnly cpuOnly2 := cpuOnly
cpuOnly2.NodeName = "machine2" cpuOnly2.NodeName = "node2"
cpuAndMemory := v1.PodSpec{ cpuAndMemory := v1.PodSpec{
NodeName: "machine2", NodeName: "node2",
Containers: []v1.Container{ Containers: []v1.Container{
{ {
Resources: v1.ResourceRequirements{ Resources: v1.ResourceRequirements{
@ -115,13 +107,6 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
}, },
}, },
} }
nonZeroContainer := v1.PodSpec{
Containers: []v1.Container{{}},
}
nonZeroContainer1 := v1.PodSpec{
NodeName: "machine1",
Containers: []v1.Container{{}},
}
defaultResourceBalancedAllocationSet := []config.ResourceSpec{ defaultResourceBalancedAllocationSet := []config.ResourceSpec{
{Name: string(v1.ResourceCPU), Weight: 1}, {Name: string(v1.ResourceCPU), Weight: 1},
@ -148,9 +133,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// CPU Fraction: 0 / 4000 = 0 % // CPU Fraction: 0 / 4000 = 0 %
// Memory Fraction: 0 / 10000 = 0% // Memory Fraction: 0 / 10000 = 0%
// Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore // Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore
pod: &v1.Pod{Spec: noResources}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000, nil), makeNode("machine2", 4000, 10000, nil)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000, nil), makeNode("node2", 4000, 10000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "nothing scheduled, nothing requested", name: "nothing scheduled, nothing requested",
args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet}, args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet},
}, },
@ -166,9 +151,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Node2 std: 0 // Node2 std: 0
// Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore // Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore
pod: &v1.Pod{Spec: cpuAndMemory}, pod: &v1.Pod{Spec: cpuAndMemory},
nodes: []*v1.Node{makeNode("machine1", 4000, 10000, nil), makeNode("machine2", 6000, 10000, nil)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000, nil), makeNode("node2", 6000, 10000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 87}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 87}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "nothing scheduled, resources requested, differently sized machines", name: "nothing scheduled, resources requested, differently sized nodes",
args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet}, args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet},
}, },
{ {
@ -182,15 +167,15 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Memory Fraction: 0 / 10000 = 0% // Memory Fraction: 0 / 10000 = 0%
// Node2 std: 0 // Node2 std: 0
// Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore // Node2 Score: (1-0) * MaxNodeScore = MaxNodeScore
pod: &v1.Pod{Spec: noResources}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000, nil), makeNode("machine2", 4000, 10000, nil)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000, nil), makeNode("node2", 4000, 10000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node2", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "no resources requested, pods without container scheduled", name: "no resources requested, pods without container scheduled",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Node("node1").Labels(labels2).Obj(),
{Spec: machine1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Node("node1").Labels(labels1).Obj(),
{Spec: machine2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Node("node2").Labels(labels1).Obj(),
{Spec: machine2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Node("node2").Labels(labels1).Obj(),
}, },
args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet}, args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet},
}, },
@ -205,13 +190,13 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Memory Fraction: 0 / 1000 = 0% // Memory Fraction: 0 / 1000 = 0%
// Node2 std: (0 - 0) / 2 = 0 // Node2 std: (0 - 0) / 2 = 0
// Node2 Score: (1 - 0)*MaxNodeScore = 100 // Node2 Score: (1 - 0)*MaxNodeScore = 100
pod: &v1.Pod{Spec: nonZeroContainer}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 250, 1000*1024*1024, nil), makeNode("machine2", 250, 1000*1024*1024, nil)}, nodes: []*v1.Node{makeNode("node1", 250, 1000*1024*1024, nil), makeNode("node2", 250, 1000*1024*1024, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 100}, {Name: "machine2", Score: 100}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 100}, {Name: "node2", Score: 100}},
name: "no resources requested, pods with container scheduled", name: "no resources requested, pods with container scheduled",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: nonZeroContainer1}, st.MakePod().Node("node1").Obj(),
{Spec: nonZeroContainer1}, st.MakePod().Node("node1").Obj(),
}, },
args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet}, args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet},
}, },
@ -226,9 +211,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Memory Fraction: 5000 / 20000 = 25% // Memory Fraction: 5000 / 20000 = 25%
// Node2 std: (0.6 - 0.25) / 2 = 0.175 // Node2 std: (0.6 - 0.25) / 2 = 0.175
// Node2 Score: (1 - 0.175)*MaxNodeScore = 82 // Node2 Score: (1 - 0.175)*MaxNodeScore = 82
pod: &v1.Pod{Spec: noResources}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 10000, 20000, nil), makeNode("machine2", 10000, 20000, nil)}, nodes: []*v1.Node{makeNode("node1", 10000, 20000, nil), makeNode("node2", 10000, 20000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 70}, {Name: "machine2", Score: 82}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 70}, {Name: "node2", Score: 82}},
name: "no resources requested, pods scheduled with resources", name: "no resources requested, pods scheduled with resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: cpuOnly, ObjectMeta: metav1.ObjectMeta{Labels: labels2}},
@ -250,8 +235,8 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Node2 std: (0.6 - 0.5) / 2 = 0.05 // Node2 std: (0.6 - 0.5) / 2 = 0.05
// Node2 Score: (1 - 0.05)*MaxNodeScore = 95 // Node2 Score: (1 - 0.05)*MaxNodeScore = 95
pod: &v1.Pod{Spec: cpuAndMemory}, pod: &v1.Pod{Spec: cpuAndMemory},
nodes: []*v1.Node{makeNode("machine1", 10000, 20000, nil), makeNode("machine2", 10000, 20000, nil)}, nodes: []*v1.Node{makeNode("node1", 10000, 20000, nil), makeNode("node2", 10000, 20000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 82}, {Name: "machine2", Score: 95}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 82}, {Name: "node2", Score: 95}},
name: "resources requested, pods scheduled with resources", name: "resources requested, pods scheduled with resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly}, {Spec: cpuOnly},
@ -271,9 +256,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Node2 std: (0.6 - 0.2) / 2 = 0.2 // Node2 std: (0.6 - 0.2) / 2 = 0.2
// Node2 Score: (1 - 0.2)*MaxNodeScore = 80 // Node2 Score: (1 - 0.2)*MaxNodeScore = 80
pod: &v1.Pod{Spec: cpuAndMemory}, pod: &v1.Pod{Spec: cpuAndMemory},
nodes: []*v1.Node{makeNode("machine1", 10000, 20000, nil), makeNode("machine2", 10000, 50000, nil)}, nodes: []*v1.Node{makeNode("node1", 10000, 20000, nil), makeNode("node2", 10000, 50000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 82}, {Name: "machine2", Score: 80}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 82}, {Name: "node2", Score: 80}},
name: "resources requested, pods scheduled with resources, differently sized machines", name: "resources requested, pods scheduled with resources, differently sized nodes",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly}, {Spec: cpuOnly},
{Spec: cpuAndMemory}, {Spec: cpuAndMemory},
@ -293,8 +278,8 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Node2 std: (1 - 0.5) / 2 = 0.25 // Node2 std: (1 - 0.5) / 2 = 0.25
// Node2 Score: (1 - 0.25)*MaxNodeScore = 75 // Node2 Score: (1 - 0.25)*MaxNodeScore = 75
pod: &v1.Pod{Spec: cpuOnly}, pod: &v1.Pod{Spec: cpuOnly},
nodes: []*v1.Node{makeNode("machine1", 6000, 10000, nil), makeNode("machine2", 6000, 10000, nil)}, nodes: []*v1.Node{makeNode("node1", 6000, 10000, nil), makeNode("node2", 6000, 10000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 50}, {Name: "machine2", Score: 75}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 50}, {Name: "node2", Score: 75}},
name: "requested resources at node capacity", name: "requested resources at node capacity",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly}, {Spec: cpuOnly},
@ -303,9 +288,9 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet}, args: config.NodeResourcesBalancedAllocationArgs{Resources: defaultResourceBalancedAllocationSet},
}, },
{ {
pod: &v1.Pod{Spec: noResources}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 0, 0, nil), makeNode("machine2", 0, 0, nil)}, nodes: []*v1.Node{makeNode("node1", 0, 0, nil), makeNode("node2", 0, 0, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 100}, {Name: "machine2", Score: 100}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 100}, {Name: "node2", Score: 100}},
name: "zero node resources, pods scheduled with resources", name: "zero node resources, pods scheduled with resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly}, {Spec: cpuOnly},
@ -326,22 +311,12 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
// Node2 std: sqrt(((0.8571 - 0.378) * (0.8571 - 0.378) + (0.378 - 0.125) * (0.378 - 0.125)) + (0.378 - 0.125) * (0.378 - 0.125)) / 3) = 0.345 // Node2 std: sqrt(((0.8571 - 0.378) * (0.8571 - 0.378) + (0.378 - 0.125) * (0.378 - 0.125)) + (0.378 - 0.125) * (0.378 - 0.125)) / 3) = 0.345
// Node2 Score: (1 - 0.358)*MaxNodeScore = 65 // Node2 Score: (1 - 0.358)*MaxNodeScore = 65
{ {
pod: &v1.Pod{ pod: st.MakePod().Req(map[v1.ResourceName]string{
Spec: v1.PodSpec{ v1.ResourceMemory: "0",
Containers: []v1.Container{ "nvidia.com/gpu": "1",
{ }).Obj(),
Resources: v1.ResourceRequirements{ nodes: []*v1.Node{makeNode("node1", 3500, 40000, scalarResource), makeNode("node2", 3500, 40000, scalarResource)},
Requests: v1.ResourceList{ expectedList: []framework.NodeScore{{Name: "node1", Score: 70}, {Name: "node2", Score: 65}},
v1.ResourceMemory: resource.MustParse("0"),
"nvidia.com/gpu": resource.MustParse("1"),
},
},
},
},
},
},
nodes: []*v1.Node{makeNode("machine1", 3500, 40000, scalarResource), makeNode("machine2", 3500, 40000, scalarResource)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 70}, {Name: "machine2", Score: 65}},
name: "include scalar resource on a node for balanced resource allocation", name: "include scalar resource on a node for balanced resource allocation",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuAndMemory}, {Spec: cpuAndMemory},
@ -353,13 +328,13 @@ func TestNodeResourcesBalancedAllocation(t *testing.T) {
{Name: "nvidia.com/gpu", Weight: 1}, {Name: "nvidia.com/gpu", Weight: 1},
}}, }},
}, },
// Only one node (machine1) has the scalar resource, pod doesn't request the scalar resource and the scalar resource should be skipped for consideration. // Only one node (node1) has the scalar resource, pod doesn't request the scalar resource and the scalar resource should be skipped for consideration.
// Node1: std = 0, score = 100 // Node1: std = 0, score = 100
// Node2: std = 0, score = 100 // Node2: std = 0, score = 100
{ {
pod: &v1.Pod{Spec: v1.PodSpec{Containers: []v1.Container{{}}}}, pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 3500, 40000, scalarResource), makeNode("machine2", 3500, 40000, nil)}, nodes: []*v1.Node{makeNode("node1", 3500, 40000, scalarResource), makeNode("node2", 3500, 40000, nil)},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 100}, {Name: "machine2", Score: 100}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 100}, {Name: "node2", Score: 100}},
name: "node without the scalar resource results to a higher score", name: "node without the scalar resource results to a higher score",
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: cpuOnly}, {Spec: cpuOnly},

View File

@ -81,7 +81,7 @@ func TestLeastAllocatedScoringStrategy(t *testing.T) {
// CPU Score: ((6000 - 3000) * MaxNodeScore) / 6000 = 50 // CPU Score: ((6000 - 3000) * MaxNodeScore) / 6000 = 50
// Memory Score: ((10000 - 5000) * MaxNodeScore) / 10000 = 50 // Memory Score: ((10000 - 5000) * MaxNodeScore) / 10000 = 50
// Node2 Score: (50 + 50) / 2 = 50 // Node2 Score: (50 + 50) / 2 = 50
name: "nothing scheduled, resources requested, differently sized machines", name: "nothing scheduled, resources requested, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -95,7 +95,7 @@ func TestLeastAllocatedScoringStrategy(t *testing.T) {
resources: defaultResources, resources: defaultResources,
}, },
{ {
name: "Resources not set, nothing scheduled, resources requested, differently sized machines", name: "Resources not set, nothing scheduled, resources requested, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -190,7 +190,7 @@ func TestLeastAllocatedScoringStrategy(t *testing.T) {
// CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40 // CPU Score: ((10000 - 6000) * MaxNodeScore) / 10000 = 40
// Memory Score: ((50000 - 10000) * MaxNodeScore) / 50000 = 80 // Memory Score: ((50000 - 10000) * MaxNodeScore) / 50000 = 80
// Node2 Score: (40 + 80) / 2 = 60 // Node2 Score: (40 + 80) / 2 = 60
name: "resources requested, pods scheduled with resources, differently sized machines", name: "resources requested, pods scheduled with resources, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -249,7 +249,7 @@ func TestLeastAllocatedScoringStrategy(t *testing.T) {
// CPU Score: ((6000 - 3000) *100) / 6000 = 50 // CPU Score: ((6000 - 3000) *100) / 6000 = 50
// Memory Score: ((10000 - 5000) *100) / 10000 = 50 // Memory Score: ((10000 - 5000) *100) / 10000 = 50
// Node2 Score: (50 * 1 + 50 * 2) / (1 + 2) = 50 // Node2 Score: (50 * 1 + 50 * 2) / (1 + 2) = 50
name: "nothing scheduled, resources requested with different weight on CPU and memory, differently sized machines", name: "nothing scheduled, resources requested with different weight on CPU and memory, differently sized nodes",
requestedPod: st.MakePod().Node("node1"). requestedPod: st.MakePod().Node("node1").
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).

View File

@ -80,7 +80,7 @@ func TestMostAllocatedScoringStrategy(t *testing.T) {
// CPU Score: (3000 * MaxNodeScore) / 6000 = 50 // CPU Score: (3000 * MaxNodeScore) / 6000 = 50
// Memory Score: (5000 * MaxNodeScore) / 10000 = 50 // Memory Score: (5000 * MaxNodeScore) / 10000 = 50
// Node2 Score: (50 + 50) / 2 = 50 // Node2 Score: (50 + 50) / 2 = 50
name: "nothing scheduled, resources requested, differently sized machines", name: "nothing scheduled, resources requested, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -94,7 +94,7 @@ func TestMostAllocatedScoringStrategy(t *testing.T) {
resources: defaultResources, resources: defaultResources,
}, },
{ {
name: "Resources not set, nothing scheduled, resources requested, differently sized machines", name: "Resources not set, nothing scheduled, resources requested, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -185,7 +185,7 @@ func TestMostAllocatedScoringStrategy(t *testing.T) {
// CPU Score: (3000 *100) / 6000 = 50 // CPU Score: (3000 *100) / 6000 = 50
// Memory Score: (5000 *100) / 10000 = 50 // Memory Score: (5000 *100) / 10000 = 50
// Node2 Score: (50 * 1 + 50 * 2) / (1 + 2) = 50 // Node2 Score: (50 * 1 + 50 * 2) / (1 + 2) = 50
name: "nothing scheduled, resources requested, differently sized machines", name: "nothing scheduled, resources requested, differently sized nodes",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).

View File

@ -24,7 +24,6 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/scheduler/apis/config" "k8s.io/kubernetes/pkg/scheduler/apis/config"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
@ -73,7 +72,7 @@ func TestRequestedToCapacityRatioScoringStrategy(t *testing.T) {
shape: shape, shape: shape,
}, },
{ {
name: "nothing scheduled, resources requested, differently sized machines (default - least requested nodes have priority)", name: "nothing scheduled, resources requested, differently sized nodes (default - least requested nodes have priority)",
requestedPod: st.MakePod(). requestedPod: st.MakePod().
Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}). Req(map[v1.ResourceName]string{"cpu": "1000", "memory": "2000"}).
Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}). Req(map[v1.ResourceName]string{"cpu": "2000", "memory": "3000"}).
@ -213,38 +212,19 @@ func TestBrokenLinearFunction(t *testing.T) {
} }
func TestResourceBinPackingSingleExtended(t *testing.T) { func TestResourceBinPackingSingleExtended(t *testing.T) {
extendedResource := "intel.com/foo"
extendedResource1 := map[string]int64{ extendedResource1 := map[string]int64{
"intel.com/foo": 4, "intel.com/foo": 4,
} }
extendedResource2 := map[string]int64{ extendedResource2 := map[string]int64{
"intel.com/foo": 8, "intel.com/foo": 8,
} }
extendedResource3 := map[v1.ResourceName]string{
"intel.com/foo": "2",
}
extendedResource4 := map[v1.ResourceName]string{
"intel.com/foo": "4",
}
extendedResourcePod1 := v1.PodSpec{
Containers: []v1.Container{
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceName(extendedResource): resource.MustParse("2"),
},
},
},
},
}
extendedResourcePod2 := v1.PodSpec{
Containers: []v1.Container{
{
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceName(extendedResource): resource.MustParse("4"),
},
},
},
},
}
machine2Pod := extendedResourcePod1
machine2Pod.NodeName = "machine2"
tests := []struct { tests := []struct {
pod *v1.Pod pod *v1.Pod
pods []*v1.Pod pods []*v1.Pod
@ -255,8 +235,8 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
{ {
// Node1 Score = Node2 Score = 0 as the incoming Pod doesn't request extended resource. // Node1 Score = Node2 Score = 0 as the incoming Pod doesn't request extended resource.
pod: st.MakePod().Obj(), pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResource2), makeNode("machine2", 4000, 10000*1024*1024, extendedResource1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResource2), makeNode("node2", 4000, 10000*1024*1024, extendedResource1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "nothing scheduled, nothing requested", name: "nothing scheduled, nothing requested",
}, },
{ {
@ -271,13 +251,11 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
// resourceScoringFunction((0+2),4) // resourceScoringFunction((0+2),4)
// = 2/4 * maxUtilization = 50 = rawScoringFunction(50) // = 2/4 * maxUtilization = 50 = rawScoringFunction(50)
// Node2 Score: 5 // Node2 Score: 5
pod: &v1.Pod{Spec: extendedResourcePod1}, pod: st.MakePod().Req(extendedResource3).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResource2), makeNode("machine2", 4000, 10000*1024*1024, extendedResource1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResource2), makeNode("node2", 4000, 10000*1024*1024, extendedResource1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 2}, {Name: "machine2", Score: 5}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 2}, {Name: "node2", Score: 5}},
name: "resources requested, pods scheduled with less resources", name: "resources requested, pods scheduled with less resources",
pods: []*v1.Pod{ pods: []*v1.Pod{st.MakePod().Obj()},
st.MakePod().Obj(),
},
}, },
{ {
// Node1 scores (used resources) on 0-MaxNodeScore scale // Node1 scores (used resources) on 0-MaxNodeScore scale
@ -291,13 +269,11 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
// resourceScoringFunction((2+2),4) // resourceScoringFunction((2+2),4)
// = 4/4 * maxUtilization = maxUtilization = rawScoringFunction(maxUtilization) // = 4/4 * maxUtilization = maxUtilization = rawScoringFunction(maxUtilization)
// Node2 Score: 10 // Node2 Score: 10
pod: &v1.Pod{Spec: extendedResourcePod1}, pod: st.MakePod().Req(extendedResource3).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResource2), makeNode("machine2", 4000, 10000*1024*1024, extendedResource1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResource2), makeNode("node2", 4000, 10000*1024*1024, extendedResource1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 2}, {Name: "machine2", Score: 10}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 2}, {Name: "node2", Score: 10}},
name: "resources requested, pods scheduled with resources, on node with existing pod running ", name: "resources requested, pods scheduled with resources, on node with existing pod running ",
pods: []*v1.Pod{ pods: []*v1.Pod{st.MakePod().Req(extendedResource3).Node("node2").Obj()},
{Spec: machine2Pod},
},
}, },
{ {
// Node1 scores (used resources) on 0-MaxNodeScore scale // Node1 scores (used resources) on 0-MaxNodeScore scale
@ -311,9 +287,9 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
// resourceScoringFunction((0+4),4) // resourceScoringFunction((0+4),4)
// = 4/4 * maxUtilization = maxUtilization = rawScoringFunction(maxUtilization) // = 4/4 * maxUtilization = maxUtilization = rawScoringFunction(maxUtilization)
// Node2 Score: 10 // Node2 Score: 10
pod: &v1.Pod{Spec: extendedResourcePod2}, pod: st.MakePod().Req(extendedResource4).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResource2), makeNode("machine2", 4000, 10000*1024*1024, extendedResource1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResource2), makeNode("node2", 4000, 10000*1024*1024, extendedResource1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 5}, {Name: "machine2", Score: 10}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 5}, {Name: "node2", Score: 10}},
name: "resources requested, pods scheduled with more resources", name: "resources requested, pods scheduled with more resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
st.MakePod().Obj(), st.MakePod().Obj(),
@ -362,44 +338,24 @@ func TestResourceBinPackingSingleExtended(t *testing.T) {
} }
func TestResourceBinPackingMultipleExtended(t *testing.T) { func TestResourceBinPackingMultipleExtended(t *testing.T) {
extendedResource1 := "intel.com/foo"
extendedResource2 := "intel.com/bar"
extendedResources1 := map[string]int64{ extendedResources1 := map[string]int64{
"intel.com/foo": 4, "intel.com/foo": 4,
"intel.com/bar": 8, "intel.com/bar": 8,
} }
extendedResources2 := map[string]int64{ extendedResources2 := map[string]int64{
"intel.com/foo": 8, "intel.com/foo": 8,
"intel.com/bar": 4, "intel.com/bar": 4,
} }
extnededResourcePod1 := v1.PodSpec{ extendedResourcePod1 := map[v1.ResourceName]string{
Containers: []v1.Container{ "intel.com/foo": "2",
{ "intel.com/bar": "2",
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceName(extendedResource1): resource.MustParse("2"),
v1.ResourceName(extendedResource2): resource.MustParse("2"),
},
},
},
},
} }
extnededResourcePod2 := v1.PodSpec{ extendedResourcePod2 := map[v1.ResourceName]string{
Containers: []v1.Container{ "intel.com/foo": "4",
{ "intel.com/bar": "2",
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceName(extendedResource1): resource.MustParse("4"),
v1.ResourceName(extendedResource2): resource.MustParse("2"),
},
},
},
},
} }
machine2Pod := extnededResourcePod1
machine2Pod.NodeName = "machine2"
tests := []struct { tests := []struct {
pod *v1.Pod pod *v1.Pod
pods []*v1.Pod pods []*v1.Pod
@ -436,11 +392,10 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
// Node2 Score: (0 * 3) + (0 * 5) / 8 = 0 // Node2 Score: (0 * 3) + (0 * 5) / 8 = 0
pod: st.MakePod().Obj(), pod: st.MakePod().Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResources2), makeNode("machine2", 4000, 10000*1024*1024, extendedResources1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResources2), makeNode("node2", 4000, 10000*1024*1024, extendedResources1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "nothing scheduled, nothing requested", name: "nothing scheduled, nothing requested",
}, },
{ {
// resources["intel.com/foo"] = 3 // resources["intel.com/foo"] = 3
@ -469,15 +424,14 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
// = 2/8 * 100 = 25 = rawScoringFunction(25) // = 2/8 * 100 = 25 = rawScoringFunction(25)
// Node2 Score: (5 * 3) + (2 * 5) / 8 = 3 // Node2 Score: (5 * 3) + (2 * 5) / 8 = 3
pod: &v1.Pod{Spec: extnededResourcePod1}, pod: st.MakePod().Req(extendedResourcePod1).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResources2), makeNode("machine2", 4000, 10000*1024*1024, extendedResources1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResources2), makeNode("node2", 4000, 10000*1024*1024, extendedResources1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 4}, {Name: "machine2", Score: 3}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 4}, {Name: "node2", Score: 3}},
name: "resources requested, pods scheduled with less resources", name: "resources requested, pods scheduled with less resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
st.MakePod().Obj(), st.MakePod().Obj(),
}, },
}, },
{ {
// resources["intel.com/foo"] = 3 // resources["intel.com/foo"] = 3
@ -505,15 +459,12 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
// = 4/8 *100 = 50 = rawScoringFunction(50) // = 4/8 *100 = 50 = rawScoringFunction(50)
// Node2 Score: (10 * 3) + (5 * 5) / 8 = 7 // Node2 Score: (10 * 3) + (5 * 5) / 8 = 7
pod: &v1.Pod{Spec: extnededResourcePod1}, pod: st.MakePod().Req(extendedResourcePod1).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResources2), makeNode("machine2", 4000, 10000*1024*1024, extendedResources1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResources2), makeNode("node2", 4000, 10000*1024*1024, extendedResources1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 4}, {Name: "machine2", Score: 7}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 4}, {Name: "node2", Score: 7}},
name: "resources requested, pods scheduled with resources, on node with existing pod running ", name: "resources requested, pods scheduled with resources, on node with existing pod running ",
pods: []*v1.Pod{ pods: []*v1.Pod{st.MakePod().Req(extendedResourcePod2).Node("node2").Obj()},
{Spec: machine2Pod},
},
}, },
{ {
// resources["intel.com/foo"] = 3 // resources["intel.com/foo"] = 3
@ -556,9 +507,9 @@ func TestResourceBinPackingMultipleExtended(t *testing.T) {
// = 2/8 * 100 = 25 = rawScoringFunction(25) // = 2/8 * 100 = 25 = rawScoringFunction(25)
// Node2 Score: (10 * 3) + (2 * 5) / 8 = 5 // Node2 Score: (10 * 3) + (2 * 5) / 8 = 5
pod: &v1.Pod{Spec: extnededResourcePod2}, pod: st.MakePod().Req(extendedResourcePod2).Obj(),
nodes: []*v1.Node{makeNode("machine1", 4000, 10000*1024*1024, extendedResources2), makeNode("machine2", 4000, 10000*1024*1024, extendedResources1)}, nodes: []*v1.Node{makeNode("node1", 4000, 10000*1024*1024, extendedResources2), makeNode("node2", 4000, 10000*1024*1024, extendedResources1)},
expectedScores: []framework.NodeScore{{Name: "machine1", Score: 5}, {Name: "machine2", Score: 5}}, expectedScores: []framework.NodeScore{{Name: "node1", Score: 5}, {Name: "node2", Score: 5}},
name: "resources requested, pods scheduled with more resources", name: "resources requested, pods scheduled with more resources",
pods: []*v1.Pod{ pods: []*v1.Pod{
st.MakePod().Obj(), st.MakePod().Obj(),

View File

@ -36,6 +36,7 @@ import (
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake" fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake"
st "k8s.io/kubernetes/pkg/scheduler/testing"
volumeutil "k8s.io/kubernetes/pkg/volume/util" volumeutil "k8s.io/kubernetes/pkg/volume/util"
utilpointer "k8s.io/utils/pointer" utilpointer "k8s.io/utils/pointer"
) )
@ -68,195 +69,35 @@ func getVolumeLimitKey(filterType string) v1.ResourceName {
} }
func TestCSILimits(t *testing.T) { func TestCSILimits(t *testing.T) {
runningPod := &v1.Pod{ runningPod := st.MakePod().PVC("csi-ebs.csi.aws.com-3").Obj()
Spec: v1.PodSpec{ pendingVolumePod := st.MakePod().PVC("csi-4").Obj()
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-ebs.csi.aws.com-3",
},
},
},
},
},
}
pendingVolumePod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-4",
},
},
},
},
},
}
// Different pod than pendingVolumePod, but using the same unbound PVC // Different pod than pendingVolumePod, but using the same unbound PVC
unboundPVCPod2 := &v1.Pod{ unboundPVCPod2 := st.MakePod().PVC("csi-4").Obj()
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-4",
},
},
},
},
},
}
missingPVPod := &v1.Pod{ missingPVPod := st.MakePod().PVC("csi-6").Obj()
Spec: v1.PodSpec{ noSCPVCPod := st.MakePod().PVC("csi-5").Obj()
Volumes: []v1.Volume{
{ gceTwoVolPod := st.MakePod().PVC("csi-pd.csi.storage.gke.io-1").PVC("csi-pd.csi.storage.gke.io-2").Obj()
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-6",
},
},
},
},
},
}
noSCPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-5",
},
},
},
},
},
}
gceTwoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-pd.csi.storage.gke.io-1",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-pd.csi.storage.gke.io-2",
},
},
},
},
},
}
// In-tree volumes // In-tree volumes
inTreeOneVolPod := &v1.Pod{ inTreeOneVolPod := st.MakePod().PVC("csi-kubernetes.io/aws-ebs-0").Obj()
Spec: v1.PodSpec{ inTreeTwoVolPod := st.MakePod().PVC("csi-kubernetes.io/aws-ebs-1").PVC("csi-kubernetes.io/aws-ebs-2").Obj()
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-kubernetes.io/aws-ebs-0",
},
},
},
},
},
}
inTreeTwoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-kubernetes.io/aws-ebs-1",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-kubernetes.io/aws-ebs-2",
},
},
},
},
},
}
// pods with matching csi driver names
csiEBSOneVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-ebs.csi.aws.com-0",
},
},
},
},
},
}
csiEBSTwoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-ebs.csi.aws.com-1",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-ebs.csi.aws.com-2",
},
},
},
},
},
}
inTreeNonMigratableOneVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "csi-kubernetes.io/hostpath-0",
},
},
},
},
},
}
ephemeralVolumePod := &v1.Pod{ // pods with matching csi driver names
ObjectMeta: metav1.ObjectMeta{ csiEBSOneVolPod := st.MakePod().PVC("csi-ebs.csi.aws.com-0").Obj()
Namespace: "test", csiEBSTwoVolPod := st.MakePod().PVC("csi-ebs.csi.aws.com-1").PVC("csi-ebs.csi.aws.com-2").Obj()
Name: "abc",
UID: "12345", inTreeNonMigratableOneVolPod := st.MakePod().PVC("csi-kubernetes.io/hostpath-0").Obj()
},
Spec: v1.PodSpec{ ephemeralVolumePod := st.MakePod().Name("abc").Namespace("test").UID("12345").Volume(
Volumes: []v1.Volume{ v1.Volume{
{ Name: "xyz",
Name: "xyz", VolumeSource: v1.VolumeSource{
VolumeSource: v1.VolumeSource{ Ephemeral: &v1.EphemeralVolumeSource{},
Ephemeral: &v1.EphemeralVolumeSource{},
},
},
}, },
}, }).Obj()
}
controller := true controller := true
ephemeralClaim := &v1.PersistentVolumeClaim{ ephemeralClaim := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -278,29 +119,18 @@ func TestCSILimits(t *testing.T) {
conflictingClaim := ephemeralClaim.DeepCopy() conflictingClaim := ephemeralClaim.DeepCopy()
conflictingClaim.OwnerReferences = nil conflictingClaim.OwnerReferences = nil
ephemeralTwoVolumePod := &v1.Pod{ ephemeralTwoVolumePod := st.MakePod().Name("abc").Namespace("test").UID("12345II").Volume(v1.Volume{
ObjectMeta: metav1.ObjectMeta{ Name: "x",
Namespace: "test", VolumeSource: v1.VolumeSource{
Name: "abc", Ephemeral: &v1.EphemeralVolumeSource{},
UID: "12345II",
}, },
Spec: v1.PodSpec{ }).Volume(v1.Volume{
Volumes: []v1.Volume{ Name: "y",
{ VolumeSource: v1.VolumeSource{
Name: "x", Ephemeral: &v1.EphemeralVolumeSource{},
VolumeSource: v1.VolumeSource{
Ephemeral: &v1.EphemeralVolumeSource{},
},
},
{
Name: "y",
VolumeSource: v1.VolumeSource{
Ephemeral: &v1.EphemeralVolumeSource{},
},
},
},
}, },
} }).Obj()
ephemeralClaimX := &v1.PersistentVolumeClaim{ ephemeralClaimX := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Namespace: ephemeralTwoVolumePod.Namespace, Namespace: ephemeralTwoVolumePod.Namespace,

View File

@ -18,6 +18,7 @@ package nodevolumelimits
import ( import (
"context" "context"
"fmt"
"os" "os"
"reflect" "reflect"
"strings" "strings"
@ -29,32 +30,67 @@ import (
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake" fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake"
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
st "k8s.io/kubernetes/pkg/scheduler/testing"
utilpointer "k8s.io/utils/pointer" utilpointer "k8s.io/utils/pointer"
) )
var (
oneVolPod = st.MakePod().Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"},
},
}).Obj()
twoVolPod = st.MakePod().Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"},
},
}).Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"},
},
}).Obj()
splitVolsPod = st.MakePod().Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
}).Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"},
},
}).Obj()
nonApplicablePod = st.MakePod().Volume(v1.Volume{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
}).Obj()
deletedPVCPod = st.MakePod().PVC("deletedPVC").Obj()
twoDeletedPVCPod = st.MakePod().PVC("deletedPVC").PVC("anotherDeletedPVC").Obj()
deletedPVPod = st.MakePod().PVC("pvcWithDeletedPV").Obj()
// deletedPVPod2 is a different pod than deletedPVPod but using the same PVC
deletedPVPod2 = st.MakePod().PVC("pvcWithDeletedPV").Obj()
anotherDeletedPVPod = st.MakePod().PVC("anotherPVCWithDeletedPV").Obj()
emptyPod = st.MakePod().Obj()
unboundPVCPod = st.MakePod().PVC("unboundPVC").Obj()
// Different pod than unboundPVCPod, but using the same unbound PVC
unboundPVCPod2 = st.MakePod().PVC("unboundPVC").Obj()
// pod with unbound PVC that's different to unboundPVC
anotherUnboundPVCPod = st.MakePod().PVC("anotherUnboundPVC").Obj()
)
func TestEphemeralLimits(t *testing.T) { func TestEphemeralLimits(t *testing.T) {
// We have to specify a valid filter and arbitrarily pick Cinder here. // We have to specify a valid filter and arbitrarily pick Cinder here.
// It doesn't matter for the test cases. // It doesn't matter for the test cases.
filterName := gcePDVolumeFilterType filterName := gcePDVolumeFilterType
driverName := csilibplugins.GCEPDInTreePluginName driverName := csilibplugins.GCEPDInTreePluginName
ephemeralVolumePod := &v1.Pod{ ephemeralVolumePod := st.MakePod().Name("abc").Namespace("test").UID("12345").Volume(v1.Volume{
ObjectMeta: metav1.ObjectMeta{ Name: "xyz",
Namespace: "test", VolumeSource: v1.VolumeSource{
Name: "abc", Ephemeral: &v1.EphemeralVolumeSource{},
UID: "12345",
}, },
Spec: v1.PodSpec{ }).Obj()
Volumes: []v1.Volume{
{
Name: "xyz",
VolumeSource: v1.VolumeSource{
Ephemeral: &v1.EphemeralVolumeSource{},
},
},
},
},
}
controller := true controller := true
ephemeralClaim := &v1.PersistentVolumeClaim{ ephemeralClaim := &v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
@ -130,180 +166,6 @@ func TestEphemeralLimits(t *testing.T) {
} }
func TestAzureDiskLimits(t *testing.T) { func TestAzureDiskLimits(t *testing.T) {
oneVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"},
},
},
},
},
}
twoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"},
},
},
},
},
}
splitVolsPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"},
},
},
},
},
}
nonApplicablePod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
},
},
}
deletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
},
},
}
twoDeletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherDeletedPVC",
},
},
},
},
},
}
deletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// deletedPVPod2 is a different pod than deletedPVPod but using the same PVC
deletedPVPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC
anotherDeletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherPVCWithDeletedPV",
},
},
},
},
},
}
emptyPod := &v1.Pod{
Spec: v1.PodSpec{},
}
unboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// Different pod than unboundPVCPod, but using the same unbound PVC
unboundPVCPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// pod with unbound PVC that's different to unboundPVC
anotherUnboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherUnboundPVC",
},
},
},
},
},
}
tests := []struct { tests := []struct {
newPod *v1.Pod newPod *v1.Pod
existingPods []*v1.Pod existingPods []*v1.Pod
@ -468,205 +330,8 @@ func TestAzureDiskLimits(t *testing.T) {
} }
func TestEBSLimits(t *testing.T) { func TestEBSLimits(t *testing.T) {
oneVolPod := &v1.Pod{ unboundPVCWithInvalidSCPod := st.MakePod().PVC("unboundPVCWithInvalidSCPod").Obj()
Spec: v1.PodSpec{ unboundPVCWithDefaultSCPod := st.MakePod().PVC("unboundPVCWithDefaultSCPod").Obj()
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"},
},
},
},
},
}
twoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"},
},
},
},
},
}
unboundPVCwithInvalidSCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVCwithInvalidSCPod",
},
},
},
},
},
}
unboundPVCwithDefaultSCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVCwithDefaultSCPod",
},
},
},
},
},
}
splitVolsPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"},
},
},
},
},
}
nonApplicablePod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
},
},
}
deletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
},
},
}
twoDeletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherDeletedPVC",
},
},
},
},
},
}
deletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// deletedPVPod2 is a different pod than deletedPVPod but using the same PVC
deletedPVPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC
anotherDeletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherPVCWithDeletedPV",
},
},
},
},
},
}
emptyPod := &v1.Pod{
Spec: v1.PodSpec{},
}
unboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// Different pod than unboundPVCPod, but using the same unbound PVC
unboundPVCPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// pod with unbound PVC that's different to unboundPVC
anotherUnboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherUnboundPVC",
},
},
},
},
},
}
tests := []struct { tests := []struct {
newPod *v1.Pod newPod *v1.Pod
@ -777,7 +442,7 @@ func TestEBSLimits(t *testing.T) {
test: "two missing PVCs are not counted towards the PV limit twice", test: "two missing PVCs are not counted towards the PV limit twice",
}, },
{ {
newPod: unboundPVCwithInvalidSCPod, newPod: unboundPVCWithInvalidSCPod,
existingPods: []*v1.Pod{oneVolPod}, existingPods: []*v1.Pod{oneVolPod},
filterName: ebsVolumeFilterType, filterName: ebsVolumeFilterType,
driverName: csilibplugins.AWSEBSInTreePluginName, driverName: csilibplugins.AWSEBSInTreePluginName,
@ -785,14 +450,13 @@ func TestEBSLimits(t *testing.T) {
test: "unbound PVC with invalid SC is not counted towards the PV limit", test: "unbound PVC with invalid SC is not counted towards the PV limit",
}, },
{ {
newPod: unboundPVCwithDefaultSCPod, newPod: unboundPVCWithDefaultSCPod,
existingPods: []*v1.Pod{oneVolPod}, existingPods: []*v1.Pod{oneVolPod},
filterName: ebsVolumeFilterType, filterName: ebsVolumeFilterType,
driverName: csilibplugins.AWSEBSInTreePluginName, driverName: csilibplugins.AWSEBSInTreePluginName,
maxVols: 1, maxVols: 1,
test: "unbound PVC from different provisioner is not counted towards the PV limit", test: "unbound PVC from different provisioner is not counted towards the PV limit",
}, },
{ {
newPod: onePVCPod(ebsVolumeFilterType), newPod: onePVCPod(ebsVolumeFilterType),
existingPods: []*v1.Pod{oneVolPod, deletedPVPod}, existingPods: []*v1.Pod{oneVolPod, deletedPVPod},
@ -876,180 +540,6 @@ func TestEBSLimits(t *testing.T) {
} }
func TestGCEPDLimits(t *testing.T) { func TestGCEPDLimits(t *testing.T) {
oneVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "ovp"},
},
},
},
},
}
twoVolPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp1"},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "tvp2"},
},
},
},
},
}
splitVolsPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
{
VolumeSource: v1.VolumeSource{
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{VolumeID: "svp"},
},
},
},
},
}
nonApplicablePod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{},
},
},
},
},
}
deletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
},
},
}
twoDeletedPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "deletedPVC",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherDeletedPVC",
},
},
},
},
},
}
deletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// deletedPVPod2 is a different pod than deletedPVPod but using the same PVC
deletedPVPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "pvcWithDeletedPV",
},
},
},
},
},
}
// anotherDeletedPVPod is a different pod than deletedPVPod and uses another PVC
anotherDeletedPVPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherPVCWithDeletedPV",
},
},
},
},
},
}
emptyPod := &v1.Pod{
Spec: v1.PodSpec{},
}
unboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// Different pod than unboundPVCPod, but using the same unbound PVC
unboundPVCPod2 := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "unboundPVC",
},
},
},
},
},
}
// pod with unbound PVC that's different to unboundPVC
anotherUnboundPVCPod := &v1.Pod{
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "anotherUnboundPVC",
},
},
},
},
},
}
tests := []struct { tests := []struct {
newPod *v1.Pod newPod *v1.Pod
existingPods []*v1.Pod existingPods []*v1.Pod
@ -1299,14 +789,14 @@ func getFakePVCLister(filterName string) fakeframework.PersistentVolumeClaimList
}, },
}, },
{ {
ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCwithDefaultSCPod"}, ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCWithDefaultSCPod"},
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "", VolumeName: "",
StorageClassName: utilpointer.StringPtr("standard-sc"), StorageClassName: utilpointer.StringPtr("standard-sc"),
}, },
}, },
{ {
ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCwithInvalidSCPod"}, ObjectMeta: metav1.ObjectMeta{Name: "unboundPVCWithInvalidSCPod"},
Spec: v1.PersistentVolumeClaimSpec{ Spec: v1.PersistentVolumeClaimSpec{
VolumeName: "", VolumeName: "",
StorageClassName: utilpointer.StringPtr("invalid-sc"), StorageClassName: utilpointer.StringPtr("invalid-sc"),
@ -1335,40 +825,9 @@ func getFakePVLister(filterName string) fakeframework.PersistentVolumeLister {
} }
func onePVCPod(filterName string) *v1.Pod { func onePVCPod(filterName string) *v1.Pod {
return &v1.Pod{ return st.MakePod().PVC(fmt.Sprintf("some%sVol", filterName)).Obj()
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "some" + filterName + "Vol",
},
},
},
},
},
}
} }
func splitPVCPod(filterName string) *v1.Pod { func splitPVCPod(filterName string) *v1.Pod {
return &v1.Pod{ return st.MakePod().PVC(fmt.Sprintf("someNon%sVol", filterName)).PVC(fmt.Sprintf("some%sVol", filterName)).Obj()
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "someNon" + filterName + "Vol",
},
},
},
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "some" + filterName + "Vol",
},
},
},
},
},
}
} }

View File

@ -17,10 +17,11 @@ limitations under the License.
package queuesort package queuesort
import ( import (
v1 "k8s.io/api/core/v1"
"k8s.io/kubernetes/pkg/scheduler/framework"
"testing" "testing"
"time" "time"
"k8s.io/kubernetes/pkg/scheduler/framework"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestLess(t *testing.T) { func TestLess(t *testing.T) {
@ -37,55 +38,31 @@ func TestLess(t *testing.T) {
{ {
name: "p1.priority less than p2.priority", name: "p1.priority less than p2.priority",
p1: &framework.QueuedPodInfo{ p1: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(lowPriority).Obj()),
Spec: v1.PodSpec{
Priority: &lowPriority,
},
}),
}, },
p2: &framework.QueuedPodInfo{ p2: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
}, },
expected: false, // p2 should be ahead of p1 in the queue expected: false, // p2 should be ahead of p1 in the queue
}, },
{ {
name: "p1.priority greater than p2.priority", name: "p1.priority greater than p2.priority",
p1: &framework.QueuedPodInfo{ p1: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
}, },
p2: &framework.QueuedPodInfo{ p2: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(lowPriority).Obj()),
Spec: v1.PodSpec{
Priority: &lowPriority,
},
}),
}, },
expected: true, // p1 should be ahead of p2 in the queue expected: true, // p1 should be ahead of p2 in the queue
}, },
{ {
name: "equal priority. p1 is added to schedulingQ earlier than p2", name: "equal priority. p1 is added to schedulingQ earlier than p2",
p1: &framework.QueuedPodInfo{ p1: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
Timestamp: t1, Timestamp: t1,
}, },
p2: &framework.QueuedPodInfo{ p2: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
Timestamp: t2, Timestamp: t2,
}, },
expected: true, // p1 should be ahead of p2 in the queue expected: true, // p1 should be ahead of p2 in the queue
@ -93,19 +70,11 @@ func TestLess(t *testing.T) {
{ {
name: "equal priority. p2 is added to schedulingQ earlier than p1", name: "equal priority. p2 is added to schedulingQ earlier than p1",
p1: &framework.QueuedPodInfo{ p1: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
Timestamp: t2, Timestamp: t2,
}, },
p2: &framework.QueuedPodInfo{ p2: &framework.QueuedPodInfo{
PodInfo: framework.NewPodInfo(&v1.Pod{ PodInfo: framework.NewPodInfo(st.MakePod().Priority(highPriority).Obj()),
Spec: v1.PodSpec{
Priority: &highPriority,
},
}),
Timestamp: t1, Timestamp: t1,
}, },
expected: false, // p2 should be ahead of p1 in the queue expected: false, // p2 should be ahead of p1 in the queue

View File

@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime" frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime"
"k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/internal/cache"
st "k8s.io/kubernetes/pkg/scheduler/testing"
"k8s.io/utils/pointer" "k8s.io/utils/pointer"
) )
@ -63,10 +64,10 @@ func TestSelectorSpreadScore(t *testing.T) {
"baz": "blah", "baz": "blah",
} }
zone1Spec := v1.PodSpec{ zone1Spec := v1.PodSpec{
NodeName: "machine1", NodeName: "node1",
} }
zone2Spec := v1.PodSpec{ zone2Spec := v1.PodSpec{
NodeName: "machine2", NodeName: "node2",
} }
tests := []struct { tests := []struct {
pod *v1.Pod pod *v1.Pod
@ -81,122 +82,122 @@ func TestSelectorSpreadScore(t *testing.T) {
}{ }{
{ {
pod: new(v1.Pod), pod: new(v1.Pod),
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "nothing scheduled", name: "nothing scheduled",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{{Spec: zone1Spec}}, pods: []*v1.Pod{st.MakePod().Node("node1").Obj()},
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "no services", name: "no services",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}}, pods: []*v1.Pod{st.MakePod().Labels(labels2).Node("node1").Obj()},
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: map[string]string{"key": "value"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: map[string]string{"key": "value"}}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "different services", name: "different services",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
name: "two pods, one service pod", name: "two pods, one service pod",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, st.MakePod().Labels(labels1).Node("node1").Namespace(metav1.NamespaceDefault).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, st.MakePod().Labels(labels1).Node("node1").Namespace("ns1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
name: "five pods, one service pod in no namespace", name: "five pods, one service pod in no namespace",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, pod: st.MakePod().Labels(labels1).Namespace(metav1.NamespaceDefault).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}},
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}},
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}},
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}},
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
name: "four pods, one service pod in default namespace", name: "four pods, one service pod in default namespace",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, pod: st.MakePod().Labels(labels1).Namespace("ns1").Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: metav1.NamespaceDefault}}, st.MakePod().Labels(labels1).Node("node1").Namespace(metav1.NamespaceDefault).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns2"}}, st.MakePod().Labels(labels1).Node("node1").Namespace("ns2").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1, Namespace: "ns1"}}, st.MakePod().Labels(labels1).Node("node2").Namespace("ns1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns1"}}}, services: []*v1.Service{{Spec: v1.ServiceSpec{Selector: labels1}, ObjectMeta: metav1.ObjectMeta{Namespace: "ns1"}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: 0}},
name: "five pods, one service pod in specific namespace", name: "five pods, one service pod in specific namespace",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "three pods, two service pods on different machines", name: "three pods, two service pods on different nodes",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 50}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 50}, {Name: "node2", Score: 0}},
name: "four pods, three service pods", name: "four pods, three service pods",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, pod: st.MakePod().Labels(labels1).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels2}}, st.MakePod().Labels(labels2).Node("node1").Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node1").Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Labels: labels1}}, st.MakePod().Labels(labels1).Node("node2").Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 50}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 50}},
name: "service with partial pod label matches", name: "service with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels2).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node2").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rcs: []*v1.ReplicationController{ rcs: []*v1.ReplicationController{
{ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}},
{ObjectMeta: metav1.ObjectMeta{Name: "rc2", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"bar": "foo"}}}, {ObjectMeta: metav1.ObjectMeta{Name: "rc2", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"bar": "foo"}}},
@ -204,163 +205,162 @@ func TestSelectorSpreadScore(t *testing.T) {
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}},
// "baz=blah" matches both labels1 and labels2, and "foo=bar" matches only labels 1. This means that we assume that we want to // "baz=blah" matches both labels1 and labels2, and "foo=bar" matches only labels 1. This means that we assume that we want to
// do spreading pod2 and pod3 and not pod1. // do spreading pod2 and pod3 and not pod1.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "service with partial pod label matches with service and replication controller", name: "service with partial pod label matches with service and replication controller",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels2).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node2").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}},
rss: []*apps.ReplicaSet{ rss: []*apps.ReplicaSet{
{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rs1"}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}, {ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rs1"}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}},
{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rs2"}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"bar": "foo"}}}}, {ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rs2"}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"bar": "foo"}}}},
}, },
// We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "service with partial pod label matches with service and replica set", name: "service with partial pod label matches with service and replica set",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels2).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node1").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1}}, st.MakePod().Node("node2").Namespace(metav1.NamespaceDefault).Labels(labels1).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"baz": "blah"}}}},
sss: []*apps.StatefulSet{ sss: []*apps.StatefulSet{
{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "ss1"}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}, {ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "ss1"}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}},
{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "ss2"}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"bar": "foo"}}}}, {ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "ss2"}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"bar": "foo"}}}},
}, },
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "service with partial pod label matches with service and statefulset", name: "service with partial pod label matches with service and statefulset",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: map[string]string{"foo": "bar", "bar": "foo"}, OwnerReferences: controllerRef("rc3", rcKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(map[string]string{"foo": "bar", "bar": "foo"}).OwnerReference("rc3", rcKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rc2", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rc2", rcKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rcs: []*v1.ReplicationController{{ rcs: []*v1.ReplicationController{{
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rc3"}, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "rc3"},
Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}},
// Taken together Service and Replication Controller should match no pods. // Taken together Service and Replication Controller should match no pods.
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "disjoined service and replication controller matches no pods", name: "disjoined service and replication controller matches no pods",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: map[string]string{"foo": "bar", "bar": "foo"}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(map[string]string{"foo": "bar", "bar": "foo"}).OwnerReference("rs3", rsKind).Obj(),
OwnerReferences: controllerRef("rs3", rsKind)}},
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rs2", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rs2", rsKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}},
rss: []*apps.ReplicaSet{ rss: []*apps.ReplicaSet{
{ObjectMeta: metav1.ObjectMeta{Name: "rs3", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, {ObjectMeta: metav1.ObjectMeta{Name: "rs3", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}},
// We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "disjoined service and replica set matches no pods", name: "disjoined service and replica set matches no pods",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: map[string]string{"foo": "bar", "bar": "foo"}, OwnerReferences: controllerRef("ss3", ssKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(map[string]string{"foo": "bar", "bar": "foo"}).OwnerReference("ss3", ssKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("ss2", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("ss2", ssKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Name: "s1", Namespace: metav1.NamespaceDefault}, Spec: v1.ServiceSpec{Selector: map[string]string{"bar": "foo"}}}},
sss: []*apps.StatefulSet{ sss: []*apps.StatefulSet{
{ObjectMeta: metav1.ObjectMeta{Name: "ss3", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, {ObjectMeta: metav1.ObjectMeta{Name: "ss3", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: framework.MaxNodeScore}, {Name: "machine2", Score: framework.MaxNodeScore}}, expectedList: []framework.NodeScore{{Name: "node1", Score: framework.MaxNodeScore}, {Name: "node2", Score: framework.MaxNodeScore}},
name: "disjoined service and stateful set matches no pods", name: "disjoined service and stateful set matches no pods",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rc2", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rc2", rcKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rcs: []*v1.ReplicationController{{ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}}, rcs: []*v1.ReplicationController{{ObjectMeta: metav1.ObjectMeta{Name: "rc1", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"foo": "bar"}}}},
// Both Nodes have one pod from the given RC, hence both get 0 score. // Both Nodes have one pod from the given RC, hence both get 0 score.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "Replication controller with partial pod label matches", name: "Replication controller with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rs2", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rs2", rsKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rss: []*apps.ReplicaSet{{ObjectMeta: metav1.ObjectMeta{Name: "rs1", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, rss: []*apps.ReplicaSet{{ObjectMeta: metav1.ObjectMeta{Name: "rs1", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}},
// We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "Replica set with partial pod label matches", name: "Replica set with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("ss2", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("ss2", ssKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss1", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}}, sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss1", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}}}},
// We use StatefulSet, instead of ReplicationController. The result should be exactly as above. // We use StatefulSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "StatefulSet with partial pod label matches", name: "StatefulSet with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc3", rcKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rc3", rcKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rc2", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rc2", rcKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rc1", rcKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rc1", rcKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rcs: []*v1.ReplicationController{{ObjectMeta: metav1.ObjectMeta{Name: "rc3", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"baz": "blah"}}}}, rcs: []*v1.ReplicationController{{ObjectMeta: metav1.ObjectMeta{Name: "rc3", Namespace: metav1.NamespaceDefault}, Spec: v1.ReplicationControllerSpec{Selector: map[string]string{"baz": "blah"}}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 50}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 50}},
name: "Another replication controller with partial pod label matches", name: "Another replication controller with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs3", rsKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("rs3", rsKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("rs2", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("rs2", rsKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("rs1", rsKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("rs1", rsKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
rss: []*apps.ReplicaSet{{ObjectMeta: metav1.ObjectMeta{Name: "rs3", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}}, rss: []*apps.ReplicaSet{{ObjectMeta: metav1.ObjectMeta{Name: "rs3", Namespace: metav1.NamespaceDefault}, Spec: apps.ReplicaSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}},
// We use ReplicaSet, instead of ReplicationController. The result should be exactly as above. // We use ReplicaSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 50}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 50}},
name: "Another replication set with partial pod label matches", name: "Another replication set with partial pod label matches",
}, },
{ {
pod: &v1.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss3", ssKind)}}, pod: st.MakePod().Namespace(metav1.NamespaceDefault).Labels(labels1).OwnerReference("ss3", ssKind).Obj(),
pods: []*v1.Pod{ pods: []*v1.Pod{
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels2, OwnerReferences: controllerRef("ss2", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels2).OwnerReference("ss2", ssKind).Obj(),
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node1").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, st.MakePod().Namespace(metav1.NamespaceDefault).Node("node2").Labels(labels1).OwnerReference("ss1", ssKind).Obj(),
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss3", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}}, sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss3", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}},
// We use StatefulSet, instead of ReplicationController. The result should be exactly as above. // We use StatefulSet, instead of ReplicationController. The result should be exactly as above.
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 50}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 50}},
name: "Another stateful set with partial pod label matches", name: "Another stateful set with partial pod label matches",
}, },
{ {
@ -385,9 +385,9 @@ func TestSelectorSpreadScore(t *testing.T) {
{Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, {Spec: zone1Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}},
{Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}}, {Spec: zone2Spec, ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Labels: labels1, OwnerReferences: controllerRef("ss1", ssKind)}},
}, },
nodes: []string{"machine1", "machine2"}, nodes: []string{"node1", "node2"},
sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss1", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}}, sss: []*apps.StatefulSet{{ObjectMeta: metav1.ObjectMeta{Name: "ss1", Namespace: metav1.NamespaceDefault}, Spec: apps.StatefulSetSpec{Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"baz": "blah"}}}}},
expectedList: []framework.NodeScore{{Name: "machine1", Score: 0}, {Name: "machine2", Score: 0}}, expectedList: []framework.NodeScore{{Name: "node1", Score: 0}, {Name: "node2", Score: 0}},
name: "Another statefulset with TopologySpreadConstraints set in pod", name: "Another statefulset with TopologySpreadConstraints set in pod",
}, },
} }
@ -458,12 +458,12 @@ func TestZoneSelectorSpreadPriority(t *testing.T) {
"baz": "blah", "baz": "blah",
} }
const nodeMachine1Zone1 = "machine1.zone1" const nodeMachine1Zone1 = "node1.zone1"
const nodeMachine1Zone2 = "machine1.zone2" const nodeMachine1Zone2 = "node1.zone2"
const nodeMachine2Zone2 = "machine2.zone2" const nodeMachine2Zone2 = "node2.zone2"
const nodeMachine1Zone3 = "machine1.zone3" const nodeMachine1Zone3 = "node1.zone3"
const nodeMachine2Zone3 = "machine2.zone3" const nodeMachine2Zone3 = "node2.zone3"
const nodeMachine3Zone3 = "machine3.zone3" const nodeMachine3Zone3 = "node3.zone3"
buildNodeLabels := func(failureDomain string) map[string]string { buildNodeLabels := func(failureDomain string) map[string]string {
labels := map[string]string{ labels := map[string]string{
@ -555,7 +555,7 @@ func TestZoneSelectorSpreadPriority(t *testing.T) {
services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}}, services: []*v1.Service{{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "s1"}, Spec: v1.ServiceSpec{Selector: labels1}}},
expectedList: []framework.NodeScore{ expectedList: []framework.NodeScore{
{Name: nodeMachine1Zone1, Score: framework.MaxNodeScore}, {Name: nodeMachine1Zone1, Score: framework.MaxNodeScore},
{Name: nodeMachine1Zone2, Score: 0}, // Already have pod on machine {Name: nodeMachine1Zone2, Score: 0}, // Already have pod on node
{Name: nodeMachine2Zone2, Score: 33}, // Already have pod in zone {Name: nodeMachine2Zone2, Score: 33}, // Already have pod in zone
{Name: nodeMachine1Zone3, Score: framework.MaxNodeScore}, {Name: nodeMachine1Zone3, Score: framework.MaxNodeScore},
{Name: nodeMachine2Zone3, Score: framework.MaxNodeScore}, {Name: nodeMachine2Zone3, Score: framework.MaxNodeScore},

View File

@ -32,28 +32,21 @@ import (
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
plugintesting "k8s.io/kubernetes/pkg/scheduler/framework/plugins/testing" plugintesting "k8s.io/kubernetes/pkg/scheduler/framework/plugins/testing"
"k8s.io/kubernetes/pkg/scheduler/internal/cache" "k8s.io/kubernetes/pkg/scheduler/internal/cache"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func TestGCEDiskConflicts(t *testing.T) { func TestGCEDiskConflicts(t *testing.T) {
volState := v1.PodSpec{ volState := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
VolumeSource: v1.VolumeSource{ PDName: "foo",
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "foo",
},
},
}, },
}, },
} }
volState2 := v1.PodSpec{ volState2 := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
VolumeSource: v1.VolumeSource{ PDName: "bar",
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "bar",
},
},
}, },
}, },
} }
@ -66,9 +59,9 @@ func TestGCEDiskConflicts(t *testing.T) {
wantStatus *framework.Status wantStatus *framework.Status
}{ }{
{&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil}, {&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil},
{&v1.Pod{}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state", nil}, {&v1.Pod{}, framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "one state", nil},
{&v1.Pod{Spec: volState}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state", errStatus}, {st.MakePod().Volume(volState).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), false, "same state", errStatus},
{&v1.Pod{Spec: volState2}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state", nil}, {st.MakePod().Volume(volState2).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "different state", nil},
} }
for _, test := range tests { for _, test := range tests {
@ -85,25 +78,17 @@ func TestGCEDiskConflicts(t *testing.T) {
} }
func TestAWSDiskConflicts(t *testing.T) { func TestAWSDiskConflicts(t *testing.T) {
volState := v1.PodSpec{ volState := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
VolumeSource: v1.VolumeSource{ VolumeID: "foo",
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
VolumeID: "foo",
},
},
}, },
}, },
} }
volState2 := v1.PodSpec{ volState2 := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
VolumeSource: v1.VolumeSource{ VolumeID: "bar",
AWSElasticBlockStore: &v1.AWSElasticBlockStoreVolumeSource{
VolumeID: "bar",
},
},
}, },
}, },
} }
@ -116,9 +101,9 @@ func TestAWSDiskConflicts(t *testing.T) {
wantStatus *framework.Status wantStatus *framework.Status
}{ }{
{&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil}, {&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil},
{&v1.Pod{}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state", nil}, {&v1.Pod{}, framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "one state", nil},
{&v1.Pod{Spec: volState}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state", errStatus}, {st.MakePod().Volume(volState).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), false, "same state", errStatus},
{&v1.Pod{Spec: volState2}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state", nil}, {st.MakePod().Volume(volState2).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "different state", nil},
} }
for _, test := range tests { for _, test := range tests {
@ -135,31 +120,23 @@ func TestAWSDiskConflicts(t *testing.T) {
} }
func TestRBDDiskConflicts(t *testing.T) { func TestRBDDiskConflicts(t *testing.T) {
volState := v1.PodSpec{ volState := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ RBD: &v1.RBDVolumeSource{
VolumeSource: v1.VolumeSource{ CephMonitors: []string{"a", "b"},
RBD: &v1.RBDVolumeSource{ RBDPool: "foo",
CephMonitors: []string{"a", "b"}, RBDImage: "bar",
RBDPool: "foo", FSType: "ext4",
RBDImage: "bar",
FSType: "ext4",
},
},
}, },
}, },
} }
volState2 := v1.PodSpec{ volState2 := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ RBD: &v1.RBDVolumeSource{
VolumeSource: v1.VolumeSource{ CephMonitors: []string{"c", "d"},
RBD: &v1.RBDVolumeSource{ RBDPool: "foo",
CephMonitors: []string{"c", "d"}, RBDImage: "bar",
RBDPool: "foo", FSType: "ext4",
RBDImage: "bar",
FSType: "ext4",
},
},
}, },
}, },
} }
@ -172,9 +149,9 @@ func TestRBDDiskConflicts(t *testing.T) {
wantStatus *framework.Status wantStatus *framework.Status
}{ }{
{&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil}, {&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil},
{&v1.Pod{}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state", nil}, {&v1.Pod{}, framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "one state", nil},
{&v1.Pod{Spec: volState}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state", errStatus}, {st.MakePod().Volume(volState).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), false, "same state", errStatus},
{&v1.Pod{Spec: volState2}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state", nil}, {st.MakePod().Volume(volState2).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "different state", nil},
} }
for _, test := range tests { for _, test := range tests {
@ -191,31 +168,23 @@ func TestRBDDiskConflicts(t *testing.T) {
} }
func TestISCSIDiskConflicts(t *testing.T) { func TestISCSIDiskConflicts(t *testing.T) {
volState := v1.PodSpec{ volState := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ ISCSI: &v1.ISCSIVolumeSource{
VolumeSource: v1.VolumeSource{ TargetPortal: "127.0.0.1:3260",
ISCSI: &v1.ISCSIVolumeSource{ IQN: "iqn.2016-12.server:storage.target01",
TargetPortal: "127.0.0.1:3260", FSType: "ext4",
IQN: "iqn.2016-12.server:storage.target01", Lun: 0,
FSType: "ext4",
Lun: 0,
},
},
}, },
}, },
} }
volState2 := v1.PodSpec{ volState2 := v1.Volume{
Volumes: []v1.Volume{ VolumeSource: v1.VolumeSource{
{ ISCSI: &v1.ISCSIVolumeSource{
VolumeSource: v1.VolumeSource{ TargetPortal: "127.0.0.1:3260",
ISCSI: &v1.ISCSIVolumeSource{ IQN: "iqn.2017-12.server:storage.target01",
TargetPortal: "127.0.0.1:3260", FSType: "ext4",
IQN: "iqn.2017-12.server:storage.target01", Lun: 0,
FSType: "ext4",
Lun: 0,
},
},
}, },
}, },
} }
@ -228,9 +197,9 @@ func TestISCSIDiskConflicts(t *testing.T) {
wantStatus *framework.Status wantStatus *framework.Status
}{ }{
{&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil}, {&v1.Pod{}, framework.NewNodeInfo(), true, "nothing", nil},
{&v1.Pod{}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "one state", nil}, {&v1.Pod{}, framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "one state", nil},
{&v1.Pod{Spec: volState}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), false, "same state", errStatus}, {st.MakePod().Volume(volState).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), false, "same state", errStatus},
{&v1.Pod{Spec: volState2}, framework.NewNodeInfo(&v1.Pod{Spec: volState}), true, "different state", nil}, {st.MakePod().Volume(volState2).Obj(), framework.NewNodeInfo(st.MakePod().Volume(volState).Obj()), true, "different state", nil},
} }
for _, test := range tests { for _, test := range tests {
@ -249,44 +218,10 @@ func TestISCSIDiskConflicts(t *testing.T) {
func TestAccessModeConflicts(t *testing.T) { func TestAccessModeConflicts(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)() defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
podWithReadWriteOncePodPVC := &v1.Pod{ // Required for querying lister for PVCs in the same namespace.
ObjectMeta: metav1.ObjectMeta{ podWithReadWriteOncePodPVC := st.MakePod().Name("pod-with-rwop").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwop").Node("node-1").Obj()
// Required for querying lister for PVCs in the same namespace. // Required for querying lister for PVCs in the same namespace.
Namespace: "default", podWithReadWriteManyPVC := st.MakePod().Name("pod-with-rwx").Namespace(metav1.NamespaceDefault).PVC("claim-with-rwx").Node("node-1").Obj()
Name: "pod-with-rwop",
},
Spec: v1.PodSpec{
NodeName: "node-1",
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "claim-with-rwop",
},
},
},
},
},
}
podWithReadWriteManyPVC := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
// Required for querying lister for PVCs in the same namespace.
Namespace: "default",
Name: "pod-with-rwx",
},
Spec: v1.PodSpec{
NodeName: "node-1",
Volumes: []v1.Volume{
{
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: "claim-with-rwx",
},
},
},
},
},
}
node := &v1.Node{ node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{

View File

@ -26,24 +26,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/scheduler/framework" "k8s.io/kubernetes/pkg/scheduler/framework"
fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake" fakeframework "k8s.io/kubernetes/pkg/scheduler/framework/fake"
st "k8s.io/kubernetes/pkg/scheduler/testing"
) )
func createPodWithVolume(pod, pv, pvc string) *v1.Pod { func createPodWithVolume(pod, pv, pvc string) *v1.Pod {
return &v1.Pod{ return st.MakePod().Name(pod).Namespace(metav1.NamespaceDefault).PVC(pvc).Obj()
ObjectMeta: metav1.ObjectMeta{Name: pod, Namespace: "default"},
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: pv,
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: pvc,
},
},
},
},
},
}
} }
func TestSingleZone(t *testing.T) { func TestSingleZone(t *testing.T) {
@ -100,9 +87,7 @@ func TestSingleZone(t *testing.T) {
}{ }{
{ {
name: "pod without volume", name: "pod without volume",
Pod: &v1.Pod{ Pod: st.MakePod().Name("pod_1").Namespace(metav1.NamespaceDefault).Obj(),
ObjectMeta: metav1.ObjectMeta{Name: "pod_1", Namespace: "default"},
},
Node: &v1.Node{ Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "host1", Name: "host1",