diff --git a/api/v1alpha3/suite_test.go b/api/v1alpha3/suite_test.go index 7563e9e53695..56e6a5f10b5f 100644 --- a/api/v1alpha3/suite_test.go +++ b/api/v1alpha3/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha3 import ( - "fmt" "os" "testing" @@ -34,24 +33,10 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment utilruntime.Must(AddToScheme(scheme.Scheme)) - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/bootstrap/kubeadm/api/v1alpha3/suite_test.go b/bootstrap/kubeadm/api/v1alpha3/suite_test.go index 7563e9e53695..56e6a5f10b5f 100644 --- a/bootstrap/kubeadm/api/v1alpha3/suite_test.go +++ b/bootstrap/kubeadm/api/v1alpha3/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha3 import ( - "fmt" "os" "testing" @@ -34,24 +33,10 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment utilruntime.Must(AddToScheme(scheme.Scheme)) - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/bootstrap/kubeadm/controllers/suite_test.go b/bootstrap/kubeadm/controllers/suite_test.go index 72ccbe0995eb..ce90813153d0 100644 --- a/bootstrap/kubeadm/controllers/suite_test.go +++ b/bootstrap/kubeadm/controllers/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package controllers import ( - "fmt" "os" "testing" @@ -32,24 +31,8 @@ var ( ) func TestMain(m *testing.M) { - fmt.Println("Creating new test environment") - env = envtest.New() - - go func() { - fmt.Println("Starting the manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - - fmt.Println("Tearing down test suite") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop envtest: %v", err)) - } - - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/bootstrap/util/suite_test.go b/bootstrap/util/suite_test.go index b156de2d865f..1b611e6b49be 100644 --- a/bootstrap/util/suite_test.go +++ b/bootstrap/util/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package util import ( - "fmt" "os" "testing" @@ -32,23 +31,8 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/controllers/remote/suite_test.go b/controllers/remote/suite_test.go index b4ad7a33d695..8aaa94f71e84 100644 --- a/controllers/remote/suite_test.go +++ b/controllers/remote/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package remote import ( - "fmt" "os" "testing" "time" @@ -37,24 +36,8 @@ var ( ) func TestMain(m *testing.M) { - fmt.Println("Creating a new test environment") - env = envtest.New() - - go func() { - fmt.Println("Starting the test environment manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the test environment manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - - fmt.Println("Stopping the test environment") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the test environment: %v", err)) - } - - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/controllers/suite_test.go b/controllers/suite_test.go index a38871f41170..d5db30f5c335 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -17,6 +17,7 @@ limitations under the License. package controllers import ( + "context" "fmt" "os" "testing" @@ -30,14 +31,12 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" clientgoscheme "k8s.io/client-go/kubernetes/scheme" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/controller" - "sigs.k8s.io/controller-runtime/pkg/log" - clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4" "sigs.k8s.io/cluster-api/api/v1alpha4/index" "sigs.k8s.io/cluster-api/controllers/remote" "sigs.k8s.io/cluster-api/internal/envtest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller" // +kubebuilder:scaffold:imports ) @@ -59,86 +58,76 @@ func init() { } func TestMain(m *testing.M) { - fmt.Println("Creating a new test environment") - env = envtest.New() - - if err := index.AddDefaultIndexes(ctx, env.Manager); err != nil { - panic(fmt.Sprintf("unable to setup index: %v", err)) - } - - // Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers - // requiring a connection to a remote cluster - tracker, err := remote.NewClusterCacheTracker( - env.Manager, - remote.ClusterCacheTrackerOptions{ - Log: log.Log, - Indexes: remote.DefaultIndexes, - }, - ) - if err != nil { - panic(fmt.Sprintf("unable to create cluster cache tracker: %v", err)) - } - if err := (&remote.ClusterCacheReconciler{ - Client: env, - Log: log.Log, - Tracker: tracker, - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start ClusterCacheReconciler: %v", err)) - } - if err := (&ClusterReconciler{ - Client: env, - recorder: env.GetEventRecorderFor("cluster-controller"), - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start ClusterReconciler: %v", err)) - } - if err := (&MachineReconciler{ - Client: env, - Tracker: tracker, - recorder: env.GetEventRecorderFor("machine-controller"), - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start MachineReconciler: %v", err)) - } - if err := (&MachineSetReconciler{ - Client: env, - Tracker: tracker, - recorder: env.GetEventRecorderFor("machineset-controller"), - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start MMachineSetReconciler: %v", err)) - } - if err := (&MachineDeploymentReconciler{ - Client: env, - recorder: env.GetEventRecorderFor("machinedeployment-controller"), - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start MMachineDeploymentReconciler: %v", err)) - } - if err := (&MachineHealthCheckReconciler{ - Client: env, - Tracker: tracker, - recorder: env.GetEventRecorderFor("machinehealthcheck-controller"), - }).SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to start MachineHealthCheckReconciler : %v", err)) + setupIndexes := func(ctx context.Context, mgr ctrl.Manager) { + if err := index.AddDefaultIndexes(ctx, mgr); err != nil { + panic(fmt.Sprintf("unable to setup index: %v", err)) + } } - go func() { - fmt.Println("Starting the test environment manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the test environment manager: %v", err)) + setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { + // Set up a ClusterCacheTracker and ClusterCacheReconciler to provide to controllers + // requiring a connection to a remote cluster + tracker, err := remote.NewClusterCacheTracker( + mgr, + remote.ClusterCacheTrackerOptions{ + Log: ctrl.Log.WithName("remote").WithName("ClusterCacheTracker"), + Indexes: remote.DefaultIndexes, + }, + ) + if err != nil { + panic(fmt.Sprintf("unable to create cluster cache tracker: %v", err)) + } + if err := (&remote.ClusterCacheReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("remote").WithName("ClusterCacheReconciler"), + Tracker: tracker, + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start ClusterCacheReconciler: %v", err)) + } + if err := (&ClusterReconciler{ + Client: mgr.GetClient(), + recorder: mgr.GetEventRecorderFor("cluster-controller"), + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start ClusterReconciler: %v", err)) + } + if err := (&MachineReconciler{ + Client: mgr.GetClient(), + Tracker: tracker, + recorder: mgr.GetEventRecorderFor("machine-controller"), + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start MachineReconciler: %v", err)) + } + if err := (&MachineSetReconciler{ + Client: mgr.GetClient(), + Tracker: tracker, + recorder: mgr.GetEventRecorderFor("machineset-controller"), + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start MMachineSetReconciler: %v", err)) } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() + if err := (&MachineDeploymentReconciler{ + Client: mgr.GetClient(), + recorder: mgr.GetEventRecorderFor("machinedeployment-controller"), + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start MMachineDeploymentReconciler: %v", err)) + } + if err := (&MachineHealthCheckReconciler{ + Client: mgr.GetClient(), + Tracker: tracker, + recorder: mgr.GetEventRecorderFor("machinehealthcheck-controller"), + }).SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to start MachineHealthCheckReconciler : %v", err)) + } + } SetDefaultEventuallyPollingInterval(100 * time.Millisecond) SetDefaultEventuallyTimeout(timeout) - code := m.Run() - - fmt.Println("Stopping the test environment") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the test environment: %v", err)) - } - - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + SetupIndexes: setupIndexes, + SetupReconcilers: setupReconcilers, + })) } func ContainRefOfGroupKind(group, kind string) types.GomegaMatcher { diff --git a/controlplane/kubeadm/api/v1alpha3/suite_test.go b/controlplane/kubeadm/api/v1alpha3/suite_test.go index 7563e9e53695..56e6a5f10b5f 100644 --- a/controlplane/kubeadm/api/v1alpha3/suite_test.go +++ b/controlplane/kubeadm/api/v1alpha3/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha3 import ( - "fmt" "os" "testing" @@ -34,24 +33,10 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment utilruntime.Must(AddToScheme(scheme.Scheme)) - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/controlplane/kubeadm/controllers/suite_test.go b/controlplane/kubeadm/controllers/suite_test.go index 4ea78289ddd6..ce90813153d0 100644 --- a/controlplane/kubeadm/controllers/suite_test.go +++ b/controlplane/kubeadm/controllers/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package controllers import ( - "fmt" "os" "testing" @@ -32,23 +31,8 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/controlplane/kubeadm/internal/suite_test.go b/controlplane/kubeadm/internal/suite_test.go index 2094df0f5f50..5e0d5fa52f86 100644 --- a/controlplane/kubeadm/internal/suite_test.go +++ b/controlplane/kubeadm/internal/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package internal import ( - "fmt" "os" "testing" @@ -31,20 +30,8 @@ var ( ) func TestMain(m *testing.M) { - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop envtest: %v", err)) - } - - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/exp/addons/api/v1alpha3/suite_test.go b/exp/addons/api/v1alpha3/suite_test.go index 7563e9e53695..56e6a5f10b5f 100644 --- a/exp/addons/api/v1alpha3/suite_test.go +++ b/exp/addons/api/v1alpha3/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha3 import ( - "fmt" "os" "testing" @@ -34,24 +33,10 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment utilruntime.Must(AddToScheme(scheme.Scheme)) - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/exp/addons/controllers/suite_test.go b/exp/addons/controllers/suite_test.go index 3a28895b0c6b..6d658385e5db 100644 --- a/exp/addons/controllers/suite_test.go +++ b/exp/addons/controllers/suite_test.go @@ -17,6 +17,7 @@ limitations under the License. package controllers import ( + "context" "fmt" "os" "testing" @@ -38,46 +39,42 @@ var ( ) func TestMain(m *testing.M) { - fmt.Println("Creating new test environment") - env = envtest.New([]client.Object{&corev1.ConfigMap{}, &corev1.Secret{}, &v1alpha4.ClusterResourceSetBinding{}}...) - - if err := index.AddDefaultIndexes(ctx, env.Manager); err != nil { - panic(fmt.Sprintf("unable to setup index: %v", err)) - } - - trckr, err := remote.NewClusterCacheTracker(env.Manager, remote.ClusterCacheTrackerOptions{}) - if err != nil { - panic(fmt.Sprintf("Failed to create new cluster cache tracker: %v", err)) - } - reconciler := ClusterResourceSetReconciler{ - Client: env, - Tracker: trckr, - } - if err = reconciler.SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to set up cluster resource set reconciler: %v", err)) - } - bindingReconciler := ClusterResourceSetBindingReconciler{ - Client: env, - } - if err = bindingReconciler.SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}); err != nil { - panic(fmt.Sprintf("Failed to set up cluster resource set binding reconciler: %v", err)) + setupIndexes := func(ctx context.Context, mgr ctrl.Manager) { + if err := index.AddDefaultIndexes(ctx, mgr); err != nil { + panic(fmt.Sprintf("unable to setup index: %v", err)) + } } - go func() { - fmt.Println("Starting the manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) + setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { + tracker, err := remote.NewClusterCacheTracker(mgr, remote.ClusterCacheTrackerOptions{}) + if err != nil { + panic(fmt.Sprintf("Failed to create new cluster cache tracker: %v", err)) } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - fmt.Println("Tearing down test suite") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop envtest: %v", err)) + reconciler := ClusterResourceSetReconciler{ + Client: mgr.GetClient(), + Tracker: tracker, + } + if err = reconciler.SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to set up cluster resource set reconciler: %v", err)) + } + bindingReconciler := ClusterResourceSetBindingReconciler{ + Client: mgr.GetClient(), + } + if err = bindingReconciler.SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}); err != nil { + panic(fmt.Sprintf("Failed to set up cluster resource set binding reconciler: %v", err)) + } } - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + ManagerUncachedObjs: []client.Object{ + &corev1.ConfigMap{}, + &corev1.Secret{}, + &v1alpha4.ClusterResourceSetBinding{}, + }, + SetupIndexes: setupIndexes, + SetupReconcilers: setupReconcilers, + })) } diff --git a/exp/api/v1alpha3/suite_test.go b/exp/api/v1alpha3/suite_test.go index 7563e9e53695..56e6a5f10b5f 100644 --- a/exp/api/v1alpha3/suite_test.go +++ b/exp/api/v1alpha3/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha3 import ( - "fmt" "os" "testing" @@ -34,24 +33,10 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment utilruntime.Must(AddToScheme(scheme.Scheme)) - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/exp/controllers/suite_test.go b/exp/controllers/suite_test.go index d15d63b1653b..e5022b55612a 100644 --- a/exp/controllers/suite_test.go +++ b/exp/controllers/suite_test.go @@ -17,6 +17,7 @@ limitations under the License. package controllers import ( + "context" "fmt" "os" "testing" @@ -34,37 +35,27 @@ var ( ) func TestMain(m *testing.M) { - fmt.Println("Creating new test environment") - env = envtest.New() - - if err := index.AddDefaultIndexes(ctx, env.Manager); err != nil { - panic(fmt.Sprintf("unable to setup index: %v", err)) - } - - machinePoolReconciler := MachinePoolReconciler{ - Client: env, - recorder: env.GetEventRecorderFor("machinepool-controller"), - } - err := machinePoolReconciler.SetupWithManager(ctx, env.Manager, controller.Options{MaxConcurrentReconciles: 1}) - if err != nil { - panic(fmt.Sprintf("Failed to set up machine pool reconciler: %v", err)) + setupIndexes := func(ctx context.Context, mgr ctrl.Manager) { + if err := index.AddDefaultIndexes(ctx, mgr); err != nil { + panic(fmt.Sprintf("unable to setup index: %v", err)) + } } - go func() { - fmt.Println("Starting the manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) + setupReconcilers := func(ctx context.Context, mgr ctrl.Manager) { + machinePoolReconciler := MachinePoolReconciler{ + Client: mgr.GetClient(), + recorder: mgr.GetEventRecorderFor("machinepool-controller"), + } + err := machinePoolReconciler.SetupWithManager(ctx, mgr, controller.Options{MaxConcurrentReconciles: 1}) + if err != nil { + panic(fmt.Sprintf("Failed to set up machine pool reconciler: %v", err)) } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - - fmt.Println("Tearing down test suite") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop envtest: %v", err)) } - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + SetupIndexes: setupIndexes, + SetupReconcilers: setupReconcilers, + })) } diff --git a/internal/envtest/environment.go b/internal/envtest/environment.go index 8e89b868b8f0..24d7d1524d68 100644 --- a/internal/envtest/environment.go +++ b/internal/envtest/environment.go @@ -20,11 +20,12 @@ import ( "context" "fmt" "net" + "os" "path" "path/filepath" goruntime "runtime" "strconv" - "sync" + "testing" "time" "github.com/onsi/ginkgo" @@ -75,6 +76,52 @@ func init() { utilruntime.Must(admissionv1.AddToScheme(scheme.Scheme)) } +// RunInput is the input for Run. +type RunInput struct { + M *testing.M + ManagerUncachedObjs []client.Object + SetupIndexes func(ctx context.Context, mgr ctrl.Manager) + SetupReconcilers func(ctx context.Context, mgr ctrl.Manager) + SetupEnv func(e *Environment) +} + +// Run executes the tests of the given testing.M in a test environment. +// Note: The environment will be created in this func and should not be created before. This func takes a *Environment +// because our tests require access to the *Environment. We use this field to make the created Environment available +// to the consumer. +// Note: Test environment creation can be skipped by setting the environment variable `CAPI_DISABLE_TEST_ENV`. This only +// makes sense when executing tests which don't require the test environment, e.g. tests using only the fake client. +func Run(ctx context.Context, input RunInput) int { + if os.Getenv("CAPI_DISABLE_TEST_ENV") != "" { + return input.M.Run() + } + + // Bootstrapping test environment + env := new(input.ManagerUncachedObjs...) + + if input.SetupIndexes != nil { + input.SetupIndexes(ctx, env.Manager) + } + if input.SetupReconcilers != nil { + input.SetupReconcilers(ctx, env.Manager) + } + + // Start the environment. + env.start(ctx) + + // Expose the environment. + input.SetupEnv(env) + + // Run tests + code := input.M.Run() + + // Tearing down the test environment + if err := env.stop(); err != nil { + panic(fmt.Sprintf("Failed to stop the test environment: %v", err)) + } + return code +} + var ( cacheSyncBackoff = wait.Backoff{ Duration: 100 * time.Millisecond, @@ -82,9 +129,6 @@ var ( Steps: 8, Jitter: 0.4, } - - errAlreadyStarted = errors.New("environment has already been started") - errAlreadyStopped = errors.New("environment has already been stopped") ) // Environment encapsulates a Kubernetes local test environment. @@ -94,16 +138,14 @@ type Environment struct { Config *rest.Config env *envtest.Environment - startOnce sync.Once - stopOnce sync.Once cancelManager context.CancelFunc } -// New creates a new environment spinning up a local api-server. +// new creates a new environment spinning up a local api-server. // // This function should be called only once for each package you're running tests within, // usually the environment is initialized in a suite_test.go file within a `BeforeSuite` ginkgo block. -func New(uncachedObjs ...client.Object) *Environment { +func new(uncachedObjs ...client.Object) *Environment { // Get the root of the current file to use in CRD paths. _, filename, _, _ := goruntime.Caller(0) //nolint root := path.Join(path.Dir(filename), "..", "..") @@ -205,25 +247,26 @@ func New(uncachedObjs ...client.Object) *Environment { } } -// Start starts the manager. -func (e *Environment) Start(ctx context.Context) error { - err := errAlreadyStarted - e.startOnce.Do(func() { - ctx, cancel := context.WithCancel(ctx) - e.cancelManager = cancel - err = e.Manager.Start(ctx) - }) - return err +// start starts the manager. +func (e *Environment) start(ctx context.Context) { + ctx, cancel := context.WithCancel(ctx) + e.cancelManager = cancel + + go func() { + fmt.Println("Starting the test environment manager") + if err := e.Manager.Start(ctx); err != nil { + panic(fmt.Sprintf("Failed to start the test environment manager: %v", err)) + } + }() + e.Manager.Elected() + e.WaitForWebhooks() } -// Stop stops the test environment. -func (e *Environment) Stop() error { - err := errAlreadyStopped - e.stopOnce.Do(func() { - e.cancelManager() - err = e.env.Stop() - }) - return err +// stop stops the test environment. +func (e *Environment) stop() error { + fmt.Println("Stopping the test environment") + e.cancelManager() + return e.env.Stop() } // WaitForWebhooks waits for the webhook server to be available. diff --git a/util/collections/suite_test.go b/util/collections/suite_test.go index a24e5da13f3e..1f7bc76e9ebb 100644 --- a/util/collections/suite_test.go +++ b/util/collections/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package collections_test import ( - "fmt" "os" "testing" @@ -31,23 +30,8 @@ var ( ) func TestMain(m *testing.M) { - // Bootstrapping test environment - env = envtest.New() - go func() { - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - // Run tests - code := m.Run() - // Tearing down the test environment - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop the envtest: %v", err)) - } - - // Report exit code - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) } diff --git a/util/patch/suite_test.go b/util/patch/suite_test.go index 516930e5613b..b3f6265dffb4 100644 --- a/util/patch/suite_test.go +++ b/util/patch/suite_test.go @@ -17,7 +17,6 @@ limitations under the License. package patch import ( - "fmt" "os" "testing" "time" @@ -37,24 +36,8 @@ var ( ) func TestMain(m *testing.M) { - fmt.Println("Creating new test environment") - env = envtest.New() - - go func() { - fmt.Println("Starting the manager") - if err := env.Start(ctx); err != nil { - panic(fmt.Sprintf("Failed to start the envtest manager: %v", err)) - } - }() - <-env.Manager.Elected() - env.WaitForWebhooks() - - code := m.Run() - - fmt.Println("Tearing down test suite") - if err := env.Stop(); err != nil { - panic(fmt.Sprintf("Failed to stop envtest: %v", err)) - } - - os.Exit(code) + os.Exit(envtest.Run(ctx, envtest.RunInput{ + M: m, + SetupEnv: func(e *envtest.Environment) { env = e }, + })) }