123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664 |
- /*
- Copyright 2015 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 e2e
- import (
- "encoding/json"
- "fmt"
- "time"
- . "github.com/onsi/ginkgo"
- "k8s.io/kubernetes/pkg/api"
- apierrs "k8s.io/kubernetes/pkg/api/errors"
- "k8s.io/kubernetes/pkg/api/resource"
- "k8s.io/kubernetes/pkg/api/testapi"
- "k8s.io/kubernetes/pkg/api/unversioned"
- client "k8s.io/kubernetes/pkg/client/unversioned"
- "k8s.io/kubernetes/pkg/volume/util/volumehelper"
- "k8s.io/kubernetes/test/e2e/framework"
- )
- // Delete the nfs-server pod.
- func nfsServerPodCleanup(c *client.Client, config VolumeTestConfig) {
- defer GinkgoRecover()
- podClient := c.Pods(config.namespace)
- if config.serverImage != "" {
- podName := config.prefix + "-server"
- err := podClient.Delete(podName, nil)
- if err != nil {
- framework.Logf("Delete of %v pod failed: %v", podName, err)
- }
- }
- }
- // Delete the PV. Fail test if delete fails. If success the returned PV should
- // be nil, which prevents the AfterEach from attempting to delete it.
- func deletePersistentVolume(c *client.Client, pv *api.PersistentVolume) (*api.PersistentVolume, error) {
- if pv == nil {
- return nil, fmt.Errorf("PV to be deleted is nil")
- }
- framework.Logf("Deleting PersistentVolume %v", pv.Name)
- err := c.PersistentVolumes().Delete(pv.Name)
- if err != nil {
- return pv, fmt.Errorf("Delete() PersistentVolume %v failed: %v", pv.Name, err)
- }
- // Wait for PersistentVolume to delete
- deleteDuration := 90 * time.Second
- err = framework.WaitForPersistentVolumeDeleted(c, pv.Name, 3*time.Second, deleteDuration)
- if err != nil {
- return pv, fmt.Errorf("Unable to delete PersistentVolume %s after waiting for %v: %v", pv.Name, deleteDuration, err)
- }
- return nil, nil // success
- }
- // Delete the PVC and wait for the PV to become Available again. Validate that
- // the PV has recycled (assumption here about reclaimPolicy). Return the pv and
- // pvc to reflect that these resources have been retrieved again (Get). If the
- // delete is successful the returned pvc should be nil and the pv non-nil.
- // Note: the pv and pvc are returned back to the It() caller so that the
- // AfterEach func can delete these objects if they are not nil.
- func deletePVCandValidatePV(c *client.Client, ns string, pvc *api.PersistentVolumeClaim, pv *api.PersistentVolume) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) {
- framework.Logf("Deleting PersistentVolumeClaim %v to trigger PV Recycling", pvc.Name)
- err := c.PersistentVolumeClaims(ns).Delete(pvc.Name)
- if err != nil {
- return pv, pvc, fmt.Errorf("Delete of PVC %v failed: %v", pvc.Name, err)
- }
- // Check that the PVC is really deleted.
- pvc, err = c.PersistentVolumeClaims(ns).Get(pvc.Name)
- if err == nil {
- return pv, pvc, fmt.Errorf("PVC %v deleted yet still exists", pvc.Name)
- }
- if !apierrs.IsNotFound(err) {
- return pv, pvc, fmt.Errorf("Get on deleted PVC %v failed with error other than \"not found\": %v", pvc.Name, err)
- }
- // Wait for the PV's phase to return to Available
- framework.Logf("Waiting for recycling process to complete.")
- err = framework.WaitForPersistentVolumePhase(api.VolumeAvailable, c, pv.Name, 3*time.Second, 300*time.Second)
- if err != nil {
- return pv, pvc, fmt.Errorf("Recycling failed: %v", err)
- }
- // Examine the pv.ClaimRef and UID. Expect nil values.
- pv, err = c.PersistentVolumes().Get(pv.Name)
- if err != nil {
- return pv, pvc, fmt.Errorf("Cannot re-get PersistentVolume %v:", pv.Name)
- }
- if pv.Spec.ClaimRef != nil && len(pv.Spec.ClaimRef.UID) > 0 {
- crJSON, _ := json.Marshal(pv.Spec.ClaimRef)
- return pv, pvc, fmt.Errorf("Expected PV %v's ClaimRef to be nil, or the claimRef's UID to be blank. Instead claimRef is: %v", pv.Name, string(crJSON))
- }
- return pv, pvc, nil
- }
- // create the PV resource. Fails test on error.
- func createPV(c *client.Client, pv *api.PersistentVolume) (*api.PersistentVolume, error) {
- pv, err := c.PersistentVolumes().Create(pv)
- if err != nil {
- return pv, fmt.Errorf("Create PersistentVolume %v failed: %v", pv.Name, err)
- }
- return pv, nil
- }
- // create the PVC resource. Fails test on error.
- func createPVC(c *client.Client, ns string, pvc *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) {
- pvc, err := c.PersistentVolumeClaims(ns).Create(pvc)
- if err != nil {
- return pvc, fmt.Errorf("Create PersistentVolumeClaim %v failed: %v", pvc.Name, err)
- }
- return pvc, nil
- }
- // Create a PVC followed by the PV based on the passed in nfs-server ip and
- // namespace. If the "preBind" bool is true then pre-bind the PV to the PVC
- // via the PV's ClaimRef. Return the pv and pvc to reflect the created objects.
- // Note: the pv and pvc are returned back to the It() caller so that the
- // AfterEach func can delete these objects if they are not nil.
- // Note: in the pre-bind case the real PVC name, which is generated, is not
- // known until after the PVC is instantiated. This is why the pvc is created
- // before the pv.
- func createPVCPV(c *client.Client, serverIP, ns string, preBind bool) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) {
- var bindTo *api.PersistentVolumeClaim
- var preBindMsg string
- // make the pvc definition first
- pvc := makePersistentVolumeClaim(ns)
- if preBind {
- preBindMsg = " pre-bound"
- bindTo = pvc
- }
- // make the pv spec
- pv := makePersistentVolume(serverIP, bindTo)
- By(fmt.Sprintf("Creating a PVC followed by a%s PV", preBindMsg))
- // instantiate the pvc
- pvc, err := createPVC(c, ns, pvc)
- if err != nil {
- return nil, nil, err
- }
- // instantiate the pvc, handle pre-binding by ClaimRef if needed
- if preBind {
- pv.Spec.ClaimRef.Name = pvc.Name
- }
- pv, err = createPV(c, pv)
- if err != nil {
- return nil, pvc, err
- }
- return pv, pvc, nil
- }
- // Create a PV followed by the PVC based on the passed in nfs-server ip and
- // namespace. If the "preBind" bool is true then pre-bind the PVC to the PV
- // via the PVC's VolumeName. Return the pv and pvc to reflect the created
- // objects.
- // Note: the pv and pvc are returned back to the It() caller so that the
- // AfterEach func can delete these objects if they are not nil.
- // Note: in the pre-bind case the real PV name, which is generated, is not
- // known until after the PV is instantiated. This is why the pv is created
- // before the pvc.
- func createPVPVC(c *client.Client, serverIP, ns string, preBind bool) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) {
- preBindMsg := ""
- if preBind {
- preBindMsg = " pre-bound"
- }
- By(fmt.Sprintf("Creating a PV followed by a%s PVC", preBindMsg))
- // make the pv and pvc definitions
- pv := makePersistentVolume(serverIP, nil)
- pvc := makePersistentVolumeClaim(ns)
- // instantiate the pv
- pv, err := createPV(c, pv)
- if err != nil {
- return nil, nil, err
- }
- // instantiate the pvc, handle pre-binding by VolumeName if needed
- if preBind {
- pvc.Spec.VolumeName = pv.Name
- }
- pvc, err = createPVC(c, ns, pvc)
- if err != nil {
- return pv, nil, err
- }
- return pv, pvc, nil
- }
- // Wait for the pv and pvc to bind to each other. Fail test on errors.
- func waitOnPVandPVC(c *client.Client, ns string, pv *api.PersistentVolume, pvc *api.PersistentVolumeClaim) error {
- // Wait for newly created PVC to bind to the PV
- framework.Logf("Waiting for PV %v to bind to PVC %v", pv.Name, pvc.Name)
- err := framework.WaitForPersistentVolumeClaimPhase(api.ClaimBound, c, ns, pvc.Name, 3*time.Second, 300*time.Second)
- if err != nil {
- return fmt.Errorf("PersistentVolumeClaim failed to enter a bound state: %+v", err)
- }
- // Wait for PersistentVolume.Status.Phase to be Bound, which it should be
- // since the PVC is already bound.
- err = framework.WaitForPersistentVolumePhase(api.VolumeBound, c, pv.Name, 3*time.Second, 300*time.Second)
- if err != nil {
- return fmt.Errorf("PersistentVolume failed to enter a bound state even though PVC is Bound: %+v", err)
- }
- return nil
- }
- // Waits for the pv and pvc to be bound to each other, then checks that the pv's
- // claimRef matches the pvc. Fails test on errors. Return the pv and pvc to
- // reflect that these resources have been retrieved again (Get).
- // Note: the pv and pvc are returned back to the It() caller so that the
- // AfterEach func can delete these objects if they are not nil.
- func waitAndValidatePVandPVC(c *client.Client, ns string, pv *api.PersistentVolume, pvc *api.PersistentVolumeClaim) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) {
- var err error
- // Wait for pv and pvc to bind to each other
- if err = waitOnPVandPVC(c, ns, pv, pvc); err != nil {
- return pv, pvc, err
- }
- // Check that the PersistentVolume.ClaimRef is valid and matches the PVC
- framework.Logf("Checking PersistentVolume ClaimRef is non-nil")
- pv, err = c.PersistentVolumes().Get(pv.Name)
- if err != nil {
- return pv, pvc, fmt.Errorf("Cannot re-get PersistentVolume %v:", pv.Name)
- }
- pvc, err = c.PersistentVolumeClaims(ns).Get(pvc.Name)
- if err != nil {
- return pv, pvc, fmt.Errorf("Cannot re-get PersistentVolumeClaim %v:", pvc.Name)
- }
- if pv.Spec.ClaimRef == nil || pv.Spec.ClaimRef.UID != pvc.UID {
- pvJSON, _ := json.Marshal(pv.Spec.ClaimRef)
- return pv, pvc, fmt.Errorf("Expected Bound PersistentVolume %v to have valid ClaimRef: %+v", pv.Name, string(pvJSON))
- }
- return pv, pvc, nil
- }
- // Test the pod's exitcode to be zero.
- func testPodSuccessOrFail(f *framework.Framework, c *client.Client, ns string, pod *api.Pod) error {
- By("Pod should terminate with exitcode 0 (success)")
- err := framework.WaitForPodSuccessInNamespace(c, pod.Name, pod.Spec.Containers[0].Name, ns)
- if err != nil {
- return fmt.Errorf("Pod %v returned non-zero exitcode: %+v", pod.Name, err)
- }
- framework.Logf("pod %v exited successfully", pod.Name)
- return nil
- }
- // Delete the passed in pod.
- func deletePod(f *framework.Framework, c *client.Client, ns string, pod *api.Pod) error {
- framework.Logf("Deleting pod %v", pod.Name)
- err := c.Pods(ns).Delete(pod.Name, nil)
- if err != nil {
- return fmt.Errorf("Pod %v encountered a delete error: %v", pod.Name, err)
- }
- // Wait for pod to terminate
- err = f.WaitForPodTerminated(pod.Name, "")
- if err != nil && !apierrs.IsNotFound(err) {
- return fmt.Errorf("Pod %v will not teminate: %v", pod.Name, err)
- }
- // Re-get the pod to double check that it has been deleted; expect err
- // Note: Get() writes a log error if the pod is not found
- _, err = c.Pods(ns).Get(pod.Name)
- if err == nil {
- return fmt.Errorf("Pod %v has been deleted but able to re-Get the deleted pod", pod.Name)
- }
- if !apierrs.IsNotFound(err) {
- return fmt.Errorf("Pod %v has been deleted but still exists: %v", pod.Name, err)
- }
- framework.Logf("Ignore \"not found\" error above. Pod %v successfully deleted", pod.Name)
- return nil
- }
- // Create the test pod, wait for (hopefully) success, and then delete the pod.
- func createWaitAndDeletePod(f *framework.Framework, c *client.Client, ns string, claimName string) error {
- var errmsg string
- framework.Logf("Creating nfs test pod")
- // Make pod spec
- pod := makeWritePod(ns, claimName)
- // Instantiate pod (Create)
- runPod, err := c.Pods(ns).Create(pod)
- if err != nil || runPod == nil {
- name := ""
- if runPod != nil {
- name = runPod.Name
- }
- return fmt.Errorf("Create test pod %v failed: %v", name, err)
- }
- // Wait for the test pod to complete its lifecycle
- podErr := testPodSuccessOrFail(f, c, ns, runPod)
- // Regardless of podErr above, delete the pod if it exists
- if runPod != nil {
- err = deletePod(f, c, ns, runPod)
- }
- // Check results of pod success and pod delete
- if podErr != nil {
- errmsg = fmt.Sprintf("Pod %v exited with non-zero exitcode: %v", runPod.Name, podErr)
- }
- if err != nil { // Delete error
- if len(errmsg) > 0 {
- errmsg += "; and "
- }
- errmsg += fmt.Sprintf("Delete error on pod %v: %v", runPod.Name, err)
- }
- if len(errmsg) > 0 {
- return fmt.Errorf(errmsg)
- }
- return nil
- }
- // validate PV/PVC, create and verify writer pod, delete PVC and PV. Ensure
- // all of these steps were successful. Return the pv and pvc to reflect that
- // these resources have been retrieved again (Get).
- // Note: the pv and pvc are returned back to the It() caller so that the
- // AfterEach func can delete these objects if they are not nil.
- func completeTest(f *framework.Framework, c *client.Client, ns string, pv *api.PersistentVolume, pvc *api.PersistentVolumeClaim) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) {
- // 1. verify that the PV and PVC have binded correctly
- By("Validating the PV-PVC binding")
- pv, pvc, err := waitAndValidatePVandPVC(c, ns, pv, pvc)
- if err != nil {
- return pv, pvc, err
- }
- // 2. create the nfs writer pod, test if the write was successful,
- // then delete the pod and verify that it was deleted
- By("Checking pod has write access to PersistentVolume")
- if err = createWaitAndDeletePod(f, c, ns, pvc.Name); err != nil {
- return pv, pvc, err
- }
- // 3. delete the PVC before deleting PV, wait for PV to be "Available"
- By("Deleting the PVC to invoke the recycler")
- pv, pvc, err = deletePVCandValidatePV(c, ns, pvc, pv)
- if err != nil {
- return pv, pvc, err
- }
- // 4. cleanup by deleting the pv
- By("Deleting the PV")
- if pv, err = deletePersistentVolume(c, pv); err != nil {
- return pv, pvc, err
- }
- return pv, pvc, nil
- }
- var _ = framework.KubeDescribe("PersistentVolumes", func() {
- // global vars for the It() tests below
- f := framework.NewDefaultFramework("pv")
- var c *client.Client
- var ns string
- var NFSconfig VolumeTestConfig
- var serverIP string
- var nfsServerPod *api.Pod
- var pv *api.PersistentVolume
- var pvc *api.PersistentVolumeClaim
- var err error
- // config for the nfs-server pod in the default namespace
- NFSconfig = VolumeTestConfig{
- namespace: api.NamespaceDefault,
- prefix: "nfs",
- serverImage: "gcr.io/google_containers/volume-nfs:0.6",
- serverPorts: []int{2049},
- serverArgs: []string{"-G", "777", "/exports"},
- }
- BeforeEach(func() {
- c = f.Client
- ns = f.Namespace.Name
- // If it doesn't exist, create the nfs server pod in "default" ns
- // The "default" ns is used so that individual tests can delete
- // their ns without impacting the nfs-server pod.
- if nfsServerPod == nil {
- nfsServerPod = startVolumeServer(c, NFSconfig)
- serverIP = nfsServerPod.Status.PodIP
- framework.Logf("NFS server IP address: %v", serverIP)
- }
- })
- AfterEach(func() {
- if c != nil && len(ns) > 0 { // still have client and namespace
- if pvc != nil && len(pvc.Name) > 0 {
- // Delete the PersistentVolumeClaim
- framework.Logf("AfterEach: PVC %v is non-nil, deleting claim", pvc.Name)
- err := c.PersistentVolumeClaims(ns).Delete(pvc.Name)
- if err != nil && !apierrs.IsNotFound(err) {
- framework.Logf("AfterEach: delete of PersistentVolumeClaim %v error: %v", pvc.Name, err)
- }
- pvc = nil
- }
- if pv != nil && len(pv.Name) > 0 {
- framework.Logf("AfterEach: PV %v is non-nil, deleting pv", pv.Name)
- err := c.PersistentVolumes().Delete(pv.Name)
- if err != nil && !apierrs.IsNotFound(err) {
- framework.Logf("AfterEach: delete of PersistentVolume %v error: %v", pv.Name, err)
- }
- pv = nil
- }
- }
- })
- // Execute after *all* the tests have run
- AddCleanupAction(func() {
- if nfsServerPod != nil && c != nil {
- framework.Logf("AfterSuite: nfs-server pod %v is non-nil, deleting pod", nfsServerPod.Name)
- nfsServerPodCleanup(c, NFSconfig)
- nfsServerPod = nil
- }
- })
- // Individual tests follow:
- //
- // Create an nfs PV, then a claim that matches the PV, and a pod that
- // contains the claim. Verify that the PV and PVC bind correctly, and
- // that the pod can write to the nfs volume.
- It("should create a non-pre-bound PV and PVC: test write access [Flaky]", func() {
- pv, pvc, err = createPVPVC(c, serverIP, ns, false)
- if err != nil {
- framework.Failf("%v", err)
- }
- // validate PV-PVC, create and verify writer pod, delete PVC
- // and PV
- pv, pvc, err = completeTest(f, c, ns, pv, pvc)
- if err != nil {
- framework.Failf("%v", err)
- }
- })
- // Create a claim first, then a nfs PV that matches the claim, and a
- // pod that contains the claim. Verify that the PV and PVC bind
- // correctly, and that the pod can write to the nfs volume.
- It("create a PVC and non-pre-bound PV: test write access [Flaky]", func() {
- pv, pvc, err = createPVCPV(c, serverIP, ns, false)
- if err != nil {
- framework.Failf("%v", err)
- }
- // validate PV-PVC, create and verify writer pod, delete PVC
- // and PV
- pv, pvc, err = completeTest(f, c, ns, pv, pvc)
- if err != nil {
- framework.Failf("%v", err)
- }
- })
- // Create a claim first, then a pre-bound nfs PV that matches the claim,
- // and a pod that contains the claim. Verify that the PV and PVC bind
- // correctly, and that the pod can write to the nfs volume.
- It("create a PVC and a pre-bound PV: test write access [Flaky]", func() {
- pv, pvc, err = createPVCPV(c, serverIP, ns, true)
- if err != nil {
- framework.Failf("%v", err)
- }
- // validate PV-PVC, create and verify writer pod, delete PVC
- // and PV
- pv, pvc, err = completeTest(f, c, ns, pv, pvc)
- if err != nil {
- framework.Failf("%v", err)
- }
- })
- // Create a nfs PV first, then a pre-bound PVC that matches the PV,
- // and a pod that contains the claim. Verify that the PV and PVC bind
- // correctly, and that the pod can write to the nfs volume.
- It("create a PV and a pre-bound PVC: test write access [Flaky]", func() {
- pv, pvc, err = createPVPVC(c, serverIP, ns, true)
- if err != nil {
- framework.Failf("%v", err)
- }
- // validate PV-PVC, create and verify writer pod, delete PVC
- // and PV
- pv, pvc, err = completeTest(f, c, ns, pv, pvc)
- if err != nil {
- framework.Failf("%v", err)
- }
- })
- })
- // Returns a PV definition based on the nfs server IP. If the PVC is not nil
- // then the PV is defined with a ClaimRef which includes the PVC's namespace.
- // If the PVC is nil then the PV is not defined with a ClaimRef.
- // Note: the passed-in claim does not have a name until it is created
- // (instantiated) and thus the PV's ClaimRef cannot be completely filled-in in
- // this func. Therefore, the ClaimRef's name is added later in
- // createPVCPV.
- func makePersistentVolume(serverIP string, pvc *api.PersistentVolumeClaim) *api.PersistentVolume {
- // Specs are expected to match this test's PersistentVolumeClaim
- var claimRef *api.ObjectReference
- if pvc != nil {
- claimRef = &api.ObjectReference{
- Name: pvc.Name,
- Namespace: pvc.Namespace,
- }
- }
- return &api.PersistentVolume{
- ObjectMeta: api.ObjectMeta{
- GenerateName: "nfs-",
- Annotations: map[string]string{
- volumehelper.VolumeGidAnnotationKey: "777",
- },
- },
- Spec: api.PersistentVolumeSpec{
- PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimRecycle,
- Capacity: api.ResourceList{
- api.ResourceName(api.ResourceStorage): resource.MustParse("2Gi"),
- },
- PersistentVolumeSource: api.PersistentVolumeSource{
- NFS: &api.NFSVolumeSource{
- Server: serverIP,
- Path: "/exports",
- ReadOnly: false,
- },
- },
- AccessModes: []api.PersistentVolumeAccessMode{
- api.ReadWriteOnce,
- api.ReadOnlyMany,
- api.ReadWriteMany,
- },
- ClaimRef: claimRef,
- },
- }
- }
- // Returns a PVC definition based on the namespace.
- // Note: if this PVC is intended to be pre-bound to a PV, whose name is not
- // known until the PV is instantiated, then the func createPVPVC will add
- // pvc.Spec.VolumeName to this claim.
- func makePersistentVolumeClaim(ns string) *api.PersistentVolumeClaim {
- // Specs are expected to match this test's PersistentVolume
- return &api.PersistentVolumeClaim{
- ObjectMeta: api.ObjectMeta{
- GenerateName: "pvc-",
- Namespace: ns,
- },
- Spec: api.PersistentVolumeClaimSpec{
- AccessModes: []api.PersistentVolumeAccessMode{
- api.ReadWriteOnce,
- api.ReadOnlyMany,
- api.ReadWriteMany,
- },
- Resources: api.ResourceRequirements{
- Requests: api.ResourceList{
- api.ResourceName(api.ResourceStorage): resource.MustParse("1Gi"),
- },
- },
- },
- }
- }
- // Returns a pod definition based on the namespace. The pod references the PVC's
- // name.
- func makeWritePod(ns string, pvcName string) *api.Pod {
- // Prepare pod that mounts the NFS volume again and
- // checks that /mnt/index.html was scrubbed there
- var isPrivileged bool = true
- return &api.Pod{
- TypeMeta: unversioned.TypeMeta{
- Kind: "Pod",
- APIVersion: testapi.Default.GroupVersion().String(),
- },
- ObjectMeta: api.ObjectMeta{
- GenerateName: "write-pod-",
- Namespace: ns,
- },
- Spec: api.PodSpec{
- Containers: []api.Container{
- {
- Name: "write-pod",
- Image: "gcr.io/google_containers/busybox:1.24",
- Command: []string{"/bin/sh"},
- Args: []string{"-c", "touch /mnt/SUCCESS && (id -G | grep -E '\\b777\\b')"},
- VolumeMounts: []api.VolumeMount{
- {
- Name: "nfs-pvc",
- MountPath: "/mnt",
- },
- },
- SecurityContext: &api.SecurityContext{
- Privileged: &isPrivileged,
- },
- },
- },
- Volumes: []api.Volume{
- {
- Name: "nfs-pvc",
- VolumeSource: api.VolumeSource{
- PersistentVolumeClaim: &api.PersistentVolumeClaimVolumeSource{
- ClaimName: pvcName,
- },
- },
- },
- },
- },
- }
- }
|