Skip to content

Commit 75266db

Browse files
committed
Add integration test for VolumeZone in requeueing scenarios
1 parent 08e6500 commit 75266db

File tree

2 files changed

+142
-1
lines changed

2 files changed

+142
-1
lines changed

pkg/scheduler/testing/wrappers.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,23 @@ func (p *PersistentVolumeWrapper) NodeAffinityIn(key string, vals []string) *Per
907907
return p
908908
}
909909

910+
// Labels sets all {k,v} pair provided by `labels` to the pv.
911+
func (p *PersistentVolumeWrapper) Labels(labels map[string]string) *PersistentVolumeWrapper {
912+
for k, v := range labels {
913+
p.Label(k, v)
914+
}
915+
return p
916+
}
917+
918+
// Label sets a {k,v} pair to the pv.
919+
func (p *PersistentVolumeWrapper) Label(k, v string) *PersistentVolumeWrapper {
920+
if p.PersistentVolume.ObjectMeta.Labels == nil {
921+
p.PersistentVolume.ObjectMeta.Labels = make(map[string]string)
922+
}
923+
p.PersistentVolume.ObjectMeta.Labels[k] = v
924+
return p
925+
}
926+
910927
// ResourceClaimWrapper wraps a ResourceClaim inside.
911928
type ResourceClaimWrapper struct{ resourceapi.ResourceClaim }
912929

