sigs.k8s.io/blob-csi-driver@v1.24.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  	"encoding/json"
    22  	"flag"
    23  	"fmt"
    24  	"log"
    25  	"os"
    26  	"os/exec"
    27  	"path"
    28  	"path/filepath"
    29  	"strings"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/onsi/ginkgo/v2"
    34  	"github.com/onsi/ginkgo/v2/reporters"
    35  	"github.com/onsi/gomega"
    36  	"github.com/pborman/uuid"
    37  	"k8s.io/klog/v2"
    38  	"k8s.io/kubernetes/test/e2e/framework"
    39  	"k8s.io/kubernetes/test/e2e/framework/config"
    40  	_ "k8s.io/kubernetes/test/e2e/framework/debug/init"
    41  	"sigs.k8s.io/blob-csi-driver/pkg/blob"
    42  	"sigs.k8s.io/blob-csi-driver/pkg/util"
    43  	"sigs.k8s.io/blob-csi-driver/test/utils/azure"
    44  	"sigs.k8s.io/blob-csi-driver/test/utils/credentials"
    45  	"sigs.k8s.io/blob-csi-driver/test/utils/testutil"
    46  )
    47  
    48  const (
    49  	kubeconfigEnvVar = "KUBECONFIG"
    50  	reportDirEnv     = "ARTIFACTS"
    51  	defaultReportDir = "/workspace/_artifacts"
    52  )
    53  
    54  var isAzureStackCloud = strings.EqualFold(os.Getenv("AZURE_CLOUD_NAME"), "AZURESTACKCLOUD")
    55  var blobDriver *blob.Driver
    56  var projectRoot string
    57  
    58  type testCmd struct {
    59  	command  string
    60  	args     []string
    61  	startLog string
    62  	endLog   string
    63  }
    64  
    65  func TestMain(m *testing.M) {
    66  	flag.StringVar(&projectRoot, "project-root", "", "path to the blob csi driver project root, used for script execution")
    67  	flag.Parse()
    68  	if projectRoot == "" {
    69  		klog.Fatal("project-root must be set")
    70  	}
    71  
    72  	config.CopyFlags(config.Flags, flag.CommandLine)
    73  	framework.RegisterCommonFlags(flag.CommandLine)
    74  	framework.RegisterClusterFlags(flag.CommandLine)
    75  	flag.Parse()
    76  	framework.AfterReadingAllFlags(&framework.TestContext)
    77  	os.Exit(m.Run())
    78  }
    79  
    80  func TestE2E(t *testing.T) {
    81  	gomega.RegisterFailHandler(ginkgo.Fail)
    82  	reportDir := os.Getenv(reportDirEnv)
    83  	if reportDir == "" {
    84  		reportDir = defaultReportDir
    85  	}
    86  	r := []ginkgo.Reporter{reporters.NewJUnitReporter(path.Join(reportDir, "junit_01.xml"))}
    87  	ginkgo.RunSpecsWithDefaultAndCustomReporters(t, "Azure Blob Storage CSI driver End-to-End Tests", r)
    88  }
    89  
    90  var _ = ginkgo.SynchronizedBeforeSuite(func(ctx ginkgo.SpecContext) []byte {
    91  	creds, err := credentials.CreateAzureCredentialFile()
    92  	gomega.Expect(err).NotTo(gomega.HaveOccurred())
    93  	azureClient, err := azure.GetClient(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  	if testutil.IsRunningInProw() {
    99  		// Need to login to ACR using SP credential if we are running in Prow so we can push test images.
   100  		// If running locally, user should run 'docker login' before running E2E tests
   101  		registry := os.Getenv("REGISTRY")
   102  		gomega.Expect(registry).NotTo(gomega.Equal(""))
   103  
   104  		log.Println("Attempting docker login with Azure service principal")
   105  		cmd := exec.Command("docker", "login", fmt.Sprintf("--username=%s", creds.AADClientID), fmt.Sprintf("--password=%s", creds.AADClientSecret), registry)
   106  		err = cmd.Run()
   107  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   108  		log.Println("docker login is successful")
   109  	}
   110  
   111  	// Install Azure Blob Storage CSI driver on cluster from project root
   112  	e2eBootstrap := testCmd{
   113  		command:  "make",
   114  		args:     []string{"e2e-bootstrap"},
   115  		startLog: "Installing Azure Blob Storage CSI driver ...",
   116  		endLog:   "Azure Blob Storage CSI driver installed",
   117  	}
   118  
   119  	createMetricsSVC := testCmd{
   120  		command:  "make",
   121  		args:     []string{"create-metrics-svc"},
   122  		startLog: "create metrics service ...",
   123  		endLog:   "metrics service created",
   124  	}
   125  	execTestCmd([]testCmd{e2eBootstrap, createMetricsSVC})
   126  
   127  	if testutil.IsRunningInProw() {
   128  		data, err := json.Marshal(creds)
   129  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   130  		return data
   131  	}
   132  
   133  	return nil
   134  }, func(ctx ginkgo.SpecContext, data []byte) {
   135  	if testutil.IsRunningInProw() {
   136  		creds := &credentials.Credentials{}
   137  		err := json.Unmarshal(data, creds)
   138  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   139  		// set env for azidentity.EnvironmentCredential
   140  		os.Setenv("AZURE_TENANT_ID", creds.TenantID)
   141  		os.Setenv("AZURE_CLIENT_ID", creds.AADClientID)
   142  		os.Setenv("AZURE_CLIENT_SECRET", creds.AADClientSecret)
   143  	}
   144  
   145  	// k8s.io/kubernetes/test/e2e/framework requires env KUBECONFIG to be set
   146  	// it does not fall back to defaults
   147  	if os.Getenv(kubeconfigEnvVar) == "" {
   148  		kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
   149  		os.Setenv(kubeconfigEnvVar, kubeconfig)
   150  	}
   151  
   152  	// spin up a blob driver locally to make use of the azure client and controller service
   153  	kubeconfig := os.Getenv(kubeconfigEnvVar)
   154  	_, useBlobfuseProxy := os.LookupEnv("ENABLE_BLOBFUSE_PROXY")
   155  	os.Setenv("AZURE_CREDENTIAL_FILE", credentials.TempAzureCredentialFilePath)
   156  	driverOptions := blob.DriverOptions{
   157  		NodeID:                  os.Getenv("nodeid"),
   158  		DriverName:              blob.DefaultDriverName,
   159  		BlobfuseProxyEndpoint:   "",
   160  		EnableBlobfuseProxy:     useBlobfuseProxy,
   161  		BlobfuseProxyConnTimout: 5,
   162  		EnableBlobMockMount:     false,
   163  	}
   164  	kubeClient, err := util.GetKubeClient(kubeconfig, 25.0, 50, "")
   165  	gomega.Expect(err).NotTo(gomega.HaveOccurred())
   166  	cloud, err := blob.GetCloudProvider(context.Background(), kubeClient, driverOptions.NodeID, "", "", "", false)
   167  	gomega.Expect(err).NotTo(gomega.HaveOccurred())
   168  	blobDriver = blob.NewDriver(&driverOptions, kubeClient, cloud)
   169  	go func() {
   170  		err := blobDriver.Run(context.Background(), fmt.Sprintf("unix:///tmp/csi-%s.sock", uuid.NewUUID().String()))
   171  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   172  	}()
   173  })
   174  
   175  var _ = ginkgo.SynchronizedAfterSuite(func(ctx ginkgo.SpecContext) {},
   176  	func(ctx ginkgo.SpecContext) {
   177  		blobLog := testCmd{
   178  			command:  "bash",
   179  			args:     []string{"test/utils/blob_log.sh"},
   180  			startLog: "==============start blob log(after suite)===================",
   181  			endLog:   "==============end blob log(after suite)===================",
   182  		}
   183  		e2eTeardown := testCmd{
   184  			command:  "make",
   185  			args:     []string{"e2e-teardown"},
   186  			startLog: "Uninstalling Azure Blob Storage CSI driver...",
   187  			endLog:   "Azure Blob Storage CSI driver uninstalled",
   188  		}
   189  		execTestCmd([]testCmd{blobLog, e2eTeardown})
   190  
   191  		// install/uninstall CSI Driver deployment scripts test
   192  		installDriver := testCmd{
   193  			command:  "bash",
   194  			args:     []string{"deploy/install-driver.sh", "master", "local,enable-blobfuse-proxy"},
   195  			startLog: "===================install CSI Driver deployment scripts test===================",
   196  			endLog:   "===================================================",
   197  		}
   198  		uninstallDriver := testCmd{
   199  			command:  "bash",
   200  			args:     []string{"deploy/uninstall-driver.sh", "master", "local,enable-blobfuse-proxy"},
   201  			startLog: "===================uninstall CSI Driver deployment scripts test===================",
   202  			endLog:   "===================================================",
   203  		}
   204  		execTestCmd([]testCmd{installDriver, uninstallDriver})
   205  
   206  		checkAccountCreationLeak(ctx)
   207  
   208  		err := credentials.DeleteAzureCredentialFile()
   209  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   210  	}, ginkgo.NodeTimeout(10*time.Minute))
   211  
   212  func execTestCmd(cmds []testCmd) {
   213  	ginkgo.GinkgoHelper()
   214  
   215  	for _, cmd := range cmds {
   216  		log.Println(cmd.startLog)
   217  		cmdSh := exec.Command(cmd.command, cmd.args...)
   218  		cmdSh.Dir = projectRoot
   219  		cmdSh.Stdout = os.Stdout
   220  		cmdSh.Stderr = os.Stderr
   221  		err := cmdSh.Run()
   222  		if err != nil {
   223  			log.Printf("Failed to run command: %s %s, Error: %s\n", cmd.command, strings.Join(cmd.args, " "), err.Error())
   224  		}
   225  		gomega.Expect(err).NotTo(gomega.HaveOccurred())
   226  		log.Println(cmd.endLog)
   227  	}
   228  }
   229  
   230  func checkAccountCreationLeak(ctx context.Context) {
   231  	creds, err := credentials.CreateAzureCredentialFile()
   232  	gomega.Expect(err).NotTo(gomega.HaveOccurred())
   233  	azureClient, err := azure.GetClient(creds.Cloud, creds.SubscriptionID, creds.AADClientID, creds.TenantID, creds.AADClientSecret)
   234  	gomega.Expect(err).NotTo(gomega.HaveOccurred())
   235  
   236  	accountNum, err := azureClient.GetAccountNumByResourceGroup(ctx, creds.ResourceGroup)
   237  	framework.ExpectNoError(err, fmt.Sprintf("failed to GetAccountNumByResourceGroup(%s): %v", creds.ResourceGroup, err))
   238  	ginkgo.By(fmt.Sprintf("GetAccountNumByResourceGroup(%s) returns %d accounts", creds.ResourceGroup, accountNum))
   239  
   240  	accountLimitInTest := 20
   241  	gomega.Expect(accountNum >= accountLimitInTest).To(gomega.BeFalse())
   242  }