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 }