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

     1  /*
     2  Copyright 2017 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 vsphere
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  	"time"
    24  
    25  	"github.com/onsi/ginkgo/v2"
    26  	v1 "k8s.io/api/core/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	clientset "k8s.io/client-go/kubernetes"
    29  	admissionapi "k8s.io/pod-security-admission/api"
    30  
    31  	"k8s.io/kubernetes/test/e2e/feature"
    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  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    36  	"k8s.io/kubernetes/test/e2e/storage/utils"
    37  )
    38  
    39  const (
    40  	invalidDatastore = "invalidDatastore"
    41  	datastoreSCName  = "datastoresc"
    42  )
    43  
    44  /*
    45  	Test to verify datastore specified in storage-class is being honored while volume creation.
    46  
    47  	Steps
    48  	1. Create StorageClass with invalid datastore.
    49  	2. Create PVC which uses the StorageClass created in step 1.
    50  	3. Expect the PVC to fail.
    51  	4. Verify the error returned on PVC failure is the correct.
    52  */
    53  
    54  var _ = utils.SIGDescribe("Volume Provisioning on Datastore", feature.Vsphere, func() {
    55  	f := framework.NewDefaultFramework("volume-datastore")
    56  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    57  	var (
    58  		client                     clientset.Interface
    59  		namespace                  string
    60  		scParameters               map[string]string
    61  		vSphereCSIMigrationEnabled bool
    62  	)
    63  	ginkgo.BeforeEach(func(ctx context.Context) {
    64  		e2eskipper.SkipUnlessProviderIs("vsphere")
    65  		Bootstrap(f)
    66  		client = f.ClientSet
    67  		namespace = f.Namespace.Name
    68  		scParameters = make(map[string]string)
    69  		_, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet)
    70  		framework.ExpectNoError(err)
    71  		vSphereCSIMigrationEnabled = GetAndExpectBoolEnvVar(VSphereCSIMigrationEnabled)
    72  	})
    73  
    74  	ginkgo.It("verify dynamically provisioned pv using storageclass fails on an invalid datastore", func(ctx context.Context) {
    75  		ginkgo.By("Invoking Test for invalid datastore")
    76  		scParameters[Datastore] = invalidDatastore
    77  		scParameters[DiskFormat] = ThinDisk
    78  		err := invokeInvalidDatastoreTestNeg(ctx, client, namespace, scParameters)
    79  		framework.ExpectError(err)
    80  		var errorMsg string
    81  		if !vSphereCSIMigrationEnabled {
    82  			errorMsg = `Failed to provision volume with StorageClass \"` + datastoreSCName + `\": Datastore '` + invalidDatastore + `' not found`
    83  		} else {
    84  			errorMsg = `failed to find datastoreURL for datastore name: \"` + invalidDatastore + `\"`
    85  		}
    86  		if !strings.Contains(err.Error(), errorMsg) {
    87  			framework.ExpectNoError(err, errorMsg)
    88  		}
    89  	})
    90  })
    91  
    92  func invokeInvalidDatastoreTestNeg(ctx context.Context, client clientset.Interface, namespace string, scParameters map[string]string) error {
    93  	ginkgo.By("Creating Storage Class With Invalid Datastore")
    94  	storageclass, err := client.StorageV1().StorageClasses().Create(ctx, getVSphereStorageClassSpec(datastoreSCName, scParameters, nil, ""), metav1.CreateOptions{})
    95  	framework.ExpectNoError(err, fmt.Sprintf("Failed to create storage class with err: %v", err))
    96  	ginkgo.DeferCleanup(framework.IgnoreNotFound(client.StorageV1().StorageClasses().Delete), storageclass.Name, metav1.DeleteOptions{})
    97  
    98  	ginkgo.By("Creating PVC using the Storage Class")
    99  	pvclaim, err := e2epv.CreatePVC(ctx, client, namespace, getVSphereClaimSpecWithStorageClass(namespace, "2Gi", storageclass))
   100  	framework.ExpectNoError(err)
   101  	ginkgo.DeferCleanup(e2epv.DeletePersistentVolumeClaim, client, pvclaim.Name, namespace)
   102  
   103  	ginkgo.By("Expect claim to fail provisioning volume")
   104  	err = e2epv.WaitForPersistentVolumeClaimPhase(ctx, v1.ClaimBound, client, pvclaim.Namespace, pvclaim.Name, framework.Poll, 2*time.Minute)
   105  	framework.ExpectError(err)
   106  
   107  	eventList, err := client.CoreV1().Events(pvclaim.Namespace).List(ctx, metav1.ListOptions{})
   108  	framework.ExpectNoError(err)
   109  
   110  	var eventErrorMessages string
   111  	for _, event := range eventList.Items {
   112  		if event.Type != v1.EventTypeNormal {
   113  			eventErrorMessages = eventErrorMessages + event.Message + ";"
   114  		}
   115  	}
   116  	return fmt.Errorf("event messages: %+q", eventErrorMessages)
   117  }