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 }