Overhauled pv e2e test to reflect common lifecycle
This commit is contained in:
		@@ -17,10 +17,10 @@ limitations under the License.
 | 
				
			|||||||
package e2e
 | 
					package e2e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	. "github.com/onsi/ginkgo"
 | 
						. "github.com/onsi/ginkgo"
 | 
				
			||||||
	. "github.com/onsi/gomega"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api"
 | 
						"k8s.io/kubernetes/pkg/api"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/resource"
 | 
						"k8s.io/kubernetes/pkg/api/resource"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/testapi"
 | 
						"k8s.io/kubernetes/pkg/api/testapi"
 | 
				
			||||||
@@ -38,23 +38,32 @@ func persistentVolumeTestCleanup(client *client.Client, config VolumeTestConfig)
 | 
				
			|||||||
	if config.serverImage != "" {
 | 
						if config.serverImage != "" {
 | 
				
			||||||
		err := podClient.Delete(config.prefix+"-server", nil)
 | 
							err := podClient.Delete(config.prefix+"-server", nil)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			framework.ExpectNoError(err, "Failed to delete server pod: %v", err)
 | 
								framework.Failf("Failed to delete the server pod: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func deletePersistentVolume(c *client.Client, pv *api.PersistentVolume) {
 | 
				
			||||||
 | 
						// Delete the PersistentVolume
 | 
				
			||||||
 | 
						framework.Logf("Deleting PersistentVolume")
 | 
				
			||||||
 | 
						err := c.PersistentVolumes().Delete(pv.Name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							framework.Failf("Delete PersistentVolume failed: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Wait for PersistentVolume to Delete
 | 
				
			||||||
 | 
						framework.WaitForPersistentVolumeDeleted(c, pv.Name, 3*time.Second, 30*time.Second)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var _ = framework.KubeDescribe("PersistentVolumes", func() {
 | 
					var _ = framework.KubeDescribe("PersistentVolumes", func() {
 | 
				
			||||||
	f := framework.NewDefaultFramework("pv")
 | 
						f := framework.NewDefaultFramework("pv")
 | 
				
			||||||
	var c *client.Client
 | 
						var c *client.Client
 | 
				
			||||||
	var ns string
 | 
						var ns string
 | 
				
			||||||
 | 
					 | 
				
			||||||
	BeforeEach(func() {
 | 
						BeforeEach(func() {
 | 
				
			||||||
		c = f.Client
 | 
							c = f.Client
 | 
				
			||||||
		ns = f.Namespace.Name
 | 
							ns = f.Namespace.Name
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Flaky issue: #25294
 | 
						It("should create a PersistentVolume, Claim, and a client Pod that will test the read/write access of the volume[Flaky]", func() {
 | 
				
			||||||
	It("NFS volume can be created, bound, retrieved, unbound, and used by a pod [Flaky]", func() {
 | 
					 | 
				
			||||||
		config := VolumeTestConfig{
 | 
							config := VolumeTestConfig{
 | 
				
			||||||
			namespace:   ns,
 | 
								namespace:   ns,
 | 
				
			||||||
			prefix:      "nfs",
 | 
								prefix:      "nfs",
 | 
				
			||||||
@@ -66,58 +75,102 @@ var _ = framework.KubeDescribe("PersistentVolumes", func() {
 | 
				
			|||||||
			persistentVolumeTestCleanup(c, config)
 | 
								persistentVolumeTestCleanup(c, config)
 | 
				
			||||||
		}()
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Create the nfs server pod
 | 
				
			||||||
		pod := startVolumeServer(c, config)
 | 
							pod := startVolumeServer(c, config)
 | 
				
			||||||
		serverIP := pod.Status.PodIP
 | 
							serverIP := pod.Status.PodIP
 | 
				
			||||||
		framework.Logf("NFS server IP address: %v", serverIP)
 | 
							framework.Logf("NFS server IP address: %v", serverIP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Define the PersistentVolume and PersistentVolumeClaim
 | 
				
			||||||
		pv := makePersistentVolume(serverIP)
 | 
							pv := makePersistentVolume(serverIP)
 | 
				
			||||||
		pvc := makePersistentVolumeClaim(ns)
 | 
							pvc := makePersistentVolumeClaim(ns)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		framework.Logf("Creating PersistentVolume using NFS")
 | 
							// Create the PersistentVolume and wait for PersistentVolume.Status.Phase to be Available
 | 
				
			||||||
 | 
							// defer deletion to clean up the PV should the test fail post-creation.
 | 
				
			||||||
 | 
							framework.Logf("Creating PersistentVolume")
 | 
				
			||||||
		pv, err := c.PersistentVolumes().Create(pv)
 | 
							pv, err := c.PersistentVolumes().Create(pv)
 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("Create PersistentVolume failed: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer deletePersistentVolume(c, pv)
 | 
				
			||||||
 | 
							framework.WaitForPersistentVolumePhase(api.VolumeAvailable, c, pv.Name, 1*time.Second, 20*time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Create the PersistentVolumeClaim and wait for Bound phase
 | 
				
			||||||
		framework.Logf("Creating PersistentVolumeClaim")
 | 
							framework.Logf("Creating PersistentVolumeClaim")
 | 
				
			||||||
		pvc, err = c.PersistentVolumeClaims(ns).Create(pvc)
 | 
							pvc, err = c.PersistentVolumeClaims(ns).Create(pvc)
 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("Create PersistentVolumeClaim failed: %v", err)
 | 
				
			||||||
		// allow the binder a chance to catch up.  should not be more than 20s.
 | 
							}
 | 
				
			||||||
		framework.WaitForPersistentVolumePhase(api.VolumeBound, c, pv.Name, 1*time.Second, 30*time.Second)
 | 
							framework.WaitForPersistentVolumeClaimPhase(api.ClaimBound, c, ns, pvc.Name, 3*time.Second, 300*time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Wait for PersistentVolume.Status.Phase to be Bound. Can take several minutes.
 | 
				
			||||||
 | 
							err = framework.WaitForPersistentVolumePhase(api.VolumeBound, c, pv.Name, 3*time.Second, 300*time.Second)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("PersistentVolume failed to enter a bound state: %+v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Check the PersistentVolume.ClaimRef.UID for non-nil value as confirmation of the bound state.
 | 
				
			||||||
 | 
							framework.Logf("Checking PersistentVolume ClaimRef is non-nil")
 | 
				
			||||||
		pv, err = c.PersistentVolumes().Get(pv.Name)
 | 
							pv, err = c.PersistentVolumes().Get(pv.Name)
 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
							if pv.Spec.ClaimRef == nil || len(pv.Spec.ClaimRef.UID) == 0 {
 | 
				
			||||||
		if pv.Spec.ClaimRef == nil {
 | 
								pvJson, _ := json.MarshalIndent(pv, "", "  ")
 | 
				
			||||||
			framework.Failf("Expected PersistentVolume to be bound, but got nil ClaimRef: %+v", pv)
 | 
								framework.Failf("Expected PersistentVolume to be bound, but got nil ClaimRef or UID: %+v", string(pvJson))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Check the PersistentVolumeClaim.Status.Phase for Bound state
 | 
				
			||||||
 | 
							framework.Logf("Checking PersistentVolumeClaim status is Bound")
 | 
				
			||||||
 | 
							pvc, err = c.PersistentVolumeClaims(ns).Get(pvc.Name)
 | 
				
			||||||
 | 
							if pvcPhase := pvc.Status.Phase; pvcPhase != "Bound" {
 | 
				
			||||||
 | 
								framework.Failf("Expected PersistentVolumeClaim status Bound. Actual:  %+v.  Error: %+v", pvcPhase, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Check that the PersistentVolume's ClaimRef contains the UID of the PersistendVolumeClaim
 | 
				
			||||||
 | 
							if pvc.ObjectMeta.UID != pv.Spec.ClaimRef.UID {
 | 
				
			||||||
 | 
								framework.Failf("Binding failed: PersistentVolumeClaim UID does not match PersistentVolume's ClaimRef UID. ")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// writePod writes to the nfs volume
 | 
				
			||||||
 | 
							framework.Logf("Creating writePod")
 | 
				
			||||||
 | 
							pvc, _ = c.PersistentVolumeClaims(ns).Get(pvc.Name)
 | 
				
			||||||
 | 
							writePod := makeWritePod(ns, pvc.Name)
 | 
				
			||||||
 | 
							writePod, err = c.Pods(ns).Create(writePod)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("Create writePod failed: %+v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Wait for the writePod to complete it's lifecycle
 | 
				
			||||||
 | 
							err = framework.WaitForPodSuccessInNamespace(c, writePod.Name, writePod.Spec.Containers[0].Name, writePod.Namespace)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("WritePod exited with error: %+v", err)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								framework.Logf("WritePod exited without error.")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Delete the PersistentVolumeClaim
 | 
				
			||||||
		framework.Logf("Deleting PersistentVolumeClaim to trigger PV Recycling")
 | 
							framework.Logf("Deleting PersistentVolumeClaim to trigger PV Recycling")
 | 
				
			||||||
		err = c.PersistentVolumeClaims(ns).Delete(pvc.Name)
 | 
							err = c.PersistentVolumeClaims(ns).Delete(pvc.Name)
 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
							if err != nil {
 | 
				
			||||||
 | 
								framework.Failf("Delete PersistentVolumeClaim failed: %v", err)
 | 
				
			||||||
		// allow the recycler a chance to catch up.  it has to perform NFS scrub, which can be slow in e2e.
 | 
							}
 | 
				
			||||||
		framework.WaitForPersistentVolumePhase(api.VolumeAvailable, c, pv.Name, 5*time.Second, 300*time.Second)
 | 
					
 | 
				
			||||||
 | 
							// Wait for the PersistentVolume phase to return to Available
 | 
				
			||||||
		pv, err = c.PersistentVolumes().Get(pv.Name)
 | 
							framework.Logf("Waiting for recycling process to complete.")
 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
							err = framework.WaitForPersistentVolumePhase(api.VolumeAvailable, c, pv.Name, 3*time.Second, 300*time.Second)
 | 
				
			||||||
		if pv.Spec.ClaimRef != nil {
 | 
							if err != nil {
 | 
				
			||||||
			framework.Failf("Expected PersistentVolume to be unbound, but found non-nil ClaimRef: %+v", pv)
 | 
								framework.Failf("Recycling failed: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Examine the PersistentVolume.ClaimRef and UID.  Expect nil values.
 | 
				
			||||||
 | 
							pv, err = c.PersistentVolumes().Get(pv.Name)
 | 
				
			||||||
 | 
							if pv.Spec.ClaimRef != nil && len(pv.Spec.ClaimRef.UID) > 0 {
 | 
				
			||||||
 | 
								crjson, _ := json.MarshalIndent(pv.Spec.ClaimRef, "", "  ")
 | 
				
			||||||
 | 
								framework.Failf("Expected a nil ClaimRef or UID. Found: ", string(crjson))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// The NFS Server pod we're using contains an index.html file
 | 
					 | 
				
			||||||
		// Verify the file was really scrubbed from the volume
 | 
					 | 
				
			||||||
		podTemplate := makeCheckPod(ns, serverIP)
 | 
					 | 
				
			||||||
		checkpod, err := c.Pods(ns).Create(podTemplate)
 | 
					 | 
				
			||||||
		framework.ExpectNoError(err, "Failed to create checker pod: %v", err)
 | 
					 | 
				
			||||||
		err = framework.WaitForPodSuccessInNamespace(c, checkpod.Name, checkpod.Spec.Containers[0].Name, checkpod.Namespace)
 | 
					 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
		// must delete PV, otherwise the PV is available and next time a PVC may bind to it and cause new PV fails to bind
 | 
					 | 
				
			||||||
		framework.Logf("Deleting PersistentVolume")
 | 
					 | 
				
			||||||
		err = c.PersistentVolumes().Delete(pv.Name)
 | 
					 | 
				
			||||||
		Expect(err).NotTo(HaveOccurred())
 | 
					 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makePersistentVolume(serverIP string) *api.PersistentVolume {
 | 
					func makePersistentVolume(serverIP string) *api.PersistentVolume {
 | 
				
			||||||
 | 
						// Takes an NFS server IP address and returns a PersistentVolume object for instantiation.
 | 
				
			||||||
 | 
						// Specs are expected to match this test's PersistentVolumeClaim
 | 
				
			||||||
	return &api.PersistentVolume{
 | 
						return &api.PersistentVolume{
 | 
				
			||||||
		ObjectMeta: api.ObjectMeta{
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
			GenerateName: "nfs-",
 | 
								GenerateName: "nfs-",
 | 
				
			||||||
@@ -130,7 +183,7 @@ func makePersistentVolume(serverIP string) *api.PersistentVolume {
 | 
				
			|||||||
			PersistentVolumeSource: api.PersistentVolumeSource{
 | 
								PersistentVolumeSource: api.PersistentVolumeSource{
 | 
				
			||||||
				NFS: &api.NFSVolumeSource{
 | 
									NFS: &api.NFSVolumeSource{
 | 
				
			||||||
					Server:   serverIP,
 | 
										Server:   serverIP,
 | 
				
			||||||
					Path:     "/",
 | 
										Path:     "/exports",
 | 
				
			||||||
					ReadOnly: false,
 | 
										ReadOnly: false,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -144,6 +197,8 @@ func makePersistentVolume(serverIP string) *api.PersistentVolume {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makePersistentVolumeClaim(ns string) *api.PersistentVolumeClaim {
 | 
					func makePersistentVolumeClaim(ns string) *api.PersistentVolumeClaim {
 | 
				
			||||||
 | 
						// Takes a namespace and returns a PersistentVolumeClaim object for instantiation.
 | 
				
			||||||
 | 
						// Specs are expected to match this test's PersistentVolume
 | 
				
			||||||
	return &api.PersistentVolumeClaim{
 | 
						return &api.PersistentVolumeClaim{
 | 
				
			||||||
		ObjectMeta: api.ObjectMeta{
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
			GenerateName: "pvc-",
 | 
								GenerateName: "pvc-",
 | 
				
			||||||
@@ -164,45 +219,48 @@ func makePersistentVolumeClaim(ns string) *api.PersistentVolumeClaim {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func makeCheckPod(ns string, nfsserver string) *api.Pod {
 | 
					func makeWritePod(ns string, pvcName string) *api.Pod {
 | 
				
			||||||
	// Prepare pod that mounts the NFS volume again and
 | 
						// Prepare pod that mounts the NFS volume again and
 | 
				
			||||||
	// checks that /mnt/index.html was scrubbed there
 | 
						// checks that /mnt/index.html was scrubbed there
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var isPrivileged bool = true
 | 
				
			||||||
	return &api.Pod{
 | 
						return &api.Pod{
 | 
				
			||||||
		TypeMeta: unversioned.TypeMeta{
 | 
							TypeMeta: unversioned.TypeMeta{
 | 
				
			||||||
			Kind:       "Pod",
 | 
								Kind:       "Pod",
 | 
				
			||||||
			APIVersion: testapi.Default.GroupVersion().String(),
 | 
								APIVersion: testapi.Default.GroupVersion().String(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		ObjectMeta: api.ObjectMeta{
 | 
							ObjectMeta: api.ObjectMeta{
 | 
				
			||||||
			GenerateName: "checker-",
 | 
								GenerateName: "write-pod-",
 | 
				
			||||||
			Namespace:    ns,
 | 
								Namespace:    ns,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Spec: api.PodSpec{
 | 
							Spec: api.PodSpec{
 | 
				
			||||||
			Containers: []api.Container{
 | 
								Containers: []api.Container{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Name:    "scrub-checker",
 | 
										Name:    "write-pod",
 | 
				
			||||||
					Image:   "gcr.io/google_containers/busybox:1.24",
 | 
										Image:   "gcr.io/google_containers/busybox:1.24",
 | 
				
			||||||
					Command: []string{"/bin/sh"},
 | 
										Command: []string{"/bin/sh"},
 | 
				
			||||||
					Args:    []string{"-c", "test ! -e /mnt/index.html || exit 1"},
 | 
										Args:    []string{"-c", "touch /mnt/SUCCESS && exit 0 || exit 1"},
 | 
				
			||||||
					VolumeMounts: []api.VolumeMount{
 | 
										VolumeMounts: []api.VolumeMount{
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Name:      "nfs-volume",
 | 
												Name:      "nfs-pvc",
 | 
				
			||||||
							MountPath: "/mnt",
 | 
												MountPath: "/mnt",
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
 | 
										SecurityContext: &api.SecurityContext{
 | 
				
			||||||
 | 
											Privileged: &isPrivileged,
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			Volumes: []api.Volume{
 | 
								Volumes: []api.Volume{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					Name: "nfs-volume",
 | 
										Name: "nfs-pvc",
 | 
				
			||||||
					VolumeSource: api.VolumeSource{
 | 
										VolumeSource: api.VolumeSource{
 | 
				
			||||||
						NFS: &api.NFSVolumeSource{
 | 
											PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{
 | 
				
			||||||
							Server: nfsserver,
 | 
												ClaimName: pvcName,
 | 
				
			||||||
							Path:   "/",
 | 
					 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user