k8s.io/kubernetes@v1.29.3/test/e2e/storage/pv_protection.go (about)

     1  /*
     2  Copyright 2018 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 storage
    18  
    19  import (
    20  	"context"
    21  	"time"
    22  
    23  	"github.com/onsi/ginkgo/v2"
    24  	"github.com/onsi/gomega"
    25  
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/labels"
    29  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	volumeutil "k8s.io/kubernetes/pkg/volume/util"
    32  	"k8s.io/kubernetes/test/e2e/framework"
    33  	e2enode "k8s.io/kubernetes/test/e2e/framework/node"
    34  	e2epv "k8s.io/kubernetes/test/e2e/framework/pv"
    35  	"k8s.io/kubernetes/test/e2e/storage/utils"
    36  	admissionapi "k8s.io/pod-security-admission/api"
    37  )
    38  
    39  var _ = utils.SIGDescribe("PV Protection", func() {
    40  	var (
    41  		client    clientset.Interface
    42  		nameSpace string
    43  		err       error
    44  		pvc       *v1.PersistentVolumeClaim
    45  		pv        *v1.PersistentVolume
    46  		pvConfig  e2epv.PersistentVolumeConfig
    47  		pvcConfig e2epv.PersistentVolumeClaimConfig
    48  		volLabel  labels.Set
    49  		selector  *metav1.LabelSelector
    50  	)
    51  
    52  	f := framework.NewDefaultFramework("pv-protection")
    53  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    54  	ginkgo.BeforeEach(func(ctx context.Context) {
    55  		client = f.ClientSet
    56  		nameSpace = f.Namespace.Name
    57  		framework.ExpectNoError(e2enode.WaitForAllNodesSchedulable(ctx, client, f.Timeouts.NodeSchedulable))
    58  
    59  		// Enforce binding only within test space via selector labels
    60  		volLabel = labels.Set{e2epv.VolumeSelectorKey: nameSpace}
    61  		selector = metav1.SetAsLabelSelector(volLabel)
    62  
    63  		pvConfig = e2epv.PersistentVolumeConfig{
    64  			NamePrefix: "hostpath-",
    65  			Labels:     volLabel,
    66  			PVSource: v1.PersistentVolumeSource{
    67  				HostPath: &v1.HostPathVolumeSource{
    68  					Path: "/tmp/data",
    69  				},
    70  			},
    71  		}
    72  
    73  		emptyStorageClass := ""
    74  		pvcConfig = e2epv.PersistentVolumeClaimConfig{
    75  			Selector:         selector,
    76  			StorageClassName: &emptyStorageClass,
    77  		}
    78  
    79  		ginkgo.By("Creating a PV")
    80  		// make the pv definitions
    81  		pv = e2epv.MakePersistentVolume(pvConfig)
    82  		// create the PV
    83  		pv, err = client.CoreV1().PersistentVolumes().Create(ctx, pv, metav1.CreateOptions{})
    84  		framework.ExpectNoError(err, "Error creating PV")
    85  
    86  		ginkgo.By("Waiting for PV to enter phase Available")
    87  		framework.ExpectNoError(e2epv.WaitForPersistentVolumePhase(ctx, v1.VolumeAvailable, client, pv.Name, 1*time.Second, 30*time.Second))
    88  
    89  		ginkgo.By("Checking that PV Protection finalizer is set")
    90  		pv, err = client.CoreV1().PersistentVolumes().Get(ctx, pv.Name, metav1.GetOptions{})
    91  		framework.ExpectNoError(err, "While getting PV status")
    92  		gomega.Expect(pv.ObjectMeta.Finalizers).Should(gomega.ContainElement(volumeutil.PVProtectionFinalizer), "PV Protection finalizer(%v) is not set in %v", volumeutil.PVProtectionFinalizer, pv.ObjectMeta.Finalizers)
    93  	})
    94  
    95  	ginkgo.AfterEach(func(ctx context.Context) {
    96  		framework.Logf("AfterEach: Cleaning up test resources.")
    97  		if errs := e2epv.PVPVCCleanup(ctx, client, nameSpace, pv, pvc); len(errs) > 0 {
    98  			framework.Failf("AfterEach: Failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs))
    99  		}
   100  	})
   101  
   102  	ginkgo.It("Verify \"immediate\" deletion of a PV that is not bound to a PVC", func(ctx context.Context) {
   103  		ginkgo.By("Deleting the PV")
   104  		err = client.CoreV1().PersistentVolumes().Delete(ctx, pv.Name, *metav1.NewDeleteOptions(0))
   105  		framework.ExpectNoError(err, "Error deleting PV")
   106  		err = e2epv.WaitForPersistentVolumeDeleted(ctx, client, pv.Name, framework.Poll, f.Timeouts.PVDelete)
   107  		framework.ExpectNoError(err, "waiting for PV to be deleted")
   108  	})
   109  
   110  	ginkgo.It("Verify that PV bound to a PVC is not removed immediately", func(ctx context.Context) {
   111  		ginkgo.By("Creating a PVC")
   112  		pvc = e2epv.MakePersistentVolumeClaim(pvcConfig, nameSpace)
   113  		pvc, err = client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Create(ctx, pvc, metav1.CreateOptions{})
   114  		framework.ExpectNoError(err, "Error creating PVC")
   115  
   116  		ginkgo.By("Waiting for PVC to become Bound")
   117  		err = e2epv.WaitForPersistentVolumeClaimPhase(ctx, v1.ClaimBound, client, nameSpace, pvc.Name, framework.Poll, f.Timeouts.ClaimBound)
   118  		framework.ExpectNoError(err, "Failed waiting for PVC to be bound %v", err)
   119  
   120  		ginkgo.By("Deleting the PV, however, the PV must not be removed from the system as it's bound to a PVC")
   121  		err = client.CoreV1().PersistentVolumes().Delete(ctx, pv.Name, *metav1.NewDeleteOptions(0))
   122  		framework.ExpectNoError(err, "Error deleting PV")
   123  
   124  		ginkgo.By("Checking that the PV status is Terminating")
   125  		pv, err = client.CoreV1().PersistentVolumes().Get(ctx, pv.Name, metav1.GetOptions{})
   126  		framework.ExpectNoError(err, "While checking PV status")
   127  		gomega.Expect(pv.ObjectMeta.DeletionTimestamp).ToNot(gomega.BeNil())
   128  
   129  		ginkgo.By("Deleting the PVC that is bound to the PV")
   130  		err = client.CoreV1().PersistentVolumeClaims(pvc.Namespace).Delete(ctx, pvc.Name, *metav1.NewDeleteOptions(0))
   131  		framework.ExpectNoError(err, "Error deleting PVC")
   132  
   133  		ginkgo.By("Checking that the PV is automatically removed from the system because it's no longer bound to a PVC")
   134  		err = e2epv.WaitForPersistentVolumeDeleted(ctx, client, pv.Name, framework.Poll, f.Timeouts.PVDelete)
   135  		framework.ExpectNoError(err, "waiting for PV to be deleted")
   136  	})
   137  })