Skip to content

Commit

Permalink
Merge pull request #79 from mayankshah1607/e2e
Browse files Browse the repository at this point in the history
Add E2E test cases for dynamic provisioning
  • Loading branch information
k8s-ci-robot authored Nov 12, 2020
2 parents 1b936d5 + a43b9f8 commit cf5280d
Show file tree
Hide file tree
Showing 15 changed files with 1,841 additions and 4 deletions.
151 changes: 151 additions & 0 deletions test/e2e/dynamic_provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,157 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {

test.Run(cs, ns)
})

ginkgo.It("should create multiple PV objects, bind to PVCs and attach all to different pods on the same node [nfs.csi.k8s.io]", func() {
pods := []testsuites.PodDetails{
{
Cmd: "while true; do echo $(date -u) >> /mnt/test-1/data; sleep 100; done",
Volumes: []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
},
},
},
},
{
Cmd: "while true; do echo $(date -u) >> /mnt/test-1/data; sleep 100; done",
Volumes: []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
},
},
},
},
}
test := testsuites.DynamicallyProvisionedCollocatedPodTest{
CSIDriver: testDriver,
Pods: pods,
ColocatePods: true,
StorageClassParameters: defaultStorageClassParameters,
}
test.Run(cs, ns)
})

// Track issue https://github.com/kubernetes/kubernetes/issues/70505
ginkgo.It("should create a volume on demand and mount it as readOnly in a pod [nfs.csi.k8s.io]", func() {
pods := []testsuites.PodDetails{
{
Cmd: "touch /mnt/test-1/data",
Volumes: []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
ReadOnly: true,
},
},
},
},
}
test := testsuites.DynamicallyProvisionedReadOnlyVolumeTest{
CSIDriver: testDriver,
Pods: pods,
StorageClassParameters: defaultStorageClassParameters,
}
test.Run(cs, ns)
})

ginkgo.It("should create a deployment object, write and read to it, delete the pod and write and read to it again [nfs.csi.k8s.io]", func() {
pod := testsuites.PodDetails{
Cmd: "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 100; done",
Volumes: []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
},
},
},
}

podCheckCmd := []string{"cat", "/mnt/test-1/data"}
expectedString := "hello world\n"

test := testsuites.DynamicallyProvisionedDeletePodTest{
CSIDriver: testDriver,
Pod: pod,
PodCheck: &testsuites.PodExecCheck{
Cmd: podCheckCmd,
ExpectedString: expectedString, // pod will be restarted so expect to see 2 instances of string
},
StorageClassParameters: defaultStorageClassParameters,
}
test.Run(cs, ns)
})

ginkgo.It(fmt.Sprintf("should delete PV with reclaimPolicy %q [nfs.csi.k8s.io]", v1.PersistentVolumeReclaimDelete), func() {
reclaimPolicy := v1.PersistentVolumeReclaimDelete
volumes := []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
ReclaimPolicy: &reclaimPolicy,
},
}
test := testsuites.DynamicallyProvisionedReclaimPolicyTest{
CSIDriver: testDriver,
Volumes: volumes,
StorageClassParameters: defaultStorageClassParameters,
ControllerServer: *controllerServer,
}
test.Run(cs, ns)
})

ginkgo.It(fmt.Sprintf("should retain PV with reclaimPolicy %q [nfs.csi.k8s.io]", v1.PersistentVolumeReclaimRetain), func() {
reclaimPolicy := v1.PersistentVolumeReclaimRetain
volumes := []testsuites.VolumeDetails{
{
ClaimSize: "10Gi",
ReclaimPolicy: &reclaimPolicy,
},
}
test := testsuites.DynamicallyProvisionedReclaimPolicyTest{
CSIDriver: testDriver,
Volumes: volumes,
ControllerServer: *controllerServer,
StorageClassParameters: defaultStorageClassParameters,
}
test.Run(cs, ns)
})

ginkgo.It("should create a pod with multiple volumes [nfs.csi.k8s.io]", func() {
volumes := []testsuites.VolumeDetails{}
for i := 1; i <= 6; i++ {
volume := testsuites.VolumeDetails{
ClaimSize: "100Gi",
VolumeMount: testsuites.VolumeMountDetails{
NameGenerate: "test-volume-",
MountPathGenerate: "/mnt/test-",
},
}
volumes = append(volumes, volume)
}

pods := []testsuites.PodDetails{
{
Cmd: "echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data",
Volumes: volumes,
},
}
test := testsuites.DynamicallyProvisionedPodWithMultiplePVsTest{
CSIDriver: testDriver,
Pods: pods,
StorageClassParameters: defaultStorageClassParameters,
}
test.Run(cs, ns)
})
})