test/integration/scheduler/queue_test.go

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2727
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
2828
"k8s.io/apimachinery/pkg/api/errors"
29+
"k8s.io/apimachinery/pkg/api/resource"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3132
"k8s.io/apimachinery/pkg/runtime"
@@ -38,6 +39,7 @@ import (
3839
"k8s.io/client-go/dynamic"
3940
"k8s.io/client-go/kubernetes"
4041
featuregatetesting "k8s.io/component-base/featuregate/testing"
42+
"k8s.io/component-helpers/storage/volume"
4143
"k8s.io/klog/v2"
4244
configv1 "k8s.io/kube-scheduler/config/v1"
4345
apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
@@ -186,6 +188,7 @@ func TestSchedulingGates(t *testing.T) {
186188
// TestCoreResourceEnqueue verify Pods failed by in-tree default plugins can be
187189
// moved properly upon their registered events.
188190
func TestCoreResourceEnqueue(t *testing.T) {
191+
volType := v1.HostPathDirectoryOrCreate
189192
tests := []struct {
190193
name string
191194
// initialNodes is the list of Nodes to be created at first.
@@ -194,6 +197,12 @@ func TestCoreResourceEnqueue(t *testing.T) {
194197
// Note that the scheduler won't schedule those Pods,
195198
// meaning, those Pods should be already scheduled basically; they should have .spec.nodename.
196199
initialPods []*v1.Pod
200+
// initialPVCs are the list of PersistentVolumeClaims to be created at first.
201+
// Note that PVs are automatically created following PVCs.
202+
// Also, the namespace of pvcs is automatically filled in.
203+
initialPVCs []*v1.PersistentVolumeClaim
204+
// initialPVs are the list of PersistentVolume to be created at first.
205+
initialPVs []*v1.PersistentVolume
197206
// pods are the list of Pods to be created.
198207
// All of them are expected to be unschedulable at first.
199208
pods []*v1.Pod
@@ -748,7 +757,109 @@ func TestCoreResourceEnqueue(t *testing.T) {
748757
}
749758
return nil
750759
},
751-
wantRequeuedPods: sets.New("pod4"),
760+
wantRequeuedPods: sets.New("pod4"),
761+
},
762+
{
763+
name: "Pod rejected with node by the VolumeZone plugin is requeued when the PV is added",
764+
initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()},
765+
initialPVs: []*v1.PersistentVolume{
766+
st.MakePersistentVolume().
767+
Name("pv1").
768+
Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}).
769+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}).
770+
Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}).
771+
HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}).
772+
Obj(),
773+
},
774+
initialPVCs: []*v1.PersistentVolumeClaim{
775+
st.MakePersistentVolumeClaim().
776+
Name("pvc1").
777+
Annotation(volume.AnnBindCompleted, "true").
778+
VolumeName("pv1").
779+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}).
780+
Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}).
781+
Obj(),
782+
st.MakePersistentVolumeClaim().
783+
Name("pvc2").
784+
Annotation(volume.AnnBindCompleted, "true").
785+
VolumeName("pv2").
786+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}).
787+
Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}).
788+
Obj(),
789+
},
790+
initialPods: []*v1.Pod{
791+
st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(),
792+
},
793+
pods: []*v1.Pod{
794+
st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(),
795+
},
796+
triggerFn: func(testCtx *testutils.TestContext) error {
797+
pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a").
798+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}).
799+
Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}).
800+
HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}).
801+
Obj()
802+
if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Create(testCtx.Ctx, pv2, metav1.CreateOptions{}); err != nil {
803+
return fmt.Errorf("failed to update pod1: %w", err)
804+
}
805+
return nil
806+
},
807+
wantRequeuedPods: sets.New("pod2"),
808+
enableSchedulingQueueHint: []bool{true},
809+
},
810+
{
811+
name: "Pod rejected with node by the VolumeZone plugin is requeued when the PV is updated",
812+
initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()},
813+
initialPVs: []*v1.PersistentVolume{
814+
st.MakePersistentVolume().
815+
Name("pv1").
816+
Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}).
817+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}).
818+
Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}).
819+
HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}).
820+
Obj(),
821+
st.MakePersistentVolume().
822+
Name("pv2").
823+
Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}).
824+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}).
825+
Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}).
826+
HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}).
827+
Obj(),
828+
},
829+
initialPVCs: []*v1.PersistentVolumeClaim{
830+
st.MakePersistentVolumeClaim().
831+
Name("pvc1").
832+
Annotation(volume.AnnBindCompleted, "true").
833+
VolumeName("pv1").
834+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}).
835+
Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}).
836+
Obj(),
837+
st.MakePersistentVolumeClaim().
838+
Name("pvc2").
839+
Annotation(volume.AnnBindCompleted, "true").
840+
VolumeName("pv2").
841+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}).
842+
Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}).
843+
Obj(),
844+
},
845+
initialPods: []*v1.Pod{
846+
st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(),
847+
},
848+
pods: []*v1.Pod{
849+
st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(),
850+
},
851+
triggerFn: func(testCtx *testutils.TestContext) error {
852+
pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a").
853+
AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}).
854+
Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}).
855+
HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}).
856+
Obj()
857+
if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil {
858+
return fmt.Errorf("failed to update pod1: %w", err)
859+
}
860+
return nil
861+
},
862+
wantRequeuedPods: sets.New("pod2"),
752863
enableSchedulingQueueHint: []bool{true},
753864
},
754865
}
@@ -785,6 +896,19 @@ func TestCoreResourceEnqueue(t *testing.T) {
785896
}
786897
}
787898

899+
for _, pv := range tt.initialPVs {
900+
if _, err := testutils.CreatePV(cs, pv); err != nil {
901+
t.Fatalf("Failed to create a PV %q: %v", pv.Name, err)
902+
}
903+
}
904+
905+
for _, pvc := range tt.initialPVCs {
906+
pvc.Namespace = ns
907+
if _, err := testutils.CreatePVC(cs, pvc); err != nil {
908+
t.Fatalf("Failed to create a PVC %q: %v", pvc.Name, err)
909+
}
910+
}
911+
788912
for _, pod := range tt.initialPods {
789913
if _, err := cs.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}); err != nil {
790914
t.Fatalf("Failed to create an initial Pod %q: %v", pod.Name, err)

0 commit comments

Comments
 (0)