Skip to content

Commit 4ef7151

Browse files
authored
Merge pull request #813 from cvvz/e2e-unmount-test
add e2e test for unmount deleted volume
2 parents 3ff3e1d + 75c5ba5 commit 4ef7151

5 files changed

+197
-4
lines changed

test/e2e/dynamic_provisioning_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,4 +708,107 @@ var _ = ginkgo.Describe("[blob-csi-e2e] Dynamic Provisioning", func() {
708708
}
709709
test.Run(cs, ns)
710710
})
711+
712+
ginkgo.It("should be able to unmount blobfuse volume if volume is already deleted [blob.csi.azure.com]", func() {
713+
pod := testsuites.PodDetails{
714+
Cmd: "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 1; done",
715+
Volumes: []testsuites.VolumeDetails{
716+
{
717+
ClaimSize: "10Gi",
718+
MountOptions: []string{
719+
"-o allow_other",
720+
"--file-cache-timeout-in-seconds=120",
721+
"--cancel-list-on-mount-seconds=0",
722+
},
723+
VolumeMount: testsuites.VolumeMountDetails{
724+
NameGenerate: "test-volume-",
725+
MountPathGenerate: "/mnt/test-",
726+
},
727+
},
728+
},
729+
}
730+
731+
test := testsuites.DynamicallyProvisionedVolumeUnmountTest{
732+
CSIDriver: testDriver,
733+
Driver: blobDriver,
734+
Pod: pod,
735+
PodCheck: &testsuites.PodExecCheck{
736+
Cmd: []string{"cat", "/mnt/test-1/data"},
737+
ExpectedString: "hello world\n",
738+
},
739+
StorageClassParameters: map[string]string{
740+
"skuName": "Standard_LRS",
741+
"protocol": "fuse",
742+
},
743+
}
744+
test.Run(cs, ns)
745+
})
746+
747+
ginkgo.It("should be able to unmount blobfuse2 volume if volume is already deleted [blob.csi.azure.com]", func() {
748+
pod := testsuites.PodDetails{
749+
Cmd: "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 1; done",
750+
Volumes: []testsuites.VolumeDetails{
751+
{
752+
ClaimSize: "10Gi",
753+
MountOptions: []string{
754+
"-o allow_other",
755+
"--virtual-directory=true", // blobfuse2 mount options
756+
},
757+
VolumeMount: testsuites.VolumeMountDetails{
758+
NameGenerate: "test-volume-",
759+
MountPathGenerate: "/mnt/test-",
760+
},
761+
},
762+
},
763+
}
764+
765+
test := testsuites.DynamicallyProvisionedVolumeUnmountTest{
766+
CSIDriver: testDriver,
767+
Driver: blobDriver,
768+
Pod: pod,
769+
PodCheck: &testsuites.PodExecCheck{
770+
Cmd: []string{"cat", "/mnt/test-1/data"},
771+
ExpectedString: "hello world\n",
772+
},
773+
StorageClassParameters: map[string]string{
774+
"skuName": "Standard_LRS",
775+
"protocol": "fuse2",
776+
},
777+
}
778+
test.Run(cs, ns)
779+
})
780+
781+
ginkgo.It("should be able to unmount NFS volume if volume is already deleted [blob.csi.azure.com]", func() {
782+
pod := testsuites.PodDetails{
783+
Cmd: "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 1; done",
784+
Volumes: []testsuites.VolumeDetails{
785+
{
786+
ClaimSize: "10Gi",
787+
MountOptions: []string{
788+
"nconnect=8",
789+
},
790+
VolumeMount: testsuites.VolumeMountDetails{
791+
NameGenerate: "test-volume-",
792+
MountPathGenerate: "/mnt/test-",
793+
},
794+
},
795+
},
796+
}
797+
798+
test := testsuites.DynamicallyProvisionedVolumeUnmountTest{
799+
CSIDriver: testDriver,
800+
Driver: blobDriver,
801+
Pod: pod,
802+
PodCheck: &testsuites.PodExecCheck{
803+
Cmd: []string{"cat", "/mnt/test-1/data"},
804+
ExpectedString: "hello world\n",
805+
},
806+
StorageClassParameters: map[string]string{
807+
"skuName": "Premium_LRS",
808+
"protocol": "nfs",
809+
"mountPermissions": "0755",
810+
},
811+
}
812+
test.Run(cs, ns)
813+
})
711814
})

test/e2e/testsuites/dynamically_provisioned_delete_pod_tester.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type PodExecCheck struct {
4040
}
4141

