From cb1501f71654d75f25348e0310fa805ddf5acc99 Mon Sep 17 00:00:00 2001 From: Marco Bebway Date: Wed, 6 Dec 2023 14:50:52 +0100 Subject: [PATCH 01/17] Add make target to clean the go test cache (#284) --- .gitignore | 3 ++- Makefile | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5a270867..1c9ca1dc 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ module-template.yaml eventing-manager.yaml module-config.yaml -.env.dev +**/.env +**/.env.dev diff --git a/Makefile b/Makefile index deda1e5a..5eb988a2 100644 --- a/Makefile +++ b/Makefile @@ -323,3 +323,8 @@ $(TABLE_GEN): $(LOCALBIN) .PHONY: crd-docs-gen crd-docs-gen: tablegen ## Generates CRD spec into docs folder ${TABLE_GEN} --crd-filename ./config/crd/bases/operator.kyma-project.io_eventings.yaml --md-filename ./docs/user/02-configuration.md + +# clean-testcache cleans the go test cache. +.PHONY: clean-testcache +clean-testcache: + go clean -testcache From a5cadce5afc0eefc2adbf10e1e9e6a1782954faf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 09:20:53 +0100 Subject: [PATCH 02/17] Bump actions/setup-go from 4 to 5 (#287) Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5. - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](https://github.com/actions/setup-go/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-go dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint.yml | 2 +- .github/workflows/sink.yml | 2 +- .github/workflows/test.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 25615703..b714c580 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -17,7 +17,7 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '1.21' cache: false diff --git a/.github/workflows/sink.yml b/.github/workflows/sink.yml index 28105645..b6bd08e0 100644 --- a/.github/workflows/sink.yml +++ b/.github/workflows/sink.yml @@ -35,7 +35,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@v5 with: go-version: 1.19 cache: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a706597e..c2768a5b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - uses: actions/setup-go@v4 + - uses: actions/setup-go@v5 with: go-version: '1.21' cache: false From e4b79e4d2f95f43b023907825587cd5cec5f746c Mon Sep 17 00:00:00 2001 From: Mansur Uralov Date: Thu, 7 Dec 2023 11:32:51 +0100 Subject: [PATCH 03/17] Allow empty backend (#274) * Allow empty backend w/o defaulting * Set warning state for empty backend Make state warning and BackendAvailable condition false for empty backend config * Set Warning if NATS module is missing * Set Warning state if EventMes secret missing * Set Warning state if EventMes secret missing * Fix failing tests * Fix linting errors * Forbid deleting backend configuration It is not allowed to delete existing backend config, but evneting CR can be created with empty backend config. * Revert golangci-lint configuration * Implement int tests Create integration tests for backend config deletion validation * Revert the documentation Auto generation of doc is breaking the documentation * Move Retrieving EventMesh Secret * Improve for review comments --- .golangci.yaml | 2 + api/operator/v1alpha1/eventing_types.go | 14 ++- api/operator/v1alpha1/eventing_types_test.go | 8 +- api/operator/v1alpha1/status.go | 8 +- .../v1alpha1/zz_generated.deepcopy.go | 8 +- .../operator.kyma-project.io_eventings.yaml | 23 +--- docs/user/02-configuration.md | 2 +- hack/e2e/common/fixtures/fixtures.go | 4 +- .../operator/eventing/controller.go | 31 +++++- .../controller/operator/eventing/eventmesh.go | 11 +- .../operator/eventing/eventmesh_test.go | 44 ++------ .../controller/integration_test.go | 73 +++++++++++-- .../nats_disabled/integration_test.go | 2 +- .../validation/integration_test.go | 103 +++++++++++++++++- .../controller/operator/eventing/status.go | 35 +++++- pkg/env/nats_config_test.go | 2 +- test/matchers/matchers.go | 13 ++- test/utils/integration/integration.go | 4 + test/utils/options.go | 13 ++- test/utils/utils.go | 2 +- 20 files changed, 301 insertions(+), 101 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 1de839f0..ee4bad9b 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -137,6 +137,8 @@ linters-settings: alias: kctrl - pkg: sigs.k8s.io/controller-runtime/pkg/log alias: kctrllog + - pkg: sigs.k8s.io/controller-runtime/pkg/client + alias: kctrlclient - pkg: k8s.io/api/autoscaling/v1 alias: kautoscalingv1 - pkg: k8s.io/api/autoscaling/v2 diff --git a/api/operator/v1alpha1/eventing_types.go b/api/operator/v1alpha1/eventing_types.go index c7b21be0..5bead265 100644 --- a/api/operator/v1alpha1/eventing_types.go +++ b/api/operator/v1alpha1/eventing_types.go @@ -33,7 +33,7 @@ const ( StateProcessing string = "Processing" StateWarning string = "Warning" - ConditionNATSAvailable ConditionType = "NATSAvailable" + ConditionBackendAvailable ConditionType = "BackendAvailable" ConditionPublisherProxyReady ConditionType = "PublisherProxyReady" ConditionWebhookReady ConditionType = "WebhookReady" ConditionSubscriptionManagerReady ConditionType = "SubscriptionManagerReady" @@ -48,8 +48,9 @@ const ( ConditionReasonDeployed ConditionReason = "Deployed" ConditionReasonDeployedFailed ConditionReason = "DeployFailed" ConditionReasonDeploymentStatusSyncFailed ConditionReason = "DeploymentStatusSyncFailed" - ConditionReasonNATSAvailable ConditionReason = "Available" - ConditionReasonNATSNotAvailable ConditionReason = "NotAvailable" + ConditionReasonNATSAvailable ConditionReason = "NATSAvailable" + ConditionReasonNATSNotAvailable ConditionReason = "NATSUnavailable" + ConditionReasonBackendNotSpecified ConditionReason = "BackendNotSpecified" ConditionReasonForbidden ConditionReason = "Forbidden" ConditionReasonWebhookFailed ConditionReason = "WebhookFailed" ConditionReasonWebhookReady ConditionReason = "Ready" @@ -63,6 +64,7 @@ const ( ConditionPublisherProxyProcessingMessage = "Eventing publisher proxy deployment is in progress" ConditionSubscriptionManagerReadyMessage = "Subscription manager is ready" ConditionSubscriptionManagerStoppedMessage = "Subscription manager is stopped" + ConditionBackendNotSpecifiedMessage = "Backend config is not provided. Please specify a backend." // subscription manager reasons. ConditionReasonEventMeshSubManagerReady ConditionReason = "EventMeshSubscriptionManagerReady" @@ -82,7 +84,8 @@ type Eventing struct { kmetav1.TypeMeta `json:",inline"` kmetav1.ObjectMeta `json:"metadata,omitempty"` - // +kubebuilder:default:={backend:{type:"NATS", config:{natsStreamStorageType:"File", natsStreamReplicas:3, natsStreamMaxSize:"700Mi", natsMaxMsgsPerTopic:1000000}}, logging:{logLevel:Info}, publisher:{replicas:{min:2,max:2}, resources:{limits:{cpu:"500m",memory:"512Mi"}, requests:{cpu:"40m",memory:"256Mi"}}}} + // +kubebuilder:default:={logging:{logLevel:Info}, publisher:{replicas:{min:2,max:2}, resources:{limits:{cpu:"500m",memory:"512Mi"}, requests:{cpu:"40m",memory:"256Mi"}}}} + // +kubebuilder:validation:XValidation:rule="!(oldSelf!=null && has(oldSelf.backend)) || has(self.backend)", message="backend config cannot be deleted" Spec EventingSpec `json:"spec,omitempty"` Status EventingStatus `json:"status,omitempty"` } @@ -98,9 +101,8 @@ type EventingStatus struct { // EventingSpec defines the desired state of Eventing. type EventingSpec struct { // Backend defines the active backend used by Eventing. - // +kubebuilder:default:={type:"NATS", config:{natsStreamStorageType:"File", natsStreamReplicas:3, natsStreamMaxSize:"700Mi", natsMaxMsgsPerTopic:1000000}} // +kubebuilder:validation:XValidation:rule=" (self.type != 'EventMesh') || ((self.type == 'EventMesh') && (self.config.eventMeshSecret != ''))", message="secret cannot be empty if EventMesh backend is used" - Backend Backend `json:"backend"` + Backend *Backend `json:"backend,omitempty"` // Publisher defines the configurations for eventing-publisher-proxy. // +kubebuilder:default:={replicas:{min:2,max:2}, resources:{limits:{cpu:"500m",memory:"512Mi"}, requests:{cpu:"40m",memory:"256Mi"}}} diff --git a/api/operator/v1alpha1/eventing_types_test.go b/api/operator/v1alpha1/eventing_types_test.go index a53e2e0f..8cbc3b79 100644 --- a/api/operator/v1alpha1/eventing_types_test.go +++ b/api/operator/v1alpha1/eventing_types_test.go @@ -19,7 +19,7 @@ func TestSyncStatusActiveBackend(t *testing.T) { name: "it should set ActiveBackend to NATS", givenEventing: &Eventing{ Spec: EventingSpec{ - Backend: Backend{Type: NatsBackendType}, + Backend: &Backend{Type: NatsBackendType}, }, Status: EventingStatus{}, }, @@ -29,7 +29,7 @@ func TestSyncStatusActiveBackend(t *testing.T) { name: "it should set ActiveBackend to EventMesh", givenEventing: &Eventing{ Spec: EventingSpec{ - Backend: Backend{Type: EventMeshBackendType}, + Backend: &Backend{Type: EventMeshBackendType}, }, Status: EventingStatus{}, }, @@ -65,7 +65,7 @@ func TestIsSpecBackendTypeChanged(t *testing.T) { name: "it should return false if backend is not changed", givenEventing: &Eventing{ Spec: EventingSpec{ - Backend: Backend{Type: NatsBackendType}, + Backend: &Backend{Type: NatsBackendType}, }, Status: EventingStatus{ ActiveBackend: NatsBackendType, @@ -77,7 +77,7 @@ func TestIsSpecBackendTypeChanged(t *testing.T) { name: "it should return true if backend is changed", givenEventing: &Eventing{ Spec: EventingSpec{ - Backend: Backend{Type: NatsBackendType}, + Backend: &Backend{Type: NatsBackendType}, }, Status: EventingStatus{ ActiveBackend: EventMeshBackendType, diff --git a/api/operator/v1alpha1/status.go b/api/operator/v1alpha1/status.go index f79fda59..bff8971d 100644 --- a/api/operator/v1alpha1/status.go +++ b/api/operator/v1alpha1/status.go @@ -8,11 +8,11 @@ import ( kmetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (es *EventingStatus) UpdateConditionNATSAvailable(status kmetav1.ConditionStatus, reason ConditionReason, +func (es *EventingStatus) UpdateConditionBackendAvailable(status kmetav1.ConditionStatus, reason ConditionReason, message string, ) { condition := kmetav1.Condition{ - Type: string(ConditionNATSAvailable), + Type: string(ConditionBackendAvailable), Status: status, LastTransitionTime: kmetav1.Now(), Reason: string(reason), @@ -80,7 +80,7 @@ func (es *EventingStatus) SetSubscriptionManagerReadyConditionToTrue() { func (es *EventingStatus) SetStateReady() { es.State = StateReady - es.UpdateConditionNATSAvailable(kmetav1.ConditionTrue, ConditionReasonNATSAvailable, ConditionNATSAvailableMessage) + es.UpdateConditionBackendAvailable(kmetav1.ConditionTrue, ConditionReasonNATSAvailable, ConditionNATSAvailableMessage) es.UpdateConditionPublisherProxyReady(kmetav1.ConditionTrue, ConditionReasonDeployed, ConditionPublisherProxyReadyMessage) } @@ -89,7 +89,7 @@ func (ns *EventingStatus) SetStateWarning() { } func (es *EventingStatus) SetNATSAvailableConditionToTrue() { - es.UpdateConditionNATSAvailable(kmetav1.ConditionTrue, ConditionReasonNATSAvailable, ConditionNATSAvailableMessage) + es.UpdateConditionBackendAvailable(kmetav1.ConditionTrue, ConditionReasonNATSAvailable, ConditionNATSAvailableMessage) } func (es *EventingStatus) SetSubscriptionManagerReadyConditionToFalse(reason ConditionReason, message string) { diff --git a/api/operator/v1alpha1/zz_generated.deepcopy.go b/api/operator/v1alpha1/zz_generated.deepcopy.go index 28204a61..a7bd0a7a 100644 --- a/api/operator/v1alpha1/zz_generated.deepcopy.go +++ b/api/operator/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ limitations under the License. package v1alpha1 import ( - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -120,7 +120,11 @@ func (in *EventingList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EventingSpec) DeepCopyInto(out *EventingSpec) { *out = *in - in.Backend.DeepCopyInto(&out.Backend) + if in.Backend != nil { + in, out := &in.Backend, &out.Backend + *out = new(Backend) + (*in).DeepCopyInto(*out) + } in.Publisher.DeepCopyInto(&out.Publisher) out.Logging = in.Logging if in.Annotations != nil { diff --git a/config/crd/bases/operator.kyma-project.io_eventings.yaml b/config/crd/bases/operator.kyma-project.io_eventings.yaml index 67b7fc49..3513c2cc 100644 --- a/config/crd/bases/operator.kyma-project.io_eventings.yaml +++ b/config/crd/bases/operator.kyma-project.io_eventings.yaml @@ -47,13 +47,6 @@ spec: type: object spec: default: - backend: - config: - natsMaxMsgsPerTopic: 1000000 - natsStreamMaxSize: 700Mi - natsStreamReplicas: 3 - natsStreamStorageType: File - type: NATS logging: logLevel: Info publisher: @@ -67,7 +60,7 @@ spec: requests: cpu: 40m memory: 256Mi - description: EventingSpec defines the desired state of Eventing + description: EventingSpec defines the desired state of Eventing. properties: annotations: additionalProperties: @@ -75,13 +68,6 @@ spec: description: Annotations allows to add annotations to resources. type: object backend: - default: - config: - natsMaxMsgsPerTopic: 1000000 - natsStreamMaxSize: 700Mi - natsStreamReplicas: 3 - natsStreamStorageType: File - type: NATS description: Backend defines the active backend used by Eventing. properties: config: @@ -261,11 +247,12 @@ spec: type: object type: object type: object - required: - - backend type: object + x-kubernetes-validations: + - message: backend config cannot be deleted + rule: '!(oldSelf!=null && has(oldSelf.backend)) || has(self.backend)' status: - description: EventingStatus defines the observed state of Eventing + description: EventingStatus defines the observed state of Eventing. properties: activeBackend: type: string diff --git a/docs/user/02-configuration.md b/docs/user/02-configuration.md index 65a72b6d..f88b228f 100644 --- a/docs/user/02-configuration.md +++ b/docs/user/02-configuration.md @@ -31,7 +31,7 @@ Use the following sample CRs as guidance. Each can be applied immediately when y | Parameter | Type | Description | |----------------------------------------------------------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **annotations** | map\[string\]string | Annotations allows to add annotations to resources. | -| **backend** (required) | object | Backend defines the active backend used by Eventing. | +| **backend** | object | Backend defines the active backend used by Eventing. | | **backend.​config** | object | Config defines configuration for eventing backend. | | **backend.​config.​domain** | string | Domain defines the cluster public domain used to configure the EventMesh Subscriptions and their corresponding ApiRules. | | **backend.​config.​eventMeshSecret** | string | EventMeshSecret defines the namespaced name of K8s Secret containing EventMesh credentials. The format of name is "namespace/name". | diff --git a/hack/e2e/common/fixtures/fixtures.go b/hack/e2e/common/fixtures/fixtures.go index 01de7c2b..4db73194 100644 --- a/hack/e2e/common/fixtures/fixtures.go +++ b/hack/e2e/common/fixtures/fixtures.go @@ -63,7 +63,7 @@ func EventingNATSCR() *operatorv1alpha1.Eventing { Namespace: NamespaceName, }, Spec: operatorv1alpha1.EventingSpec{ - Backend: operatorv1alpha1.Backend{ + Backend: &operatorv1alpha1.Backend{ Type: "NATS", Config: operatorv1alpha1.BackendConfig{ NATSStreamStorageType: "File", @@ -88,7 +88,7 @@ func EventingEventMeshCR() *operatorv1alpha1.Eventing { Namespace: NamespaceName, }, Spec: operatorv1alpha1.EventingSpec{ - Backend: operatorv1alpha1.Backend{ + Backend: &operatorv1alpha1.Backend{ Type: "EventMesh", Config: operatorv1alpha1.BackendConfig{ EventMeshSecret: fmt.Sprintf("%s/%s", EventMeshSecretNamespace, EventMeshSecretName), diff --git a/internal/controller/operator/eventing/controller.go b/internal/controller/operator/eventing/controller.go index e9efdc71..85494795 100644 --- a/internal/controller/operator/eventing/controller.go +++ b/internal/controller/operator/eventing/controller.go @@ -379,6 +379,12 @@ func (r *Reconciler) handleEventingDeletion(ctx context.Context, eventing *opera return kctrl.Result{}, nil } + if eventing.Spec.Backend == nil { + // backend config can only be empty during creation and nothing is created if it is missing. + // Hence, eventing can be safely removed. + return r.removeFinalizer(ctx, eventing) + } + // check if subscription resources exist exists, err := r.eventingManager.SubscriptionExists(ctx) if err != nil { @@ -441,6 +447,12 @@ func (r *Reconciler) handleEventingReconcile(ctx context.Context, // set state processing if not set yet r.InitStateProcessing(eventing) + if eventing.Spec.Backend == nil { + return kctrl.Result{Requeue: true}, r.syncStatusForEmptyBackend(ctx, + operatorv1alpha1.ConditionReasonBackendNotSpecified, + operatorv1alpha1.ConditionBackendNotSpecifiedMessage, + eventing, log) + } // sync webhooks CABundle. if err := r.reconcileWebhooksWithCABundle(ctx); err != nil { @@ -514,9 +526,13 @@ func (r *Reconciler) reconcileNATSBackend(ctx context.Context, eventing *operato // into CrashLoopBackOff. log.Infof("NATS module not enabled, deleting publisher proxy resources") delErr := r.eventingManager.DeletePublisherProxyResources(ctx, eventing) + if delErr != nil { + return kctrl.Result{}, delErr + } // update the Eventing CR status. notFoundErr := fmt.Errorf("NATS module has to be installed: %v", err) - return kctrl.Result{}, errors.Join(r.syncStatusWithNATSErr(ctx, eventing, notFoundErr, log), delErr) + return kctrl.Result{}, r.syncStatusWithNATSState(ctx, operatorv1alpha1.StateWarning, eventing, + notFoundErr, log) } return kctrl.Result{}, err } @@ -596,8 +612,19 @@ func (r *Reconciler) reconcileEventMeshBackend(ctx context.Context, eventing *op return kctrl.Result{}, r.syncStatusWithSubscriptionManagerErr(ctx, eventing, apiRuleMissingErr, log) } + // retrieve secret used to authenticate with EventMesh + eventMeshSecret, err := r.kubeClient.GetSecret(ctx, eventing.Spec.Backend.Config.EventMeshSecret) + if err != nil { + if kerrors.IsNotFound(err) { + return kctrl.Result{}, r.syncSubManagerStatusWithNATSState(ctx, operatorv1alpha1.StateWarning, eventing, + fmt.Errorf(EventMeshSecretMissingMessage), log) + } + return kctrl.Result{}, r.syncStatusWithSubscriptionManagerErr(ctx, eventing, + fmt.Errorf("failed to get EventMesh secret: %v", err), log) + } + // Start the EventMesh subscription controller - err = r.reconcileEventMeshSubManager(ctx, eventing) + err = r.reconcileEventMeshSubManager(ctx, eventing, eventMeshSecret, 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 cfc37cbc..cd1a092f 100644 --- a/internal/controller/operator/eventing/eventmesh.go +++ b/internal/controller/operator/eventing/eventmesh.go @@ -36,17 +36,16 @@ type oauth2Credentials struct { certsURL []byte } -func (r *Reconciler) reconcileEventMeshSubManager(ctx context.Context, eventing *v1alpha1.Eventing) error { +const EventMeshSecretMissingMessage = "The specified EventMesh secret is not found. Please provide an existing secret." + +func (r *Reconciler) reconcileEventMeshSubManager(ctx context.Context, eventing *v1alpha1.Eventing, + eventMeshSecret *kcorev1.Secret, log *zap.SugaredLogger, +) error { // gets oauth2ClientID and secret and stops the EventMesh subscription manager if changed err := r.syncOauth2ClientIDAndSecret(ctx, eventing) if err != nil { return errors.Errorf("failed to sync OAuth secret: %v", err) } - // retrieve secret to authenticate with EventMesh - eventMeshSecret, err := r.kubeClient.GetSecret(ctx, eventing.Spec.Backend.Config.EventMeshSecret) - if err != nil { - return errors.Errorf("failed to get EventMesh secret: %v", err) - } // CreateOrUpdate deployment for publisher proxy secret secretForPublisher, err := r.SyncPublisherProxySecret(ctx, eventMeshSecret) if err != nil { diff --git a/internal/controller/operator/eventing/eventmesh_test.go b/internal/controller/operator/eventing/eventmesh_test.go index efa1e4b7..4d017295 100644 --- a/internal/controller/operator/eventing/eventmesh_test.go +++ b/internal/controller/operator/eventing/eventmesh_test.go @@ -92,30 +92,6 @@ func Test_reconcileEventMeshSubManager(t *testing.T) { wantError: errors.New("failed to sync OAuth secret"), wantHashAfter: int64(0), }, - { - name: "it should do nothing because failed syncing EventMesh secret", - givenIsEventMeshSubManagerStarted: true, - givenHashBefore: int64(0), - givenEventMeshSubManagerMock: func() *submgrmanagermocks.Manager { - eventMeshSubManagerMock := new(submgrmanagermocks.Manager) - eventMeshSubManagerMock.On("Stop", mock.Anything).Return(nil).Once() - return eventMeshSubManagerMock - }, - givenEventingManagerMock: func() *eventingmocks.Manager { - return nil - }, - givenManagerFactoryMock: func(_ *submgrmanagermocks.Manager) *submgrmocks.ManagerFactory { - return nil - }, - givenKubeClientMock: func() k8s.Client { - mockKubeClient := new(k8smocks.Client) - mockKubeClient.On("GetSecret", ctx, mock.Anything, mock.Anything).Return(nil, - errors.New("failed getting secret")).Once() - return mockKubeClient - }, - wantError: errors.New("failed to get EventMesh secret"), - wantHashAfter: int64(0), - }, { name: "it should do nothing because failed sync Publisher Proxy secret", givenIsEventMeshSubManagerStarted: true, @@ -274,6 +250,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) @@ -296,15 +274,18 @@ func Test_reconcileEventMeshSubManager(t *testing.T) { givenEventing.Status.BackendConfigHash = tc.givenHashBefore // when - err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing) + + eventMeshSecret := utils.NewEventMeshSecret("eventing-backend", givenEventing.Namespace) + + err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing, eventMeshSecret, 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, eventMeshSecret, logger) } if tc.givenUpdateTest { // Run reconcile again with newBackendConfig: - err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing) + err = testEnv.Reconciler.reconcileEventMeshSubManager(ctx, givenEventing, eventMeshSecret, logger) require.NoError(t, err) } @@ -386,8 +367,6 @@ func Test_reconcileEventMeshSubManager_ReadClusterDomain(t *testing.T) { givenKubeClientMock: func() (k8s.Client, *k8smocks.Client) { mockKubeClient := new(k8smocks.Client) mockKubeClient.On("PatchApply", ctx, mock.Anything).Return(nil).Once() - mockKubeClient.On("GetSecret", ctx, mock.Anything, mock.Anything).Return( - utils.NewEventMeshSecret("test-secret", namespace), nil).Once() return mockKubeClient, mockKubeClient }, }, @@ -419,8 +398,6 @@ func Test_reconcileEventMeshSubManager_ReadClusterDomain(t *testing.T) { mockKubeClient := new(k8smocks.Client) mockKubeClient.On("GetConfigMap", ctx, mock.Anything, mock.Anything).Return(givenConfigMap, nil).Once() mockKubeClient.On("PatchApply", ctx, mock.Anything).Return(nil).Once() - mockKubeClient.On("GetSecret", ctx, mock.Anything, mock.Anything).Return( - utils.NewEventMeshSecret("test-secret", namespace), nil).Once() return mockKubeClient, mockKubeClient }, }, @@ -433,6 +410,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() @@ -448,7 +427,8 @@ func Test_reconcileEventMeshSubManager_ReadClusterDomain(t *testing.T) { testEnv.Reconciler.eventMeshSubManager = nil // when - err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, tc.givenEventing) + eventMeshSecret := utils.NewEventMeshSecret("test-secret", tc.givenEventing.Namespace) + err := testEnv.Reconciler.reconcileEventMeshSubManager(ctx, tc.givenEventing, eventMeshSecret, 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 422b9eb5..eeeeb894 100644 --- a/internal/controller/operator/eventing/integrationtests/controller/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go @@ -16,6 +16,7 @@ import ( kapiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" kmetav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kctrlclient "sigs.k8s.io/controller-runtime/pkg/client" eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" operatorv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" @@ -146,12 +147,28 @@ func Test_CreateEventingCR_NATS(t *testing.T) { ), givenNATSCRDMissing: true, wantMatches: 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"), matchers.HaveFinalizer(), ), }, + { + name: "Eventing CR should have warning state when backend config is empty", + givenEventing: utils.NewEventingCR( + utils.WithEventingEmptyBackend(), + utils.WithEventingPublisherData(2, 2, "199m", "99Mi", "399m", "199Mi"), + ), + givenNATS: natstestutils.NewNATSCR( + natstestutils.WithNATSCRDefaults(), + ), + wantMatches: gomega.And( + matchers.HaveStatusWarning(), + matchers.HaveBackendNotAvailableConditionWith(operatorv1alpha1.ConditionBackendNotSpecifiedMessage, + operatorv1alpha1.ConditionReasonBackendNotSpecified), + matchers.HaveFinalizer(), + ), + }, } for _, tc := range testCases { @@ -202,13 +219,13 @@ func Test_CreateEventingCR_NATS(t *testing.T) { // then // check Eventing CR status. testEnvironment.GetEventingAssert(g, tc.givenEventing).Should(tc.wantMatches) - if tc.givenDeploymentReady { + if tc.givenDeploymentReady && tc.givenEventing.Spec.Backend != nil { // check if EPP deployment, HPA resources created and values are reflected including owner reference. ensureEPPDeploymentAndHPAResources(t, tc.givenEventing, testEnvironment) // TODO: ensure NATS Backend config is reflected. Done as subscription controller is implemented. } - if tc.wantEnsureK8sObjects { + if tc.wantEnsureK8sObjects && tc.givenEventing.Spec.Backend != nil { // check if EPP resources exists. ensureK8sResources(t, tc.givenEventing, testEnvironment) // check if webhook configurations are updated with correct CABundle. @@ -574,12 +591,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", @@ -591,11 +609,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( @@ -648,18 +681,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) @@ -1061,3 +1106,7 @@ func (mkc *MockKubeClient) GetCRD(ctx context.Context, name string) (*kapiextens } return nil, notFoundError } + +func (mkc *MockKubeClient) PatchApply(ctx context.Context, object kctrlclient.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 11a9052c..40c8f746 100644 --- a/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go @@ -117,7 +117,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"), )) diff --git a/internal/controller/operator/eventing/integrationtests/validation/integration_test.go b/internal/controller/operator/eventing/integrationtests/validation/integration_test.go index 71d1ba61..6cbedbe0 100644 --- a/internal/controller/operator/eventing/integrationtests/validation/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/validation/integration_test.go @@ -686,6 +686,20 @@ func Test_Validate_CreateEventing(t *testing.T) { }, }, }, + { + name: `validation of spec.backend is empty`, + givenUnstructuredEventing: unstructured.Unstructured{ + Object: map[string]any{ + kind: kindEventing, + apiVersion: apiVersionEventing, + metadata: map[string]any{ + name: test.GetRandK8sName(7), + namespace: test.GetRandK8sName(7), + }, + spec: map[string]any{}, + }, + }, + }, } for _, tc := range testCases { @@ -714,6 +728,93 @@ func Test_Validate_CreateEventing(t *testing.T) { } } +// Test_Validate_UpdateEventing updates an eventing CR with correct and purposefully incorrect values, and compares +// the error that was caused by this against a wantErrMsg to test the eventing CR validation rules. +func Test_Validate_UpdateEventing(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + givenOriginalUnstructuredEventing unstructured.Unstructured + givenTargetUnstructuredEventing unstructured.Unstructured + wantErrMsg string + }{ + { + name: `validation of spec.backend deletion, which is not allowed`, + givenOriginalUnstructuredEventing: unstructured.Unstructured{ + Object: map[string]any{ + kind: kindEventing, + apiVersion: apiVersionEventing, + metadata: map[string]any{ + name: "test-name-777", + namespace: "test-namespace-777", + }, + spec: map[string]any{ + backend: map[string]any{ + backendType: typeNats, + }, + publisher: map[string]any{ + replicas: map[string]any{ + min: 2, + max: 3, + }, + }, + }, + }, + }, + givenTargetUnstructuredEventing: unstructured.Unstructured{ + Object: map[string]any{ + kind: kindEventing, + apiVersion: apiVersionEventing, + metadata: map[string]any{ + name: "test-name-777", + namespace: "test-namespace-777", + }, + spec: map[string]any{ + publisher: map[string]any{ + replicas: map[string]any{ + min: 2, + max: 3, + }, + }, + }, + }, + }, + wantErrMsg: "backend config cannot be deleted", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + // given + testEnvironment.EnsureNamespaceCreation(t, tc.givenOriginalUnstructuredEventing.GetNamespace()) + + // when + err := testEnvironment.CreateUnstructuredK8sResource(&tc.givenOriginalUnstructuredEventing) + require.NoError(t, err, "Expected error message to be empty but got error instead.") + + tc.givenTargetUnstructuredEventing.SetResourceVersion(tc.givenOriginalUnstructuredEventing.GetResourceVersion()) + + err = testEnvironment.UpdateUnstructuredK8sResource(&tc.givenTargetUnstructuredEventing) + + // then + if tc.wantErrMsg == noError { + require.NoError(t, err, "Expected error message to be empty but got error instead."+ + " Check the validation rule of the eventing CR.") + } else { + require.Error(t, err, fmt.Sprintf("Expected the following error message: \n \" %s \" \n"+ + " but got no error. Check the validation rules of the eventing CR.", tc.wantErrMsg)) + + require.Contains(t, err.Error(), tc.wantErrMsg, "Expected a specific error message"+ + " but messages do not match. Check the validation rules of the eventing CR.") + } + }) + } +} + // Test_Validate_CreateEventing creates an eventing CR with correct and purposefully incorrect values, and compares // the error that was caused by this against a wantErrMsg to test the eventing CR validation rules. func Test_Validate_Defaulting(t *testing.T) { @@ -737,7 +838,6 @@ func Test_Validate_Defaulting(t *testing.T) { }, }, wantMatches: gomega.And( - testmatchers.HaveBackendTypeNats(defaultBackendConfig()), testmatchers.HavePublisher(defaultPublisher()), testmatchers.HavePublisherResources(defaultPublisherResources()), testmatchers.HaveLogging(defaultLogging()), @@ -757,7 +857,6 @@ func Test_Validate_Defaulting(t *testing.T) { }, }, wantMatches: gomega.And( - testmatchers.HaveBackendTypeNats(defaultBackendConfig()), testmatchers.HavePublisher(defaultPublisher()), testmatchers.HavePublisherResources(defaultPublisherResources()), testmatchers.HaveLogging(defaultLogging()), diff --git a/internal/controller/operator/eventing/status.go b/internal/controller/operator/eventing/status.go index 63562514..a11be7fc 100644 --- a/internal/controller/operator/eventing/status.go +++ b/internal/controller/operator/eventing/status.go @@ -27,15 +27,34 @@ func (es *Reconciler) InitStateProcessing(eventing *operatorv1alpha1.Eventing) { // Returns the relevant error. func (r *Reconciler) syncStatusWithNATSErr(ctx context.Context, eventing *operatorv1alpha1.Eventing, err error, log *zap.SugaredLogger, +) error { + return r.syncStatusWithNATSState(ctx, operatorv1alpha1.StateError, eventing, err, log) +} + +func (r *Reconciler) syncStatusWithNATSState(ctx context.Context, state string, + eventing *operatorv1alpha1.Eventing, err error, log *zap.SugaredLogger, ) error { // Set error state in status - eventing.Status.SetStateError() - eventing.Status.UpdateConditionNATSAvailable(kmetav1.ConditionFalse, operatorv1alpha1.ConditionReasonNATSNotAvailable, + eventing.Status.State = state + eventing.Status.UpdateConditionBackendAvailable(kmetav1.ConditionFalse, + operatorv1alpha1.ConditionReasonNATSNotAvailable, err.Error()) return errors.Join(err, r.syncEventingStatus(ctx, eventing, log)) } +func (r *Reconciler) syncStatusForEmptyBackend(ctx context.Context, reason operatorv1alpha1.ConditionReason, + message string, eventing *operatorv1alpha1.Eventing, log *zap.SugaredLogger, +) error { + // Set error state in status + eventing.Status.SetStateWarning() + eventing.Status.UpdateConditionBackendAvailable( + kmetav1.ConditionFalse, + operatorv1alpha1.ConditionReasonBackendNotSpecified, + message) + return r.syncEventingStatus(ctx, eventing, log) +} + // syncStatusWithPublisherProxyErr updates Publisher Proxy condition and sets an error state. // Returns the relevant error. func (r *Reconciler) syncStatusWithPublisherProxyErr(ctx context.Context, @@ -66,6 +85,18 @@ func (r *Reconciler) syncStatusWithSubscriptionManagerErr(ctx context.Context, operatorv1alpha1.ConditionReasonEventMeshSubManagerFailed, eventing, err, log) } +func (r *Reconciler) syncSubManagerStatusWithNATSState(ctx context.Context, state string, + eventing *operatorv1alpha1.Eventing, err error, log *zap.SugaredLogger, +) error { + // Set error state in status + eventing.Status.State = state + eventing.Status.UpdateConditionSubscriptionManagerReady(kmetav1.ConditionFalse, + operatorv1alpha1.ConditionReasonEventMeshSubManagerFailed, + err.Error()) + + return errors.Join(err, r.syncEventingStatus(ctx, eventing, log)) +} + func (r *Reconciler) syncStatusWithSubscriptionManagerErrWithReason(ctx context.Context, reason operatorv1alpha1.ConditionReason, eventing *operatorv1alpha1.Eventing, diff --git a/pkg/env/nats_config_test.go b/pkg/env/nats_config_test.go index 1a6df157..9072e955 100644 --- a/pkg/env/nats_config_test.go +++ b/pkg/env/nats_config_test.go @@ -43,7 +43,7 @@ func Test_GetNewNATSConfig(t *testing.T) { UID: "1234-5678-1234-5678", }, Spec: v1alpha1.EventingSpec{ - Backend: v1alpha1.Backend{ + Backend: &v1alpha1.Backend{ Type: v1alpha1.NatsBackendType, Config: v1alpha1.BackendConfig{ EventTypePrefix: "sap.kyma.custom", diff --git a/test/matchers/matchers.go b/test/matchers/matchers.go index f57c6aaa..948865ae 100644 --- a/test/matchers/matchers.go +++ b/test/matchers/matchers.go @@ -90,16 +90,25 @@ func HavePublisherProxyConditionForbiddenWithMsg(msg string) gomegatypes.GomegaM func HaveNATSAvailableCondition() gomegatypes.GomegaMatcher { return HaveCondition(kmetav1.Condition{ - Type: string(v1alpha1.ConditionNATSAvailable), + Type: string(v1alpha1.ConditionBackendAvailable), Status: kmetav1.ConditionTrue, Reason: string(v1alpha1.ConditionReasonNATSAvailable), Message: v1alpha1.ConditionNATSAvailableMessage, }) } +func HaveBackendNotAvailableConditionWith(message string, reason v1alpha1.ConditionReason) gomegatypes.GomegaMatcher { + return HaveCondition(kmetav1.Condition{ + Type: string(v1alpha1.ConditionBackendAvailable), + Status: kmetav1.ConditionFalse, + Reason: string(reason), + Message: message, + }) +} + func HaveNATSNotAvailableConditionWith(message string) gomegatypes.GomegaMatcher { return HaveCondition(kmetav1.Condition{ - Type: string(v1alpha1.ConditionNATSAvailable), + Type: string(v1alpha1.ConditionBackendAvailable), Status: kmetav1.ConditionFalse, Reason: string(v1alpha1.ConditionReasonNATSNotAvailable), Message: message, diff --git a/test/utils/integration/integration.go b/test/utils/integration/integration.go index f2fa5aad..1b7ee2e1 100644 --- a/test/utils/integration/integration.go +++ b/test/utils/integration/integration.go @@ -1144,6 +1144,10 @@ func (env TestEnvironment) CreateUnstructuredK8sResource(obj *unstructured.Unstr return env.k8sClient.Create(env.Context, obj) } +func (env TestEnvironment) UpdateUnstructuredK8sResource(obj *unstructured.Unstructured) error { + return env.k8sClient.Update(env.Context, obj) +} + func (env TestEnvironment) EnsureK8sUnStructResourceCreated(t *testing.T, obj *unstructured.Unstructured) { require.NoError(t, env.k8sClient.Create(env.Context, obj)) } diff --git a/test/utils/options.go b/test/utils/options.go index 9ba703fe..be8ae7fb 100644 --- a/test/utils/options.go +++ b/test/utils/options.go @@ -12,7 +12,7 @@ import ( func WithEventingCRMinimal() EventingOption { return func(e *v1alpha1.Eventing) error { e.Spec = v1alpha1.EventingSpec{ - Backend: v1alpha1.Backend{ + Backend: &v1alpha1.Backend{ Type: v1alpha1.NatsBackendType, }, } @@ -20,6 +20,13 @@ func WithEventingCRMinimal() EventingOption { } } +func WithEventingEmptyBackend() EventingOption { + return func(e *v1alpha1.Eventing) error { + e.Spec = v1alpha1.EventingSpec{} + return nil + } +} + func WithEventingCRName(name string) EventingOption { return func(e *v1alpha1.Eventing) error { e.Name = name @@ -78,7 +85,7 @@ func WithEventingPublisherData(minReplicas, maxReplicas int, requestCPU, request func WithEventingInvalidBackend() EventingOption { return func(e *v1alpha1.Eventing) error { e.Spec = v1alpha1.EventingSpec{ - Backend: v1alpha1.Backend{ + Backend: &v1alpha1.Backend{ Type: "invalid", }, } @@ -109,7 +116,7 @@ func WithEventingLogLevel(logLevel string) EventingOption { func WithEventMeshBackend(eventMeshSecretName string) EventingOption { return func(e *v1alpha1.Eventing) error { - e.Spec.Backend = v1alpha1.Backend{ + e.Spec.Backend = &v1alpha1.Backend{ Type: v1alpha1.EventMeshBackendType, Config: v1alpha1.BackendConfig{ EventMeshSecret: e.Namespace + "/" + eventMeshSecretName, diff --git a/test/utils/utils.go b/test/utils/utils.go index 53e0411a..2e4a804f 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -120,7 +120,7 @@ func NewEventingCR(opts ...EventingOption) *v1alpha1.Eventing { UID: "1234-5678-1234-5678", }, Spec: v1alpha1.EventingSpec{ - Backend: v1alpha1.Backend{ + Backend: &v1alpha1.Backend{ Type: v1alpha1.NatsBackendType, }, }, From 5ca4bf3d6469fab6aeff6d19e796245ddaf15d3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 19:28:51 +0100 Subject: [PATCH 04/17] Bump github.com/nats-io/nats-server/v2 from 2.10.6 to 2.10.7 (#302) Bumps [github.com/nats-io/nats-server/v2](https://github.com/nats-io/nats-server) from 2.10.6 to 2.10.7. - [Release notes](https://github.com/nats-io/nats-server/releases) - [Changelog](https://github.com/nats-io/nats-server/blob/main/.goreleaser.yml) - [Commits](https://github.com/nats-io/nats-server/compare/v2.10.6...v2.10.7) --- updated-dependencies: - dependency-name: github.com/nats-io/nats-server/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 56d27f47..bad8240a 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/kyma-project/kyma/common/logging v0.0.0-20231113125307-562a57ab5198 github.com/kyma-project/nats-manager v1.0.3-0.20231124103356-1904d89ab2b2 github.com/mitchellh/hashstructure/v2 v2.0.2 - github.com/nats-io/nats-server/v2 v2.10.6 + github.com/nats-io/nats-server/v2 v2.10.7 github.com/nats-io/nats.go v1.31.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.30.0 @@ -62,7 +62,7 @@ require ( github.com/jinzhu/copier v0.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.3 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index 4c6cdc8f..74a6e1ea 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,8 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -252,8 +252,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nats-io/jwt/v2 v2.5.3 h1:/9SWvzc6hTfamcgXJ3uYRpgj+QuY2aLNqRiqrKcrpEo= github.com/nats-io/jwt/v2 v2.5.3/go.mod h1:iysuPemFcc7p4IoYots3IuELSI4EDe9Y0bQMe+I3Bf4= -github.com/nats-io/nats-server/v2 v2.10.6 h1:40U3ngyAKyC1tNT4Kw7PjuvivY74NTYD3qyIHxZUHKQ= -github.com/nats-io/nats-server/v2 v2.10.6/go.mod h1:IrTXS8o4Roa3G2kW8L5mEtSdmSrFjKhYb/m2g0gQ/vc= +github.com/nats-io/nats-server/v2 v2.10.7 h1:f5VDy+GMu7JyuFA0Fef+6TfulfCs5nBTgq7MMkFJx5Y= +github.com/nats-io/nats-server/v2 v2.10.7/go.mod h1:V2JHOvPiPdtfDXTuEUsthUnCvSDeFrK4Xn9hRo6du7c= github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= From def15e8082a52e9d98132aae1164eda81374248b Mon Sep 17 00:00:00 2001 From: Carina Kothe <69976260+grischperl@users.noreply.github.com> Date: Fri, 8 Dec 2023 11:50:52 +0100 Subject: [PATCH 05/17] Update UI with improved notifications (#286) * Nats backend notification * First try: human-readable info * Add callout warning when NATS unavailable * Add alert for empty backend * Add empty backend sample Improve visibility of alerts --- config/samples/empty_backend.yaml | 22 +++++++++++++++++++ config/ui-extensions/eventing/details | 8 +++++++ config/ui-extensions/eventing/form | 6 +++++ .../ui-extensions/eventing/kustomization.yaml | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 config/samples/empty_backend.yaml diff --git a/config/samples/empty_backend.yaml b/config/samples/empty_backend.yaml new file mode 100644 index 00000000..7120e7ac --- /dev/null +++ b/config/samples/empty_backend.yaml @@ -0,0 +1,22 @@ +apiVersion: operator.kyma-project.io/v1alpha1 +kind: Eventing +metadata: + labels: + app.kubernetes.io/name: eventing + app.kubernetes.io/instance: eventing + app.kubernetes.io/part-of: eventing-manager + app.kubernetes.io/created-by: eventing-manager + name: eventing + namespace: kyma-system +spec: + publisher: + replicas: + min: 2 + max: 2 + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 40m + memory: 64Mi diff --git a/config/ui-extensions/eventing/details b/config/ui-extensions/eventing/details index 0b1fdb83..d6b2e20b 100644 --- a/config/ui-extensions/eventing/details +++ b/config/ui-extensions/eventing/details @@ -25,6 +25,14 @@ body: - source: '$readableTimestamp(lastTransitionTime)' name: Last transition sort: true + - source: "'NATS unavailable: If you chose the NATS backend, you must enable the NATS module.'" + widget: Alert + severity: warning + visibility: "$exists(status.conditions[reason = 'NATSUnavailable'])" + - source: "'No backend: If you enable the Eventing module, you must configure a backend.'" + widget: Alert + severity: warning + visibility: "$exists(status.conditions[reason = 'BackendNotSpecified'])" - name: Events widget: EventList filter: '$matchEvents($$, $root.kind, $root.metadata.name)' diff --git a/config/ui-extensions/eventing/form b/config/ui-extensions/eventing/form index c599c5e4..f7672769 100644 --- a/config/ui-extensions/eventing/form +++ b/config/ui-extensions/eventing/form @@ -7,6 +7,12 @@ - EventMesh description: Choose a backend type from the dropdown. +- simple: true + widget: Alert + severity: info + alert: "'If you choose the NATS backend, you must enable the NATS module.'" + visibility: "spec.backend.type = 'NATS'" + - path: spec.backend.config.eventMeshSecret visibility: "spec.backend.type = 'EventMesh'" widget: ResourceRef diff --git a/config/ui-extensions/eventing/kustomization.yaml b/config/ui-extensions/eventing/kustomization.yaml index 9175e1a1..2e87ec5a 100644 --- a/config/ui-extensions/eventing/kustomization.yaml +++ b/config/ui-extensions/eventing/kustomization.yaml @@ -1,6 +1,6 @@ configMapGenerator: - name: eventings.operator.kyma-project.io - namespace: kube-public + namespace: kyma-system files: - general - form From 6c641dd88b3cdc0cabe8db776dd950def0eac924 Mon Sep 17 00:00:00 2001 From: Friedrich Date: Fri, 8 Dec 2023 14:54:52 +0100 Subject: [PATCH 06/17] add codeowners (#308) --- CODEOWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index eb18de28..c264d10e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,3 +8,11 @@ * @kyma-project/eventing *.md @kyma-project/technical-writers + +*.sh @kyma-project/eventing @the1bit + +/.github/ @kyma-project/eventing @the1bit + +/.version @kyma-project/eventing @the1bit + +/.sec-scanners-config.yaml @kyma-project/eventing @the1bit From 5c4f1071cb89e4e8c1730bd609d2e7904073d280 Mon Sep 17 00:00:00 2001 From: Marco Bebway Date: Fri, 8 Dec 2023 15:08:52 +0100 Subject: [PATCH 07/17] Add publisher service in the Eventing CR status (#283) * Add publisher service in the Eventing CR status * Update tests --- api/operator/v1alpha1/eventing_types.go | 1 + api/operator/v1alpha1/status.go | 11 +++ api/operator/v1alpha1/status_test.go | 68 +++++++++++++++++++ .../operator.kyma-project.io_eventings.yaml | 2 + docs/user/02-configuration.md | 5 +- .../controller/integration_test.go | 25 ++++--- .../controller/operator/eventing/status.go | 27 +++++--- test/utils/integration/integration.go | 21 ++++++ 8 files changed, 139 insertions(+), 21 deletions(-) diff --git a/api/operator/v1alpha1/eventing_types.go b/api/operator/v1alpha1/eventing_types.go index 5bead265..2afa3660 100644 --- a/api/operator/v1alpha1/eventing_types.go +++ b/api/operator/v1alpha1/eventing_types.go @@ -95,6 +95,7 @@ type EventingStatus struct { ActiveBackend BackendType `json:"activeBackend"` BackendConfigHash int64 `json:"specHash"` State string `json:"state"` + PublisherService string `json:"publisherService,omitempty"` Conditions []kmetav1.Condition `json:"conditions,omitempty"` } diff --git a/api/operator/v1alpha1/status.go b/api/operator/v1alpha1/status.go index bff8971d..814d2836 100644 --- a/api/operator/v1alpha1/status.go +++ b/api/operator/v1alpha1/status.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + "fmt" "reflect" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" @@ -134,3 +135,13 @@ func (es *EventingStatus) IsEqual(status EventingStatus) bool { return reflect.DeepEqual(thisWithoutCond, statusWithoutCond) && natsv1alpha1.ConditionsEquals(es.Conditions, status.Conditions) } + +// ClearPublisherService clears the PublisherService. +func (es *EventingStatus) ClearPublisherService() { + es.PublisherService = "" +} + +// SetPublisherService sets the PublisherService from the given service name and namespace. +func (es *EventingStatus) SetPublisherService(name, namespace string) { + es.PublisherService = fmt.Sprintf("%s.%s", name, namespace) +} diff --git a/api/operator/v1alpha1/status_test.go b/api/operator/v1alpha1/status_test.go index 4ac9a833..af39b57b 100644 --- a/api/operator/v1alpha1/status_test.go +++ b/api/operator/v1alpha1/status_test.go @@ -29,3 +29,71 @@ func TestClearConditions(t *testing.T) { // then require.Len(t, givenEventingStatus.Conditions, 0) } + +func TestClearPublisherService(t *testing.T) { + // given + t.Parallel() + testCases := []struct { + name string + givenStatus EventingStatus + givenServiceName string + givenServiceNamespace string + wantStatus EventingStatus + }{ + { + name: "should clear the publisher service", + givenStatus: EventingStatus{ + PublisherService: "test-service.test-namespace", + }, + givenServiceName: "test-service", + givenServiceNamespace: "test-namespace", + wantStatus: EventingStatus{ + PublisherService: "", + }, + }, + } + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // when + tc.givenStatus.ClearPublisherService() + + // then + require.Equal(t, tc.wantStatus, tc.givenStatus) + }) + } +} + +func TestSetPublisherService(t *testing.T) { + // given + t.Parallel() + testCases := []struct { + name string + givenStatus EventingStatus + givenServiceName string + givenServiceNamespace string + wantStatus EventingStatus + }{ + { + name: "should set the correct publisher service", + givenStatus: EventingStatus{ + PublisherService: "", + }, + givenServiceName: "test-service", + givenServiceNamespace: "test-namespace", + wantStatus: EventingStatus{ + PublisherService: "test-service.test-namespace", + }, + }, + } + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // when + tc.givenStatus.SetPublisherService(tc.givenServiceName, tc.givenServiceNamespace) + + // then + require.Equal(t, tc.wantStatus, tc.givenStatus) + }) + } +} diff --git a/config/crd/bases/operator.kyma-project.io_eventings.yaml b/config/crd/bases/operator.kyma-project.io_eventings.yaml index 3513c2cc..3f292bc9 100644 --- a/config/crd/bases/operator.kyma-project.io_eventings.yaml +++ b/config/crd/bases/operator.kyma-project.io_eventings.yaml @@ -324,6 +324,8 @@ spec: - type type: object type: array + publisherService: + type: string specHash: format: int64 type: integer diff --git a/docs/user/02-configuration.md b/docs/user/02-configuration.md index f88b228f..1dd71051 100644 --- a/docs/user/02-configuration.md +++ b/docs/user/02-configuration.md @@ -65,9 +65,10 @@ Use the following sample CRs as guidance. Each can be applied immediately when y | **conditions.​message** (required) | string | message is a human readable message indicating details about the transition. This may be an empty string. | | **conditions.​observedGeneration** | integer | observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. | | **conditions.​reason** (required) | string | reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. | -| **conditions.​status** (required) | string | status of the condition, one of `True`, `False`, `Unknown`. | +| **conditions.​status** (required) | string | status of the condition, one of `True`, `False`, `Unknown`. | | **conditions.​type** (required) | string | type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) | +| **publisherService** | string | | | **specHash** (required) | integer | | | **state** (required) | string | | - \ No newline at end of file + diff --git a/internal/controller/operator/eventing/integrationtests/controller/integration_test.go b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go index eeeeb894..3d11f90b 100644 --- a/internal/controller/operator/eventing/integrationtests/controller/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go @@ -29,8 +29,7 @@ import ( ) const ( - projectRootDir = "../../../../../../" - eventTypePrefix = "test-prefix" + projectRootDir = "../../../../../../" ) var testEnvironment *testutilsintegration.TestEnvironment //nolint:gochecknoglobals // used in tests @@ -231,6 +230,9 @@ func Test_CreateEventingCR_NATS(t *testing.T) { // check if webhook configurations are updated with correct CABundle. testEnvironment.EnsureCABundleInjectedIntoWebhooks(t) } + + // check the publisher service in the Eventing CR status + testEnvironment.EnsurePublishServiceInEventingStatus(t, tc.givenEventing.Name, tc.givenEventing.Namespace) }) } } @@ -291,12 +293,12 @@ func Test_UpdateEventingCR(t *testing.T) { }() // get Eventing CR. - eventing, err := testEnvironment.GetEventingFromK8s(tc.givenExistingEventing.Name, givenNamespace) + eventingCR, err := testEnvironment.GetEventingFromK8s(tc.givenExistingEventing.Name, givenNamespace) require.NoError(t, err) // when // update NATS CR. - newEventing := eventing.DeepCopy() + newEventing := eventingCR.DeepCopy() newEventing.Spec = tc.givenNewEventingForUpdate.Spec testEnvironment.EnsureK8sResourceUpdated(t, newEventing) @@ -304,6 +306,9 @@ func Test_UpdateEventingCR(t *testing.T) { testEnvironment.EnsureEventingSpecPublisherReflected(t, newEventing) testEnvironment.EnsureEventingReplicasReflected(t, newEventing) testEnvironment.EnsureDeploymentOwnerReferenceSet(t, tc.givenExistingEventing) + + // check the publisher service in the Eventing CR status + testEnvironment.EnsurePublishServiceInEventingStatus(t, eventingCR.Name, eventingCR.Namespace) }) } } @@ -311,9 +316,7 @@ func Test_UpdateEventingCR(t *testing.T) { func Test_ReconcileSameEventingCR(t *testing.T) { t.Parallel() - //// // given - //// eventingcontroller.IsDeploymentReady = func(deployment *kappsv1.Deployment) bool { return true } eventingCR := utils.NewEventingCR( @@ -356,9 +359,7 @@ func Test_ReconcileSameEventingCR(t *testing.T) { const runs = 3 resourceVersionBefore := eppDeployment.ObjectMeta.ResourceVersion for r := 0; r < runs; r++ { - //// // when - //// runId := fmt.Sprintf("run-%d", r) eventingCR, err = testEnvironment.GetEventingFromK8s(eventingCR.Name, namespace) @@ -374,9 +375,7 @@ func Test_ReconcileSameEventingCR(t *testing.T) { require.NotNil(t, eventingCR) require.Equal(t, eventingCR.ObjectMeta.Labels["reconcile"], runId) - //// // then - //// testEnvironment.EnsureEventingSpecPublisherReflected(t, eventingCR) testEnvironment.EnsureEventingReplicasReflected(t, eventingCR) testEnvironment.EnsureDeploymentOwnerReferenceSet(t, eventingCR) @@ -387,6 +386,9 @@ func Test_ReconcileSameEventingCR(t *testing.T) { resourceVersionAfter := eppDeployment.ObjectMeta.ResourceVersion require.Equal(t, resourceVersionBefore, resourceVersionAfter) + + // check the publisher service in the Eventing CR status + testEnvironment.EnsurePublishServiceInEventingStatus(t, eventingCR.Name, eventingCR.Namespace) } } @@ -725,6 +727,9 @@ func Test_CreateEventingCR_EventMesh(t *testing.T) { // check if webhook configurations are updated with correct CABundle. testEnvironment.EnsureCABundleInjectedIntoWebhooks(t) } + + // check the publisher service in the Eventing CR status + testEnvironment.EnsurePublishServiceInEventingStatus(t, tc.givenEventing.Name, givenNamespace) }) } } diff --git a/internal/controller/operator/eventing/status.go b/internal/controller/operator/eventing/status.go index a11be7fc..a554c6da 100644 --- a/internal/controller/operator/eventing/status.go +++ b/internal/controller/operator/eventing/status.go @@ -12,6 +12,7 @@ import ( kctrl "sigs.k8s.io/controller-runtime" operatorv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" + "github.com/kyma-project/eventing-manager/pkg/eventing" ) const RequeueTimeForStatusCheck = 10 @@ -184,29 +185,37 @@ func (r *Reconciler) updateStatus(ctx context.Context, oldEventing, newEventing return nil } -func (r *Reconciler) handleEventingState(ctx context.Context, deployment *kappsv1.Deployment, eventing *operatorv1alpha1.Eventing, log *zap.SugaredLogger) (kctrl.Result, error) { +func (r *Reconciler) handleEventingState(ctx context.Context, deployment *kappsv1.Deployment, + eventingCR *operatorv1alpha1.Eventing, log *zap.SugaredLogger, +) (kctrl.Result, error) { + // Clear the publisher service until the publisher proxy is ready. + eventingCR.Status.ClearPublisherService() + // checking if publisher proxy is ready. // get k8s deployment for publisher proxy deployment, err := r.kubeClient.GetDeployment(ctx, deployment.Name, deployment.Namespace) if err != nil { - eventing.Status.UpdateConditionPublisherProxyReady(kmetav1.ConditionFalse, + eventingCR.Status.UpdateConditionPublisherProxyReady(kmetav1.ConditionFalse, operatorv1alpha1.ConditionReasonDeploymentStatusSyncFailed, err.Error()) - return kctrl.Result{}, r.syncStatusWithPublisherProxyErr(ctx, eventing, err, log) + return kctrl.Result{}, r.syncStatusWithPublisherProxyErr(ctx, eventingCR, err, log) } if !IsDeploymentReady(deployment) { - eventing.Status.SetStateProcessing() - eventing.Status.UpdateConditionPublisherProxyReady(kmetav1.ConditionFalse, + eventingCR.Status.SetStateProcessing() + eventingCR.Status.UpdateConditionPublisherProxyReady(kmetav1.ConditionFalse, operatorv1alpha1.ConditionReasonProcessing, operatorv1alpha1.ConditionPublisherProxyProcessingMessage) log.Info("Reconciliation successful: waiting for publisher proxy to get ready...") - return kctrl.Result{RequeueAfter: RequeueTimeForStatusCheck * time.Second}, r.syncEventingStatus(ctx, eventing, log) + return kctrl.Result{RequeueAfter: RequeueTimeForStatusCheck * time.Second}, r.syncEventingStatus(ctx, eventingCR, log) } - // - eventing.Status.SetPublisherProxyReadyToTrue() + + eventingCR.Status.SetPublisherProxyReadyToTrue() + + // Set the publisher service after the publisher proxy is ready. + eventingCR.Status.SetPublisherService(eventing.GetPublisherPublishServiceName(*eventingCR), eventingCR.Namespace) // @TODO: emit events for any change in conditions log.Info("Reconciliation successful") - return kctrl.Result{}, r.syncEventingStatus(ctx, eventing, log) + return kctrl.Result{}, r.syncEventingStatus(ctx, eventingCR, log) } // to be able to mock this function in tests. diff --git a/test/utils/integration/integration.go b/test/utils/integration/integration.go index 1b7ee2e1..0cf9999d 100644 --- a/test/utils/integration/integration.go +++ b/test/utils/integration/integration.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/rand" + "fmt" "log" "path/filepath" "strings" @@ -880,6 +881,26 @@ func (env TestEnvironment) EnsureOAuthSecretCreated(t *testing.T, eventing *v1al env.EnsureK8sResourceCreated(t, secret) } +func (env TestEnvironment) EnsurePublishServiceInEventingStatus(t *testing.T, name, namespace string) { + eventingCR, err := env.GetEventingFromK8s(name, namespace) + require.NoError(t, err) + require.NotNil(t, eventingCR) + + switch eventingCR.Status.State { + case v1alpha1.StateReady: + { + serviceName := eventing.GetPublisherPublishServiceName(*eventingCR) + wantPublisherService := fmt.Sprintf("%s.%s", serviceName, namespace) + require.Equal(t, wantPublisherService, eventingCR.Status.PublisherService) + } + default: + { + const wantPublisherService = "" + require.Equal(t, wantPublisherService, eventingCR.Status.PublisherService) + } + } +} + func (env TestEnvironment) DeleteServiceFromK8s(name, namespace string) error { return env.k8sClient.Delete(env.Context, &kcorev1.Service{ ObjectMeta: kmetav1.ObjectMeta{ From 551b0e139d52efcfb492e1fc81e4656d72f79760 Mon Sep 17 00:00:00 2001 From: Korbinian Stoemmer Date: Mon, 11 Dec 2023 16:37:25 +0100 Subject: [PATCH 08/17] remove reference to old publisher proxy service (#291) --- docs/user/tutorials/evnt-02-subs-with-multiple-filters.md | 2 +- docs/user/tutorials/evnt-03-type-cleanup.md | 2 +- docs/user/tutorials/evnt-04-change-max-in-flight-in-sub.md | 2 +- docs/user/tutorials/evnt-05-send-legacy-events.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/user/tutorials/evnt-02-subs-with-multiple-filters.md b/docs/user/tutorials/evnt-02-subs-with-multiple-filters.md index bffc92e4..e6a03edc 100644 --- a/docs/user/tutorials/evnt-02-subs-with-multiple-filters.md +++ b/docs/user/tutorials/evnt-02-subs-with-multiple-filters.md @@ -73,7 +73,7 @@ In the following example, you port-forward the [Event Publisher Proxy](../evnt-a 1. Port-forward the [Event Publisher Proxy](../evnt-architecture.md) Service to localhost, using port `3000`. Run: ```bash - kubectl -n kyma-system port-forward service/eventing-event-publisher-proxy 3000:80 + kubectl -n kyma-system port-forward service/eventing-publisher-proxy 3000:80 ``` 2. Publish an event of type `order.received.v1` to trigger your Function. In another terminal window, run: diff --git a/docs/user/tutorials/evnt-03-type-cleanup.md b/docs/user/tutorials/evnt-03-type-cleanup.md index a0fa409b..8ed1dd96 100644 --- a/docs/user/tutorials/evnt-03-type-cleanup.md +++ b/docs/user/tutorials/evnt-03-type-cleanup.md @@ -131,7 +131,7 @@ Next, you see that you can still publish events with the original Event name (i. 1. Port-forward the [Event Publisher Proxy](../evnt-architecture.md) Service to localhost, using port `3000`. Run: ```bash - kubectl -n kyma-system port-forward service/eventing-event-publisher-proxy 3000:80 + kubectl -n kyma-system port-forward service/eventing-publisher-proxy 3000:80 ``` 2. Publish an event to trigger your Function. In another terminal window, run: diff --git a/docs/user/tutorials/evnt-04-change-max-in-flight-in-sub.md b/docs/user/tutorials/evnt-04-change-max-in-flight-in-sub.md index 80de8b6d..9a0da5a4 100644 --- a/docs/user/tutorials/evnt-04-change-max-in-flight-in-sub.md +++ b/docs/user/tutorials/evnt-04-change-max-in-flight-in-sub.md @@ -131,7 +131,7 @@ Next, publish 15 events at once and see how Kyma Eventing triggers the workload. 1. Port-forward the [Event Publisher Proxy](../evnt-architecture.md) Service to localhost, using port `3000`. Run: ```bash - kubectl -n kyma-system port-forward service/eventing-event-publisher-proxy 3000:80 + kubectl -n kyma-system port-forward service/eventing-publisher-proxy 3000:80 ``` 2. Now publish 15 events to the Event Publisher Proxy Service. In another terminal window, run: diff --git a/docs/user/tutorials/evnt-05-send-legacy-events.md b/docs/user/tutorials/evnt-05-send-legacy-events.md index d10af35d..d2220917 100644 --- a/docs/user/tutorials/evnt-05-send-legacy-events.md +++ b/docs/user/tutorials/evnt-05-send-legacy-events.md @@ -71,7 +71,7 @@ You created the `lastorder` Function, and subscribed to the `order.received.v1` 1. Port-forward the [Event Publisher Proxy](../evnt-architecture.md) Service to localhost, using port `3000`. Run: ```bash - kubectl -n kyma-system port-forward service/eventing-event-publisher-proxy 3000:80 + kubectl -n kyma-system port-forward service/eventing-publisher-proxy 3000:80 ``` 2. Publish an event to trigger your Function. In another terminal window, run: From 2036473ea3a9ae0a93a8d8e6cce65a297b5b4947 Mon Sep 17 00:00:00 2001 From: Friedrich Date: Tue, 12 Dec 2023 09:41:23 +0100 Subject: [PATCH 09/17] Refactor verify script (#313) * format and relplace backticks * add retry --- scripts/verify-status.sh | 45 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/scripts/verify-status.sh b/scripts/verify-status.sh index a9381f99..ae82c441 100755 --- a/scripts/verify-status.sh +++ b/scripts/verify-status.sh @@ -3,15 +3,42 @@ echo "Checking status of POST Jobs for Eventing-Manager" REF_NAME="${1:-"main"}" +TIMEOUT_TIME="${2:-120}" +INTERVAL_TIME="${3:-3}" + +# Generate job Status URL STATUS_URL="https://api.github.com/repos/kyma-project/eventing-manager/commits/${REF_NAME}/status" -fullstatus=`curl -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" ${STATUS_URL} | head -n 2 ` -sleep 10 -echo $fullstatus +function retry { + local start_time=$(date +%s) + # Get status result + local statusresult=$(curl -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" ${STATUS_URL}) + # Get overall state + local fullstatus=$(echo $statusresult | jq '.state' | tr -d '"') + + while [ "$fullstatus" == "pending" ]; do + current_time=$(date +%s) + elapsed_time=$((current_time - start_time)) + + if [ $elapsed_time -ge $TIMEOUT_TIME ]; then + echo "Timeout reached. Exiting." + exit 1 + fi + + echo "Status is 'pending'. Retrying in $interval seconds..." + sleep $INTERVAL_TIME + done + + # Show overall state to user + echo "$statusresult" -if [[ "$fullstatus" == *"success"* ]]; then - echo "All jobs succeeded" -else - echo "Jobs failed or pending - Check Prow status" - exit 1 -fi \ No newline at end of file + if [ "$fullstatus" == "success" ]; then + echo "Success!" + elif [ "$fullstatus" == "failed" ]; then + echo "Failure! Exiting with an error." + exit 1 + else + echo "Invalid result: $result" + exit 1 + fi +} From 949ce03262bd99f21c007faa7e8a1f7d8e62b20d Mon Sep 17 00:00:00 2001 From: Mansur Uralov Date: Wed, 13 Dec 2023 00:01:24 +0100 Subject: [PATCH 10/17] Document Warning State (#317) * Document Warning State Write documentation in which cases Eventing CR state gets Warning state * Improve for review comments * Improve doc for second review --- api/operator/v1alpha1/eventing_types.go | 14 +++++++++----- docs/user/02-configuration.md | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/api/operator/v1alpha1/eventing_types.go b/api/operator/v1alpha1/eventing_types.go index 2afa3660..a6111468 100644 --- a/api/operator/v1alpha1/eventing_types.go +++ b/api/operator/v1alpha1/eventing_types.go @@ -92,11 +92,15 @@ type Eventing struct { // EventingStatus defines the observed state of Eventing. type EventingStatus struct { - ActiveBackend BackendType `json:"activeBackend"` - BackendConfigHash int64 `json:"specHash"` - State string `json:"state"` - PublisherService string `json:"publisherService,omitempty"` - Conditions []kmetav1.Condition `json:"conditions,omitempty"` + ActiveBackend BackendType `json:"activeBackend"` + BackendConfigHash int64 `json:"specHash"` + // Can have one of the following values: Ready, Error, Processing, Warning. Ready state is set + // when all the resources are deployed successfully and backend is connected. + // It gets Warning state in case backend is not specified and NATS module is not installed or EventMesh secret is missing in the cluster. + // Error state is set when there is an error. Processing state is set if recources are being created or changed. + State string `json:"state"` + PublisherService string `json:"publisherService,omitempty"` + Conditions []kmetav1.Condition `json:"conditions,omitempty"` } // EventingSpec defines the desired state of Eventing. diff --git a/docs/user/02-configuration.md b/docs/user/02-configuration.md index 1dd71051..902add5a 100644 --- a/docs/user/02-configuration.md +++ b/docs/user/02-configuration.md @@ -8,7 +8,11 @@ The CustomResourceDefinition (CRD) `eventings.operator.kyma-project.io` describe View the complete [Eventing CRD](https://github.com/kyma-project/eventing-manager/blob/main/config/crd/bases/operator.kyma-project.io_eventings.yaml) including detailed descriptions for each field. -The CRD is equipped with validation rules and defaulting, so the CR is automatically filled with sensible defaults. You can override the defaults. The validation rules provide guidance when you edit the CR. +The CRD is equipped with validation rules and defaulting, so the CR is automatically filled with default values. + +You can override the defaults. However, you must make sure that a backend is set; otherwise the Eventing Manager does not create any resources and goes into warning state. + +The validation rules provide guidance when you edit the CR. For example, you are not allowed to delete an existing backend. ## Examples @@ -69,6 +73,6 @@ Use the following sample CRs as guidance. Each can be applied immediately when y | **conditions.​type** (required) | string | type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) | | **publisherService** | string | | | **specHash** (required) | integer | | -| **state** (required) | string | | +| **state** (required) | string | Can have one of the following values: Ready, Error, Processing, Warning. Ready state is set when all the resources are deployed successfully and backend is connected. It gets Warning state in case backend is not specified and NATS module is not installed or EventMesh secret is missing in the cluster. Error state is set when there is an error. Processing state is set if recources are being created or changed. | From 2f2a1b6b12584b159540283c87b46af4b5359ad6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:51:27 +0100 Subject: [PATCH 11/17] Bump istio.io/api from 1.20.0 to 1.20.1 (#320) Bumps [istio.io/api](https://github.com/istio/api) from 1.20.0 to 1.20.1. - [Commits](https://github.com/istio/api/compare/1.20.0...1.20.1) --- updated-dependencies: - dependency-name: istio.io/api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bad8240a..73aa8edc 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( go.uber.org/zap v1.26.0 golang.org/x/oauth2 v0.15.0 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 - istio.io/api v1.20.0 + istio.io/api v1.20.1 istio.io/client-go v1.20.0 k8s.io/api v0.28.4 k8s.io/apiextensions-apiserver v0.28.4 diff --git a/go.sum b/go.sum index 74a6e1ea..e30cb228 100644 --- a/go.sum +++ b/go.sum @@ -710,8 +710,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -istio.io/api v1.20.0 h1:heE1eQoMsuZlwWOf7Xm8TKqKLNKVs11G/zMe5QyR1u4= -istio.io/api v1.20.0/go.mod h1:hm1PE/mGdIAsjCDkTIAplP53H7TjO5LUQCiVvF26SVg= +istio.io/api v1.20.1 h1:Itku+LK5FwNzkKJY+5BGRCTRimVA5gShwFXdNNXtAHk= +istio.io/api v1.20.1/go.mod h1:hm1PE/mGdIAsjCDkTIAplP53H7TjO5LUQCiVvF26SVg= istio.io/client-go v1.20.0 h1:TSSv6A4sYvuBtoKOwyuRmBmPwSb4s++lWlh7RB7+7gY= istio.io/client-go v1.20.0/go.mod h1:6D76gZsdjz8JtVeIarUYdOn3WA8Zh+j8fIv2+2K3M+Q= k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= From a77a4fabb2e05b0c3d54504cfc07c90c5a93c00b Mon Sep 17 00:00:00 2001 From: Tibor Kiss <32801432+the1bit@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:41:27 +0100 Subject: [PATCH 12/17] Semantic versioning in security scan config (#319) * check_image.sh * check_image.sh * release.sh * Remove `.version` file check in release * Call retry function * Refactoring * Verify status * Check tags in security-scan-config.yaml * Check on both place * Collect latest run related data --- .github/workflows/create-release.yml | 31 +++++++++----- scripts/check_image.sh | 16 -------- scripts/check_tag_info.sh | 32 +++++++++++++++ scripts/release.sh | 10 +++-- scripts/verify-status.sh | 60 +++++++++++++++++++++------- sec-scanners-config.yaml | 4 +- 6 files changed, 105 insertions(+), 48 deletions(-) delete mode 100755 scripts/check_image.sh create mode 100755 scripts/check_tag_info.sh diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 66e420f7..99264735 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -4,31 +4,37 @@ on: workflow_dispatch: inputs: name: - description: 'Release name' + description: 'Release name ( e.g. "2.1.3" )' default: "" required: true jobs: verify-head-status: - name: Verify head + name: Verify head (image version and prow job) runs-on: ubuntu-latest steps: + - name: Verify that the current branch has a name that starts with 'release-' + run: | + CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + if [[ "$CURRENT_BRANCH" == release-* ]]; then + echo "Branch name starts with 'release-'." + else + echo "Branch name does not start with 'release-'." + exit 1 + fi + - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 + + - name: Check image Tag + run: ./scripts/check_tag_info.sh ${{ github.ref_name }} - - name: Check tag - run: ./scripts/check_release_tag.sh ${{ github.event.inputs.name }} - - - name: Check image - run: ./scripts/check_image.sh ${{ github.ref_name }} - - - name: Verify + - name: Verify prow post jobs run: ./scripts/verify-status.sh ${{ github.ref_name }} - - # run-unit-tests: + # run-unit-tests: # name: Unit tests # needs: verify-head-status # uses: "./.github/workflows/run-unit-tests.yaml" @@ -62,6 +68,9 @@ jobs: git tag ${{ github.event.inputs.name }} git push origin ${{ github.event.inputs.name }} + - name: Verify prow post jobs + run: ./scripts/verify-status.sh ${{ github.ref_name }} + outputs: release_id: ${{ steps.create-draft.outputs.release_id }} diff --git a/scripts/check_image.sh b/scripts/check_image.sh deleted file mode 100755 index 0d82fe92..00000000 --- a/scripts/check_image.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -REF_NAME="${1:-"main"}" -SHORT_EXPECTED_SHA=$(git rev-parse --short=8 "${REF_NAME}~") -DATE="v$(git show ${SHORT_EXPECTED_SHA} --date=format:'%Y%m%d' --format=%ad -q)" -EXPECTED_TAG="${DATE}-${SHORT_EXPECTED_SHA}" - -IMAGE_TO_CHECK="${2:-europe-docker.pkg.dev/kyma-project/prod/eventing-manager}" -BUMPED_IMAGE_TAG=$(cat sec-scanners-config.yaml | grep "${IMAGE_TO_CHECK}" | cut -d : -f 2) - -if [[ "$BUMPED_IMAGE_TAG" != "$EXPECTED_TAG" ]]; then - echo "Tags are not correct: wanted $EXPECTED_TAG but got $BUMPED_IMAGE_TAG" - exit 1 -fi -echo "Tags are correct" -exit 0 \ No newline at end of file diff --git a/scripts/check_tag_info.sh b/scripts/check_tag_info.sh new file mode 100755 index 00000000..f13032bd --- /dev/null +++ b/scripts/check_tag_info.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +############################## +# Check tags in security-scan-config.yaml +# Image Tag, rc-tag +############################## + + +# Get release version +DESIRED_TAG="${1:-"main"}" + +# Get eventing-manager tag from sec-scanners-config.yaml +SEC_SCAN_TO_CHECK="${2:-europe-docker.pkg.dev/kyma-project/prod/eventing-manager}" +IMAGE_TAG=$(cat sec-scanners-config.yaml | grep "${SEC_SCAN_TO_CHECK}" | cut -d : -f 2) + +# Get rc-tag +RC_TAG_TO_CHECK="${3:-rc-tag}" +RC_TAG=$(cat sec-scanners-config.yaml | grep "${RC_TAG_TO_CHECK}" | cut -d : -f 2) + +# Check IMAGE_TAG and required image tag +if [[ "$IMAGE_TAG" != "$DESIRED_TAG" ]] || [[ "$RC_TAG" != "$DESIRED_TAG" ]]; then + # ERROR: Tag issue + echo "Tags are not correct: + - wanted $DESIRED_TAG + - security-scanner image tag: $IMAGE_TAG + - rc-tag: $RC_TAG" + exit 1 +fi + +# OK: Everything is fine +echo "Tags are correct" +exit 0 diff --git a/scripts/release.sh b/scripts/release.sh index 2808f860..3fcd427d 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -14,11 +14,12 @@ uploadFile() { filePath=${1} ghAsset=${2} + echo "Uploading ${filePath} as ${ghAsset}" response=$(curl -s -o output.txt -w "%{http_code}" \ --request POST --data-binary @"$filePath" \ -H "Authorization: token $BOT_GITHUB_TOKEN" \ -H "Content-Type: text/yaml" \ - $ghAsset) + $ghAsset) if [[ "$response" != "201" ]]; then echo "Unable to upload the asset ($filePath): " echo "HTTP Status: $response" @@ -46,7 +47,7 @@ echo "Updating github release with eventing-manager.yaml" echo "Finding release id for: ${PULL_BASE_REF}" CURL_RESPONSE=$(curl -w "%{http_code}" -sL \ -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $BOT_GITHUB_TOKEN"\ + -H "Authorization: Bearer $BOT_GITHUB_TOKEN" \ https://api.github.com/repos/kyma-project/eventing-manager/releases) JSON_RESPONSE=$(sed '$ d' <<< "${CURL_RESPONSE}") HTTP_CODE=$(tail -n1 <<< "${CURL_RESPONSE}") @@ -54,7 +55,8 @@ if [[ "${HTTP_CODE}" != "200" ]]; then echo "${JSON_RESPONSE}" && exit 1 fi -RELEASE_ID=$(jq <<< ${JSON_RESPONSE} --arg tag "${PULL_BASE_REF}" '.[] | select(.tag_name == $ARGS.named.tag) | .id') +echo "Finding release id for: ${PULL_BASE_REF}" +RELEASE_ID=$(jq <<<${JSON_RESPONSE} --arg tag "${PULL_BASE_REF}" '.[] | select(.tag_name == $ARGS.named.tag) | .id') if [ -z "${RELEASE_ID}" ] then @@ -66,4 +68,4 @@ UPLOAD_URL="https://uploads.github.com/repos/kyma-project/eventing-manager/relea uploadFile "eventing-manager.yaml" "${UPLOAD_URL}?name=eventing-manager.yaml" uploadFile "module-template.yaml" "${UPLOAD_URL}?name=module-template.yaml" -uploadFile "config/samples/default.yaml" "${UPLOAD_URL}?name=eventing_default_cr.yaml" \ No newline at end of file +uploadFile "config/samples/default.yaml" "${UPLOAD_URL}?name=eventing_default_cr.yaml" diff --git a/scripts/verify-status.sh b/scripts/verify-status.sh index ae82c441..ba9f3fee 100755 --- a/scripts/verify-status.sh +++ b/scripts/verify-status.sh @@ -3,42 +3,72 @@ echo "Checking status of POST Jobs for Eventing-Manager" REF_NAME="${1:-"main"}" -TIMEOUT_TIME="${2:-120}" +TIMEOUT_TIME="${2:-600}" INTERVAL_TIME="${3:-3}" # Generate job Status URL STATUS_URL="https://api.github.com/repos/kyma-project/eventing-manager/commits/${REF_NAME}/status" +# Dates +START_TIME=$(date +%s) +TODAY_DATE=$(date '+%Y-%m-%d') + +# Retry function function retry { - local start_time=$(date +%s) + # Get status result local statusresult=$(curl -L -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" ${STATUS_URL}) + # Get overall state - local fullstatus=$(echo $statusresult | jq '.state' | tr -d '"') + fullstatus=$(echo $statusresult | jq '.state' | tr -d '"') - while [ "$fullstatus" == "pending" ]; do - current_time=$(date +%s) - elapsed_time=$((current_time - start_time)) + # Collect latest run related data + local latestrun=$(echo $statusresult | jq '.statuses[-1]') + local latestrun_state=$(echo $latestrun | jq '.state' | tr -d '"') + local latestrun_createdat=$(echo $latestrun | jq '.created_at' | tr -d '"') + local latestrun_targeturl=$(echo $latestrun | jq '.target_url' | tr -d '"') - if [ $elapsed_time -ge $TIMEOUT_TIME ]; then - echo "Timeout reached. Exiting." - exit 1 - fi + # Check Today's run data + if [[ $latestrun_createdat == *"$TODAY_DATE"* ]]; then + echo $latestrun_createdat + echo $latestrun_state + echo $latestrun_targeturl + fi - echo "Status is 'pending'. Retrying in $interval seconds..." - sleep $INTERVAL_TIME - done + # Show all execution for Today + echo $statusresult | jq --arg t $TODAY_DATE '.statuses[]|select(.created_at | contains($t))' - # Show overall state to user - echo "$statusresult" + # Date time for time-out + local CURRENT_TIME=$(date +%s) + local elapsed_time=$((CURRENT_TIME - START_TIME)) + + # Check time-out + if [ $elapsed_time -ge $TIMEOUT_TIME ]; then + echo "Timeout reached. Exiting." + exit 1 + fi if [ "$fullstatus" == "success" ]; then echo "Success!" elif [ "$fullstatus" == "failed" ]; then + # Show overall state to user + echo "$statusresult" echo "Failure! Exiting with an error." exit 1 + elif [ "$fullstatus" == "pending" ]; then + echo "Status is '$fullstatus'. Retrying in $INTERVAL_TIME seconds..." + sleep $INTERVAL_TIME else echo "Invalid result: $result" exit 1 fi + } + +# Initial wait +sleep 0 +# Call retry function +retry +while [ "$fullstatus" == "pending" ]; do + retry +done diff --git a/sec-scanners-config.yaml b/sec-scanners-config.yaml index 7bf36c18..302ec865 100644 --- a/sec-scanners-config.yaml +++ b/sec-scanners-config.yaml @@ -1,7 +1,7 @@ module-name: eventing -rc-tag: 1.0.0 +rc-tag: 0.0.0 protecode: - - europe-docker.pkg.dev/kyma-project/prod/eventing-manager:v20231114-4bbffe1a + - europe-docker.pkg.dev/kyma-project/prod/eventing-manager:0.0.0 - europe-docker.pkg.dev/kyma-project/prod/event-publisher-proxy:v20231025-3f5d1600 - europe-docker.pkg.dev/kyma-project/prod/eventing-webhook-certificates:1.7.0 whitesource: From 7221a4fd63f7c494e627746ebb6bd712ff855057 Mon Sep 17 00:00:00 2001 From: Tibor Kiss <32801432+the1bit@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:11:27 +0100 Subject: [PATCH 13/17] Checkout code (#323) --- .github/workflows/create-release.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 99264735..5044540f 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -14,6 +14,11 @@ jobs: runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Verify that the current branch has a name that starts with 'release-' run: | CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) @@ -22,21 +27,16 @@ jobs: else echo "Branch name does not start with 'release-'." exit 1 - fi - - - name: Checkout code - uses: actions/checkout@v4 - with: - fetch-depth: 0 - + fi + - name: Check image Tag run: ./scripts/check_tag_info.sh ${{ github.ref_name }} - name: Verify prow post jobs run: ./scripts/verify-status.sh ${{ github.ref_name }} # run-unit-tests: - # name: Unit tests - # needs: verify-head-status + # name: Unit tests + # needs: verify-head-status # uses: "./.github/workflows/run-unit-tests.yaml" create-draft: @@ -93,4 +93,4 @@ jobs: - name: Publish release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: ./scripts/publish_release.sh ${{ needs.create-draft.outputs.release_id }} \ No newline at end of file + run: ./scripts/publish_release.sh ${{ needs.create-draft.outputs.release_id }} From ef8ed61abdce63a605628a80eb385e10d610298f Mon Sep 17 00:00:00 2001 From: Tibor Kiss <32801432+the1bit@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:27:26 +0100 Subject: [PATCH 14/17] Release input variable for tag checking (#324) --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 5044540f..dd106645 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -30,7 +30,7 @@ jobs: fi - name: Check image Tag - run: ./scripts/check_tag_info.sh ${{ github.ref_name }} + run: ./scripts/check_tag_info.sh ${{ github.event.inputs.name }} - name: Verify prow post jobs run: ./scripts/verify-status.sh ${{ github.ref_name }} From 7fe318ba8e748fabbe80f7b9fc8b1e9863cd5d2e Mon Sep 17 00:00:00 2001 From: Tibor Kiss <32801432+the1bit@users.noreply.github.com> Date: Wed, 13 Dec 2023 16:45:26 +0100 Subject: [PATCH 15/17] Release input variable for tag checking (#326) * Release input variable for tag checking * Remove whitespace * Remove white space at rc-tag --- scripts/check_tag_info.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/check_tag_info.sh b/scripts/check_tag_info.sh index f13032bd..28a5c8b9 100755 --- a/scripts/check_tag_info.sh +++ b/scripts/check_tag_info.sh @@ -15,13 +15,13 @@ IMAGE_TAG=$(cat sec-scanners-config.yaml | grep "${SEC_SCAN_TO_CHECK}" | cut -d # Get rc-tag RC_TAG_TO_CHECK="${3:-rc-tag}" -RC_TAG=$(cat sec-scanners-config.yaml | grep "${RC_TAG_TO_CHECK}" | cut -d : -f 2) +RC_TAG=$(cat sec-scanners-config.yaml | grep "${RC_TAG_TO_CHECK}" | cut -d : -f 2 | xargs) # Check IMAGE_TAG and required image tag if [[ "$IMAGE_TAG" != "$DESIRED_TAG" ]] || [[ "$RC_TAG" != "$DESIRED_TAG" ]]; then # ERROR: Tag issue echo "Tags are not correct: - - wanted $DESIRED_TAG + - wanted: $DESIRED_TAG - security-scanner image tag: $IMAGE_TAG - rc-tag: $RC_TAG" exit 1 From a2c4f3c9dbec039c68c30e106d601bf1f37d15cc Mon Sep 17 00:00:00 2001 From: Tibor Kiss <32801432+the1bit@users.noreply.github.com> Date: Thu, 14 Dec 2023 09:43:25 +0100 Subject: [PATCH 16/17] Initial Wait Time (#327) * Initial Wait Time * Parameters * Remove first check --- .github/workflows/create-release.yml | 6 ++---- scripts/verify-status.sh | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index dd106645..c34cd594 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -32,8 +32,6 @@ jobs: - name: Check image Tag run: ./scripts/check_tag_info.sh ${{ github.event.inputs.name }} - - name: Verify prow post jobs - run: ./scripts/verify-status.sh ${{ github.ref_name }} # run-unit-tests: # name: Unit tests # needs: verify-head-status @@ -68,8 +66,8 @@ jobs: git tag ${{ github.event.inputs.name }} git push origin ${{ github.event.inputs.name }} - - name: Verify prow post jobs - run: ./scripts/verify-status.sh ${{ github.ref_name }} + - name: Verify job status + run: ./scripts/verify-status.sh ${{ github.ref_name }} 600 10 30 outputs: release_id: ${{ steps.create-draft.outputs.release_id }} diff --git a/scripts/verify-status.sh b/scripts/verify-status.sh index ba9f3fee..21fd686a 100755 --- a/scripts/verify-status.sh +++ b/scripts/verify-status.sh @@ -5,6 +5,7 @@ echo "Checking status of POST Jobs for Eventing-Manager" REF_NAME="${1:-"main"}" TIMEOUT_TIME="${2:-600}" INTERVAL_TIME="${3:-3}" +INITIAL_WAIT_TIME="${4:-30}" # Generate job Status URL STATUS_URL="https://api.github.com/repos/kyma-project/eventing-manager/commits/${REF_NAME}/status" @@ -66,7 +67,7 @@ function retry { } # Initial wait -sleep 0 +sleep $INITIAL_WAIT_TIME # Call retry function retry while [ "$fullstatus" == "pending" ]; do From e7a0190f454a05b243a2a0a258afa88765b3dc8b Mon Sep 17 00:00:00 2001 From: Friedrich Date: Thu, 14 Dec 2023 11:37:26 +0100 Subject: [PATCH 17/17] Run github action workflows on release-branches. (#330) --- .github/workflows/e2e.yml | 12 ++-- .github/workflows/lint.yml | 12 ++-- .github/workflows/sink.yml | 100 +++++++++++++++++---------------- .github/workflows/test.yml | 22 +++++--- .github/workflows/validate.yml | 16 ++++-- 5 files changed, 88 insertions(+), 74 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 7ab976fa..c9d3343d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,11 +7,13 @@ env: on: pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" jobs: nats: @@ -59,7 +61,7 @@ jobs: - name: Setup and test the eventing-manager run: | - make e2e-setup + make e2e-setup - name: Setup eventing run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b714c580..ff60295c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,11 +2,13 @@ name: golangci-lint on: pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" permissions: contents: read @@ -19,7 +21,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: "1.21" cache: false - uses: actions/checkout@v4 - name: golangci-lint diff --git a/.github/workflows/sink.yml b/.github/workflows/sink.yml index b6bd08e0..5fbb74bb 100644 --- a/.github/workflows/sink.yml +++ b/.github/workflows/sink.yml @@ -10,17 +10,19 @@ env: on: push: branches: - - main - tags: [ '*.*.*' ] + - main + - "release-*" + tags: ["*.*.*"] paths: - - 'hack/e2e/sink/**' - - '.github/workflows/sink.yml' + - "hack/e2e/sink/**" + - ".github/workflows/sink.yml" pull_request: branches: - - main + - main + - "release-*" paths: - - 'hack/e2e/sink/**' - - '.github/workflows/sink.yml' + - "hack/e2e/sink/**" + - ".github/workflows/sink.yml" jobs: build: @@ -32,51 +34,51 @@ jobs: working-directory: ${{ env.E2E_SINK_DIR }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: 1.19 - cache: true + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.19 + cache: true - - name: Build - run: go build -v ./... + - name: Build + run: go build -v ./... - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - # if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + # if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=sha - type=semver,pattern={{version}},event=tag - labels: | - org.opencontainers.image.title=E2E Tests Sink - org.opencontainers.image.description=A webserver imitating an eventing sink that receives events and stores in memory - org.opencontainers.image.url=https://github.com/kyma-project/eventing-manager/${{ env.E2E_SINK_DIR }} + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha + type=semver,pattern={{version}},event=tag + labels: | + org.opencontainers.image.title=E2E Tests Sink + org.opencontainers.image.description=A webserver imitating an eventing sink that receives events and stores in memory + org.opencontainers.image.url=https://github.com/kyma-project/eventing-manager/${{ env.E2E_SINK_DIR }} - - name: Build Docker image - id: build-and-push - uses: docker/build-push-action@v5 - with: - context: ${{ env.E2E_SINK_DIR }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - load: ${{ github.event_name == 'pull_request' }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Build Docker image + id: build-and-push + uses: docker/build-push-action@v5 + with: + context: ${{ env.E2E_SINK_DIR }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + load: ${{ github.event_name == 'pull_request' }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c2768a5b..2b257025 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,17 +6,21 @@ env: on: push: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" jobs: unit: @@ -26,7 +30,7 @@ jobs: uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: "1.21" cache: false - name: Sync GO dependencies run: | diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 6243ffa0..db16acbf 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -6,15 +6,19 @@ env: on: push: - branches: [ "main" ] + branches: + - main + - "release-*" paths: - - 'api/**' - - 'config/crd/**' + - "api/**" + - "config/crd/**" pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths: - - 'api/**' - - 'config/crd/**' + - "api/**" + - "config/crd/**" jobs: crd: