sigs.k8s.io/cluster-api@v1.7.1/internal/controllers/machine/suite_test.go (about) 1 /* 2 Copyright 2022 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 machine 18 19 import ( 20 "context" 21 "fmt" 22 "os" 23 "testing" 24 "time" 25 26 . "github.com/onsi/gomega" 27 "github.com/onsi/gomega/types" 28 "github.com/pkg/errors" 29 corev1 "k8s.io/api/core/v1" 30 apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "k8s.io/apimachinery/pkg/runtime" 33 "k8s.io/apimachinery/pkg/runtime/schema" 34 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 35 ctrl "sigs.k8s.io/controller-runtime" 36 "sigs.k8s.io/controller-runtime/pkg/client" 37 "sigs.k8s.io/controller-runtime/pkg/controller" 38 39 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 40 "sigs.k8s.io/cluster-api/api/v1beta1/index" 41 "sigs.k8s.io/cluster-api/controllers/remote" 42 "sigs.k8s.io/cluster-api/internal/test/envtest" 43 ) 44 45 const ( 46 timeout = time.Second * 30 47 ) 48 49 var ( 50 env *envtest.Environment 51 ctx = ctrl.SetupSignalHandler() 52 fakeScheme = runtime.NewScheme() 53 ) 54 55 func init() { 56 _ = clientgoscheme.AddToScheme(fakeScheme) 57 _ = clusterv1.AddToScheme(fakeScheme) 58 _ = apiextensionsv1.AddToScheme(fakeScheme) 59 _ = corev1.AddToScheme(fakeScheme) 60 } 61 62 func TestMain(m *testing.M) { 63 setupIndexes := func(ctx context.Context, mgr ctrl.Manager) { 64 if err := index.AddDefaultIndexes(ctx, mgr); err != nil { 65 panic(fmt.Sprintf("unable to setup index: %v", err)) 66 } 67 } 68 69 setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { 70 // Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers 71 // requiring a connection to a remote cluster 72 tracker, err := remote.NewClusterCacheTracker( 73 mgr, 74 remote.ClusterCacheTrackerOptions{ 75 Log: &ctrl.Log, 76 Indexes: []remote.Index{remote.NodeProviderIDIndex}, 77 }, 78 ) 79 if err != nil { 80 panic(fmt.Sprintf("unable to create cluster cache tracker: %v", err)) 81 } 82 if err := (&remote.ClusterCacheReconciler{ 83 Client: mgr.GetClient(), 84 Tracker: tracker, 85 }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { 86 panic(fmt.Sprintf("Failed to start ClusterCacheReconciler: %v", err)) 87 } 88 89 unstructuredCachingClient, err := client.New(mgr.GetConfig(), client.Options{ 90 HTTPClient: mgr.GetHTTPClient(), 91 Cache: &client.CacheOptions{ 92 Reader: mgr.GetCache(), 93 Unstructured: true, 94 }, 95 }) 96 if err != nil { 97 panic(fmt.Sprintf("unable to create unstructuredCachineClient: %v", err)) 98 } 99 100 if err := (&Reconciler{ 101 Client: mgr.GetClient(), 102 UnstructuredCachingClient: unstructuredCachingClient, 103 APIReader: mgr.GetAPIReader(), 104 Tracker: tracker, 105 }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { 106 panic(fmt.Sprintf("Failed to start MachineReconciler: %v", err)) 107 } 108 } 109 110 SetDefaultEventuallyPollingInterval(100 * time.Millisecond) 111 SetDefaultEventuallyTimeout(timeout) 112 113 os.Exit(envtest.Run(ctx, envtest.RunInput{ 114 M: m, 115 SetupEnv: func(e *envtest.Environment) { env = e }, 116 SetupIndexes: setupIndexes, 117 SetupReconcilers: setupReconcilers, 118 })) 119 } 120 121 func ContainRefOfGroupKind(group, kind string) types.GomegaMatcher { 122 return &refGroupKindMatcher{ 123 kind: kind, 124 group: group, 125 } 126 } 127 128 type refGroupKindMatcher struct { 129 kind string 130 group string 131 } 132 133 func (matcher *refGroupKindMatcher) Match(actual interface{}) (success bool, err error) { 134 ownerRefs, ok := actual.([]metav1.OwnerReference) 135 if !ok { 136 return false, errors.Errorf("expected []metav1.OwnerReference; got %T", actual) 137 } 138 139 for _, ref := range ownerRefs { 140 gv, err := schema.ParseGroupVersion(ref.APIVersion) 141 if err != nil { 142 return false, nil //nolint:nilerr // If we can't get the group version we can't match, but it's not a failure 143 } 144 if ref.Kind == matcher.kind && gv.Group == clusterv1.GroupVersion.Group { 145 return true, nil 146 } 147 } 148 149 return false, nil 150 } 151 152 func (matcher *refGroupKindMatcher) FailureMessage(actual interface{}) (message string) { 153 return fmt.Sprintf("Expected %+v to contain refs of Group %s and Kind %s", actual, matcher.group, matcher.kind) 154 } 155 156 func (matcher *refGroupKindMatcher) NegatedFailureMessage(actual interface{}) (message string) { 157 return fmt.Sprintf("Expected %+v not to contain refs of Group %s and Kind %s", actual, matcher.group, matcher.kind) 158 }