sigs.k8s.io/cluster-api-provider-azure@v1.14.3/internal/test/env/env.go (about) 1 /* 2 Copyright 2020 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 env 18 19 import ( 20 "context" 21 "fmt" 22 "go/build" 23 "os" 24 "path" 25 "path/filepath" 26 "regexp" 27 goruntime "runtime" 28 "strings" 29 30 "github.com/go-logr/logr" 31 "github.com/onsi/ginkgo/v2" 32 "k8s.io/apimachinery/pkg/runtime" 33 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 34 clientgoscheme "k8s.io/client-go/kubernetes/scheme" 35 "k8s.io/client-go/rest" 36 "k8s.io/klog/v2" 37 "k8s.io/utils/ptr" 38 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 39 infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1" 40 "sigs.k8s.io/cluster-api-provider-azure/internal/test/record" 41 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 42 expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" 43 "sigs.k8s.io/controller-runtime/pkg/client" 44 "sigs.k8s.io/controller-runtime/pkg/envtest" 45 "sigs.k8s.io/controller-runtime/pkg/manager" 46 "sigs.k8s.io/controller-runtime/pkg/metrics/server" 47 ) 48 49 var ( 50 logger = record.NewLogger(record.WithThreshold(ptr.To(1)), record.WithWriter(ginkgo.GinkgoWriter)) 51 scheme = runtime.NewScheme() 52 env *envtest.Environment 53 clusterAPIVersionRegex = regexp.MustCompile(`^(\W)sigs\.k8s\.io/cluster-api v(.+)`) 54 ) 55 56 func init() { 57 // Calculate the scheme. 58 utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 59 utilruntime.Must(clusterv1.AddToScheme(scheme)) 60 utilruntime.Must(expv1.AddToScheme(scheme)) 61 utilruntime.Must(infrav1.AddToScheme(scheme)) 62 utilruntime.Must(infrav1exp.AddToScheme(scheme)) 63 64 // Get the root of the current file to use in CRD paths. 65 _, filename, _, _ := goruntime.Caller(0) //nolint:dogsled // Ignore "declaration has 3 blank identifiers" check. 66 root := path.Join(path.Dir(filename), "..", "..", "..") 67 68 crdPaths := []string{ 69 filepath.Join(root, "config", "crd", "bases"), 70 } 71 72 if capiPath := getFilePathToCAPICRDs(root); capiPath != "" { 73 crdPaths = append(crdPaths, capiPath) 74 } 75 76 // Create the test environment. 77 env = &envtest.Environment{ 78 ErrorIfCRDPathMissing: true, 79 CRDDirectoryPaths: crdPaths, 80 } 81 } 82 83 type ( 84 // TestEnvironment encapsulates a Kubernetes local test environment. 85 TestEnvironment struct { 86 manager.Manager 87 client.Client 88 Config *rest.Config 89 Log logr.LogSink 90 LogRecorder *record.Logger 91 doneMgr chan struct{} 92 } 93 ) 94 95 // NewTestEnvironment creates a new environment spinning up a local api-server. 96 // 97 // This function should be called only once for each package you're running tests within, 98 // usually the environment is initialized in a suite_test.go file within a `BeforeSuite` ginkgo block. 99 func NewTestEnvironment() *TestEnvironment { 100 if _, err := env.Start(); err != nil { 101 panic(err) 102 } 103 104 mgr, err := manager.New(env.Config, manager.Options{ 105 Scheme: scheme, 106 Metrics: server.Options{ 107 BindAddress: "0", 108 }, 109 }) 110 if err != nil { 111 klog.Fatalf("Failed to start testenv manager: %v", err) 112 } 113 114 return &TestEnvironment{ 115 Manager: mgr, 116 Client: mgr.GetClient(), 117 Config: mgr.GetConfig(), 118 LogRecorder: logger, 119 Log: logger, 120 doneMgr: make(chan struct{}), 121 } 122 } 123 124 // StartManager starts the test environment manager and blocks until the context is canceled. 125 func (t *TestEnvironment) StartManager(ctx context.Context) error { 126 return t.Manager.Start(ctx) 127 } 128 129 // Stop stops the test environment. 130 func (t *TestEnvironment) Stop() error { 131 return env.Stop() 132 } 133 134 func getFilePathToCAPICRDs(root string) string { 135 modBits, err := os.ReadFile(filepath.Join(root, "go.mod")) 136 if err != nil { 137 return "" 138 } 139 140 var clusterAPIVersion string 141 for _, line := range strings.Split(string(modBits), "\n") { 142 matches := clusterAPIVersionRegex.FindStringSubmatch(line) 143 if len(matches) == 3 { 144 clusterAPIVersion = matches[2] 145 } 146 } 147 148 if clusterAPIVersion == "" { 149 return "" 150 } 151 152 gopath := envOr("GOPATH", build.Default.GOPATH) 153 return filepath.Join(gopath, "pkg", "mod", "sigs.k8s.io", fmt.Sprintf("cluster-api@v%s", clusterAPIVersion), "config", "crd", "bases") 154 } 155 156 func envOr(envKey, defaultValue string) string { 157 if value, ok := os.LookupEnv(envKey); ok { 158 return value 159 } 160 return defaultValue 161 }