func restClient(group string, version string) (restclientset.Interface, error) {
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var (
"server": "nfs-server.default.svc.cluster.local",
"share": "/",
}
controllerServer = nfs.NewControllerServer(nfsDriver)
)

type testCmd struct {
Expand Down Expand Up @@ -79,7 +80,7 @@ var _ = ginkgo.AfterSuite(func() {
command: "make",
args: []string{"e2e-teardown"},
startLog: "Uninstalling NFS CSI Driver...",
endLog: "SMB Driver uninstalled",
endLog: "NFS Driver uninstalled",
}
execTestCmd([]testCmd{e2eTeardown})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2020 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"
)

// DynamicallyProvisionedCollocatedPodTest will provision required StorageClass(es), PVC(s) and Pod(s)
// Waiting for the PV provisioner to create a new PV
// Testing if multiple Pod(s) can write simultaneously
type DynamicallyProvisionedCollocatedPodTest struct {
CSIDriver driver.DynamicPVTestDriver
Pods []PodDetails
ColocatePods bool
StorageClassParameters map[string]string
}

func (t *DynamicallyProvisionedCollocatedPodTest) Run(client clientset.Interface, namespace *v1.Namespace) {
nodeName := ""
for _, pod := range t.Pods {
tpod, cleanup := pod.SetupWithDynamicVolumes(client, namespace, t.CSIDriver, t.StorageClassParameters)
if t.ColocatePods && nodeName != "" {
tpod.SetNodeSelector(map[string]string{"name": nodeName})
}
// 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 pod is running")
tpod.WaitForRunning()
nodeName = tpod.pod.Spec.NodeName
}

}
70 changes: 70 additions & 0 deletions test/e2e/testsuites/dynamically_provisioned_delete_pod_tester.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
Copyright 2020 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"
)

// DynamicallyProvisionedDeletePodTest will provision required StorageClass and Deployment
// Testing if the Pod can write and read to mounted volumes
// Deleting a pod, and again testing if the Pod can write and read to mounted volumes
type DynamicallyProvisionedDeletePodTest struct {
CSIDriver driver.DynamicPVTestDriver
Pod PodDetails
PodCheck *PodExecCheck
StorageClassParameters map[string]string
}

type PodExecCheck struct {
Cmd []string
ExpectedString string
}

func (t *DynamicallyProvisionedDeletePodTest) Run(client clientset.Interface, namespace *v1.Namespace) {
tDeployment, cleanup := t.Pod.SetupDeployment(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 deployment")
tDeployment.Create()

ginkgo.By("checking that the pod is running")
tDeployment.WaitForPodReady()

if t.PodCheck != nil {
ginkgo.By("checking pod exec")
tDeployment.Exec(t.PodCheck.Cmd, t.PodCheck.ExpectedString)
}

ginkgo.By("deleting the pod for deployment")
tDeployment.DeletePodAndWait()

ginkgo.By("checking again that the pod is running")
tDeployment.WaitForPodReady()

if t.PodCheck != nil {
ginkgo.By("checking pod exec")
// pod will be restarted so expect to see 2 instances of string
tDeployment.Exec(t.PodCheck.Cmd, t.PodCheck.ExpectedString+t.PodCheck.ExpectedString)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2020 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"
)

// DynamicallyProvisionedPodWithMultiplePVsTest will provision
// one pod with multiple PVs
// Waiting for the PV provisioner to create a new PV
// Testing if the Pod(s) Cmd is run with a 0 exit code
type DynamicallyProvisionedPodWithMultiplePVsTest struct {
CSIDriver driver.DynamicPVTestDriver
Pods []PodDetails
StorageClassParameters map[string]string
}

func (t *DynamicallyProvisionedPodWithMultiplePVsTest) Run(client clientset.Interface, namespace *v1.Namespace) {
for _, pod := range t.Pods {
tpod, cleanup := pod.SetupWithDynamicMultipleVolumes(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()
}
}
Loading

0 comments on commit cf5280d

Please sign in to comment.