Move VolumeZone predicate to its Filter plugin
Signed-off-by: Zou Nengren <zouyee1989@gmail.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
|
Reference in New Issue
Block a user