From 75266db65bc85347e2566d75afda5d5168249357 Mon Sep 17 00:00:00 2001 From: moriya Date: Sat, 14 Sep 2024 09:59:10 +0900 Subject: [PATCH 1/6] Add integration test for VolumeZone in requeueing scenarios --- pkg/scheduler/testing/wrappers.go | 17 +++ test/integration/scheduler/queue_test.go | 126 ++++++++++++++++++++++- 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/pkg/scheduler/testing/wrappers.go b/pkg/scheduler/testing/wrappers.go index bfb854f9edf..94918f3c5a7 100644 --- a/pkg/scheduler/testing/wrappers.go +++ b/pkg/scheduler/testing/wrappers.go @@ -907,6 +907,23 @@ func (p *PersistentVolumeWrapper) NodeAffinityIn(key string, vals []string) *Per return p } +// Labels sets all {k,v} pair provided by `labels` to the pv. +func (p *PersistentVolumeWrapper) Labels(labels map[string]string) *PersistentVolumeWrapper { + for k, v := range labels { + p.Label(k, v) + } + return p +} + +// Label sets a {k,v} pair to the pv. +func (p *PersistentVolumeWrapper) Label(k, v string) *PersistentVolumeWrapper { + if p.PersistentVolume.ObjectMeta.Labels == nil { + p.PersistentVolume.ObjectMeta.Labels = make(map[string]string) + } + p.PersistentVolume.ObjectMeta.Labels[k] = v + return p +} + // ResourceClaimWrapper wraps a ResourceClaim inside. type ResourceClaimWrapper struct{ resourceapi.ResourceClaim } diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index e99a94c54a1..b91499a4e6e 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -26,6 +26,7 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -38,6 +39,7 @@ import ( "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/component-helpers/storage/volume" "k8s.io/klog/v2" configv1 "k8s.io/kube-scheduler/config/v1" apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" @@ -186,6 +188,7 @@ func TestSchedulingGates(t *testing.T) { // TestCoreResourceEnqueue verify Pods failed by in-tree default plugins can be // moved properly upon their registered events. func TestCoreResourceEnqueue(t *testing.T) { + volType := v1.HostPathDirectoryOrCreate tests := []struct { name string // initialNodes is the list of Nodes to be created at first. @@ -194,6 +197,12 @@ func TestCoreResourceEnqueue(t *testing.T) { // Note that the scheduler won't schedule those Pods, // meaning, those Pods should be already scheduled basically; they should have .spec.nodename. initialPods []*v1.Pod + // initialPVCs are the list of PersistentVolumeClaims to be created at first. + // Note that PVs are automatically created following PVCs. + // Also, the namespace of pvcs is automatically filled in. + initialPVCs []*v1.PersistentVolumeClaim + // initialPVs are the list of PersistentVolume to be created at first. + initialPVs []*v1.PersistentVolume // pods are the list of Pods to be created. // All of them are expected to be unschedulable at first. pods []*v1.Pod @@ -748,7 +757,109 @@ func TestCoreResourceEnqueue(t *testing.T) { } return nil }, - wantRequeuedPods: sets.New("pod4"), + wantRequeuedPods: sets.New("pod4"), + }, + { + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PV is added", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Create(testCtx.Ctx, pv2, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to update pod1: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod2"), + enableSchedulingQueueHint: []bool{true}, + }, + { + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PV is updated", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + st.MakePersistentVolume(). + Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update pod1: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod2"), enableSchedulingQueueHint: []bool{true}, }, } @@ -785,6 +896,19 @@ func TestCoreResourceEnqueue(t *testing.T) { } } + for _, pv := range tt.initialPVs { + if _, err := testutils.CreatePV(cs, pv); err != nil { + t.Fatalf("Failed to create a PV %q: %v", pv.Name, err) + } + } + + for _, pvc := range tt.initialPVCs { + pvc.Namespace = ns + if _, err := testutils.CreatePVC(cs, pvc); err != nil { + t.Fatalf("Failed to create a PVC %q: %v", pvc.Name, err) + } + } + for _, pod := range tt.initialPods { if _, err := cs.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}); err != nil { t.Fatalf("Failed to create an initial Pod %q: %v", pod.Name, err) From 7b8985dc03c4a33ce73aa1557ce243dbc4b9765d Mon Sep 17 00:00:00 2001 From: moriya Date: Sat, 21 Sep 2024 01:09:10 +0900 Subject: [PATCH 2/6] add_test_cases --- pkg/scheduler/testing/wrappers.go | 32 ++++ test/integration/scheduler/queue_test.go | 213 ++++++++++++++++++++++- 2 files changed, 243 insertions(+), 2 deletions(-) diff --git a/pkg/scheduler/testing/wrappers.go b/pkg/scheduler/testing/wrappers.go index 94918f3c5a7..fcfa8dfca2b 100644 --- a/pkg/scheduler/testing/wrappers.go +++ b/pkg/scheduler/testing/wrappers.go @@ -22,6 +22,7 @@ import ( v1 "k8s.io/api/core/v1" resourceapi "k8s.io/api/resource/v1alpha3" + storagev1 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -1131,3 +1132,34 @@ func (wrapper *ResourceSliceWrapper) Device(name string, attrs map[resourceapi.Q wrapper.Spec.Devices = append(wrapper.Spec.Devices, resourceapi.Device{Name: name, Basic: &resourceapi.BasicDevice{Attributes: attrs}}) return wrapper } + +// StorageClassWrapper wraps a StorageClass inside. +type StorageClassWrapper struct{ storagev1.StorageClass } + +// MakeStorageClass creates a StorageClass wrapper. +func MakeStorageClass() *StorageClassWrapper { + return &StorageClassWrapper{} +} + +// Obj returns the inner StorageClass. +func (s *StorageClassWrapper) Obj() *storagev1.StorageClass { + return &s.StorageClass +} + +// Name sets `n` as the name of the inner StorageClass. +func (s *StorageClassWrapper) Name(n string) *StorageClassWrapper { + s.SetName(n) + return s +} + +// VolumeBindingMode sets mode as the mode of the inner StorageClass. +func (s *StorageClassWrapper) VolumeBindingMode(mode storagev1.VolumeBindingMode) *StorageClassWrapper { + s.StorageClass.VolumeBindingMode = &mode + return s +} + +// Provisoner sets p as the provisioner of the inner StorageClass. +func (s *StorageClassWrapper) Provisioner(p string) *StorageClassWrapper { + s.StorageClass.Provisioner = p + return s +} diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index b91499a4e6e..98c05e03a6a 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -23,6 +23,7 @@ import ( "time" v1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" "k8s.io/apimachinery/pkg/api/errors" @@ -800,7 +801,7 @@ func TestCoreResourceEnqueue(t *testing.T) { HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). Obj() if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Create(testCtx.Ctx, pv2, metav1.CreateOptions{}); err != nil { - return fmt.Errorf("failed to update pod1: %w", err) + return fmt.Errorf("failed to create pv2: %w", err) } return nil }, @@ -855,13 +856,221 @@ func TestCoreResourceEnqueue(t *testing.T) { HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). Obj() if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("failed to update pod1: %w", err) + return fmt.Errorf("failed to update pv2: %w", err) } return nil }, wantRequeuedPods: sets.New("pod2"), enableSchedulingQueueHint: []bool{true}, }, + { + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC is added", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + st.MakePersistentVolume(). + Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pvc2 := st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumeClaims(testCtx.NS.Name).Create(testCtx.Ctx, pvc2, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to add pvc2: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod2"), + enableSchedulingQueueHint: []bool{true}, + }, + { + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC is updated", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + st.MakePersistentVolume(). + Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pvc2 := st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumeClaims(testCtx.NS.Name).Update(testCtx.Ctx, pvc2, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update pvc2: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod2"), + enableSchedulingQueueHint: []bool{true}, + }, + { + name: "Pod rejected with node by the VolumeZone plugin is requeued when the Storage class is added", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + sc1 := st.MakeStorageClass(). + Name("sc1"). + VolumeBindingMode(storagev1.VolumeBindingWaitForFirstConsumer). + Provisioner("p"). + Obj() + if _, err := testCtx.ClientSet.StorageV1().StorageClasses().Create(testCtx.Ctx, sc1, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create sc1: %w", err) + } + return nil + }, + wantRequeuedPods: sets.New("pod2"), + enableSchedulingQueueHint: []bool{true}, + }, + { + name: "Pod rejected with node by the VolumeZone plugin is not requeued when the unrelated label of PV is updated", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + st.MakePersistentVolume(). + Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pv2 := st.MakePersistentVolume().Name("pv2").Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update pv2: %w", err) + } + return nil + }, + wantRequeuedPods: sets.Set[string]{}, + enableSchedulingQueueHint: []bool{true}, + }, } for _, tt := range tests { From d5e9199229bedcbd6591ba90e8bfee7cbb844f28 Mon Sep 17 00:00:00 2001 From: moriya Date: Sat, 21 Sep 2024 14:06:52 +0900 Subject: [PATCH 3/6] add test-cases --- test/integration/scheduler/queue_test.go | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index 98c05e03a6a..7cd3567e123 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -864,7 +864,7 @@ func TestCoreResourceEnqueue(t *testing.T) { enableSchedulingQueueHint: []bool{true}, }, { - name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC is added", + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC bound to the pod is added", initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, initialPVs: []*v1.PersistentVolume{ st.MakePersistentVolume(). @@ -914,7 +914,7 @@ func TestCoreResourceEnqueue(t *testing.T) { enableSchedulingQueueHint: []bool{true}, }, { - name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC is updated", + name: "Pod rejected with node by the VolumeZone plugin is requeued when the PVC bound to the pod is updated", initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, initialPVs: []*v1.PersistentVolume{ st.MakePersistentVolume(). @@ -1018,7 +1018,7 @@ func TestCoreResourceEnqueue(t *testing.T) { enableSchedulingQueueHint: []bool{true}, }, { - name: "Pod rejected with node by the VolumeZone plugin is not requeued when the unrelated label of PV is updated", + name: "Pod rejected with node by the VolumeZone plugin is not requeued when the unrelated PVC is added", initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, initialPVs: []*v1.PersistentVolume{ st.MakePersistentVolume(). @@ -1058,13 +1058,14 @@ func TestCoreResourceEnqueue(t *testing.T) { st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), }, triggerFn: func(testCtx *testutils.TestContext) error { - pv2 := st.MakePersistentVolume().Name("pv2").Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). - Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + pvc3 := st.MakePersistentVolumeClaim(). + Name("pvc3"). + Annotation(volume.AnnBindCompleted, "true"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). Obj() - if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { - return fmt.Errorf("failed to update pv2: %w", err) + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumeClaims(testCtx.NS.Name).Create(testCtx.Ctx, pvc3, metav1.CreateOptions{}); err != nil { + return fmt.Errorf("failed to create pvc3: %w", err) } return nil }, From 090145aadfd5b77bdcfdc4057b76f8ee9a34ddfb Mon Sep 17 00:00:00 2001 From: moriya Date: Mon, 23 Sep 2024 21:24:09 +0900 Subject: [PATCH 4/6] add_non_queued_pod --- test/integration/scheduler/queue_test.go | 57 +----------------------- 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index 7cd3567e123..f342db6ed9b 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -896,6 +896,7 @@ func TestCoreResourceEnqueue(t *testing.T) { }, pods: []*v1.Pod{ st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + st.MakePod().Name("pod3").Container("image").PVC("pvc3").Obj(), }, triggerFn: func(testCtx *testutils.TestContext) error { pvc2 := st.MakePersistentVolumeClaim(). @@ -952,6 +953,7 @@ func TestCoreResourceEnqueue(t *testing.T) { }, pods: []*v1.Pod{ st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + st.MakePod().Name("pod3").Container("image").PVC("pvc3").Obj(), }, triggerFn: func(testCtx *testutils.TestContext) error { pvc2 := st.MakePersistentVolumeClaim(). @@ -1017,61 +1019,6 @@ func TestCoreResourceEnqueue(t *testing.T) { wantRequeuedPods: sets.New("pod2"), enableSchedulingQueueHint: []bool{true}, }, - { - name: "Pod rejected with node by the VolumeZone plugin is not requeued when the unrelated PVC is added", - initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, - initialPVs: []*v1.PersistentVolume{ - st.MakePersistentVolume(). - Name("pv1"). - Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). - Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). - Obj(), - st.MakePersistentVolume(). - Name("pv2"). - Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). - Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). - Obj(), - }, - initialPVCs: []*v1.PersistentVolumeClaim{ - st.MakePersistentVolumeClaim(). - Name("pvc1"). - Annotation(volume.AnnBindCompleted, "true"). - VolumeName("pv1"). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). - Obj(), - st.MakePersistentVolumeClaim(). - Name("pvc2"). - Annotation(volume.AnnBindCompleted, "true"). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). - Obj(), - }, - initialPods: []*v1.Pod{ - st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), - }, - pods: []*v1.Pod{ - st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), - }, - triggerFn: func(testCtx *testutils.TestContext) error { - pvc3 := st.MakePersistentVolumeClaim(). - Name("pvc3"). - Annotation(volume.AnnBindCompleted, "true"). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). - Obj() - if _, err := testCtx.ClientSet.CoreV1().PersistentVolumeClaims(testCtx.NS.Name).Create(testCtx.Ctx, pvc3, metav1.CreateOptions{}); err != nil { - return fmt.Errorf("failed to create pvc3: %w", err) - } - return nil - }, - wantRequeuedPods: sets.Set[string]{}, - enableSchedulingQueueHint: []bool{true}, - }, } for _, tt := range tests { From cd0e0fc88164ba9afbf104d46cffaea4902ae721 Mon Sep 17 00:00:00 2001 From: moriya Date: Mon, 23 Sep 2024 21:49:09 +0900 Subject: [PATCH 5/6] add_test --- test/integration/scheduler/queue_test.go | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index f342db6ed9b..34977003b37 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -1019,6 +1019,62 @@ func TestCoreResourceEnqueue(t *testing.T) { wantRequeuedPods: sets.New("pod2"), enableSchedulingQueueHint: []bool{true}, }, + { + name: "Pod rejected with node by the VolumeZone plugin is not requeued when the PV is updated but the topology is same", + initialNodes: []*v1.Node{st.MakeNode().Name("fake-node").Label("node", "fake-node").Label(v1.LabelTopologyZone, "us-west1-a").Obj()}, + initialPVs: []*v1.PersistentVolume{ + st.MakePersistentVolume(). + Name("pv1"). + Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + st.MakePersistentVolume(). + Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj(), + }, + initialPVCs: []*v1.PersistentVolumeClaim{ + st.MakePersistentVolumeClaim(). + Name("pvc1"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + st.MakePersistentVolumeClaim(). + Name("pvc2"). + Annotation(volume.AnnBindCompleted, "true"). + VolumeName("pv2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}}). + Obj(), + }, + initialPods: []*v1.Pod{ + st.MakePod().Name("pod1").Container("image").PVC("pvc1").Node("fake-node").Obj(), + }, + pods: []*v1.Pod{ + st.MakePod().Name("pod2").Container("image").PVC("pvc2").Obj(), + }, + triggerFn: func(testCtx *testutils.TestContext) error { + pv2 := st.MakePersistentVolume().Name("pv2"). + Labels(map[string]string{v1.LabelTopologyZone: "us-east1", "unrelated": "unrelated"}). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). + Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + Obj() + if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update pv2: %w", err) + } + return nil + }, + wantRequeuedPods: sets.Set[string]{}, + enableSchedulingQueueHint: []bool{true}, + }, } for _, tt := range tests { From 3e57d5cf673f3dd79677c5b78ad3faca9478b7f1 Mon Sep 17 00:00:00 2001 From: moriya Date: Wed, 2 Oct 2024 06:54:32 +0900 Subject: [PATCH 6/6] fix --- test/integration/scheduler/queue_test.go | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/test/integration/scheduler/queue_test.go b/test/integration/scheduler/queue_test.go index 34977003b37..993d573c2a0 100644 --- a/test/integration/scheduler/queue_test.go +++ b/test/integration/scheduler/queue_test.go @@ -189,7 +189,6 @@ func TestSchedulingGates(t *testing.T) { // TestCoreResourceEnqueue verify Pods failed by in-tree default plugins can be // moved properly upon their registered events. func TestCoreResourceEnqueue(t *testing.T) { - volType := v1.HostPathDirectoryOrCreate tests := []struct { name string // initialNodes is the list of Nodes to be created at first. @@ -769,7 +768,7 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -798,7 +797,7 @@ func TestCoreResourceEnqueue(t *testing.T) { pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a"). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj() if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Create(testCtx.Ctx, pv2, metav1.CreateOptions{}); err != nil { return fmt.Errorf("failed to create pv2: %w", err) @@ -817,14 +816,14 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), st.MakePersistentVolume(). Name("pv2"). Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -853,7 +852,7 @@ func TestCoreResourceEnqueue(t *testing.T) { pv2 := st.MakePersistentVolume().Name("pv2").Label(v1.LabelTopologyZone, "us-west1-a"). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj() if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { return fmt.Errorf("failed to update pv2: %w", err) @@ -872,14 +871,14 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), st.MakePersistentVolume(). Name("pv2"). Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -923,14 +922,14 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), st.MakePersistentVolume(). Name("pv2"). Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -980,7 +979,7 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -1028,14 +1027,14 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-west1-a"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), st.MakePersistentVolume(). Name("pv2"). Labels(map[string]string{v1.LabelTopologyZone: "us-east1"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj(), }, initialPVCs: []*v1.PersistentVolumeClaim{ @@ -1065,7 +1064,7 @@ func TestCoreResourceEnqueue(t *testing.T) { Labels(map[string]string{v1.LabelTopologyZone: "us-east1", "unrelated": "unrelated"}). AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadOnlyMany}). Capacity(v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: &volType}). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/tmp", Type: ptr.To(v1.HostPathDirectoryOrCreate)}). Obj() if _, err := testCtx.ClientSet.CoreV1().PersistentVolumes().Update(testCtx.Ctx, pv2, metav1.UpdateOptions{}); err != nil { return fmt.Errorf("failed to update pv2: %w", err)