github.com/interconnectedcloud/qdr-operator@v0.0.0-20210826174505-576d2b33dac7/test/e2e/framework/test_context.go (about)

     1  /*
     2  Copyright 2019 The Interconnectedcloud 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 framework
    18  
    19  import (
    20  	"flag"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  
    25  	"github.com/onsi/ginkgo/config"
    26  	restclient "k8s.io/client-go/rest"
    27  	"k8s.io/client-go/tools/clientcmd"
    28  	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
    29  	"k8s.io/klog"
    30  )
    31  
    32  const (
    33  	defaultHost          = "http://127.0.0.1:8080"
    34  	defaultOperatorImage = "quay.io/interconnectedcloud/qdr-operator"
    35  	defaultQdrImage      = "quay.io/interconnectedcloud/qdrouterd:1.13.0"
    36  )
    37  
    38  // TestContextType contains test settings and global state.
    39  type TestContextType struct {
    40  	KubeConfig               string
    41  	KubeContext              string
    42  	CertDir                  string
    43  	Host                     string
    44  	RepoRoot                 string
    45  	KubectlPath              string
    46  	OutputDir                string
    47  	ReportDir                string
    48  	ReportPrefix             string
    49  	Prefix                   string
    50  	QdrImage                 string
    51  	OperatorImage            string
    52  	DeleteNamespace          bool
    53  	DeleteNamespaceOnFailure bool
    54  	CleanStart               bool
    55  }
    56  
    57  // TestContext should be used by all tests to access common context data.
    58  var TestContext TestContextType
    59  
    60  // RegisterFlags registers flags for e2e test suites.
    61  func RegisterFlags() {
    62  	// Turn on verbose by default to get spec names
    63  	config.DefaultReporterConfig.Verbose = true
    64  
    65  	// Turn on EmitSpecProgress to get spec progress (especially on interrupt)
    66  	config.GinkgoConfig.EmitSpecProgress = true
    67  
    68  	// Randomize specs as well as suites
    69  	config.GinkgoConfig.RandomizeAllSpecs = true
    70  
    71  	flag.BoolVar(&TestContext.DeleteNamespace, "delete-namespace", true, "If true tests will delete namespace after completion. It is only designed to make debugging easier, DO NOT turn it off by default.")
    72  	flag.BoolVar(&TestContext.DeleteNamespaceOnFailure, "delete-namespace-on-failure", true, "If true, framework will delete test namespace on failure. Used only during test debugging.")
    73  	flag.StringVar(&TestContext.Host, "host", "", fmt.Sprintf("The host, or apiserver, to connect to. Will default to %s if this argument and --kubeconfig are not set", defaultHost))
    74  	flag.StringVar(&TestContext.ReportPrefix, "report-prefix", "", "Optional prefix for JUnit XML reports. Default is empty, which doesn't prepend anything to the default name.")
    75  	flag.StringVar(&TestContext.ReportDir, "report-dir", "", "Path to the directory where the JUnit XML reports should be saved. Default is empty, which doesn't generate these reports.")
    76  	flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.")
    77  	flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'")
    78  	flag.StringVar(&TestContext.CertDir, "cert-dir", "", "Path to the directory containing the certs. Default is empty, which doesn't use certs.")
    79  	flag.StringVar(&TestContext.RepoRoot, "repo-root", "../../", "Root directory of kubernetes repository, for finding test files.")
    80  	flag.StringVar(&TestContext.KubectlPath, "kubectl-path", "kubectl", "The kubectl binary to use. For development, you might use 'cluster/kubectl.sh' here.")
    81  	flag.StringVar(&TestContext.OutputDir, "e2e-output-dir", "/tmp", "Output directory for interesting/useful test data, like performance data, benchmarks, and other metrics.")
    82  	flag.StringVar(&TestContext.Prefix, "prefix", "e2e", "A prefix to be added to cloud resources created during testing.")
    83  	flag.BoolVar(&TestContext.CleanStart, "clean-start", false, "If true, purge all namespaces except default and system before running tests. This serves to Cleanup test namespaces from failed/interrupted e2e runs in a long-lived cluster.")
    84  	flag.StringVar(&TestContext.QdrImage, "qdr-image", defaultQdrImage, fmt.Sprintf("The qdrouterd image to use. Default: %s", defaultQdrImage))
    85  	flag.StringVar(&TestContext.OperatorImage, "operator-image", defaultOperatorImage, fmt.Sprintf("The operator image to use. Default: %s", defaultOperatorImage))
    86  }
    87  
    88  // HandleFlags sets up all flags and parses the command line.
    89  func HandleFlags() {
    90  	RegisterFlags()
    91  	flag.Parse()
    92  }
    93  
    94  func createKubeConfig(clientCfg *restclient.Config) *clientcmdapi.Config {
    95  	clusterNick := "cluster"
    96  	userNick := "user"
    97  	contextNick := "context"
    98  
    99  	config := clientcmdapi.NewConfig()
   100  
   101  	credentials := clientcmdapi.NewAuthInfo()
   102  	credentials.Token = clientCfg.BearerToken
   103  	credentials.ClientCertificate = clientCfg.TLSClientConfig.CertFile
   104  	if len(credentials.ClientCertificate) == 0 {
   105  		credentials.ClientCertificateData = clientCfg.TLSClientConfig.CertData
   106  	}
   107  	credentials.ClientKey = clientCfg.TLSClientConfig.KeyFile
   108  	if len(credentials.ClientKey) == 0 {
   109  		credentials.ClientKeyData = clientCfg.TLSClientConfig.KeyData
   110  	}
   111  	config.AuthInfos[userNick] = credentials
   112  
   113  	cluster := clientcmdapi.NewCluster()
   114  	cluster.Server = clientCfg.Host
   115  	cluster.CertificateAuthority = clientCfg.CAFile
   116  	if len(cluster.CertificateAuthority) == 0 {
   117  		cluster.CertificateAuthorityData = clientCfg.CAData
   118  	}
   119  	cluster.InsecureSkipTLSVerify = clientCfg.Insecure
   120  	config.Clusters[clusterNick] = cluster
   121  
   122  	context := clientcmdapi.NewContext()
   123  	context.Cluster = clusterNick
   124  	context.AuthInfo = userNick
   125  	config.Contexts[contextNick] = context
   126  	config.CurrentContext = contextNick
   127  
   128  	return config
   129  }
   130  
   131  // AfterReadingAllFlags makes changes to the context after all flags
   132  // have been read.
   133  func AfterReadingAllFlags(t *TestContextType) {
   134  	// Only set a default host if one won't be supplied via kubeconfig
   135  	if len(t.Host) == 0 && len(t.KubeConfig) == 0 {
   136  		// Check if we can use the in-cluster config
   137  		if clusterConfig, err := restclient.InClusterConfig(); err == nil {
   138  			if tempFile, err := ioutil.TempFile(os.TempDir(), "kubeconfig-"); err == nil {
   139  				kubeConfig := createKubeConfig(clusterConfig)
   140  				clientcmd.WriteToFile(*kubeConfig, tempFile.Name())
   141  				t.KubeConfig = tempFile.Name()
   142  				klog.Infof("Using a temporary kubeconfig file from in-cluster config : %s", tempFile.Name())
   143  			}
   144  		}
   145  		if len(t.KubeConfig) == 0 {
   146  			klog.Warningf("Unable to find in-cluster config, using default host : %s", defaultHost)
   147  			t.Host = defaultHost
   148  		}
   149  	}
   150  }