4242
func (t *DynamicallyProvisionedDeletePodTest) Run(client clientset.Interface, namespace *v1.Namespace) {
43-
tDeployment, cleanup := t.Pod.SetupDeployment(client, namespace, t.CSIDriver, t.StorageClassParameters)
43+
tDeployment, cleanup, _ := t.Pod.SetupDeployment(client, namespace, t.CSIDriver, t.StorageClassParameters)
4444
// defer must be called here for resources not get removed before using them
4545
for i := range cleanup {
4646
defer cleanup[i]()

test/e2e/testsuites/dynamically_provisioned_restart_driver_tester.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type DynamicallyProvisionedRestartDriverTest struct {
3535
}
3636

3737
func (t *DynamicallyProvisionedRestartDriverTest) Run(client clientset.Interface, namespace *v1.Namespace) {
38-
tDeployment, cleanup := t.Pod.SetupDeployment(client, namespace, t.CSIDriver, t.StorageClassParameters)
38+
tDeployment, cleanup, _ := t.Pod.SetupDeployment(client, namespace, t.CSIDriver, t.StorageClassParameters)
3939
// defer must be called here for resources not get removed before using them
4040
for i := range cleanup {
4141
defer cleanup[i]()
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package testsuites
18+
19+
import (
20+
"context"
21+
"time"
22+
23+
"sigs.k8s.io/blob-csi-driver/pkg/blob"
24+
"sigs.k8s.io/blob-csi-driver/test/e2e/driver"
25+
26+
"github.com/container-storage-interface/spec/lib/go/csi"
27+
"github.com/onsi/ginkgo/v2"
28+
"github.com/onsi/gomega"
29+
v1 "k8s.io/api/core/v1"
30+
clientset "k8s.io/client-go/kubernetes"
31+
)
32+
33+
// DynamicallyProvisionedVolumeUnmountTest will provision required StorageClass and Deployment
34+
// Testing if the Pod can write and read to mounted volumes
35+
// Delete the volume and check whether pod could be terminated successfully
36+
type DynamicallyProvisionedVolumeUnmountTest struct {
37+
CSIDriver driver.DynamicPVTestDriver
38+
Driver *blob.Driver
39+
Pod PodDetails
40+
PodCheck *PodExecCheck
41+
StorageClassParameters map[string]string
42+
}
43+
44+
func (t *DynamicallyProvisionedVolumeUnmountTest) Run(client clientset.Interface, namespace *v1.Namespace) {
45+
tDeployment, cleanup, volumeID := t.Pod.SetupDeployment(client, namespace, t.CSIDriver, t.StorageClassParameters)
46+
// defer must be called here for resources not get removed before using them
47+
for i := range cleanup {
48+
defer cleanup[i]()
49+
}
50+
51+
ginkgo.By("deploying the deployment")
52+
tDeployment.Create()
53+
54+
ginkgo.By("checking that the pod is running")
55+
tDeployment.WaitForPodReady()
56+
57+
if t.PodCheck != nil {
58+
time.Sleep(time.Second)
59+
ginkgo.By("check pod exec")
60+
tDeployment.PollForStringInPodsExec(t.PodCheck.Cmd, t.PodCheck.ExpectedString)
61+
}
62+
63+
ginkgo.By("delete volume " + volumeID + " first, make sure pod could still be terminated")
64+
_, err := t.Driver.DeleteVolume(context.TODO(), &csi.DeleteVolumeRequest{VolumeId: volumeID})
65+
gomega.Expect(err).NotTo(gomega.HaveOccurred())
66+
67+
ginkgo.By("check whether " + volumeID + " has been deleted")
68+
multiNodeVolCap := []*csi.VolumeCapability{
69+
{
70+
AccessMode: &csi.VolumeCapability_AccessMode{
71+
Mode: csi.VolumeCapability_AccessMode_MULTI_NODE_SINGLE_WRITER,
72+
},
73+
},
74+
}
75+
req := &csi.ValidateVolumeCapabilitiesRequest{
76+
VolumeId: volumeID,
77+
VolumeCapabilities: multiNodeVolCap,
78+
}
79+
if _, err = t.Driver.ValidateVolumeCapabilities(context.TODO(), req); err != nil {
80+
ginkgo.By("ValidateVolumeCapabilities " + volumeID + " returned with error: " + err.Error())
81+
}
82+
gomega.Expect(err).To(gomega.HaveOccurred())
83+
84+
ginkgo.By("deleting the pod for deployment")
85+
tDeployment.DeletePodAndWait()
86+
}

test/e2e/testsuites/specs.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func (pod *PodDetails) SetupWithPreProvisionedVolumes(client clientset.Interface
148148
return tpod, cleanupFuncs
149149
}
150150

151-
func (pod *PodDetails) SetupDeployment(client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestDeployment, []func()) {
151+
func (pod *PodDetails) SetupDeployment(client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestDeployment, []func(), string) {
152152
cleanupFuncs := make([]func(), 0)
153153
volume := pod.Volumes[0]
154154
ginkgo.By("setting up the StorageClass")
@@ -166,7 +166,11 @@ func (pod *PodDetails) SetupDeployment(client clientset.Interface, namespace *v1
166166
tDeployment := NewTestDeployment(client, namespace, pod.Cmd, tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", volume.VolumeMount.NameGenerate, 1), fmt.Sprintf("%s%d", volume.VolumeMount.MountPathGenerate, 1), volume.VolumeMount.ReadOnly)
167167

168168
cleanupFuncs = append(cleanupFuncs, tDeployment.Cleanup)
169-
return tDeployment, cleanupFuncs
169+
var volumeID string
170+
if tpvc.persistentVolume != nil && tpvc.persistentVolume.Spec.CSI != nil {
171+
volumeID = tpvc.persistentVolume.Spec.CSI.VolumeHandle
172+
}
173+
return tDeployment, cleanupFuncs, volumeID
170174
}
171175

172176
func (volume *VolumeDetails) SetupDynamicPersistentVolumeClaim(client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestPersistentVolumeClaim, []func()) {

0 commit comments

Comments
 (0)