diff --git a/internal/controller/operator/eventing/controller.go b/internal/controller/operator/eventing/controller.go index 181b081e3..106d4c3b9 100644 --- a/internal/controller/operator/eventing/controller.go +++ b/internal/controller/operator/eventing/controller.go @@ -540,7 +540,7 @@ func (r *Reconciler) reconcileNATSBackend(ctx context.Context, eventing *operato // check nats CR if it exists and is in natsAvailable state err = r.checkNATSAvailability(ctx, eventing) if err != nil { - return kctrl.Result{}, r.syncStatusWithNATSState(ctx, operatorv1alpha1.StateWarning, eventing, err, log) + return kctrl.Result{}, r.syncStatusWithNATSErr(ctx, eventing, err, log) } // set NATSAvailable condition to true and update status @@ -608,7 +608,7 @@ func (r *Reconciler) reconcileEventMeshBackend(ctx context.Context, eventing *op } // Start the EventMesh subscription controller - err = r.reconcileEventMeshSubManager(ctx, eventing) + err = r.reconcileEventMeshSubManager(ctx, eventing, log) if err != nil { return kctrl.Result{}, r.syncStatusWithSubscriptionManagerErr(ctx, eventing, err, log) } diff --git a/internal/controller/operator/eventing/eventmesh.go b/internal/controller/operator/eventing/eventmesh.go index 07937daf5..df2465f8b 100644 --- a/internal/controller/operator/eventing/eventmesh.go +++ b/internal/controller/operator/eventing/eventmesh.go @@ -36,7 +36,10 @@ type oauth2Credentials struct { certsURL []byte } -func (r *Reconciler) reconcileEventMeshSubManager(ctx context.Context, eventing *v1alpha1.Eventing) error { +const EventMeshSecretMissingMessage = "the specified EventMesh secret is missing. Please provide the secret" + +func (r *Reconciler) reconcileEventMeshSubManager(ctx context.Context, eventing *v1alpha1.Eventing, + log *zap.SugaredLogger) error { // gets oauth2ClientID and secret and stops the EventMesh subscription manager if changed err := r.syncOauth2ClientIDAndSecret(ctx, eventing) if err != nil { @@ -45,6 +48,10 @@ func (r *Reconciler) reconcileEventMeshSubManager(ctx context.Context, eventing // retrieve secret to authenticate with EventMesh eventMeshSecret, err := r.kubeClient.GetSecret(ctx, eventing.Spec.Backend.Config.EventMeshSecret) if err != nil { + if k8serrors.IsNotFound(err) { + return r.syncStatusWithNATSState(ctx, v1alpha1.StateWarning, eventing, + errors.New(EventMeshSecretMissingMessage), log) + } return errors.Errorf("failed to get EventMesh secret: %v", err) } // CreateOrUpdate deployment for publisher proxy secret diff --git a/internal/controller/operator/eventing/eventmesh_test.go b/internal/controller/operator/eventing/eventmesh_test.go index b1eaf61a8..70a2c3e7e 100644 --- a/internal/controller/operator/eventing/eventmesh_test.go +++ b/internal/controller/operator/eventing/eventmesh_test.go @@ -276,6 +276,8 @@ func Test_reconcileEventMeshSubManager(t *testing.T) { testEnv := NewMockedUnitTestEnvironment(t, givenEventing, givenOauthSecret) testEnv.Reconciler.backendConfig = *givenBackendConfig + logger := testEnv.Reconciler.logger.WithContext().Named(ControllerName) + // get mocks from test-case. givenEventMeshSubManagerMock := tc.givenEventMeshSubManagerMock() givenManagerFactoryMock := tc.givenManagerFactoryMock(givenEventMeshSubManagerMock) @@ -298,15 +300,15 @@ func Test_reconcileEventMeshSubManager(t *testing.T) { givenEventing.Status.BackendConfigHash = tc.givenHashBefore // when - err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing) + err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing, logger) if err != nil && tc.givenShouldRetry { // This is to test the scenario where initialization of eventMeshSubManager was successful but // starting the eventMeshSubManager failed. So on next try it should again try to start the eventMeshSubManager. - err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing) + err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing, logger) } if tc.givenUpdateTest { // Run reconcile again with newBackendConfig: - err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing) + err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing, logger) require.NoError(t, err) } @@ -435,6 +437,8 @@ func Test_reconcileEventMeshSubManager_ReadClusterDomain(t *testing.T) { testEnv := NewMockedUnitTestEnvironment(t, tc.givenEventing, givenOauthSecret) testEnv.Reconciler.backendConfig = *givenBackendConfig + logger := testEnv.Reconciler.logger.WithContext().Named(ControllerName) + givenEventMeshSubManagerMock := tc.givenEventMeshSubManagerMock() givenManagerFactoryMock := tc.givenManagerFactoryMock(givenEventMeshSubManagerMock) givenEventingManagerMock := tc.givenEventingManagerMock() @@ -450,7 +454,7 @@ func Test_reconcileEventMeshSubManager_ReadClusterDomain(t *testing.T) { testEnv.Reconciler.eventMeshSubManager = nil // when - err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, tc.givenEventing) + err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, tc.givenEventing, logger) // then require.NoError(t, err) diff --git a/internal/controller/operator/eventing/integrationtests/controller/integration_test.go b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go index 71512b372..0f5d1900b 100644 --- a/internal/controller/operator/eventing/integrationtests/controller/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go @@ -90,7 +90,7 @@ func Test_CreateEventingCR_NATS(t *testing.T) { ), givenNATSReady: false, wantMatches: gomega.And( - matchers.HaveStatusWarning(), + matchers.HaveStatusError(), matchers.HaveNATSNotAvailableCondition(), matchers.HaveFinalizer(), ), @@ -593,12 +593,13 @@ func Test_WatcherEventingCRK8sObjects(t *testing.T) { func Test_CreateEventingCR_EventMesh(t *testing.T) { testCases := []struct { - name string - givenEventing *operatorv1alpha1.Eventing - givenDeploymentReady bool - shouldFailSubManager bool - wantMatches gomegatypes.GomegaMatcher - wantEnsureK8sObjects bool + name string + givenEventing *operatorv1alpha1.Eventing + givenDeploymentReady bool + shouldFailSubManager bool + shouldEventMeshSecretNotFound bool + wantMatches gomegatypes.GomegaMatcher + wantEnsureK8sObjects bool }{ { name: "Eventing CR should have error state when subscription manager is not ready", @@ -610,11 +611,26 @@ func Test_CreateEventingCR_EventMesh(t *testing.T) { wantMatches: gomega.And( matchers.HaveStatusError(), matchers.HaveEventMeshSubManagerNotReadyCondition( - "failed to get EventMesh secret: Secret \"test-secret-name1\" not found"), + "failed to sync Publisher Proxy secret: unexpected error"), matchers.HaveFinalizer(), ), shouldFailSubManager: true, }, + { + name: "Eventing CR should have warning state when EventMesh secret is missing", + givenEventing: utils.NewEventingCR( + utils.WithEventMeshBackend("test-secret-name2"), + utils.WithEventingPublisherData(1, 1, "199m", "99Mi", "399m", "199Mi"), + utils.WithEventingEventTypePrefix("test-prefix"), + ), + wantMatches: gomega.And( + matchers.HaveStatusWarning(), + matchers.HaveEventMeshSubManagerNotReadyCondition( + eventingcontroller.EventMeshSecretMissingMessage), + matchers.HaveFinalizer(), + ), + shouldEventMeshSecretNotFound: true, + }, { name: "Eventing CR should have ready state when all deployment replicas are ready", givenEventing: utils.NewEventingCR( @@ -667,18 +683,30 @@ func Test_CreateEventingCR_EventMesh(t *testing.T) { // create eventing-webhook-auth secret. testEnvironment.EnsureOAuthSecretCreated(t, tc.givenEventing) - if !tc.shouldFailSubManager { + if !tc.shouldEventMeshSecretNotFound { // create EventMesh secret. testEnvironment.EnsureEventMeshSecretCreated(t, tc.givenEventing) } + originalKubeClient := testEnvironment.KubeClient + if tc.shouldFailSubManager { + mockedKubeClient := &MockKubeClient{ + Client: originalKubeClient, + } + testEnvironment.KubeClient = mockedKubeClient + testEnvironment.Reconciler.SetKubeClient(mockedKubeClient) + } + // when // create Eventing CR. testEnvironment.EnsureK8sResourceCreated(t, tc.givenEventing) defer func() { + testEnvironment.KubeClient = originalKubeClient + testEnvironment.Reconciler.SetKubeClient(originalKubeClient) + testEnvironment.EnsureEventingResourceDeletion(t, tc.givenEventing.Name, givenNamespace) - if !*testEnvironment.EnvTestInstance.UseExistingCluster && !tc.shouldFailSubManager { + if !*testEnvironment.EnvTestInstance.UseExistingCluster && !tc.shouldFailSubManager && !tc.shouldEventMeshSecretNotFound { testEnvironment.EnsureDeploymentDeletion(t, eventing.GetPublisherDeploymentName(*tc.givenEventing), givenNamespace) } testEnvironment.EnsureNamespaceDeleted(t, givenNamespace) @@ -1080,3 +1108,7 @@ func (mkc *MockKubeClient) GetCRD(ctx context.Context, name string) (*kapiextens } return nil, notFoundError } + +func (mkc *MockKubeClient) PatchApply(ctx context.Context, object client.Object) error { + return fmt.Errorf("unexpected error") +} diff --git a/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go index 057d2e7ac..b3af6d54e 100644 --- a/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go @@ -120,7 +120,7 @@ func Test_DeletionOfPublisherResourcesWhenNATSNotEnabled(t *testing.T) { // then // wait until Eventing CR status is Error. testEnvironment.GetEventingAssert(g, givenEventing).Should(gomega.And( - matchers.HaveStatusError(), + matchers.HaveStatusWarning(), matchers.HaveNATSNotAvailableConditionWith("NATS module has to be installed: customresourcedefinitions.apiextensions.k8s.io \"nats.operator.kyma-project.io\" not found"), ))