From 3a9b724316853fd06bfe5e2d9ca957529fae0087 Mon Sep 17 00:00:00 2001 From: Manohar Reddy Date: Wed, 7 Apr 2021 12:22:27 +0000 Subject: [PATCH] add subPath e2e test --- test/e2e/dynamic_provisioning_test.go | 23 +++++++++ test/e2e/e2e_suite_test.go | 25 +++++++++- ...cally_provisioned_volume_subpath_tester.go | 50 +++++++++++++++++++ test/e2e/testsuites/specs.go | 11 ++++ test/e2e/testsuites/testsuites.go | 22 ++++++++ 5 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 test/e2e/testsuites/dynamically_provisioned_volume_subpath_tester.go diff --git a/test/e2e/dynamic_provisioning_test.go b/test/e2e/dynamic_provisioning_test.go index 1b577a77..700ccebd 100644 --- a/test/e2e/dynamic_provisioning_test.go +++ b/test/e2e/dynamic_provisioning_test.go @@ -234,6 +234,29 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() { } test.Run(cs, ns) }) + + ginkgo.It("should create a pod with volume mount subpath [nfs.csi.k8s.io]", func() { + pods := []testsuites.PodDetails{ + { + Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"), + Volumes: []testsuites.VolumeDetails{ + { + ClaimSize: "10Gi", + VolumeMount: testsuites.VolumeMountDetails{ + NameGenerate: "test-volume-", + MountPathGenerate: "/mnt/test-", + }, + }, + }, + }, + } + test := testsuites.DynamicallyProvisionedVolumeSubpathTester{ + CSIDriver: testDriver, + Pods: pods, + StorageClassParameters: defaultStorageClassParameters, + } + test.Run(cs, ns) + }) }) func restClient(group string, version string) (restclientset.Interface, error) { diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index e6eed16c..e69075cb 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -35,13 +35,15 @@ import ( ) const ( - kubeconfigEnvVar = "KUBECONFIG" + kubeconfigEnvVar = "KUBECONFIG" + testWindowsEnvVar = "TEST_WINDOWS" ) var ( nodeID = os.Getenv("NODE_ID") perm *uint32 nfsDriver *nfs.Driver + isWindowsCluster = os.Getenv(testWindowsEnvVar) != "" defaultStorageClassParameters = map[string]string{ "server": "nfs-server.default.svc.cluster.local", "share": "/", @@ -168,3 +170,24 @@ func TestE2E(t *testing.T) { gomega.RegisterFailHandler(ginkgo.Fail) ginkgo.RunSpecs(t, "E2E Suite") } + +func convertToPowershellCommandIfNecessary(command string) string { + if !isWindowsCluster { + return command + } + + switch command { + case "echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data": + return "echo 'hello world' | Out-File -FilePath C:\\mnt\\test-1\\data.txt; Get-Content C:\\mnt\\test-1\\data.txt | findstr 'hello world'" + case "touch /mnt/test-1/data": + return "echo $null >> C:\\mnt\\test-1\\data" + case "while true; do echo $(date -u) >> /mnt/test-1/data; sleep 100; done": + return "while (1) { Add-Content -Encoding Unicode C:\\mnt\\test-1\\data.txt $(Get-Date -Format u); sleep 1 }" + case "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 100; done": + return "Add-Content -Encoding Unicode C:\\mnt\\test-1\\data.txt 'hello world'; while (1) { sleep 1 }" + case "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 3600; done": + return "Add-Content -Encoding Unicode C:\\mnt\\test-1\\data.txt 'hello world'; while (1) { sleep 1 }" + } + + return command +} diff --git a/test/e2e/testsuites/dynamically_provisioned_volume_subpath_tester.go b/test/e2e/testsuites/dynamically_provisioned_volume_subpath_tester.go new file mode 100644 index 00000000..65a6332e --- /dev/null +++ b/test/e2e/testsuites/dynamically_provisioned_volume_subpath_tester.go @@ -0,0 +1,50 @@ +/* +Copyright 2021 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testsuites + +import ( + "github.com/kubernetes-csi/csi-driver-nfs/test/e2e/driver" + + "github.com/onsi/ginkgo" + v1 "k8s.io/api/core/v1" + clientset "k8s.io/client-go/kubernetes" +) + +// DynamicallyProvisionedCmdVolumeTest will provision required StorageClass(es), PVC(s) and Pod(s) +// Waiting for the PV provisioner to create a new PV +// Testing if the Pod(s) Cmd is run with a 0 exit code +type DynamicallyProvisionedVolumeSubpathTester struct { + CSIDriver driver.DynamicPVTestDriver + Pods []PodDetails + StorageClassParameters map[string]string +} + +func (t *DynamicallyProvisionedVolumeSubpathTester) Run(client clientset.Interface, namespace *v1.Namespace) { + for _, pod := range t.Pods { + tpod, cleanup := pod.SetupWithDynamicVolumesWithSubpath(client, namespace, t.CSIDriver, t.StorageClassParameters) + // defer must be called here for resources not get removed before using them + for i := range cleanup { + defer cleanup[i]() + } + + ginkgo.By("deploying the pod") + tpod.Create() + defer tpod.Cleanup() + ginkgo.By("checking that the pods command exits with no error") + tpod.WaitForSuccess() + } +} diff --git a/test/e2e/testsuites/specs.go b/test/e2e/testsuites/specs.go index 9e038b10..3c52a639 100644 --- a/test/e2e/testsuites/specs.go +++ b/test/e2e/testsuites/specs.go @@ -159,3 +159,14 @@ func (pod *PodDetails) SetupWithDynamicMultipleVolumes(client clientset.Interfac } return tpod, cleanupFuncs } + +func (pod *PodDetails) SetupWithDynamicVolumesWithSubpath(client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestPod, []func()) { + tpod := NewTestPod(client, namespace, pod.Cmd) + cleanupFuncs := make([]func(), 0) + for n, v := range pod.Volumes { + tpvc, funcs := v.SetupDynamicPersistentVolumeClaim(client, namespace, csiDriver, storageClassParameters) + cleanupFuncs = append(cleanupFuncs, funcs...) + tpod.SetupVolumeMountWithSubpath(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeMount.NameGenerate, n+1), fmt.Sprintf("%s%d", v.VolumeMount.MountPathGenerate, n+1), "testSubpath", v.VolumeMount.ReadOnly) + } + return tpod, cleanupFuncs +} diff --git a/test/e2e/testsuites/testsuites.go b/test/e2e/testsuites/testsuites.go index 68407cfd..c9812274 100644 --- a/test/e2e/testsuites/testsuites.go +++ b/test/e2e/testsuites/testsuites.go @@ -573,3 +573,25 @@ func (t *TestPersistentVolumeClaim) DeleteBackingVolume(cs *nfs.ControllerServer ginkgo.Fail(fmt.Sprintf("could not delete volume %q: %v", volumeID, err)) } } + +func (t *TestPod) SetupVolumeMountWithSubpath(pvc *v1.PersistentVolumeClaim, name, mountPath string, subpath string, readOnly bool) { + volumeMount := v1.VolumeMount{ + Name: name, + MountPath: mountPath, + SubPath: subpath, + ReadOnly: readOnly, + } + + t.pod.Spec.Containers[0].VolumeMounts = append(t.pod.Spec.Containers[0].VolumeMounts, volumeMount) + + volume := v1.Volume{ + Name: name, + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc.Name, + }, + }, + } + + t.pod.Spec.Volumes = append(t.pod.Spec.Volumes, volume) +}