sigs.k8s.io/azuredisk-csi-driver@v1.30.1/test/e2e/suite_test.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 e2e 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "log" 24 "os" 25 "os/exec" 26 "path" 27 "path/filepath" 28 "strings" 29 "testing" 30 31 "github.com/onsi/ginkgo/v2" 32 "github.com/onsi/ginkgo/v2/reporters" 33 "github.com/onsi/gomega" 34 "k8s.io/apimachinery/pkg/util/uuid" 35 "k8s.io/kubernetes/test/e2e/framework" 36 "k8s.io/kubernetes/test/e2e/framework/config" 37 consts "sigs.k8s.io/azuredisk-csi-driver/pkg/azureconstants" 38 "sigs.k8s.io/azuredisk-csi-driver/pkg/azuredisk" 39 "sigs.k8s.io/azuredisk-csi-driver/test/e2e/driver" 40 "sigs.k8s.io/azuredisk-csi-driver/test/utils/azure" 41 "sigs.k8s.io/azuredisk-csi-driver/test/utils/credentials" 42 ) 43 44 const ( 45 kubeconfigEnvVar = "KUBECONFIG" 46 reportDirEnvVar = "ARTIFACTS" 47 testMigrationEnvVar = "TEST_MIGRATION" 48 testWindowsEnvVar = "TEST_WINDOWS" 49 testWinServerVerEnvVar = "WINDOWS_SERVER_VERSION" 50 cloudNameEnvVar = "AZURE_CLOUD_NAME" 51 defaultReportDir = "/workspace/_artifacts" 52 inTreeStorageClass = "kubernetes.io/azure-disk" 53 ) 54 55 var ( 56 azurediskDriver azuredisk.CSIDriver 57 isUsingInTreeVolumePlugin = os.Getenv(driver.AzureDriverNameVar) == inTreeStorageClass 58 isTestingMigration = os.Getenv(testMigrationEnvVar) != "" 59 isWindowsCluster = os.Getenv(testWindowsEnvVar) != "" 60 winServerVer = os.Getenv(testWinServerVerEnvVar) 61 isAzureStackCloud = strings.EqualFold(os.Getenv(cloudNameEnvVar), "AZURESTACKCLOUD") 62 isWindowsHPCDeployment = strings.EqualFold(os.Getenv("WINDOWS_USE_HOST_PROCESS_CONTAINERS"), "true") 63 isCapzTest = os.Getenv("NODE_MACHINE_TYPE") != "" 64 location string 65 supportsZRS bool 66 ) 67 68 type testCmd struct { 69 command string 70 args []string 71 startLog string 72 endLog string 73 } 74 75 var _ = ginkgo.BeforeSuite(func(ctx ginkgo.SpecContext) { 76 log.Println(driver.AzureDriverNameVar, os.Getenv(driver.AzureDriverNameVar), fmt.Sprintf("%v", isUsingInTreeVolumePlugin)) 77 log.Println(testMigrationEnvVar, os.Getenv(testMigrationEnvVar), fmt.Sprintf("%v", isTestingMigration)) 78 log.Println(testWindowsEnvVar, os.Getenv(testWindowsEnvVar), fmt.Sprintf("%v", isWindowsCluster)) 79 log.Println(testWinServerVerEnvVar, os.Getenv(testWinServerVerEnvVar), fmt.Sprintf("%v", winServerVer)) 80 81 // k8s.io/kubernetes/test/e2e/framework requires env KUBECONFIG to be set 82 // it does not fall back to defaults 83 if os.Getenv(kubeconfigEnvVar) == "" { 84 kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config") 85 os.Setenv(kubeconfigEnvVar, kubeconfig) 86 } 87 88 // Default storage driver configuration is CSI. Freshly built 89 // CSI driver is installed for that case. 90 if isTestingMigration || !isUsingInTreeVolumePlugin { 91 creds, err := credentials.CreateAzureCredentialFile() 92 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 93 azureClient, err := azure.GetAzureClient(creds.Cloud, creds.SubscriptionID, creds.AADClientID, creds.TenantID, creds.AADClientSecret) 94 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 95 _, err = azureClient.EnsureResourceGroup(ctx, creds.ResourceGroup, creds.Location, nil) 96 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 97 98 location = creds.Location 99 supportZRSRegions := []string{ 100 "southafricanorth", 101 "eastasia", 102 "southeastasia", 103 "australiaeast", 104 "brazilsouth", 105 "westeurope", 106 "northeurope", 107 "francecentral", 108 "centralindia", 109 "italynorth", 110 "japaneast", 111 "koreacentral", 112 "norwayeast", 113 "polandcentral", 114 "qatarcentral", 115 "swedencentral", 116 "switzerlandnorth", 117 "uaenorth", 118 "uksouth", 119 "eastus", 120 "eastus2", 121 "southcentralus", 122 "westus2", 123 "westus3", 124 } 125 supportsZRS = false 126 for _, region := range supportZRSRegions { 127 if location == region { 128 supportsZRS = true 129 break 130 } 131 } 132 133 // Install Azure Disk CSI Driver on cluster from project root 134 e2eBootstrap := testCmd{ 135 command: "make", 136 args: []string{"e2e-bootstrap"}, 137 startLog: "Installing Azure Disk CSI Driver...", 138 endLog: "Azure Disk CSI Driver installed", 139 } 140 141 createMetricsSVC := testCmd{ 142 command: "make", 143 args: []string{"create-metrics-svc"}, 144 startLog: "create metrics service ...", 145 endLog: "metrics service created", 146 } 147 execTestCmd([]testCmd{e2eBootstrap, createMetricsSVC}) 148 149 driverOptions := azuredisk.DriverOptions{ 150 NodeID: os.Getenv("nodeid"), 151 DriverName: consts.DefaultDriverName, 152 VolumeAttachLimit: 16, 153 EnablePerfOptimization: false, 154 Kubeconfig: os.Getenv(kubeconfigEnvVar), 155 Endpoint: fmt.Sprintf("unix:///tmp/csi-%s.sock", string(uuid.NewUUID())), 156 } 157 os.Setenv("AZURE_CREDENTIAL_FILE", credentials.TempAzureCredentialFilePath) 158 azurediskDriver = azuredisk.NewDriver(&driverOptions) 159 160 go func() { 161 err := azurediskDriver.Run(context.Background()) 162 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 163 }() 164 } 165 }) 166 167 var _ = ginkgo.AfterSuite(func(ctx ginkgo.SpecContext) { 168 // Default storage driver configuration is CSI. Freshly built 169 // CSI driver is installed for that case. 170 if isTestingMigration || isUsingInTreeVolumePlugin { 171 cmLog := testCmd{ 172 command: "bash", 173 args: []string{"test/utils/controller-manager-log.sh"}, 174 startLog: "===================controller-manager log=======", 175 endLog: "===================================================", 176 } 177 execTestCmd([]testCmd{cmLog}) 178 } 179 180 if isTestingMigration || !isUsingInTreeVolumePlugin { 181 checkPodsRestart := testCmd{ 182 command: "bash", 183 args: []string{"test/utils/check_driver_pods_restart.sh", "log"}, 184 startLog: "Check driver pods if restarts ...", 185 endLog: "Check successfully", 186 } 187 execTestCmd([]testCmd{checkPodsRestart}) 188 189 os := "linux" 190 cloud := "azurepubliccloud" 191 if isWindowsCluster { 192 os = "windows" 193 if winServerVer == "windows-2022" { 194 os = winServerVer 195 } 196 } 197 if isAzureStackCloud { 198 cloud = "azurestackcloud" 199 } 200 createExampleDeployment := testCmd{ 201 command: "bash", 202 args: []string{"hack/verify-examples.sh", os, cloud}, 203 startLog: "create example deployments", 204 endLog: "example deployments created", 205 } 206 execTestCmd([]testCmd{createExampleDeployment}) 207 208 azurediskLog := testCmd{ 209 command: "bash", 210 args: []string{"test/utils/azuredisk_log.sh"}, 211 startLog: "===================azuredisk log===================", 212 endLog: "===================================================", 213 } 214 215 deleteMetricsSVC := testCmd{ 216 command: "make", 217 args: []string{"delete-metrics-svc"}, 218 startLog: "delete metrics service...", 219 endLog: "metrics service deleted", 220 } 221 222 e2eTeardown := testCmd{ 223 command: "make", 224 args: []string{"e2e-teardown"}, 225 startLog: "Uninstalling Azure Disk CSI Driver...", 226 endLog: "Azure Disk CSI Driver uninstalled", 227 } 228 execTestCmd([]testCmd{azurediskLog, deleteMetricsSVC, e2eTeardown}) 229 230 if !isTestingMigration { 231 // install Azure Disk CSI Driver deployment scripts test 232 installDriver := testCmd{ 233 command: "bash", 234 args: []string{"deploy/install-driver.sh", "master", "windows,snapshot,local"}, 235 startLog: "===================install Azure Disk CSI Driver deployment scripts test===================", 236 endLog: "===================================================", 237 } 238 execTestCmd([]testCmd{installDriver}) 239 240 // run example deployment again 241 createExampleDeployment := testCmd{ 242 command: "bash", 243 args: []string{"hack/verify-examples.sh", os, cloud}, 244 startLog: "create example deployments#2", 245 endLog: "example deployments#2 created", 246 } 247 execTestCmd([]testCmd{createExampleDeployment}) 248 249 // uninstall Azure Disk CSI Driver deployment scripts test 250 uninstallDriver := testCmd{ 251 command: "bash", 252 args: []string{"deploy/uninstall-driver.sh", "master", "windows,snapshot,local"}, 253 startLog: "===================uninstall Azure Disk CSI Driver deployment scripts test===================", 254 endLog: "===================================================", 255 } 256 execTestCmd([]testCmd{uninstallDriver}) 257 } 258 err := credentials.DeleteAzureCredentialFile() 259 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 260 } 261 }) 262 263 func TestE2E(t *testing.T) { 264 gomega.RegisterFailHandler(ginkgo.Fail) 265 reportDir := os.Getenv(reportDirEnvVar) 266 if reportDir == "" { 267 reportDir = defaultReportDir 268 } 269 r := []ginkgo.Reporter{reporters.NewJUnitReporter(path.Join(reportDir, "junit_01.xml"))} 270 ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "AzureDisk CSI Driver End-to-End Tests", r) 271 } 272 273 func execTestCmd(cmds []testCmd) { 274 err := os.Chdir("../..") 275 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 276 defer func() { 277 err := os.Chdir("test/e2e") 278 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 279 }() 280 281 projectRoot, err := os.Getwd() 282 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 283 gomega.Expect(strings.HasSuffix(projectRoot, "azuredisk-csi-driver")).To(gomega.Equal(true)) 284 285 for _, cmd := range cmds { 286 log.Println(cmd.startLog) 287 cmdSh := exec.Command(cmd.command, cmd.args...) 288 cmdSh.Dir = projectRoot 289 cmdSh.Stdout = os.Stdout 290 cmdSh.Stderr = os.Stderr 291 err = cmdSh.Run() 292 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 293 log.Println(cmd.endLog) 294 } 295 } 296 297 func skipIfTestingInWindowsCluster() { 298 if isWindowsCluster { 299 ginkgo.Skip("test case not supported by Windows clusters") 300 } 301 } 302 303 func skipIfUsingInTreeVolumePlugin() { 304 if isUsingInTreeVolumePlugin { 305 ginkgo.Skip("test case is only available for CSI drivers") 306 } 307 } 308 309 func skipIfOnAzureStackCloud() { 310 if isAzureStackCloud { 311 ginkgo.Skip("test case not supported on Azure Stack Cloud") 312 } 313 } 314 315 func skipIfNotZRSSupported() { 316 if !supportsZRS { 317 ginkgo.Skip("test case not supported on regions without ZRS") 318 } 319 } 320 321 func convertToPowershellorCmdCommandIfNecessary(command string) string { 322 if !isWindowsCluster { 323 return command 324 } 325 326 switch command { 327 case "echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data": 328 return "echo 'hello world' | Out-File -FilePath C:\\mnt\\test-1\\data.txt; Get-Content C:\\mnt\\test-1\\data.txt | findstr 'hello world'" 329 case "touch /mnt/test-1/data": 330 return "echo $null >> C:\\mnt\\test-1\\data" 331 case "while true; do echo $(date -u) >> /mnt/test-1/data; sleep 3600; done": 332 return "while (1) { Add-Content -Encoding Ascii C:\\mnt\\test-1\\data.txt $(Get-Date -Format u); sleep 3600 }" 333 case "echo 'hello world' >> /mnt/test-1/data && while true; do sleep 3600; done": 334 return "echo 'hello world' | Out-File -Append -FilePath C:\\mnt\\test-1\\data.txt; Get-Content C:\\mnt\\test-1\\data.txt | findstr 'hello world'; Start-Sleep 3600" 335 case "echo 'hello world' > /mnt/test-1/data && echo 'hello world' > /mnt/test-2/data && echo 'hello world' > /mnt/test-3/data && grep 'hello world' /mnt/test-1/data && grep 'hello world' /mnt/test-2/data && grep 'hello world' /mnt/test-3/data": 336 return "echo 'hello world' | Out-File -FilePath C:\\mnt\\test-1\\data.txt; Get-Content C:\\mnt\\test-1\\data.txt | findstr 'hello world'; echo 'hello world' | Out-File -FilePath C:\\mnt\\test-2\\data.txt; Get-Content C:\\mnt\\test-2\\data.txt | findstr 'hello world'; echo 'hello world' | Out-File -FilePath C:\\mnt\\test-3\\data.txt; Get-Content C:\\mnt\\test-3\\data.txt | findstr 'hello world'" 337 case "while true; do sleep 5; done": 338 return "while ($true) { Start-Sleep 5 }" 339 case "echo 'hello world' > /mnt/test-1/data": 340 return "echo 'hello world' | Out-File -FilePath C:\\mnt\\test-1\\data.txt" 341 case "echo 'overwrite' > /mnt/test-1/data; sleep 3600": 342 return "echo 'overwrite' | Out-File -FilePath C:\\mnt\\test-1\\data.txt; Start-Sleep 3600" 343 case "grep 'hello world' /mnt/test-1/data": 344 return "Get-Content C:\\mnt\\test-1\\data.txt | findstr 'hello world'" 345 case "df -h | grep /mnt/test- | awk '{print $2}' | grep -E '19|20'": 346 return "fsutil volume diskfree C:\\mnt\\ | Select-String 'Total bytes' | Select-String -Pattern '19|20'" 347 } 348 349 return command 350 } 351 352 // handleFlags sets up all flags and parses the command line. 353 func TestMain(m *testing.M) { 354 config.CopyFlags(config.Flags, flag.CommandLine) 355 framework.RegisterCommonFlags(flag.CommandLine) 356 framework.RegisterClusterFlags(flag.CommandLine) 357 framework.AfterReadingAllFlags(&framework.TestContext) 358 flag.Parse() 359 os.Exit(m.Run()) 360 } 361 362 func getFSType(IsWindowsCluster bool) string { 363 if IsWindowsCluster { 364 return "ntfs" 365 } 366 return "ext4" 367 }