Move VolumeZone predicate to its Filter plugin

Signed-off-by: Zou Nengren <zouyee1989@gmail.com>
This commit is contained in:
zouyee
2019-12-26 21:36:11 +08:00
parent 04d71d8a7b
commit c4331b0369
6 changed files with 134 additions and 503 deletions

View File

@@ -24,7 +24,6 @@ import (
"testing"
v1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
@@ -33,7 +32,6 @@ import (
api "k8s.io/kubernetes/pkg/apis/core"
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
"k8s.io/kubernetes/pkg/features"
fakelisters "k8s.io/kubernetes/pkg/scheduler/listers/fake"
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
)
@@ -1722,364 +1720,6 @@ func TestPodToleratesTaints(t *testing.T) {
}
}
func createPodWithVolume(pod, pv, pvc string) *v1.Pod {
return &v1.Pod{
ObjectMeta: metav1.ObjectMeta{Name: pod, Namespace: "default"},
Spec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: pv,
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{
ClaimName: pvc,
},
},
},
},
},
}
}
func TestVolumeZonePredicate(t *testing.T) {
pvLister := fakelisters.PersistentVolumeLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a"}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_2", Labels: map[string]string{v1.LabelZoneRegion: "us-west1-b", "uselessLabel": "none"}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_3", Labels: map[string]string{v1.LabelZoneRegion: "us-west1-c"}},
},
}
pvcLister := fakelisters.PersistentVolumeClaimLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_2", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_2"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_3", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_3"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_4", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_not_exist"},
},
}
tests := []struct {
name string
Pod *v1.Pod
Fits bool
Node *v1.Node
}{
{
name: "pod without volume",
Pod: &v1.Pod{
ObjectMeta: metav1.ObjectMeta{Name: "pod_1", Namespace: "default"},
},
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a"},
},
},
Fits: true,
},
{
name: "node without labels",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_1"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
},
},
Fits: true,
},
{
name: "label zone failure domain matched",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_1"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a", "uselessLabel": "none"},
},
},
Fits: true,
},
{
name: "label zone region matched",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_2"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneRegion: "us-west1-b", "uselessLabel": "none"},
},
},
Fits: true,
},
{
name: "label zone region failed match",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_2"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneRegion: "no_us-west1-b", "uselessLabel": "none"},
},
},
Fits: false,
},
{
name: "label zone failure domain failed match",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_1"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "no_us-west1-a", "uselessLabel": "none"},
},
},
Fits: false,
},
}
expectedFailureReasons := []PredicateFailureReason{ErrVolumeZoneConflict}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fit := NewVolumeZonePredicate(pvLister, pvcLister, nil)
node := &schedulernodeinfo.NodeInfo{}
node.SetNode(test.Node)
fits, reasons, err := fit(test.Pod, nil, node)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) {
t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons)
}
if fits != test.Fits {
t.Errorf("expected %v got %v", test.Fits, fits)
}
})
}
}
func TestVolumeZonePredicateMultiZone(t *testing.T) {
pvLister := fakelisters.PersistentVolumeLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a"}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_2", Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-b", "uselessLabel": "none"}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_3", Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-c__us-west1-a"}},
},
}
pvcLister := fakelisters.PersistentVolumeClaimLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_2", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_2"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_3", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_3"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_4", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_not_exist"},
},
}
tests := []struct {
name string
Pod *v1.Pod
Fits bool
Node *v1.Node
}{
{
name: "node without labels",
Pod: createPodWithVolume("pod_1", "Vol_3", "PVC_3"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
},
},
Fits: true,
},
{
name: "label zone failure domain matched",
Pod: createPodWithVolume("pod_1", "Vol_3", "PVC_3"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a", "uselessLabel": "none"},
},
},
Fits: true,
},
{
name: "label zone failure domain failed match",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_1"),
Node: &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-b", "uselessLabel": "none"},
},
},
Fits: false,
},
}
expectedFailureReasons := []PredicateFailureReason{ErrVolumeZoneConflict}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fit := NewVolumeZonePredicate(pvLister, pvcLister, nil)
node := &schedulernodeinfo.NodeInfo{}
node.SetNode(test.Node)
fits, reasons, err := fit(test.Pod, nil, node)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if !fits && !reflect.DeepEqual(reasons, expectedFailureReasons) {
t.Errorf("unexpected failure reasons: %v, want: %v", reasons, expectedFailureReasons)
}
if fits != test.Fits {
t.Errorf("expected %v got %v", test.Fits, fits)
}
})
}
}
func TestVolumeZonePredicateWithVolumeBinding(t *testing.T) {
var (
modeWait = storagev1.VolumeBindingWaitForFirstConsumer
class0 = "Class_0"
classWait = "Class_Wait"
classImmediate = "Class_Immediate"
)
scLister := fakelisters.StorageClassLister{
{
ObjectMeta: metav1.ObjectMeta{Name: classImmediate},
},
{
ObjectMeta: metav1.ObjectMeta{Name: classWait},
VolumeBindingMode: &modeWait,
},
}
pvLister := fakelisters.PersistentVolumeLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "Vol_1", Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a"}},
},
}
pvcLister := fakelisters.PersistentVolumeClaimLister{
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_1", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{VolumeName: "Vol_1"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_NoSC", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &class0},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_EmptySC", Namespace: "default"},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_WaitSC", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &classWait},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "PVC_ImmediateSC", Namespace: "default"},
Spec: v1.PersistentVolumeClaimSpec{StorageClassName: &classImmediate},
},
}
testNode := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "host1",
Labels: map[string]string{v1.LabelZoneFailureDomain: "us-west1-a", "uselessLabel": "none"},
},
}
tests := []struct {
name string
Pod *v1.Pod
Fits bool
Node *v1.Node
ExpectFailure bool
}{
{
name: "label zone failure domain matched",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_1"),
Node: testNode,
Fits: true,
},
{
name: "unbound volume empty storage class",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_EmptySC"),
Node: testNode,
Fits: false,
ExpectFailure: true,
},
{
name: "unbound volume no storage class",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_NoSC"),
Node: testNode,
Fits: false,
ExpectFailure: true,
},
{
name: "unbound volume immediate binding mode",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_ImmediateSC"),
Node: testNode,
Fits: false,
ExpectFailure: true,
},
{
name: "unbound volume wait binding mode",
Pod: createPodWithVolume("pod_1", "vol_1", "PVC_WaitSC"),
Node: testNode,
Fits: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fit := NewVolumeZonePredicate(pvLister, pvcLister, scLister)
node := &schedulernodeinfo.NodeInfo{}
node.SetNode(test.Node)
fits, _, err := fit(test.Pod, nil, node)
if !test.ExpectFailure && err != nil {
t.Errorf("unexpected error: %v", err)
}
if test.ExpectFailure && err == nil {
t.Errorf("expected error, got success")
}
if fits != test.Fits {
t.Errorf("expected %v got %v", test.Fits, fits)
}
})
}
}
func TestGetMaxVols(t *testing.T) {
previousValue := os.Getenv(KubeMaxPDVols)