diff --git a/internal/controller/runtime/runtime_controller_test.go b/internal/controller/runtime/runtime_controller_test.go index ba8bd095..84852e3a 100644 --- a/internal/controller/runtime/runtime_controller_test.go +++ b/internal/controller/runtime/runtime_controller_test.go @@ -70,11 +70,85 @@ var _ = Describe("Runtime Controller", func() { }, time.Second*300, time.Second*3).Should(BeTrue()) + By("Wait for Runtime to process shoot creation process and finish processing in Ready State") + + // should go into Pending Processing state + Eventually(func() bool { + runtime := imv1.Runtime{} + err := k8sClient.Get(ctx, typeNamespacedName, &runtime) + if err != nil { + return false + } + + // check state + if runtime.Status.State != imv1.RuntimeStatePending { + return false + } + + if !runtime.IsConditionSetWithStatus(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonShootCreationPending, "Unknown") { + return false + } + + return true + }, time.Second*300, time.Second*3).Should(BeTrue()) + + // and end as Ready state with ConfigurationCompleted condition == True + Eventually(func() bool { + runtime := imv1.Runtime{} + err := k8sClient.Get(ctx, typeNamespacedName, &runtime) + + if err != nil { + return false + } + + // check state + if runtime.Status.State != imv1.RuntimeStateReady { + return false + } + + if !runtime.IsConditionSet(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConfigurationCompleted) { + return false + } + + return true + }, time.Second*300, time.Second*3).Should(BeTrue()) + + Expect(customTracker.IsSequenceFullyUsed()).To(BeTrue()) + + By("Wait for Runtime to process shoot update process and finish processing in Ready State") + setupGardenerTestClientForUpdate() + runtime := imv1.Runtime{} + err := k8sClient.Get(ctx, typeNamespacedName, &runtime) + + Expect(err).To(BeNil()) - By("Wait for Runtime to process shoot creation process and end in ready State") + runtime.Spec.Shoot.Provider.Workers[0].Maximum = 5 + Expect(k8sClient.Update(ctx, &runtime)).To(Succeed()) + + // should go into Pending Processing state Eventually(func() bool { + runtime := imv1.Runtime{} + err := k8sClient.Get(ctx, typeNamespacedName, &runtime) + if err != nil { + return false + } + + // check state + if runtime.Status.State != imv1.RuntimeStatePending { + return false + } + if !runtime.IsConditionSetWithStatus(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonProcessing, "Unknown") { + return false + } + + return true + }, time.Second*300, time.Second*3).Should(BeTrue()) + + // and end as Ready state with ConfigurationCompleted condition == True + Eventually(func() bool { + runtime := imv1.Runtime{} err := k8sClient.Get(ctx, typeNamespacedName, &runtime) if err != nil { @@ -85,7 +159,6 @@ var _ = Describe("Runtime Controller", func() { if runtime.Status.State != imv1.RuntimeStateReady { return false } - // check conditions if !runtime.IsConditionSet(imv1.ConditionTypeRuntimeProvisioned, imv1.ConditionReasonConfigurationCompleted) { return false @@ -118,7 +191,8 @@ func CreateRuntimeStub(resourceName string) *imv1.Runtime { Type: "aws", Workers: []gardener.Worker{ { - Zones: []string{""}, + Zones: []string{""}, + Maximum: 1, }, }, }, diff --git a/internal/controller/runtime/suite_test.go b/internal/controller/runtime/suite_test.go index e03b72d9..22bf7a36 100644 --- a/internal/controller/runtime/suite_test.go +++ b/internal/controller/runtime/suite_test.go @@ -144,6 +144,27 @@ func setupGardenerTestClientForProvisioning() { runtimeReconciler.UpdateShootClient(gardenerTestClient) } +func setupGardenerTestClientForUpdate() { + runtimeStub := CreateRuntimeStub("test-resource") + converterConfig := fixConverterConfigForTests() + converter := gardener_shoot.NewConverter(converterConfig) + convertedShoot, err := converter.ToShoot(*runtimeStub) + if err != nil { + panic(err) + } + + shoots := fixGardenerShootsForUpdate(&convertedShoot) + + clientScheme := runtime.NewScheme() + _ = gardener_api.AddToScheme(clientScheme) + + tracker := clienttesting.NewObjectTracker(clientScheme, serializer.NewCodecFactory(clientScheme).UniversalDecoder()) + customTracker = NewCustomTracker(tracker, shoots) + gardenerTestClient = fake.NewClientBuilder().WithScheme(clientScheme).WithObjectTracker(customTracker).Build() + + runtimeReconciler.UpdateShootClient(gardenerTestClient) +} + // func setupGardenerTestClientForDeleting() { // runtimeStub := CreateRuntimeStub("test-resource") // converterConfig := fixConverterConfigForTests() @@ -190,6 +211,34 @@ func fixGardenerShootsForProvisioning(shoot *gardener_api.Shoot) []*gardener_api return []*gardener_api.Shoot{missingShoot, missingShoot, missingShoot, initialisedShoot, dnsShoot, pendingShoot, processingShoot, readyShoot, readyShoot} } +func fixGardenerShootsForUpdate(shoot *gardener_api.Shoot) []*gardener_api.Shoot { + + pendingShoot := shoot.DeepCopy() + + pendingShoot.Spec.DNS = &gardener_api.DNS{ + Domain: ptrTo("test.domain"), + } + + pendingShoot.Status = gardener_api.ShootStatus{ + LastOperation: &gardener_api.LastOperation{ + Type: gardener_api.LastOperationTypeReconcile, + State: gardener_api.LastOperationStatePending, + }, + } + + processingShoot := pendingShoot.DeepCopy() + + processingShoot.Status.LastOperation.State = gardener_api.LastOperationStateProcessing + + readyShoot := processingShoot.DeepCopy() + + readyShoot.Status.LastOperation.State = gardener_api.LastOperationStateSucceeded + + // processedShoot := processingShoot.DeepCopy() // will add specific data later + + return []*gardener_api.Shoot{pendingShoot, processingShoot, readyShoot, readyShoot} +} + func fixConverterConfigForTests() gardener_shoot.ConverterConfig { return gardener_shoot.ConverterConfig{ Kubernetes: gardener_shoot.KubernetesConfig{ diff --git a/internal/controller/runtime/test_client_obj_tracker.go b/internal/controller/runtime/test_client_obj_tracker.go index 8ebe35a2..9c2115ab 100644 --- a/internal/controller/runtime/test_client_obj_tracker.go +++ b/internal/controller/runtime/test_client_obj_tracker.go @@ -12,6 +12,7 @@ import ( ) // CustomTracker implements ObjectTracker with a sequence of Shoot objects +// it will be updated with a different shoot sequence for each test case type CustomTracker struct { clienttesting.ObjectTracker shootSequence []*gardener_api.Shoot