github.com/operator-framework/operator-lifecycle-manager@v0.30.0/test/e2e/ctx/ctx.go (about)

     1  package ctx
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  
     9  	"github.com/operator-framework/operator-lifecycle-manager/test/e2e/util"
    10  	appsv1 "k8s.io/api/apps/v1"
    11  	apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
    12  
    13  	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    14  	"k8s.io/apimachinery/pkg/runtime"
    15  	"k8s.io/client-go/dynamic"
    16  	kscheme "k8s.io/client-go/kubernetes/scheme"
    17  	"k8s.io/client-go/rest"
    18  	k8scontrollerclient "sigs.k8s.io/controller-runtime/pkg/client"
    19  
    20  	operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
    21  	operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
    22  	operatorsv2 "github.com/operator-framework/api/pkg/operators/v2"
    23  	"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
    24  	controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
    25  	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
    26  	pversioned "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned"
    27  )
    28  
    29  var ctx TestContext
    30  
    31  // TestContext represents the environment of an executing test. It can
    32  // be considered roughly analogous to a kubeconfig context.
    33  type TestContext struct {
    34  	restConfig     *rest.Config
    35  	kubeClient     operatorclient.ClientInterface
    36  	operatorClient versioned.Interface
    37  	dynamicClient  dynamic.Interface
    38  	packageClient  pversioned.Interface
    39  	e2eClient      *util.E2EKubeClient
    40  	ssaClient      *controllerclient.ServerSideApplier
    41  
    42  	kubeconfigPath      string
    43  	artifactsDir        string
    44  	artifactsScriptPath string
    45  
    46  	scheme *runtime.Scheme
    47  
    48  	// client is the controller-runtime client -- we should use this from now on
    49  	client k8scontrollerclient.Client
    50  }
    51  
    52  // Ctx returns a pointer to the global test context. During parallel
    53  // test executions, Ginkgo starts one process per test "node", and
    54  // each node will have its own context, which may or may not point to
    55  // the same test cluster.
    56  func Ctx() *TestContext {
    57  	return &ctx
    58  }
    59  
    60  func (ctx TestContext) Logf(f string, v ...interface{}) {
    61  	util.Logf(f, v...)
    62  }
    63  
    64  func (ctx TestContext) Scheme() *runtime.Scheme {
    65  	return ctx.scheme
    66  }
    67  
    68  func (ctx TestContext) RESTConfig() *rest.Config {
    69  	return rest.CopyConfig(ctx.restConfig)
    70  }
    71  
    72  func (ctx TestContext) KubeClient() operatorclient.ClientInterface {
    73  	return ctx.kubeClient
    74  }
    75  
    76  func (ctx TestContext) OperatorClient() versioned.Interface {
    77  	return ctx.operatorClient
    78  }
    79  
    80  func (ctx TestContext) DynamicClient() dynamic.Interface {
    81  	return ctx.dynamicClient
    82  }
    83  
    84  func (ctx TestContext) PackageClient() pversioned.Interface {
    85  	return ctx.packageClient
    86  }
    87  
    88  func (ctx TestContext) Client() k8scontrollerclient.Client {
    89  	return ctx.client
    90  }
    91  
    92  func (ctx TestContext) SSAClient() *controllerclient.ServerSideApplier {
    93  	return ctx.ssaClient
    94  }
    95  
    96  func (ctx TestContext) E2EClient() *util.E2EKubeClient {
    97  	return ctx.e2eClient
    98  }
    99  
   100  func (ctx TestContext) NewE2EClientSession() {
   101  	if ctx.e2eClient != nil {
   102  		_ = ctx.e2eClient.Reset()
   103  	}
   104  	ctx.e2eClient = util.NewK8sResourceManager(ctx.Client())
   105  }
   106  
   107  func (ctx TestContext) DumpNamespaceArtifacts(namespace string) error {
   108  	if ctx.artifactsDir == "" {
   109  		ctx.Logf("$ARTIFACT_DIR is unset -- not collecting failed test case logs")
   110  		return nil
   111  	}
   112  	ctx.Logf("collecting logs in the %s artifacts directory", ctx.artifactsDir)
   113  
   114  	logDir := filepath.Join(ctx.artifactsDir, namespace)
   115  	if err := os.MkdirAll(logDir, os.ModePerm); err != nil {
   116  		return err
   117  	}
   118  	kubeconfigPath := ctx.kubeconfigPath
   119  	if kubeconfigPath == "" {
   120  		ctx.Logf("unable to determine kubeconfig path so defaulting to the $KUBECONFIG value")
   121  		kubeconfigPath = os.Getenv("KUBECONFIG")
   122  	}
   123  
   124  	envvars := []string{
   125  		"TEST_NAMESPACE=" + namespace,
   126  		"TEST_ARTIFACTS_DIR=" + logDir,
   127  		"KUBECONFIG=" + kubeconfigPath,
   128  		"KUBECTL=" + os.Getenv("KUBECTL"),
   129  	}
   130  
   131  	cmd := exec.Command(ctx.artifactsScriptPath)
   132  	cmd.Env = append(os.Environ(), envvars...)
   133  	cmd.Stdout = os.Stdout
   134  	cmd.Stderr = os.Stderr
   135  	if err := cmd.Run(); err != nil {
   136  		return err
   137  	}
   138  
   139  	return nil
   140  }
   141  
   142  func setDerivedFields(ctx *TestContext) error {
   143  	if ctx == nil {
   144  		return fmt.Errorf("nil test context")
   145  	}
   146  
   147  	if ctx.restConfig == nil {
   148  		return fmt.Errorf("nil RESTClient")
   149  	}
   150  
   151  	if ctx.artifactsDir == "" {
   152  		if artifactsDir := os.Getenv("ARTIFACT_DIR"); artifactsDir != "" {
   153  			ctx.artifactsDir = artifactsDir
   154  		}
   155  	}
   156  	if ctx.artifactsScriptPath == "" {
   157  		if scriptPath := os.Getenv("E2E_ARTIFACT_SCRIPT"); scriptPath != "" {
   158  			ctx.artifactsScriptPath = scriptPath
   159  		}
   160  	}
   161  
   162  	kubeClient, err := operatorclient.NewClientFromRestConfig(ctx.restConfig)
   163  	if err != nil {
   164  		return err
   165  	}
   166  	ctx.kubeClient = kubeClient
   167  
   168  	operatorClient, err := versioned.NewForConfig(ctx.restConfig)
   169  	if err != nil {
   170  		return err
   171  	}
   172  	ctx.operatorClient = operatorClient
   173  
   174  	dynamicClient, err := dynamic.NewForConfig(ctx.restConfig)
   175  	if err != nil {
   176  		return err
   177  	}
   178  	ctx.dynamicClient = dynamicClient
   179  
   180  	packageClient, err := pversioned.NewForConfig(ctx.restConfig)
   181  	if err != nil {
   182  		return err
   183  	}
   184  	ctx.packageClient = packageClient
   185  
   186  	ctx.scheme = runtime.NewScheme()
   187  	localSchemeBuilder := runtime.NewSchemeBuilder(
   188  		apiextensionsv1.AddToScheme,
   189  		kscheme.AddToScheme,
   190  		operatorsv1alpha1.AddToScheme,
   191  		operatorsv1.AddToScheme,
   192  		operatorsv2.AddToScheme,
   193  		apiextensionsv1.AddToScheme,
   194  		appsv1.AddToScheme,
   195  		apiregistrationv1.AddToScheme,
   196  	)
   197  	if err := localSchemeBuilder.AddToScheme(ctx.scheme); err != nil {
   198  		return err
   199  	}
   200  
   201  	client, err := k8scontrollerclient.New(ctx.restConfig, k8scontrollerclient.Options{
   202  		Scheme: ctx.scheme,
   203  	})
   204  	if err != nil {
   205  		return err
   206  	}
   207  	ctx.e2eClient = util.NewK8sResourceManager(client)
   208  	ctx.client = ctx.e2eClient
   209  
   210  	ctx.ssaClient, err = controllerclient.NewForConfig(ctx.restConfig, ctx.scheme, "test.olm.registry")
   211  	if err != nil {
   212  		return err
   213  	}
   214  
   215  	return nil
   216  }