github.com/ironcore-dev/gardener-extension-provider-ironcore@v0.3.2-0.20240314231816-8336447fb9a0/pkg/controller/controlplane/suite_test.go (about)

     1  // SPDX-FileCopyrightText: 2022 SAP SE or an SAP affiliate company and IronCore contributors
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package controlplane
     5  
     6  import (
     7  	"context"
     8  	"encoding/json"
     9  	"path/filepath"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/gardener/gardener/pkg/apis/core/v1beta1"
    14  	extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1"
    15  	"github.com/ironcore-dev/controller-utils/buildutils"
    16  	"github.com/ironcore-dev/controller-utils/modutils"
    17  	storagev1alpha1 "github.com/ironcore-dev/ironcore/api/storage/v1alpha1"
    18  	utilsenvtest "github.com/ironcore-dev/ironcore/utils/envtest"
    19  	"github.com/ironcore-dev/ironcore/utils/envtest/apiserver"
    20  	. "github.com/onsi/ginkgo/v2"
    21  	. "github.com/onsi/gomega"
    22  	corev1 "k8s.io/api/core/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apimachinery/pkg/runtime"
    25  	"k8s.io/apimachinery/pkg/runtime/serializer"
    26  	"k8s.io/client-go/kubernetes/scheme"
    27  	"k8s.io/client-go/rest"
    28  	"k8s.io/utils/ptr"
    29  	"sigs.k8s.io/controller-runtime/pkg/client"
    30  	"sigs.k8s.io/controller-runtime/pkg/envtest"
    31  	"sigs.k8s.io/controller-runtime/pkg/envtest/komega"
    32  	logf "sigs.k8s.io/controller-runtime/pkg/log"
    33  	"sigs.k8s.io/controller-runtime/pkg/log/zap"
    34  	"sigs.k8s.io/controller-runtime/pkg/manager"
    35  	metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
    36  	"sigs.k8s.io/controller-runtime/pkg/webhook"
    37  
    38  	ironcoreextensionv1alpha1 "github.com/ironcore-dev/gardener-extension-provider-ironcore/pkg/apis/ironcore/v1alpha1"
    39  )
    40  
    41  const (
    42  	pollingInterval      = 50 * time.Millisecond
    43  	eventuallyTimeout    = 10 * time.Second
    44  	consistentlyDuration = 1 * time.Second
    45  	apiServiceTimeout    = 5 * time.Minute
    46  )
    47  
    48  var (
    49  	testEnv    *envtest.Environment
    50  	testEnvExt *utilsenvtest.EnvironmentExtensions
    51  	cfg        *rest.Config
    52  	k8sClient  client.Client
    53  )
    54  
    55  func TestAPIs(t *testing.T) {
    56  	SetDefaultConsistentlyPollingInterval(pollingInterval)
    57  	SetDefaultEventuallyPollingInterval(pollingInterval)
    58  	SetDefaultEventuallyTimeout(eventuallyTimeout)
    59  	SetDefaultConsistentlyDuration(consistentlyDuration)
    60  
    61  	RegisterFailHandler(Fail)
    62  	RunSpecs(t, "Infrastructure Controller Suite")
    63  }
    64  
    65  var _ = BeforeSuite(func() {
    66  	logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))
    67  
    68  	var err error
    69  
    70  	By("bootstrapping test environment")
    71  	testEnv = &envtest.Environment{
    72  		CRDDirectoryPaths: []string{
    73  			filepath.Join("..", "..", "..", "example", "20-crd-resources.gardener.cloud_managedresources.yaml"),
    74  			filepath.Join("..", "..", "..", "example", "20-crd-extensions.gardener.cloud_clusters.yaml"),
    75  			filepath.Join("..", "..", "..", "example", "20-crd-extensions.gardener.cloud_infrastructures.yaml"),
    76  			filepath.Join("..", "..", "..", "example", "20-crd-extensions.gardener.cloud_controlplanes.yaml"),
    77  		},
    78  		ErrorIfCRDPathMissing: true,
    79  	}
    80  
    81  	testEnvExt = &utilsenvtest.EnvironmentExtensions{
    82  		APIServiceDirectoryPaths: []string{
    83  			modutils.Dir("github.com/ironcore-dev/ironcore", "config", "apiserver", "apiservice", "bases"),
    84  		},
    85  		ErrorIfAPIServicePathIsMissing: true,
    86  	}
    87  
    88  	cfg, err = utilsenvtest.StartWithExtensions(testEnv, testEnvExt)
    89  	Expect(err).NotTo(HaveOccurred())
    90  	Expect(cfg).NotTo(BeNil())
    91  	DeferCleanup(utilsenvtest.StopWithExtensions, testEnv, testEnvExt)
    92  
    93  	Expect(extensionsv1alpha1.AddToScheme(scheme.Scheme)).To(Succeed())
    94  	Expect(ironcoreextensionv1alpha1.AddToScheme(scheme.Scheme)).To(Succeed())
    95  	Expect(corev1.AddToScheme(scheme.Scheme)).To(Succeed())
    96  	Expect(storagev1alpha1.AddToScheme(scheme.Scheme)).To(Succeed())
    97  
    98  	// Init package-level k8sClient
    99  	k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
   100  	Expect(err).NotTo(HaveOccurred())
   101  	Expect(k8sClient).NotTo(BeNil())
   102  
   103  	komega.SetClient(k8sClient)
   104  
   105  	apiSrv, err := apiserver.New(cfg, apiserver.Options{
   106  		MainPath:     "github.com/ironcore-dev/ironcore/cmd/ironcore-apiserver",
   107  		BuildOptions: []buildutils.BuildOption{buildutils.ModModeMod},
   108  		ETCDServers:  []string{testEnv.ControlPlane.Etcd.URL.String()},
   109  		Host:         testEnvExt.APIServiceInstallOptions.LocalServingHost,
   110  		Port:         testEnvExt.APIServiceInstallOptions.LocalServingPort,
   111  		CertDir:      testEnvExt.APIServiceInstallOptions.LocalServingCertDir,
   112  	})
   113  	Expect(err).NotTo(HaveOccurred())
   114  
   115  	Expect(apiSrv.Start()).To(Succeed())
   116  	DeferCleanup(apiSrv.Stop)
   117  
   118  	err = utilsenvtest.WaitUntilAPIServicesReadyWithTimeout(apiServiceTimeout, testEnvExt, k8sClient, scheme.Scheme)
   119  	Expect(err).NotTo(HaveOccurred())
   120  })
   121  
   122  func SetupTest() (*corev1.Namespace, *valuesProvider, *extensionsv1alpha1.Cluster) {
   123  	var (
   124  		namespace = &corev1.Namespace{}
   125  		cluster   = &extensionsv1alpha1.Cluster{}
   126  		vp        = &valuesProvider{}
   127  	)
   128  
   129  	BeforeEach(func(ctx SpecContext) {
   130  		var mgrCtx context.Context
   131  		mgrCtx, cancel := context.WithCancel(context.Background())
   132  		DeferCleanup(cancel)
   133  
   134  		*namespace = corev1.Namespace{
   135  			ObjectMeta: metav1.ObjectMeta{
   136  				GenerateName: "testns-",
   137  			},
   138  		}
   139  		Expect(k8sClient.Create(ctx, namespace)).To(Succeed(), "failed to create test namespace")
   140  		DeferCleanup(k8sClient.Delete, namespace)
   141  
   142  		shoot := v1beta1.Shoot{
   143  			ObjectMeta: metav1.ObjectMeta{
   144  				Namespace: namespace.Name,
   145  				Name:      "foo",
   146  			},
   147  			Spec: v1beta1.ShootSpec{
   148  				Kubernetes: v1beta1.Kubernetes{
   149  					Version: "1.26.0",
   150  				},
   151  				Region: "foo",
   152  				Provider: v1beta1.Provider{
   153  					Workers: []v1beta1.Worker{
   154  						{Name: "foo"},
   155  						{Name: "bar"},
   156  					},
   157  				},
   158  				Networking: &v1beta1.Networking{
   159  					Nodes: ptr.To[string]("10.0.0.0/24"),
   160  				},
   161  			},
   162  		}
   163  		shootJson, err := json.Marshal(shoot)
   164  		Expect(err).NotTo(HaveOccurred())
   165  
   166  		*cluster = extensionsv1alpha1.Cluster{
   167  			ObjectMeta: metav1.ObjectMeta{
   168  				Name: namespace.Name,
   169  			},
   170  			Spec: extensionsv1alpha1.ClusterSpec{
   171  				CloudProfile: runtime.RawExtension{Raw: []byte("{}")},
   172  				Seed:         runtime.RawExtension{Raw: []byte("{}")},
   173  				Shoot:        runtime.RawExtension{Raw: shootJson},
   174  			},
   175  		}
   176  		Expect(k8sClient.Create(ctx, cluster)).Should(Succeed())
   177  		DeferCleanup(k8sClient.Delete, cluster)
   178  
   179  		mgr, err := manager.New(cfg, manager.Options{
   180  			Scheme:  scheme.Scheme,
   181  			Metrics: metricsserver.Options{BindAddress: "0"},
   182  			WebhookServer: &webhook.DefaultServer{Options: webhook.Options{
   183  				CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir,
   184  			}},
   185  		})
   186  		Expect(err).NotTo(HaveOccurred())
   187  
   188  		secret := &corev1.Secret{
   189  			ObjectMeta: metav1.ObjectMeta{
   190  				Namespace: namespace.Name,
   191  				Name:      "my-infra-creds",
   192  			},
   193  			Data: map[string][]byte{
   194  				"namespace": []byte(namespace.Name),
   195  				"token":     []byte("foo"),
   196  			},
   197  		}
   198  		Expect(k8sClient.Create(ctx, secret)).To(Succeed())
   199  
   200  		user, err := testEnv.AddUser(envtest.User{
   201  			Name:   "dummy",
   202  			Groups: []string{"system:authenticated", "system:masters"},
   203  		}, cfg)
   204  		Expect(err).NotTo(HaveOccurred())
   205  
   206  		kubeconfig, err := user.KubeConfig()
   207  		Expect(err).NotTo(HaveOccurred())
   208  
   209  		By("creating a test cloudprovider secret")
   210  		cloudproviderSecret := &corev1.Secret{
   211  			ObjectMeta: metav1.ObjectMeta{
   212  				Namespace: namespace.Name,
   213  				Name:      "cloudprovider",
   214  			},
   215  			Data: map[string][]byte{
   216  				"namespace":  []byte(namespace.Name),
   217  				"token":      []byte("foo"),
   218  				"kubeconfig": kubeconfig,
   219  			},
   220  		}
   221  		Expect(k8sClient.Create(ctx, cloudproviderSecret)).To(Succeed())
   222  		DeferCleanup(k8sClient.Delete, cloudproviderSecret)
   223  
   224  		Expect(AddToManagerWithOptions(mgrCtx, mgr, AddOptions{
   225  			IgnoreOperationAnnotation: true,
   226  		})).NotTo(HaveOccurred())
   227  
   228  		*vp = valuesProvider{
   229  			client:  mgr.GetClient(),
   230  			decoder: serializer.NewCodecFactory(mgr.GetScheme(), serializer.EnableStrict).UniversalDecoder(),
   231  		}
   232  
   233  		go func() {
   234  			defer GinkgoRecover()
   235  			Expect(mgr.Start(mgrCtx)).To(Succeed(), "failed to start manager")
   236  		}()
   237  	})
   238  
   239  	return namespace, vp, cluster
   240  }