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  }