sigs.k8s.io/blob-csi-driver@v1.24.1/test/e2e/testsuites/specs.go (about)

     1  /*
     2  Copyright 2019 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 testsuites
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"strings"
    24  
    25  	"sigs.k8s.io/blob-csi-driver/test/e2e/driver"
    26  
    27  	"github.com/onsi/ginkgo/v2"
    28  	v1 "k8s.io/api/core/v1"
    29  	storagev1 "k8s.io/api/storage/v1"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  )
    32  
    33  type PodDetails struct {
    34  	Cmd     string
    35  	Volumes []VolumeDetails
    36  }
    37  
    38  type VolumeDetails struct {
    39  	VolumeType            string
    40  	FSType                string
    41  	Encrypted             bool
    42  	MountOptions          []string
    43  	ClaimSize             string
    44  	ReclaimPolicy         *v1.PersistentVolumeReclaimPolicy
    45  	VolumeBindingMode     *storagev1.VolumeBindingMode
    46  	AllowedTopologyValues []string
    47  	VolumeMode            VolumeMode
    48  	VolumeMount           VolumeMountDetails
    49  	VolumeDevice          VolumeDeviceDetails
    50  	// Optional, used with pre-provisioned volumes
    51  	VolumeID string
    52  	// Optional, used with PVCs created from snapshots
    53  	DataSource *DataSource
    54  	// Optional, used with specified StorageClass
    55  	StorageClass       *storagev1.StorageClass
    56  	NodeStageSecretRef string
    57  	Attrib             map[string]string
    58  }
    59  
    60  type VolumeMode int
    61  
    62  const (
    63  	FileSystem VolumeMode = iota
    64  	Block
    65  )
    66  
    67  const (
    68  	VolumePVCKind      = "PersistentVolumeClaim"
    69  	APIVersionv1alpha1 = "v1alpha1"
    70  )
    71  
    72  var (
    73  	isAzureStackCloud                            = strings.EqualFold(os.Getenv("AZURE_CLOUD_NAME"), "AZURESTACKCLOUD")
    74  	azurePublicCloudSupportedStorageAccountTypes = []string{"Standard_LRS", "Premium_LRS", "Standard_GRS", "Standard_RAGRS"}
    75  	azureStackCloudSupportedStorageAccountTypes  = []string{"Standard_LRS", "Premium_LRS"}
    76  )
    77  
    78  type VolumeMountDetails struct {
    79  	NameGenerate      string
    80  	MountPathGenerate string
    81  	ReadOnly          bool
    82  }
    83  
    84  type VolumeDeviceDetails struct {
    85  	NameGenerate string
    86  	DevicePath   string
    87  }
    88  
    89  type DataSource struct {
    90  	Kind string
    91  	Name string
    92  }
    93  
    94  func (pod *PodDetails) SetupWithCSIInlineVolumes(client clientset.Interface, namespace *v1.Namespace, secretName, shareName string, readOnly bool) (*TestPod, []func(context.Context)) {
    95  	tpod := NewTestPod(client, namespace, pod.Cmd)
    96  	cleanupFuncs := make([]func(ctx context.Context), 0)
    97  	for n, v := range pod.Volumes {
    98  		tpod.SetupInlineVolume(fmt.Sprintf("%s%d", v.VolumeMount.NameGenerate, n+1), fmt.Sprintf("%s%d", v.VolumeMount.MountPathGenerate, n+1), secretName, shareName, readOnly)
    99  	}
   100  	return tpod, cleanupFuncs
   101  }
   102  
   103  func (pod *PodDetails) SetupWithDynamicVolumes(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestPod, []func(context.Context)) {
   104  	tpod := NewTestPod(client, namespace, pod.Cmd)
   105  	cleanupFuncs := make([]func(ctx context.Context), 0)
   106  	for n, v := range pod.Volumes {
   107  		tpvc, funcs := v.SetupDynamicPersistentVolumeClaim(ctx, client, namespace, csiDriver, storageClassParameters)
   108  		cleanupFuncs = append(cleanupFuncs, funcs...)
   109  		if v.VolumeMode == Block {
   110  			tpod.SetupRawBlockVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeDevice.NameGenerate, n+1), v.VolumeDevice.DevicePath)
   111  		} else {
   112  			tpod.SetupVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeMount.NameGenerate, n+1), fmt.Sprintf("%s%d", v.VolumeMount.MountPathGenerate, n+1), v.VolumeMount.ReadOnly)
   113  		}
   114  	}
   115  	return tpod, cleanupFuncs
   116  }
   117  
   118  // SetupWithDynamicMultipleVolumes each pod will be mounted with multiple volumes with different storage account types
   119  func (pod *PodDetails) SetupWithDynamicMultipleVolumes(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver) (*TestPod, []func(context.Context)) {
   120  	tpod := NewTestPod(client, namespace, pod.Cmd)
   121  	cleanupFuncs := make([]func(ctx context.Context), 0)
   122  	supportedStorageAccountTypes := azurePublicCloudSupportedStorageAccountTypes
   123  	if isAzureStackCloud {
   124  		supportedStorageAccountTypes = azureStackCloudSupportedStorageAccountTypes
   125  	}
   126  	accountTypeCount := len(supportedStorageAccountTypes)
   127  	for n, v := range pod.Volumes {
   128  		storageClassParameters := map[string]string{"skuName": supportedStorageAccountTypes[n%accountTypeCount]}
   129  		tpvc, funcs := v.SetupDynamicPersistentVolumeClaim(ctx, client, namespace, csiDriver, storageClassParameters)
   130  		cleanupFuncs = append(cleanupFuncs, funcs...)
   131  		if v.VolumeMode == Block {
   132  			tpod.SetupRawBlockVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeDevice.NameGenerate, n+1), v.VolumeDevice.DevicePath)
   133  		} else {
   134  			tpod.SetupVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeMount.NameGenerate, n+1), fmt.Sprintf("%s%d", v.VolumeMount.MountPathGenerate, n+1), v.VolumeMount.ReadOnly)
   135  		}
   136  	}
   137  	return tpod, cleanupFuncs
   138  }
   139  
   140  func (pod *PodDetails) SetupWithPreProvisionedVolumes(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.PreProvisionedVolumeTestDriver) (*TestPod, []func(context.Context)) {
   141  	tpod := NewTestPod(client, namespace, pod.Cmd)
   142  	cleanupFuncs := make([]func(ctx context.Context), 0)
   143  	for n, v := range pod.Volumes {
   144  		tpvc, funcs := v.SetupPreProvisionedPersistentVolumeClaim(ctx, client, namespace, csiDriver)
   145  		cleanupFuncs = append(cleanupFuncs, funcs...)
   146  
   147  		if v.VolumeMode == Block {
   148  			tpod.SetupRawBlockVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeDevice.NameGenerate, n+1), v.VolumeDevice.DevicePath)
   149  		} else {
   150  			tpod.SetupVolume(tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", v.VolumeMount.NameGenerate, n+1), fmt.Sprintf("%s%d", v.VolumeMount.MountPathGenerate, n+1), v.VolumeMount.ReadOnly)
   151  		}
   152  	}
   153  	return tpod, cleanupFuncs
   154  }
   155  
   156  func (pod *PodDetails) SetupDeployment(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestDeployment, []func(context.Context), string) {
   157  	cleanupFuncs := make([]func(ctx context.Context), 0)
   158  	volume := pod.Volumes[0]
   159  	ginkgo.By("setting up the StorageClass")
   160  	storageClass := csiDriver.GetProvisionStorageClass(storageClassParameters, volume.MountOptions, volume.ReclaimPolicy, volume.VolumeBindingMode, volume.AllowedTopologyValues, namespace.Name)
   161  	tsc := NewTestStorageClass(client, namespace, storageClass)
   162  	createdStorageClass := tsc.Create(ctx)
   163  	cleanupFuncs = append(cleanupFuncs, tsc.Cleanup)
   164  	ginkgo.By("setting up the PVC")
   165  	tpvc := NewTestPersistentVolumeClaim(client, namespace, volume.ClaimSize, volume.VolumeMode, &createdStorageClass)
   166  	tpvc.Create(ctx)
   167  	tpvc.WaitForBound(ctx)
   168  	tpvc.ValidateProvisionedPersistentVolume(ctx)
   169  	cleanupFuncs = append(cleanupFuncs, tpvc.Cleanup)
   170  	ginkgo.By("setting up the Deployment")
   171  	tDeployment := NewTestDeployment(client, namespace, pod.Cmd, tpvc.persistentVolumeClaim, fmt.Sprintf("%s%d", volume.VolumeMount.NameGenerate, 1), fmt.Sprintf("%s%d", volume.VolumeMount.MountPathGenerate, 1), volume.VolumeMount.ReadOnly)
   172  
   173  	cleanupFuncs = append(cleanupFuncs, tDeployment.Cleanup)
   174  	var volumeID string
   175  	if tpvc.persistentVolume != nil && tpvc.persistentVolume.Spec.CSI != nil {
   176  		volumeID = tpvc.persistentVolume.Spec.CSI.VolumeHandle
   177  	}
   178  	return tDeployment, cleanupFuncs, volumeID
   179  }
   180  
   181  func (volume *VolumeDetails) SetupDynamicPersistentVolumeClaim(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestPersistentVolumeClaim, []func(context.Context)) {
   182  	cleanupFuncs := make([]func(ctx context.Context), 0)
   183  	ginkgo.By("setting up the StorageClass")
   184  	storageClass := csiDriver.GetProvisionStorageClass(storageClassParameters, volume.MountOptions, volume.ReclaimPolicy, volume.VolumeBindingMode, volume.AllowedTopologyValues, namespace.Name)
   185  	tsc := NewTestStorageClass(client, namespace, storageClass)
   186  	createdStorageClass := tsc.Create(ctx)
   187  	cleanupFuncs = append(cleanupFuncs, tsc.Cleanup)
   188  	ginkgo.By("setting up the PVC and PV")
   189  	var tpvc *TestPersistentVolumeClaim
   190  	if volume.DataSource != nil {
   191  		dataSource := &v1.TypedLocalObjectReference{
   192  			Name: volume.DataSource.Name,
   193  			Kind: volume.DataSource.Kind,
   194  		}
   195  		tpvc = NewTestPersistentVolumeClaimWithDataSource(client, namespace, volume.ClaimSize, volume.VolumeMode, &createdStorageClass, dataSource)
   196  	} else {
   197  		tpvc = NewTestPersistentVolumeClaim(client, namespace, volume.ClaimSize, volume.VolumeMode, &createdStorageClass)
   198  	}
   199  	tpvc.Create(ctx)
   200  	cleanupFuncs = append(cleanupFuncs, tpvc.Cleanup)
   201  	// PV will not be ready until PVC is used in a pod when volumeBindingMode: WaitForFirstConsumer
   202  	if volume.VolumeBindingMode == nil || *volume.VolumeBindingMode == storagev1.VolumeBindingImmediate {
   203  		tpvc.WaitForBound(ctx)
   204  		tpvc.ValidateProvisionedPersistentVolume(ctx)
   205  	}
   206  
   207  	return tpvc, cleanupFuncs
   208  }
   209  
   210  func (volume *VolumeDetails) SetupPreProvisionedPersistentVolumeClaim(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.PreProvisionedVolumeTestDriver) (*TestPersistentVolumeClaim, []func(ctx context.Context)) {
   211  	cleanupFuncs := make([]func(ctx context.Context), 0)
   212  	ginkgo.By("setting up the PV")
   213  	attrib := volume.Attrib
   214  	nodeStageSecretRef := volume.NodeStageSecretRef
   215  	pv := csiDriver.GetPersistentVolume(volume.VolumeID, volume.FSType, volume.ClaimSize, volume.ReclaimPolicy, namespace.Name, attrib, nodeStageSecretRef)
   216  	tpv := NewTestPreProvisionedPersistentVolume(client, pv)
   217  	tpv.Create(ctx)
   218  	ginkgo.By("setting up the PVC")
   219  	tpvc := NewTestPersistentVolumeClaim(client, namespace, volume.ClaimSize, volume.VolumeMode, nil)
   220  	tpvc.Create(ctx)
   221  	cleanupFuncs = append(cleanupFuncs, tpvc.DeleteBoundPersistentVolume)
   222  	cleanupFuncs = append(cleanupFuncs, tpvc.Cleanup)
   223  	tpvc.WaitForBound(ctx)
   224  	tpvc.ValidateProvisionedPersistentVolume(ctx)
   225  
   226  	return tpvc, cleanupFuncs
   227  }
   228  
   229  func (volume *VolumeDetails) CreateStorageClass(ctx context.Context, client clientset.Interface, namespace *v1.Namespace, csiDriver driver.DynamicPVTestDriver, storageClassParameters map[string]string) (*TestStorageClass, func(ctx context.Context)) {
   230  	ginkgo.By("setting up the StorageClass")
   231  	storageClass := csiDriver.GetProvisionStorageClass(storageClassParameters, volume.MountOptions, volume.ReclaimPolicy, volume.VolumeBindingMode, volume.AllowedTopologyValues, namespace.Name)
   232  	tsc := NewTestStorageClass(client, namespace, storageClass)
   233  	tsc.Create(ctx)
   234  	return tsc, tsc.Cleanup
   235  }