diff --git a/docs/development/testing.md b/docs/development/testing.md index 116dd12cabf..b06460c7da7 100644 --- a/docs/development/testing.md +++ b/docs/development/testing.md @@ -261,7 +261,7 @@ k get managedresource -A -w Run a `gardenerenvtest` suite (using `gardener-apiserver`) against an existing test environment: ```bash -# modify test/start-envtest to disable admission plugins and enable feature gates like in test suite... +# modify GardenerTestEnvironment{} in test/start-envtest to disable admission plugins and enable feature gates like in test suite... make start-envtest ENVTEST_TYPE=gardener diff --git a/example/provider-local/seed-kind-ha-multi-zone/local/kustomization.yaml b/example/provider-local/seed-kind-ha-multi-zone/local/kustomization.yaml deleted file mode 100644 index ce94bf1800f..00000000000 --- a/example/provider-local/seed-kind-ha-multi-zone/local/kustomization.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../base -- seed.yaml diff --git a/example/provider-local/seed-kind-ha-multi-zone/local/seed.yaml b/example/provider-local/seed-kind-ha-multi-zone/local/seed.yaml deleted file mode 100644 index 22e0e7d0b99..00000000000 --- a/example/provider-local/seed-kind-ha-multi-zone/local/seed.yaml +++ /dev/null @@ -1,47 +0,0 @@ -apiVersion: core.gardener.cloud/v1beta1 -kind: Seed -metadata: - name: local-ha-multi-zone -spec: - backup: - provider: local - region: local - secretRef: - name: backup-local - namespace: garden - provider: - type: local - region: local - zones: - - "0" - - "1" - - "2" - dns: - provider: - type: local - secretRef: - name: internal-domain-local - namespace: garden - ingress: - domain: ingress.local-ha-multi-zone.seed.local.gardener.cloud - controller: - kind: nginx - secretRef: - name: seed-local-ha-multi-zone - namespace: garden - networks: - nodes: 172.18.0.0/16 - pods: 10.1.0.0/16 - services: 10.2.0.0/16 - shootDefaults: - pods: 10.3.0.0/16 - services: 10.4.0.0/16 - settings: - excessCapacityReservation: - enabled: false - scheduling: - visible: true - verticalPodAutoscaler: - enabled: true - topologyAwareRouting: - enabled: true diff --git a/pkg/api/indexer/gardener_core.go b/pkg/api/indexer/gardener_core.go index 5cce743ccd0..85b78ca433a 100644 --- a/pkg/api/indexer/gardener_core.go +++ b/pkg/api/indexer/gardener_core.go @@ -61,6 +61,15 @@ func ControllerInstallationSeedRefNameIndexerFunc(obj client.Object) []string { return []string{controllerInstallation.Spec.SeedRef.Name} } +// ControllerInstallationRegistrationRefNameIndexerFunc extracts the .spec.registrationRef.name field of a ControllerInstallation. +func ControllerInstallationRegistrationRefNameIndexerFunc(obj client.Object) []string { + controllerInstallation, ok := obj.(*gardencorev1beta1.ControllerInstallation) + if !ok { + return []string{""} + } + return []string{controllerInstallation.Spec.RegistrationRef.Name} +} + // InternalSecretTypeIndexerFunc extracts the .type field of an InternalSecret. func InternalSecretTypeIndexerFunc(obj client.Object) []string { internalSecret, ok := obj.(*gardencorev1beta1.InternalSecret) @@ -146,13 +155,7 @@ func AddControllerInstallationSeedRefName(ctx context.Context, indexer client.Fi // AddControllerInstallationRegistrationRefName adds an index for core.ControllerInstallationRegistrationRefName to the given indexer. func AddControllerInstallationRegistrationRefName(ctx context.Context, indexer client.FieldIndexer) error { - if err := indexer.IndexField(ctx, &gardencorev1beta1.ControllerInstallation{}, core.RegistrationRefName, func(obj client.Object) []string { - controllerInstallation, ok := obj.(*gardencorev1beta1.ControllerInstallation) - if !ok { - return []string{""} - } - return []string{controllerInstallation.Spec.RegistrationRef.Name} - }); err != nil { + if err := indexer.IndexField(ctx, &gardencorev1beta1.ControllerInstallation{}, core.RegistrationRefName, ControllerInstallationRegistrationRefNameIndexerFunc); err != nil { return fmt.Errorf("failed to add indexer for %s to ControllerInstallation Informer: %w", core.RegistrationRefName, err) } return nil diff --git a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go index f7258e5e734..1e5f25ff9b5 100644 --- a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go +++ b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler.go @@ -24,6 +24,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" + gardencore "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/gardener/gardener/pkg/controllerutils" ) @@ -61,21 +62,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( } controllerInstallationList := &gardencorev1beta1.ControllerInstallationList{} - if err := r.Client.List(ctx, controllerInstallationList); err != nil { + if err := r.Client.List(ctx, controllerInstallationList, client.MatchingFields{gardencore.RegistrationRefName: controllerRegistration.Name}); err != nil { return reconcile.Result{}, err } - for _, controllerInstallation := range controllerInstallationList.Items { - if controllerInstallation.Spec.RegistrationRef.Name == controllerRegistration.Name { - return reconcile.Result{}, fmt.Errorf("cannot remove finalizer of ControllerRegistration %q because still found at least one ControllerInstallation", controllerRegistration.Name) - } + if len(controllerInstallationList.Items) > 0 { + return reconcile.Result{}, fmt.Errorf("cannot remove finalizer of ControllerRegistration %q because still found ControllerInstallations: %s", controllerRegistration.Name, controllerutils.GetControllerInstallationNames(controllerInstallationList.Items)) } - if controllerutil.ContainsFinalizer(controllerRegistration, FinalizerName) { - log.Info("Removing finalizer") - if err := controllerutils.RemoveFinalizers(ctx, r.Client, controllerRegistration, FinalizerName); err != nil { - return reconcile.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) - } + log.Info("Removing finalizer") + if err := controllerutils.RemoveFinalizers(ctx, r.Client, controllerRegistration, FinalizerName); err != nil { + return reconcile.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) } return reconcile.Result{}, nil diff --git a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler_test.go b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler_test.go index 7b14f2f4e89..2346c0650c0 100644 --- a/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler_test.go +++ b/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer/reconciler_test.go @@ -16,39 +16,44 @@ package controllerregistrationfinalizer_test import ( "context" - "fmt" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "go.uber.org/mock/gomock" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/gardener/gardener/pkg/api/indexer" + "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/gardener/gardener/pkg/client/kubernetes" . "github.com/gardener/gardener/pkg/controllermanager/controller/controllerregistration/controllerregistrationfinalizer" - mockclient "github.com/gardener/gardener/pkg/mock/controller-runtime/client" - kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes" + . "github.com/gardener/gardener/pkg/utils/test/matchers" ) var _ = Describe("ControllerRegistration", func() { var ( - ctx = context.TODO() - fakeErr = fmt.Errorf("fake err") + ctx = context.TODO() ctrl *gomock.Controller - c *mockclient.MockClient + c client.Client + + reconciler *Reconciler + controllerRegistration *gardencorev1beta1.ControllerRegistration controllerRegistrationName = "controllerRegistration" ) BeforeEach(func() { ctrl = gomock.NewController(GinkgoT()) - c = mockclient.NewMockClient(ctrl) + c = fakeclient.NewClientBuilder(). + WithScheme(kubernetes.GardenScheme). + WithIndex(&gardencorev1beta1.ControllerInstallation{}, core.RegistrationRefName, indexer.ControllerInstallationRegistrationRefNameIndexerFunc). + Build() }) AfterEach(func() { @@ -56,149 +61,73 @@ var _ = Describe("ControllerRegistration", func() { }) Describe("Reconciler", func() { - const finalizerName = "core.gardener.cloud/controllerregistration" - - var ( - reconciler *Reconciler - controllerRegistration *gardencorev1beta1.ControllerRegistration - ) - BeforeEach(func() { reconciler = &Reconciler{Client: c} controllerRegistration = &gardencorev1beta1.ControllerRegistration{ ObjectMeta: metav1.ObjectMeta{ - Name: controllerRegistrationName, - ResourceVersion: "42", + Name: controllerRegistrationName, }, } }) It("should return nil because object not found", func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(controllerRegistrationName), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{})).Return(apierrors.NewNotFound(schema.GroupResource{}, "")) - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) }) - It("should return err because object reading failed", func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(controllerRegistrationName), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{})).Return(fakeErr) - - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) - }) - Context("deletion timestamp not set", func() { BeforeEach(func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(controllerRegistrationName), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{})).DoAndReturn(func(_ context.Context, _ client.ObjectKey, obj *gardencorev1beta1.ControllerRegistration, _ ...client.GetOption) error { - *obj = *controllerRegistration - return nil - }) - }) - - It("should ensure the finalizer (error)", func() { - errToReturn := apierrors.NewNotFound(schema.GroupResource{}, controllerRegistrationName) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(fmt.Sprintf(`{"metadata":{"finalizers":["%s"],"resourceVersion":"42"}}`, finalizerName))) - return errToReturn - }) - - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(err)) + Expect(c.Create(ctx, controllerRegistration)).To(Succeed()) }) - It("should ensure the finalizer (no error)", func() { - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(fmt.Sprintf(`{"metadata":{"finalizers":["%s"],"resourceVersion":"42"}}`, finalizerName))) - return nil - }) - + It("should ensure the finalizer", func() { result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) + + Expect(c.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration)).To(Succeed()) + Expect(controllerRegistration.Finalizers).To(ConsistOf("core.gardener.cloud/controllerregistration")) }) }) Context("deletion timestamp set", func() { BeforeEach(func() { - now := metav1.Now() - controllerRegistration.DeletionTimestamp = &now - controllerRegistration.Finalizers = []string{FinalizerName} - - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(controllerRegistrationName), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{})).DoAndReturn(func(_ context.Context, _ client.ObjectKey, obj *gardencorev1beta1.ControllerRegistration, _ ...client.GetOption) error { - *obj = *controllerRegistration - return nil - }) - }) - - It("should do nothing because finalizer is not present", func() { - controllerRegistration.Finalizers = nil - + Expect(c.Create(ctx, controllerRegistration)).To(Succeed()) result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) - }) - - It("should return an error because installation list failed", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).Return(fakeErr) + Expect(c.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration)).To(Succeed()) + Expect(controllerRegistration.Finalizers).To(ConsistOf("core.gardener.cloud/controllerregistration")) - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) + Expect(c.Delete(ctx, controllerRegistration)).To(Succeed()) }) It("should return an error because installation referencing controllerRegistration exists", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{Items: []gardencorev1beta1.ControllerInstallation{ - { - Spec: gardencorev1beta1.ControllerInstallationSpec{ - RegistrationRef: corev1.ObjectReference{ - Name: controllerRegistrationName, - }, - }, + controllerInstallation := &gardencorev1beta1.ControllerInstallation{ + ObjectMeta: metav1.ObjectMeta{ + Name: "controllerInstallation", + }, + Spec: gardencorev1beta1.ControllerInstallationSpec{ + RegistrationRef: corev1.ObjectReference{ + Name: controllerRegistrationName, }, - }}).DeepCopyInto(obj) - return nil - }) + }, + } - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(ContainSubstring("cannot remove finalizer"))) - }) - - It("should remove the finalizer (error)", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{}).DeepCopyInto(obj) - return nil - }) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(`{"metadata":{"finalizers":null,"resourceVersion":"42"}}`)) - return fakeErr - }) + Expect(c.Create(ctx, controllerInstallation)).To(Succeed()) result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) + Expect(err).To(MatchError(ContainSubstring("cannot remove finalizer of ControllerRegistration %q because still found ControllerInstallations: [%s]", controllerRegistration.Name, controllerInstallation.Name))) }) - It("should remove the finalizer (no error)", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{}).DeepCopyInto(obj) - return nil - }) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerRegistration{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(`{"metadata":{"finalizers":null,"resourceVersion":"42"}}`)) - return nil - }) - + It("should remove the finalizer", func() { result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: controllerRegistrationName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) + + Expect(c.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration)).To(BeNotFoundError()) }) }) }) diff --git a/pkg/controllermanager/controller/controllerregistration/seed/add.go b/pkg/controllermanager/controller/controllerregistration/seed/add.go index 90ec60973db..b769b67a977 100644 --- a/pkg/controllermanager/controller/controllerregistration/seed/add.go +++ b/pkg/controllermanager/controller/controllerregistration/seed/add.go @@ -108,8 +108,8 @@ func (r *Reconciler) AddToManager(ctx context.Context, mgr manager.Manager) erro ) } -// SeedPredicate returns true for all Seed events except for updates. Here, it only returns true when there is a change -// in the .spec.dns.provider field or when the deletion timestamp is set. +// SeedPredicate returns true for all Seed events except for updates. Here, it returns true when there is a change +// in the spec or labels or annotations or when the deletion timestamp is set. func (r *Reconciler) SeedPredicate() predicate.Predicate { return predicate.Funcs{ UpdateFunc: func(e event.UpdateEvent) bool { diff --git a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go index 843b74e723e..1f70c837865 100644 --- a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go +++ b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler.go @@ -24,6 +24,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" + gardencore "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" "github.com/gardener/gardener/pkg/controllerutils" ) @@ -61,21 +62,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( } controllerInstallationList := &gardencorev1beta1.ControllerInstallationList{} - if err := r.Client.List(ctx, controllerInstallationList); err != nil { + if err := r.Client.List(ctx, controllerInstallationList, client.MatchingFields{gardencore.SeedRefName: seed.Name}); err != nil { return reconcile.Result{}, err } - for _, controllerInstallation := range controllerInstallationList.Items { - if controllerInstallation.Spec.SeedRef.Name == seed.Name { - return reconcile.Result{}, fmt.Errorf("cannot remove finalizer of Seed %q because still found at least one ControllerInstallation", seed.Name) - } + if len(controllerInstallationList.Items) > 0 { + return reconcile.Result{}, fmt.Errorf("cannot remove finalizer of Seed %q because still found ControllerInstallations: %s", seed.Name, controllerutils.GetControllerInstallationNames(controllerInstallationList.Items)) } - if controllerutil.ContainsFinalizer(seed, FinalizerName) { - log.Info("Removing finalizer") - if err := controllerutils.RemoveFinalizers(ctx, r.Client, seed, FinalizerName); err != nil { - return reconcile.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) - } + log.Info("Removing finalizer") + if err := controllerutils.RemoveFinalizers(ctx, r.Client, seed, FinalizerName); err != nil { + return reconcile.Result{}, fmt.Errorf("failed to remove finalizer: %w", err) } return reconcile.Result{}, nil diff --git a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler_test.go b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler_test.go index 9ac1582aa65..13becd2115d 100644 --- a/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler_test.go +++ b/pkg/controllermanager/controller/controllerregistration/seedfinalizer/reconciler_test.go @@ -16,49 +16,48 @@ package seedfinalizer_test import ( "context" - "fmt" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "go.uber.org/mock/gomock" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" + "github.com/gardener/gardener/pkg/api/indexer" + "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + "github.com/gardener/gardener/pkg/client/kubernetes" . "github.com/gardener/gardener/pkg/controllermanager/controller/controllerregistration/seedfinalizer" - mockclient "github.com/gardener/gardener/pkg/mock/controller-runtime/client" - kubernetesutils "github.com/gardener/gardener/pkg/utils/kubernetes" + . "github.com/gardener/gardener/pkg/utils/test/matchers" ) var _ = Describe("Reconciler", func() { - const finalizerName = "core.gardener.cloud/controllerregistration" - var ( ctrl *gomock.Controller - c *mockclient.MockClient + c client.Client reconciler *Reconciler ctx = context.TODO() - fakeErr = fmt.Errorf("fake err") seedName = "seed" seed *gardencorev1beta1.Seed ) BeforeEach(func() { ctrl = gomock.NewController(GinkgoT()) - c = mockclient.NewMockClient(ctrl) + c = fakeclient.NewClientBuilder(). + WithScheme(kubernetes.GardenScheme). + WithIndex(&gardencorev1beta1.ControllerInstallation{}, core.SeedRefName, indexer.ControllerInstallationSeedRefNameIndexerFunc). + Build() reconciler = &Reconciler{Client: c} seed = &gardencorev1beta1.Seed{ ObjectMeta: metav1.ObjectMeta{ - Name: seedName, - ResourceVersion: "42", + Name: seedName, }, } }) @@ -69,131 +68,63 @@ var _ = Describe("Reconciler", func() { Describe("#Reconcile", func() { It("should return nil because object not found", func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).Return(apierrors.NewNotFound(schema.GroupResource{}, "")) - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) }) - It("should return err because object reading failed", func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).Return(fakeErr) - - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) - }) - Context("deletion timestamp not set", func() { BeforeEach(func() { - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).DoAndReturn(func(_ context.Context, _ client.ObjectKey, obj *gardencorev1beta1.Seed, _ ...client.GetOption) error { - *obj = *seed - return nil - }) + Expect(c.Create(ctx, seed)).To(Succeed()) }) - It("should ensure the finalizer (error)", func() { - errToReturn := apierrors.NewNotFound(schema.GroupResource{}, seedName) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(fmt.Sprintf(`{"metadata":{"finalizers":["%s"],"resourceVersion":"42"}}`, finalizerName))) - return errToReturn - }) - - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(errToReturn)) - }) - - It("should ensure the finalizer (no error)", func() { - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(fmt.Sprintf(`{"metadata":{"finalizers":["%s"],"resourceVersion":"42"}}`, finalizerName))) - return nil - }) - + It("should ensure the finalizer", func() { result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) + + Expect(c.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed()) + Expect(seed.Finalizers).To(ConsistOf("core.gardener.cloud/controllerregistration")) }) }) Context("deletion timestamp set", func() { BeforeEach(func() { - now := metav1.Now() - seed.DeletionTimestamp = &now - seed.Finalizers = []string{FinalizerName} - - c.EXPECT().Get(gomock.Any(), kubernetesutils.Key(seedName), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{})).DoAndReturn(func(_ context.Context, _ client.ObjectKey, obj *gardencorev1beta1.Seed, _ ...client.GetOption) error { - *obj = *seed - return nil - }) - }) - - It("should do nothing because finalizer is not present", func() { - seed.Finalizers = nil - + Expect(c.Create(ctx, seed)).To(Succeed()) result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) - }) + Expect(c.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed()) + Expect(seed.Finalizers).To(ConsistOf("core.gardener.cloud/controllerregistration")) - It("should return an error because installation list failed", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).Return(fakeErr) - - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) + Expect(c.Delete(ctx, seed)).To(Succeed()) }) It("should return an error because installation referencing seed exists", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{Items: []gardencorev1beta1.ControllerInstallation{ - { - Spec: gardencorev1beta1.ControllerInstallationSpec{ - SeedRef: corev1.ObjectReference{ - Name: seedName, - }, - }, + controllerInstallation := &gardencorev1beta1.ControllerInstallation{ + ObjectMeta: metav1.ObjectMeta{ + Name: "controllerInstallation", + }, + Spec: gardencorev1beta1.ControllerInstallationSpec{ + SeedRef: corev1.ObjectReference{ + Name: seedName, }, - }}).DeepCopyInto(obj) - return nil - }) + }, + } - result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) - Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(ContainSubstring("cannot remove finalizer"))) - }) - - It("should remove the finalizer (error)", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{}).DeepCopyInto(obj) - return nil - }) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(`{"metadata":{"finalizers":null,"resourceVersion":"42"}}`)) - return fakeErr - }) + Expect(c.Create(ctx, controllerInstallation)).To(Succeed()) result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) Expect(result).To(Equal(reconcile.Result{})) - Expect(err).To(MatchError(fakeErr)) + Expect(err).To(MatchError(ContainSubstring("cannot remove finalizer of Seed %q because still found ControllerInstallations: [%s]", seed.Name, controllerInstallation.Name))) }) - It("should remove the finalizer (no error)", func() { - c.EXPECT().List(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.ControllerInstallationList{})).DoAndReturn(func(_ context.Context, obj *gardencorev1beta1.ControllerInstallationList, _ ...client.ListOption) error { - (&gardencorev1beta1.ControllerInstallationList{}).DeepCopyInto(obj) - return nil - }) - - c.EXPECT().Patch(gomock.Any(), gomock.AssignableToTypeOf(&gardencorev1beta1.Seed{}), gomock.Any()).DoAndReturn(func(_ context.Context, o client.Object, patch client.Patch, opts ...client.PatchOption) error { - Expect(patch.Data(o)).To(BeEquivalentTo(`{"metadata":{"finalizers":null,"resourceVersion":"42"}}`)) - return nil - }) - + It("should remove the finalizer", func() { result, err := reconciler.Reconcile(ctx, reconcile.Request{NamespacedName: types.NamespacedName{Name: seedName}}) Expect(result).To(Equal(reconcile.Result{})) Expect(err).NotTo(HaveOccurred()) + + Expect(c.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(BeNotFoundError()) }) }) }) diff --git a/pkg/controllerutils/miscellaneous.go b/pkg/controllerutils/miscellaneous.go index e4189e3d0a3..67cf9438d9d 100644 --- a/pkg/controllerutils/miscellaneous.go +++ b/pkg/controllerutils/miscellaneous.go @@ -19,6 +19,7 @@ import ( "strings" "time" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" v1beta1constants "github.com/gardener/gardener/pkg/apis/core/v1beta1/constants" "github.com/gardener/gardener/pkg/utils" ) @@ -107,3 +108,14 @@ func GetChildReconciliationContext(ctx context.Context, timeout time.Duration) ( return context.WithTimeout(ctx, t/2) } + +// GetControllerInstallationNames returns a list of the names of the controllerinstallations passed. +func GetControllerInstallationNames(controllerInstallations []gardencorev1beta1.ControllerInstallation) []string { + var names = make([]string, 0, len(controllerInstallations)) + + for _, controllerInstallation := range controllerInstallations { + names = append(names, controllerInstallation.Name) + } + + return names +} diff --git a/test/integration/controllermanager/controllerregistration/controllerregistration_suite_test.go b/test/integration/controllermanager/controllerregistration/controllerregistration_suite_test.go index 8db8736c375..5be93d3848b 100644 --- a/test/integration/controllermanager/controllerregistration/controllerregistration_suite_test.go +++ b/test/integration/controllermanager/controllerregistration/controllerregistration_suite_test.go @@ -24,6 +24,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/client-go/rest" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/cache" @@ -33,12 +34,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager" "github.com/gardener/gardener/pkg/api/indexer" + "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" "github.com/gardener/gardener/pkg/client/kubernetes" "github.com/gardener/gardener/pkg/controllermanager/apis/config" "github.com/gardener/gardener/pkg/controllermanager/controller/controllerregistration" gardenerenvtest "github.com/gardener/gardener/pkg/envtest" "github.com/gardener/gardener/pkg/logger" + "github.com/gardener/gardener/pkg/utils" + gardenerutils "github.com/gardener/gardener/pkg/utils/gardener" . "github.com/gardener/gardener/pkg/utils/test/matchers" ) @@ -57,9 +62,17 @@ var ( restConfig *rest.Config testEnv *gardenerenvtest.GardenerTestEnvironment testClient client.Client + mgrClient client.Client testNamespace *corev1.Namespace testRunID string + + providerType = "provider" + seedName string + seed *gardencorev1beta1.Seed + seedNamespace *corev1.Namespace + seedSecret *corev1.Secret + seedControllerRegistration *gardencorev1beta1.ControllerRegistration ) var _ = BeforeSuite(func() { @@ -69,7 +82,7 @@ var _ = BeforeSuite(func() { By("Start test environment") testEnv = &gardenerenvtest.GardenerTestEnvironment{ GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{ - Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator"}, + Args: []string{"--disable-admission-plugins=DeletionConfirmation,ResourceReferenceManager,ExtensionValidator,ShootDNS,ShootQuotaValidator,ShootTolerationRestriction,ShootValidator,ControllerRegistrationResources"}, }, } @@ -111,10 +124,14 @@ var _ = BeforeSuite(func() { SelectorsByObject: map[client.Object]cache.ObjectSelector{ &gardencorev1beta1.ControllerRegistration{}: {Label: labels.SelectorFromSet(labels.Set{testID: testRunID})}, &gardencorev1beta1.Seed{}: {Label: labels.SelectorFromSet(labels.Set{testID: testRunID})}, + &gardencorev1beta1.BackupBucket{}: {Label: labels.SelectorFromSet(labels.Set{testID: testRunID})}, + &gardencorev1beta1.BackupEntry{}: {Label: labels.SelectorFromSet(labels.Set{testID: testRunID})}, + &gardencorev1beta1.Shoot{}: {Label: labels.SelectorFromSet(labels.Set{testID: testRunID})}, }, }), }) Expect(err).NotTo(HaveOccurred()) + mgrClient = mgr.GetClient() By("Setup field indexes") Expect(indexer.AddBackupBucketSeedName(ctx, mgr.GetFieldIndexer())).To(Succeed()) @@ -122,6 +139,7 @@ var _ = BeforeSuite(func() { Expect(indexer.AddShootSeedName(ctx, mgr.GetFieldIndexer())).To(Succeed()) Expect(indexer.AddShootStatusSeedName(ctx, mgr.GetFieldIndexer())).To(Succeed()) Expect(indexer.AddControllerInstallationSeedRefName(ctx, mgr.GetFieldIndexer())).To(Succeed()) + Expect(indexer.AddControllerInstallationRegistrationRefName(ctx, mgr.GetFieldIndexer())).To(Succeed()) By("Register controller") Expect(controllerregistration.AddToManager(ctx, mgr, config.ControllerManagerConfiguration{ @@ -144,4 +162,138 @@ var _ = BeforeSuite(func() { By("Stop manager") mgrCancel() }) + + seedControllerRegistration = &gardencorev1beta1.ControllerRegistration{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "ctrlreg-seed-", + Labels: map[string]string{testID: testRunID}, + }, + Spec: gardencorev1beta1.ControllerRegistrationSpec{ + Resources: []gardencorev1beta1.ControllerResource{ + {Kind: extensionsv1alpha1.DNSRecordResource, Type: providerType}, + {Kind: extensionsv1alpha1.ControlPlaneResource, Type: providerType}, + {Kind: extensionsv1alpha1.InfrastructureResource, Type: providerType}, + {Kind: extensionsv1alpha1.WorkerResource, Type: providerType}, + }, + }, + } + + By("Create ControllerRegistration") + Expect(testClient.Create(ctx, seedControllerRegistration)).To(Succeed()) + log.Info("Created ControllerRegistration for seed", "controllerRegistration", client.ObjectKeyFromObject(seedControllerRegistration)) + + DeferCleanup(func() { + By("Delete seed ControllerRegistration") + Expect(testClient.Delete(ctx, seedControllerRegistration)).To(Or(Succeed(), BeNotFoundError())) + + By("Wait until manager has observed controllerregistration deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(seedControllerRegistration), seedControllerRegistration) + }).Should(BeNotFoundError()) + }) + + seedName = "seed-ctrl-reg-test-" + utils.ComputeSHA256Hex([]byte(testID + uuid.NewUUID()))[:8] + seedNamespace = &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: gardenerutils.ComputeGardenNamespace(seedName), + }, + } + + seedSecret = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "seed-secret", + Namespace: seedNamespace.Name, + Labels: map[string]string{"gardener.cloud/role": "global-monitoring"}, + }, + } + + By("Create Seed Namespace") + Expect(testClient.Create(ctx, seedNamespace)).To(Succeed()) + log.Info("Created Seed Namespace for test", "namespace", client.ObjectKeyFromObject(seedNamespace)) + + By("Create Seed Secret") + Expect(testClient.Create(ctx, seedSecret)).To(Succeed()) + log.Info("Created Seed Secret for test", "secret", client.ObjectKeyFromObject(seedSecret)) + + DeferCleanup(func() { + By("Delete Seed Secret") + Expect(testClient.Delete(ctx, seedSecret)).To(Or(Succeed(), BeNotFoundError())) + + By("Delete Seed Namespace") + Expect(testClient.Delete(ctx, seedNamespace)).To(Or(Succeed(), BeNotFoundError())) + }) + + seed = &gardencorev1beta1.Seed{ + ObjectMeta: metav1.ObjectMeta{ + Name: seedName, + Labels: map[string]string{testID: testRunID}, + }, + Spec: gardencorev1beta1.SeedSpec{ + Provider: gardencorev1beta1.SeedProvider{ + Region: "region", + Type: providerType, + }, + Ingress: &gardencorev1beta1.Ingress{ + Domain: "seed.example.com", + Controller: gardencorev1beta1.IngressController{ + Kind: "nginx", + }, + }, + DNS: gardencorev1beta1.SeedDNS{ + Provider: &gardencorev1beta1.SeedDNSProvider{ + Type: providerType, + SecretRef: corev1.SecretReference{ + Name: "some-secret", + Namespace: "some-namespace", + }, + }, + }, + Settings: &gardencorev1beta1.SeedSettings{ + Scheduling: &gardencorev1beta1.SeedSettingScheduling{Visible: true}, + }, + Networks: gardencorev1beta1.SeedNetworks{ + Pods: "10.0.0.0/16", + Services: "10.1.0.0/16", + Nodes: pointer.String("10.2.0.0/16"), + ShootDefaults: &gardencorev1beta1.ShootNetworks{ + Pods: pointer.String("100.128.0.0/11"), + Services: pointer.String("100.72.0.0/13"), + }, + }, + }, + } + + By("Create Seed") + Expect(testClient.Create(ctx, seed)).To(Succeed()) + log.Info("Created Seed for test", "seed", client.ObjectKeyFromObject(seed)) + + DeferCleanup(func() { + By("Delete Seed") + Expect(testClient.Delete(ctx, seed)).To(Or(Succeed(), BeNotFoundError())) + + By("Wait until manager has observed seed deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(seed), seed) + }).Should(BeNotFoundError()) + }) + + Eventually(func(g Gomega) []string { + g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed()) + return seed.Finalizers + }).Should(ConsistOf("core.gardener.cloud/controllerregistration")) +}) + +var _ = AfterSuite(func() { + By("Delete Seed") + Expect(testClient.Delete(ctx, seed)).To(Succeed()) + + By("Expect ControllerInstallation to be deleted") + Eventually(func(g Gomega) { + controllerInstallationList := &gardencorev1beta1.ControllerInstallationList{} + g.Expect(testClient.List(ctx, controllerInstallationList, client.MatchingFields{ + core.RegistrationRefName: seedControllerRegistration.Name, + core.SeedRefName: seed.Name, + })).To(Succeed()) + g.Expect(controllerInstallationList.Items).To(HaveLen(0)) + }).Should(Succeed()) }) diff --git a/test/integration/controllermanager/controllerregistration/controllerregistration_test.go b/test/integration/controllermanager/controllerregistration/controllerregistration_test.go index 8f0c14fe6fd..460fded051b 100644 --- a/test/integration/controllermanager/controllerregistration/controllerregistration_test.go +++ b/test/integration/controllermanager/controllerregistration/controllerregistration_test.go @@ -25,133 +25,10 @@ import ( "github.com/gardener/gardener/pkg/apis/core" gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" extensionsv1alpha1 "github.com/gardener/gardener/pkg/apis/extensions/v1alpha1" - gardenerutils "github.com/gardener/gardener/pkg/utils/gardener" . "github.com/gardener/gardener/pkg/utils/test/matchers" ) var _ = Describe("ControllerRegistration controller test", func() { - var ( - providerType = "provider" - dnsProviderType = "dnsProvider" - - seed *gardencorev1beta1.Seed - seedNamespace *corev1.Namespace - seedSecret *corev1.Secret - seedControllerRegistration *gardencorev1beta1.ControllerRegistration - ) - - BeforeEach(func() { - seed = &gardencorev1beta1.Seed{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: testID + "-", - Labels: map[string]string{testID: testRunID}, - }, - Spec: gardencorev1beta1.SeedSpec{ - Provider: gardencorev1beta1.SeedProvider{ - Region: "region", - Type: providerType, - }, - Ingress: &gardencorev1beta1.Ingress{ - Domain: "seed.example.com", - Controller: gardencorev1beta1.IngressController{ - Kind: "nginx", - }, - }, - DNS: gardencorev1beta1.SeedDNS{ - Provider: &gardencorev1beta1.SeedDNSProvider{ - Type: dnsProviderType, - SecretRef: corev1.SecretReference{ - Name: "some-secret", - Namespace: "some-namespace", - }, - }, - }, - Settings: &gardencorev1beta1.SeedSettings{ - Scheduling: &gardencorev1beta1.SeedSettingScheduling{Visible: true}, - }, - Networks: gardencorev1beta1.SeedNetworks{ - Pods: "10.0.0.0/16", - Services: "10.1.0.0/16", - Nodes: pointer.String("10.2.0.0/16"), - ShootDefaults: &gardencorev1beta1.ShootNetworks{ - Pods: pointer.String("100.128.0.0/11"), - Services: pointer.String("100.72.0.0/13"), - }, - }, - }, - } - - By("Create Seed") - Expect(testClient.Create(ctx, seed)).To(Succeed()) - log.Info("Created Seed for test", "seed", client.ObjectKeyFromObject(seed)) - - seedNamespace = &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: gardenerutils.ComputeGardenNamespace(seed.Name), - }, - } - - seedSecret = &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "seed-secret", - Namespace: seedNamespace.Name, - Labels: map[string]string{"gardener.cloud/role": "global-monitoring"}, - }, - } - - By("Create Seed Namespace") - Expect(testClient.Create(ctx, seedNamespace)).To(Succeed()) - log.Info("Created Seed Namespace for test", "namespace", client.ObjectKeyFromObject(seedNamespace)) - - By("Create Seed Secret") - Expect(testClient.Create(ctx, seedSecret)).To(Succeed()) - log.Info("Created Seed Secret for test", "secret", client.ObjectKeyFromObject(seedSecret)) - - Eventually(func(g Gomega) []string { - g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed)).To(Succeed()) - return seed.Finalizers - }).Should(ConsistOf("core.gardener.cloud/controllerregistration")) - - seedControllerRegistration = &gardencorev1beta1.ControllerRegistration{ - ObjectMeta: metav1.ObjectMeta{ - GenerateName: "ctrlreg-" + testID + "-", - Labels: map[string]string{testID: testRunID}, - }, - Spec: gardencorev1beta1.ControllerRegistrationSpec{ - Resources: []gardencorev1beta1.ControllerResource{ - {Kind: extensionsv1alpha1.DNSRecordResource, Type: dnsProviderType}, - {Kind: extensionsv1alpha1.ControlPlaneResource, Type: providerType}, - {Kind: extensionsv1alpha1.InfrastructureResource, Type: providerType}, - {Kind: extensionsv1alpha1.WorkerResource, Type: providerType}, - }, - }, - } - - By("Create ControllerRegistration") - Expect(testClient.Create(ctx, seedControllerRegistration)).To(Succeed()) - - DeferCleanup(func() { - By("Delete Seed") - Expect(testClient.Delete(ctx, seed)).To(Or(Succeed(), BeNotFoundError())) - - By("Delete ControllerInstallations") - Expect(testClient.DeleteAllOf(ctx, &gardencorev1beta1.ControllerInstallation{})).To(Or(Succeed(), BeNotFoundError())) - - By("Delete ControllerRegistrations") - Expect(testClient.DeleteAllOf(ctx, &gardencorev1beta1.ControllerRegistration{})).To(Or(Succeed(), BeNotFoundError())) - - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(seed), seed) - }).Should(BeNotFoundError()) - - By("Delete Seed Secret") - Expect(testClient.Delete(ctx, seedSecret)).To(Or(Succeed(), BeNotFoundError())) - - By("Delete Seed Namespace") - Expect(testClient.Delete(ctx, seedNamespace)).To(Or(Succeed(), BeNotFoundError())) - }) - }) - Context("Seed", func() { It("should reconcile the ControllerInstallations", func() { By("Expect finalizer to be added to ControllerRegistration") @@ -169,27 +46,6 @@ var _ = Describe("ControllerRegistration controller test", func() { })).To(Succeed()) g.Expect(controllerInstallationList.Items).To(HaveLen(1)) }).Should(Succeed()) - - By("Delete object") - Expect(testClient.Delete(ctx, seed)).To(Succeed()) - - By("Expect ControllerInstallation be deleted") - Eventually(func(g Gomega) { - controllerInstallationList := &gardencorev1beta1.ControllerInstallationList{} - g.Expect(testClient.List(ctx, controllerInstallationList, client.MatchingFields{ - core.RegistrationRefName: seedControllerRegistration.Name, - core.SeedRefName: seed.Name, - })).To(Succeed()) - g.Expect(controllerInstallationList.Items).To(HaveLen(0)) - }).Should(Succeed()) - - By("Delete ControllerRegistration") - Expect(testClient.Delete(ctx, seedControllerRegistration)).To(Succeed()) - - By("Expect ControllerRegistration to be deleted") - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(seedControllerRegistration), seedControllerRegistration) - }).Should(BeNotFoundError()) }) }) @@ -219,6 +75,17 @@ var _ = Describe("ControllerRegistration controller test", func() { By("Create ControllerRegistration") Expect(testClient.Create(ctx, controllerRegistration)).To(Succeed()) + log.Info("Created ControllerRegistration for test", "controllerRegistration", client.ObjectKeyFromObject(controllerRegistration)) + + DeferCleanup(func() { + By("Delete ControllerRegistration") + Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) + + By("Wait until manager has observed controllerregistration deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) + }).Should(BeNotFoundError()) + }) By("Expect finalizer to be added to ControllerRegistration") Eventually(func(g Gomega) []string { @@ -251,14 +118,6 @@ var _ = Describe("ControllerRegistration controller test", func() { })).To(Succeed()) g.Expect(controllerInstallationList.Items).To(HaveLen(0)) }).Should(Succeed()) - - By("Delete ControllerRegistration") - Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) - - By("Expect ControllerRegistration to be deleted") - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) - }).Should(BeNotFoundError()) }) It("should keep the ControllerInstallation because it is required", func() { @@ -286,6 +145,17 @@ var _ = Describe("ControllerRegistration controller test", func() { By("Create ControllerRegistration") Expect(testClient.Create(ctx, controllerRegistration)).To(Succeed()) + log.Info("Created ControllerRegistration for test", "controllerRegistration", client.ObjectKeyFromObject(controllerRegistration)) + + DeferCleanup(func() { + By("Delete ControllerRegistration") + Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) + + By("Wait until manager has observed controllerregistration deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) + }).Should(BeNotFoundError()) + }) By("Expect finalizer to be added to ControllerRegistration") Eventually(func(g Gomega) []string { @@ -342,14 +212,6 @@ var _ = Describe("ControllerRegistration controller test", func() { })).To(Succeed()) g.Expect(controllerInstallationList.Items).To(HaveLen(0)) }).Should(Succeed()) - - By("Delete ControllerRegistration") - Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) - - By("Expect ControllerRegistration to be deleted") - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) - }).Should(BeNotFoundError()) }) }) @@ -358,6 +220,7 @@ var _ = Describe("ControllerRegistration controller test", func() { backupBucket := &gardencorev1beta1.BackupBucket{ ObjectMeta: metav1.ObjectMeta{ GenerateName: "bucket-", + Labels: map[string]string{testID: testRunID}, }, Spec: gardencorev1beta1.BackupBucketSpec{ Provider: gardencorev1beta1.BackupBucketProvider{Type: providerType, Region: "region"}, @@ -367,6 +230,12 @@ var _ = Describe("ControllerRegistration controller test", func() { } Expect(testClient.Create(ctx, backupBucket)).To(Succeed()) + log.Info("Created BackupBucket for test", "controllerRegistration", client.ObjectKeyFromObject(backupBucket)) + + By("Wait until manager has observed backupbucket creation") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(backupBucket), backupBucket) + }).Should(Succeed()) obj := &gardencorev1beta1.BackupEntry{ ObjectMeta: metav1.ObjectMeta{ @@ -395,6 +264,17 @@ var _ = Describe("ControllerRegistration controller test", func() { By("Create ControllerRegistration") Expect(testClient.Create(ctx, controllerRegistration)).To(Succeed()) + log.Info("Created ControllerRegistration for test", "controllerRegistration", client.ObjectKeyFromObject(controllerRegistration)) + + DeferCleanup(func() { + By("Delete ControllerRegistration") + Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) + + By("Wait until manager has observed controllerregistration deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) + }).Should(BeNotFoundError()) + }) By("Expect finalizer to be added to ControllerRegistration") Eventually(func(g Gomega) []string { @@ -430,14 +310,6 @@ var _ = Describe("ControllerRegistration controller test", func() { })).To(Succeed()) g.Expect(controllerInstallationList.Items).To(HaveLen(0)) }).Should(Succeed()) - - By("Delete ControllerRegistration") - Expect(testClient.Delete(ctx, controllerRegistration)).To(Succeed()) - - By("Expect ControllerRegistration to be deleted") - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(controllerRegistration), controllerRegistration) - }).Should(BeNotFoundError()) }) }) @@ -518,6 +390,16 @@ var _ = Describe("ControllerRegistration controller test", func() { By("Create ControllerRegistration") Expect(testClient.Create(ctx, shootControllerRegistration)).To(Succeed()) + DeferCleanup(func() { + By("Delete ControllerRegistration") + Expect(testClient.Delete(ctx, shootControllerRegistration)).To(Succeed()) + + By("Wait until manager has observed shootControllerRegistration deletion") + Eventually(func() error { + return mgrClient.Get(ctx, client.ObjectKeyFromObject(shootControllerRegistration), shootControllerRegistration) + }).Should(BeNotFoundError()) + }) + By("Expect finalizer to be added to ControllerRegistration") Eventually(func(g Gomega) []string { g.Expect(testClient.Get(ctx, client.ObjectKeyFromObject(shootControllerRegistration), shootControllerRegistration)).To(Succeed()) @@ -549,14 +431,6 @@ var _ = Describe("ControllerRegistration controller test", func() { })).To(Succeed()) g.Expect(controllerInstallationList.Items).To(HaveLen(0)) }).Should(Succeed()) - - By("Delete ControllerRegistration") - Expect(testClient.Delete(ctx, shootControllerRegistration)).To(Succeed()) - - By("Expect ControllerRegistration to be deleted") - Eventually(func() error { - return testClient.Get(ctx, client.ObjectKeyFromObject(shootControllerRegistration), shootControllerRegistration) - }).Should(BeNotFoundError()) }) }) }) diff --git a/test/start-envtest/main.go b/test/start-envtest/main.go index 2dd566acfd0..86983a9694c 100644 --- a/test/start-envtest/main.go +++ b/test/start-envtest/main.go @@ -114,6 +114,9 @@ func run(ctx context.Context, log logr.Logger, opts *options) error { if opts.environmentType == typeGardener { testEnv = &gardenerenvtest.GardenerTestEnvironment{ Environment: kubeEnvironment, + GardenerAPIServer: &gardenerenvtest.GardenerAPIServer{ + Args: []string{"--disable-admission-plugins="}, + }, } }