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

     1  package util
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/onsi/ginkgo/v2"
     8  	extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
     9  	k8scontrollerclient "sigs.k8s.io/controller-runtime/pkg/client"
    10  )
    11  
    12  const (
    13  	E2ETestNameTag = "e2e.testName"
    14  )
    15  
    16  type E2EKubeClient struct {
    17  	k8scontrollerclient.Client
    18  	createdResources *ResourceQueue
    19  }
    20  
    21  func NewK8sResourceManager(client k8scontrollerclient.Client) *E2EKubeClient {
    22  	return &E2EKubeClient{
    23  		Client:           client,
    24  		createdResources: NewResourceQueue(),
    25  	}
    26  }
    27  
    28  func (m *E2EKubeClient) Create(context context.Context, obj k8scontrollerclient.Object, options ...k8scontrollerclient.CreateOption) error {
    29  	m.annotateTestResource(obj)
    30  	if err := m.Client.Create(context, obj, options...); err != nil {
    31  		return err
    32  	}
    33  	m.createdResources.EnqueueIgnoreExisting(obj)
    34  	return nil
    35  }
    36  
    37  func (m *E2EKubeClient) Update(context context.Context, obj k8scontrollerclient.Object, options ...k8scontrollerclient.UpdateOption) error {
    38  	m.annotateTestResource(obj)
    39  	if err := m.Client.Update(context, obj, options...); err != nil {
    40  		return err
    41  	}
    42  	return nil
    43  }
    44  
    45  func (m *E2EKubeClient) Delete(context context.Context, obj k8scontrollerclient.Object, options ...k8scontrollerclient.DeleteOption) error {
    46  	if err := m.Client.Delete(context, obj, options...); err != nil {
    47  		return err
    48  	}
    49  	m.createdResources.RemoveIgnoreNotFound(obj)
    50  	return nil
    51  }
    52  
    53  func (m *E2EKubeClient) Reset() error {
    54  	Logf("resetting e2e kube client")
    55  	for {
    56  		obj, ok := m.createdResources.DequeueTail()
    57  
    58  		if !ok {
    59  			break
    60  		}
    61  
    62  		namespace := obj.GetNamespace()
    63  		if namespace == "" {
    64  			namespace = "<global>"
    65  		}
    66  
    67  		Logf("deleting %s/%s", namespace, obj.GetName())
    68  		if err := k8scontrollerclient.IgnoreNotFound(m.Delete(context.Background(), obj)); err != nil {
    69  			Logf("error deleting object %s/%s: %s", namespace, obj.GetName(), obj)
    70  			return err
    71  		}
    72  	}
    73  	return m.GarbageCollectCRDs()
    74  }
    75  
    76  // GarbageCollectCRDs deletes any CRD with a label like operatorframework.io/installed-alongside-*
    77  // these are the result of operator installations by olm and tent to be left behind after an e2e test
    78  func (m *E2EKubeClient) GarbageCollectCRDs() error {
    79  	Logf("garbage collecting CRDs")
    80  	const operatorFrameworkAnnotation = "operatorframework.io/installed-alongside-"
    81  
    82  	crds := &extensionsv1.CustomResourceDefinitionList{}
    83  	err := m.Client.List(context.Background(), crds)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	for _, crd := range crds.Items {
    89  		for key, _ := range crd.Annotations {
    90  			if strings.HasPrefix(key, operatorFrameworkAnnotation) {
    91  				Logf("deleting crd %s", crd.GetName())
    92  				if err := m.Client.Delete(context.Background(), &crd); err != nil {
    93  					return err
    94  				}
    95  				break
    96  			}
    97  		}
    98  	}
    99  	return nil
   100  }
   101  
   102  func (m *E2EKubeClient) annotateTestResource(obj k8scontrollerclient.Object) {
   103  	annotations := obj.GetAnnotations()
   104  	if annotations == nil {
   105  		annotations = make(map[string]string)
   106  	}
   107  	annotations[E2ETestNameTag] = ginkgo.CurrentSpecReport().FullText()
   108  	obj.SetAnnotations(annotations)
   109  }