diff --git a/internal/controller/nova_controller.go b/internal/controller/nova_controller.go index 345ff7db8..ef452c8f8 100644 --- a/internal/controller/nova_controller.go +++ b/internal/controller/nova_controller.go @@ -458,6 +458,8 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul novav1.NovaNotificationMQReadyErrorMessage, notificationMQError.Error(), )) + Log.Error(notificationMQError, "Notification MQ failed, aborting.") + return ctrl.Result{}, notificationMQError case nova.MQCreating: instance.Status.Conditions.Set(condition.FalseCondition( novav1.NovaNotificationMQReadyCondition, @@ -465,6 +467,10 @@ func (r *NovaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resul condition.SeverityInfo, novav1.NovaNotificationMQReadyCreatingMessage, )) + // return early - wait for notification MQ to be ready before continuing + // to avoid propagating empty transport_url to config generation + Log.Info("Notification MQ not ready yet, returning early.") + return ctrl.Result{}, nil case nova.MQCompleted: instance.Status.Conditions.MarkTrue( novav1.NovaNotificationMQReadyCondition, novav1.NovaNotificationMQReadyMessage) diff --git a/test/functional/nova_controller_test.go b/test/functional/nova_controller_test.go index 37f83656b..ebd6272e6 100644 --- a/test/functional/nova_controller_test.go +++ b/test/functional/nova_controller_test.go @@ -139,6 +139,61 @@ var _ = Describe("Nova controller - notifications", func() { infra.AssertTransportURLDoesNotExist(notificationsBus.TransportURLName) }) + + It("returns early when notification TransportURL becomes not ready", func() { + notificationsBus := GetNotificationsBusNames(novaNames.NovaName) + DeferCleanup(k8sClient.Delete, ctx, CreateNotificationTransportURLSecret(notificationsBus)) + + // add notification bus and simulate it ready + Eventually(func(g Gomega) { + nova := GetNova(novaNames.NovaName) + nova.Spec.NotificationsBus = &rabbitmqv1.RabbitMqConfig{ + Cluster: notificationsBus.BusName, + } + g.Expect(k8sClient.Update(ctx, nova)).Should(Succeed()) + }, timeout, interval).Should(Succeed()) + + infra.SimulateTransportURLReady(notificationsBus.TransportURLName) + + // wait for notification MQ to be ready + th.ExpectCondition( + novaNames.NovaName, + ConditionGetterFunc(NovaConditionGetter), + novav1.NovaNotificationMQReadyCondition, + corev1.ConditionTrue, + ) + + // get config resourceVersion + initialConfigDataMap := th.GetSecret(novaNames.APIConfigDataName) + initialResourceVersion := initialConfigDataMap.ResourceVersion + + // simulate rabbitmq pod deleted - transportURL becoming not ready + Eventually(func(g Gomega) { + transportURL := infra.GetTransportURL(notificationsBus.TransportURLName) + + transportURL.Status.Conditions.MarkFalse( + "TransportURLReady", + condition.RequestedReason, + condition.SeverityInfo, + "RabbitMQ not ready", + ) + g.Expect(k8sClient.Status().Update(ctx, transportURL)).Should(Succeed()) + }, timeout, interval).Should(Succeed()) + + // condition should become false + th.ExpectCondition( + novaNames.NovaName, + ConditionGetterFunc(NovaConditionGetter), + novav1.NovaNotificationMQReadyCondition, + corev1.ConditionFalse, + ) + + // assert resourceVersion unchanged - config was not updated + Consistently(func(g Gomega) { + configDataMap := th.GetSecret(novaNames.APIConfigDataName) + g.Expect(configDataMap.ResourceVersion).To(Equal(initialResourceVersion)) + }, consistencyTimeout, interval).Should(Succeed()) + }) }) })