diff --git a/Makefile b/Makefile index a5836056..deda1e5a 100644 --- a/Makefile +++ b/Makefile @@ -155,13 +155,9 @@ ifndef ignore-not-found endif .PHONY: install -install: download-external-crds manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. +install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/crd | kubectl apply -f - -.PHONY: download-external-crds -download-external-crds: - curl -s -L -o config/crd/external/subscriptions.eventing.kyma-project.io.crd.yaml https://raw.githubusercontent.com/kyma-project/kyma/main/installation/resources/crds/eventing/subscriptions.eventing.kyma-project.io.crd.yaml - .PHONY: uninstall uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - diff --git a/PROJECT b/PROJECT index 71755207..172a089f 100644 --- a/PROJECT +++ b/PROJECT @@ -16,6 +16,31 @@ resources: domain: kyma-project.io group: operator kind: Eventing - path: github.com/kyma-project/eventing-manager/api/batch/v1alpha1 + path: github.com/kyma-project/eventing-manager/api/operator/v1alpha1 version: v1alpha1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: kyma-project.io + group: eventing + kind: Subscription + path: github.com/kyma-project/eventing-manager/api/eventing/v1alpha1 + version: v1alpha1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: kyma-project.io + group: eventing + kind: Subscription + path: github.com/kyma-project/eventing-manager/api/eventing/v1alpha2 + version: v1alpha2 + webhooks: + defaulting: true + validation: true + conversion: true + webhookVersion: v1 version: "3" diff --git a/api/eventing/v1alpha1/condition.go b/api/eventing/v1alpha1/condition.go new file mode 100644 index 00000000..7020c9cf --- /dev/null +++ b/api/eventing/v1alpha1/condition.go @@ -0,0 +1,260 @@ +package v1alpha1 + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ConditionType string + +const ( + ConditionSubscribed ConditionType = "Subscribed" + ConditionSubscriptionActive ConditionType = "Subscription active" + ConditionAPIRuleStatus ConditionType = "APIRule status" + ConditionWebhookCallStatus ConditionType = "Webhook call status" + + ConditionPublisherProxyReady ConditionType = "Publisher Proxy Ready" + ConditionControllerReady ConditionType = "Subscription Controller Ready" +) + +var allSubscriptionConditions = MakeSubscriptionConditions() + +type Condition struct { + // Short description of the condition. + Type ConditionType `json:"type,omitempty"` + // Status of the condition. The value is either `True`, `False`, or `Unknown`. + Status corev1.ConditionStatus `json:"status"` + // Defines the date of the last condition status change. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + // Defines the reason for the condition status change. + Reason ConditionReason `json:"reason,omitempty"` + // Provides more details about the condition status change. + Message string `json:"message,omitempty"` +} + +type ConditionReason string + +const ( + // BEB Conditions. + ConditionReasonSubscriptionActive ConditionReason = "BEB Subscription active" + ConditionReasonSubscriptionNotActive ConditionReason = "BEB Subscription not active" + ConditionReasonSubscriptionDeleted ConditionReason = "BEB Subscription deleted" + ConditionReasonAPIRuleStatusReady ConditionReason = "APIRule status ready" + ConditionReasonAPIRuleStatusNotReady ConditionReason = "APIRule status not ready" + + // Common backend Conditions. + ConditionReasonSubscriptionControllerReady ConditionReason = "Subscription controller started" + ConditionReasonSubscriptionControllerNotReady ConditionReason = "Subscription controller not ready" + ConditionReasonPublisherDeploymentReady ConditionReason = "Publisher proxy deployment ready" + ConditionReasonPublisherDeploymentNotReady ConditionReason = "Publisher proxy deployment not ready" +) + +// initializeConditions sets unset conditions to Unknown. +func initializeConditions(initialConditions, currentConditions []Condition) []Condition { + givenConditions := make(map[ConditionType]Condition) + + // create map of Condition per ConditionType + for _, condition := range currentConditions { + givenConditions[condition.Type] = condition + } + + finalConditions := currentConditions + // check if every Condition is present in the current Conditions + for _, expectedCondition := range initialConditions { + if _, ok := givenConditions[expectedCondition.Type]; !ok { + // and add it if it is missing + finalConditions = append(finalConditions, expectedCondition) + } + } + return finalConditions +} + +// InitializeConditions sets unset Subscription conditions to Unknown. +func (s *SubscriptionStatus) InitializeConditions() { + initialConditions := MakeSubscriptionConditions() + s.Conditions = initializeConditions(initialConditions, s.Conditions) +} + +func (s SubscriptionStatus) IsReady() bool { + if !ContainSameConditionTypes(allSubscriptionConditions, s.Conditions) { + return false + } + + // the subscription is ready if all its conditions are evaluated to true + for _, c := range s.Conditions { + if c.Status != corev1.ConditionTrue { + return false + } + } + return true +} + +func (s SubscriptionStatus) FindCondition(conditionType ConditionType) *Condition { + for _, condition := range s.Conditions { + if conditionType == condition.Type { + return &condition + } + } + return nil +} + +// ShouldUpdateReadyStatus checks if there is a mismatch between the +// subscription Ready Status and the Ready status of all the conditions. +func (s SubscriptionStatus) ShouldUpdateReadyStatus() bool { + if !s.Ready && s.IsReady() || s.Ready && !s.IsReady() { + return true + } + return false +} + +// MakeSubscriptionConditions creates a map of all conditions which the Subscription should have. +func MakeSubscriptionConditions() []Condition { + conditions := []Condition{ + { + Type: ConditionAPIRuleStatus, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionSubscribed, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionSubscriptionActive, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionWebhookCallStatus, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + } + return conditions +} + +func ContainSameConditionTypes(conditions1, conditions2 []Condition) bool { + if len(conditions1) != len(conditions2) { + return false + } + + for _, condition := range conditions1 { + if !containConditionType(conditions2, condition.Type) { + return false + } + } + + return true +} + +func containConditionType(conditions []Condition, conditionType ConditionType) bool { + for _, condition := range conditions { + if condition.Type == conditionType { + return true + } + } + + return false +} + +func MakeCondition(conditionType ConditionType, reason ConditionReason, status corev1.ConditionStatus, message string) Condition { + return Condition{ + Type: conditionType, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + // TODO: https://github.com/kyma-project/kyma/issues/9770 + Message: message, + } +} + +func (s *SubscriptionStatus) IsConditionSubscribed() bool { + for _, condition := range s.Conditions { + if condition.Type == ConditionSubscribed && condition.Status == corev1.ConditionTrue { + return true + } + } + return false +} + +func (s *SubscriptionStatus) IsConditionWebhookCall() bool { + for _, condition := range s.Conditions { + if condition.Type == ConditionWebhookCallStatus && + (condition.Status == corev1.ConditionTrue || condition.Status == corev1.ConditionUnknown) { + return true + } + } + return false +} + +func (s *SubscriptionStatus) GetConditionAPIRuleStatus() corev1.ConditionStatus { + for _, condition := range s.Conditions { + if condition.Type == ConditionAPIRuleStatus { + return condition.Status + } + } + return corev1.ConditionUnknown +} + +func (s *SubscriptionStatus) SetConditionAPIRuleStatus(err error) { + reason := ConditionReasonAPIRuleStatusReady + status := corev1.ConditionTrue + message := "" + if err != nil { + reason = ConditionReasonAPIRuleStatusNotReady + status = corev1.ConditionFalse + message = err.Error() + } + + newConditions := []Condition{MakeCondition(ConditionAPIRuleStatus, reason, status, message)} + for _, condition := range s.Conditions { + if condition.Type == ConditionAPIRuleStatus { + continue + } + newConditions = append(newConditions, condition) + } + s.Conditions = newConditions +} + +func CreateMessageForConditionReasonSubscriptionCreated(bebName string) string { + return fmt.Sprintf("BEB-subscription-name=%s", bebName) +} + +// ConditionsEquals checks if two list of conditions are equal. +func ConditionsEquals(existing, expected []Condition) bool { + // not equal if length is different + if len(existing) != len(expected) { + return false + } + + // compile map of Conditions per ConditionType + existingMap := make(map[ConditionType]Condition, len(existing)) + for _, value := range existing { + existingMap[value.Type] = value + } + + for _, value := range expected { + if !ConditionEquals(existingMap[value.Type], value) { + return false + } + } + + return true +} + +// ConditionEquals checks if two conditions are equal. +func ConditionEquals(existing, expected Condition) bool { + isTypeEqual := existing.Type == expected.Type + isStatusEqual := existing.Status == expected.Status + isReasonEqual := existing.Reason == expected.Reason + isMessageEqual := existing.Message == expected.Message + + if !isStatusEqual || !isReasonEqual || !isMessageEqual || !isTypeEqual { + return false + } + + return true +} diff --git a/api/eventing/v1alpha1/condition_unit_test.go b/api/eventing/v1alpha1/condition_unit_test.go new file mode 100644 index 00000000..689e66c0 --- /dev/null +++ b/api/eventing/v1alpha1/condition_unit_test.go @@ -0,0 +1,470 @@ +package v1alpha1_test + +import ( + "reflect" + "testing" + "time" + + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" +) + +func Test_InitializeSubscriptionConditions(t *testing.T) { + var tests = []struct { + name string + givenConditions []v1alpha1.Condition + }{ + { + name: "Conditions empty", + givenConditions: v1alpha1.MakeSubscriptionConditions(), + }, + { + name: "Conditions partially initialized", + givenConditions: []v1alpha1.Condition{ + { + Type: v1alpha1.ConditionSubscribed, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // given + g := NewGomegaWithT(t) + s := v1alpha1.SubscriptionStatus{} + s.Conditions = tt.givenConditions + wantConditionTypes := []v1alpha1.ConditionType{ + v1alpha1.ConditionSubscribed, + v1alpha1.ConditionSubscriptionActive, + v1alpha1.ConditionAPIRuleStatus, + v1alpha1.ConditionWebhookCallStatus, + } + + // when + s.InitializeConditions() + + // then + g.Expect(s.Conditions).To(HaveLen(len(wantConditionTypes))) + foundConditionTypes := make([]v1alpha1.ConditionType, 0) + for _, condition := range s.Conditions { + g.Expect(condition.Status).To(BeEquivalentTo(corev1.ConditionUnknown)) + foundConditionTypes = append(foundConditionTypes, condition.Type) + } + g.Expect(wantConditionTypes).To(ConsistOf(foundConditionTypes)) + }) + } +} + +func Test_IsReady(t *testing.T) { + testCases := []struct { + name string + givenConditions []v1alpha1.Condition + wantReadyStatus bool + }{ + { + name: "should not be ready if conditions are nil", + givenConditions: nil, + wantReadyStatus: false, + }, + { + name: "should not be ready if conditions are empty", + givenConditions: []v1alpha1.Condition{{}}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionSubscribed is available and true", + givenConditions: []v1alpha1.Condition{{Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionSubscriptionActive is available and true", + givenConditions: []v1alpha1.Condition{{ + Type: v1alpha1.ConditionSubscriptionActive, + Status: corev1.ConditionTrue, + }}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionAPIRuleStatus is available and true", + givenConditions: []v1alpha1.Condition{{ + Type: v1alpha1.ConditionAPIRuleStatus, + Status: corev1.ConditionTrue, + }}, + wantReadyStatus: false, + }, + { + name: "should not be ready if all conditions are unknown", + givenConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionUnknown}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionUnknown}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionUnknown}, + }, + wantReadyStatus: false, + }, + { + name: "should not be ready if all conditions are false", + givenConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + }, + wantReadyStatus: false, + }, + { + name: "should be ready if all conditions are true", + givenConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantReadyStatus: true, + }, + } + + status := v1alpha1.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.givenConditions + if gotReadyStatus := status.IsReady(); tc.wantReadyStatus != gotReadyStatus { + t.Errorf("Subscription status is not valid, want: %v but got: %v", tc.wantReadyStatus, gotReadyStatus) + } + }) + } +} + +func Test_FindCondition(t *testing.T) { + currentTime := metav1.NewTime(time.Now()) + + testCases := []struct { + name string + givenConditions []v1alpha1.Condition + findConditionType v1alpha1.ConditionType + wantCondition *v1alpha1.Condition + }{ + { + name: "should be able to find the present condition", + givenConditions: []v1alpha1.Condition{ + { + Type: v1alpha1.ConditionSubscribed, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, { + Type: v1alpha1.ConditionSubscriptionActive, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, { + Type: v1alpha1.ConditionAPIRuleStatus, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, { + Type: v1alpha1.ConditionWebhookCallStatus, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, + }, + findConditionType: v1alpha1.ConditionSubscriptionActive, + wantCondition: &v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscriptionActive, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, + }, + { + name: "should not be able to find the non-present condition", + givenConditions: []v1alpha1.Condition{{ + Type: v1alpha1.ConditionSubscribed, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, { + Type: v1alpha1.ConditionAPIRuleStatus, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }, { + Type: v1alpha1.ConditionWebhookCallStatus, + Status: corev1.ConditionTrue, + LastTransitionTime: currentTime, + }}, + findConditionType: v1alpha1.ConditionSubscriptionActive, + wantCondition: nil, + }, + } + + status := v1alpha1.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.givenConditions + gotCondition := status.FindCondition(tc.findConditionType) + + if !reflect.DeepEqual(tc.wantCondition, gotCondition) { + t.Errorf("Subscription FindCondition failed, want: %v but got: %v", tc.wantCondition, gotCondition) + } + }) + } +} + +func Test_ShouldUpdateReadyStatus(t *testing.T) { + testCases := []struct { + name string + subscriptionReady bool + subscriptionConditions []v1alpha1.Condition + wantStatus bool + }{ + { + name: "should not update if the subscription is ready and the conditions are ready", + subscriptionReady: true, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantStatus: false, + }, + { + name: "should not update if the subscription is not ready and the conditions are not ready", + subscriptionReady: false, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionFalse}, + }, + wantStatus: false, + }, + { + name: "should update if the subscription is not ready and the conditions are ready", + subscriptionReady: false, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantStatus: true, + }, + { + name: "should update if the subscription is ready and the conditions are not ready", + subscriptionReady: true, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionFalse}, + }, + wantStatus: true, + }, + { + name: "should update if the subscription is ready and some of the conditions are missing", + subscriptionReady: true, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionUnknown}, + }, + wantStatus: true, + }, + { + name: "should not update if the subscription is not ready and some of the conditions are missing", + subscriptionReady: false, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionUnknown}, + }, + wantStatus: false, + }, + { + name: "should update if the subscription is ready and the status of the conditions are unknown", + subscriptionReady: true, + subscriptionConditions: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionUnknown}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionUnknown}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionUnknown}, + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionUnknown}, + }, + wantStatus: true, + }, + } + + status := v1alpha1.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.subscriptionConditions + status.Ready = tc.subscriptionReady + if gotStatus := status.ShouldUpdateReadyStatus(); tc.wantStatus != gotStatus { + t.Errorf("ShouldUpdateReadyStatus is not valid, want: %v but got: %v", tc.wantStatus, gotStatus) + } + }) + } +} + +func Test_conditionsEquals(t *testing.T) { + testCases := []struct { + name string + conditionsSet1 []v1alpha1.Condition + conditionsSet2 []v1alpha1.Condition + wantEqualStatus bool + }{ + { + name: "should not be equal if the number of conditions are not equal", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha1.Condition{}, + wantEqualStatus: false, + }, + { + name: "should be equal if the conditions are the same", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: true, + }, + { + name: "should not be equal if the condition types are different", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are the same but the status is different", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionFalse}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are different but the status is the same", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + }, + conditionsSet2: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are different and an empty key is referenced", + conditionsSet1: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha1.Condition{ + {Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha1.ConditionControllerReady, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + want := tc.wantEqualStatus + actual := v1alpha1.ConditionsEquals(tc.conditionsSet1, tc.conditionsSet2) + if actual != want { + t.Errorf("The list of conditions are not equal, want: %v but got: %v", want, actual) + } + }) + } +} + +func Test_conditionEquals(t *testing.T) { + testCases := []struct { + name string + condition1 v1alpha1.Condition + condition2 v1alpha1.Condition + wantEqualStatus bool + }{ + { + name: "should not be equal if the types are the same but the status is different", + condition1: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue, + }, + + condition2: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionUnknown, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the types are different but the status is the same", + condition1: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue, + }, + + condition2: v1alpha1.Condition{ + Type: v1alpha1.ConditionAPIRuleStatus, Status: corev1.ConditionTrue, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the message fields are different", + condition1: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue, Message: "", + }, + + condition2: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, Status: corev1.ConditionTrue, Message: "some message", + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the reason fields are different", + condition1: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, + Status: corev1.ConditionTrue, + Reason: v1alpha1.ConditionReasonSubscriptionDeleted, + }, + + condition2: v1alpha1.Condition{ + Type: v1alpha1.ConditionSubscribed, + Status: corev1.ConditionTrue, + Reason: v1alpha1.ConditionReasonSubscriptionActive, + }, + wantEqualStatus: false, + }, + { + name: "should be equal if all the fields are the same", + condition1: v1alpha1.Condition{ + Type: v1alpha1.ConditionAPIRuleStatus, + Status: corev1.ConditionFalse, + Reason: v1alpha1.ConditionReasonAPIRuleStatusNotReady, + Message: "API Rule is not ready", + }, + condition2: v1alpha1.Condition{ + Type: v1alpha1.ConditionAPIRuleStatus, + Status: corev1.ConditionFalse, + Reason: v1alpha1.ConditionReasonAPIRuleStatusNotReady, + Message: "API Rule is not ready", + }, + wantEqualStatus: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + want := tc.wantEqualStatus + actual := v1alpha1.ConditionEquals(tc.condition1, tc.condition2) + if want != actual { + t.Errorf("The conditions are not equal, want: %v but got: %v", want, actual) + } + }) + } +} diff --git a/api/eventing/v1alpha1/fixtures_test.go b/api/eventing/v1alpha1/fixtures_test.go new file mode 100644 index 00000000..a974c298 --- /dev/null +++ b/api/eventing/v1alpha1/fixtures_test.go @@ -0,0 +1,188 @@ +package v1alpha1_test + +import ( + "fmt" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + "github.com/kyma-project/eventing-manager/pkg/utils" + eventingtesting "github.com/kyma-project/eventing-manager/testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" +) + +const ( + eventSource = "source" + orderCreatedEventType = "prefix." + "noapp." + "order.created.v1" + orderUpdatedEventType = "prefix." + "app." + "order.updated.v1" + orderDeletedEventType = "prefix." + "noapp." + "order.deleted.v1" + orderDeletedEventTypeNonClean = "prefix." + "noapp." + "order.deleted_&.v1" + orderProcessedEventType = "prefix." + "noapp." + "order.processed.v1" +) + +const ( + defaultName = "test" + defaultNamespace = "test-namespace" + defaultSink = "https://svc2.test.local" + defaultID = "id" + defaultMaxInFlight = 10 + defaultStatusReady = true +) + +var ( + v2DefaultConditions = []v1alpha2.Condition{ + { + Type: v1alpha2.ConditionSubscriptionActive, + Status: "true", + }, + { + Type: v1alpha2.ConditionSubscribed, + Status: "false", + }} +) + +func newDefaultSubscription(opts ...eventingtesting.SubscriptionV1alpha1Opt) *v1alpha1.Subscription { + var defaultConditions []v1alpha1.Condition + for _, condition := range v2DefaultConditions { + defaultConditions = append(defaultConditions, v1alpha1.ConditionV2ToV1(condition)) + } + newSub := &v1alpha1.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: "Subscription", + APIVersion: "eventing.kyma-project.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: defaultName, + Namespace: defaultNamespace, + }, + Spec: v1alpha1.SubscriptionSpec{ + Sink: defaultSink, + ID: defaultID, + Config: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: defaultMaxInFlight}, + }, + Status: v1alpha1.SubscriptionStatus{ + Conditions: defaultConditions, + Ready: defaultStatusReady, + Config: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: defaultMaxInFlight}, + }, + } + for _, o := range opts { + o(newSub) + } + + // remove nats specific field in eventmesh case + if newSub.Status.EmsSubscriptionStatus != nil { + newSub.Spec.Config = nil + newSub.Status.Config = nil + } + + return newSub +} + +// extend the v1 Subscription helpers with Status fields + +func v1WithWebhookAuthForBEB() eventingtesting.SubscriptionV1alpha1Opt { + return func(s *v1alpha1.Subscription) { + s.Spec.Protocol = "BEB" + s.Spec.ProtocolSettings = &v1alpha1.ProtocolSettings{ + ContentMode: func() *string { + contentMode := v1alpha1.ProtocolSettingsContentModeBinary + return &contentMode + }(), + Qos: func() *string { + qos := "AT_LEAST_ONCE" + return &qos + }(), + ExemptHandshake: utils.BoolPtr(true), + WebhookAuth: &v1alpha1.WebhookAuth{ + Type: "oauth2", + GrantType: "client_credentials", + ClientID: "xxx", + ClientSecret: "xxx", + TokenURL: "https://oauth2.xxx.com/oauth2/token", + Scope: []string{"guid-identifier", "root"}, + }, + } + } +} + +func v1WithBEBStatusFields() eventingtesting.SubscriptionV1alpha1Opt { + return func(s *v1alpha1.Subscription) { + s.Status.Ev2hash = 123 + s.Status.ExternalSink = "testlink.com" + s.Status.FailedActivation = "123156464672" + s.Status.APIRuleName = "APIRule" + s.Status.EmsSubscriptionStatus = &v1alpha1.EmsSubscriptionStatus{ + SubscriptionStatus: "not active", + SubscriptionStatusReason: "reason", + LastSuccessfulDelivery: "", + LastFailedDelivery: "1345613234", + LastFailedDeliveryReason: "failed", + } + } +} + +func newV2DefaultSubscription(opts ...eventingtesting.SubscriptionOpt) *v1alpha2.Subscription { + newSub := &v1alpha2.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: "Subscription", + APIVersion: "eventing.kyma-project.io/v1alpha2", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: defaultName, + Namespace: defaultNamespace, + }, + Spec: v1alpha2.SubscriptionSpec{ + TypeMatching: v1alpha2.TypeMatchingExact, + Sink: defaultSink, + ID: defaultID, + Config: map[string]string{ + v1alpha2.MaxInFlightMessages: fmt.Sprint(defaultMaxInFlight), + }, + }, + Status: v1alpha2.SubscriptionStatus{ + Ready: defaultStatusReady, + Conditions: v2DefaultConditions, + }, + } + for _, o := range opts { + o(newSub) + } + + return newSub +} + +// extend the v2 Subscription helpers with Status fields + +func v2WithBEBStatusFields() eventingtesting.SubscriptionOpt { + return func(s *v1alpha2.Subscription) { + s.Status.Backend.Ev2hash = 123 + s.Status.Backend.ExternalSink = "testlink.com" + s.Status.Backend.FailedActivation = "123156464672" + s.Status.Backend.APIRuleName = "APIRule" + s.Status.Backend.EventMeshSubscriptionStatus = &v1alpha2.EventMeshSubscriptionStatus{ + Status: "not active", + StatusReason: "reason", + LastSuccessfulDelivery: "", + LastFailedDelivery: "1345613234", + LastFailedDeliveryReason: "failed", + } + } +} + +func v2WithStatusTypes(statusTypes []v1alpha2.EventType) eventingtesting.SubscriptionOpt { + return func(sub *v1alpha2.Subscription) { + if statusTypes == nil { + sub.Status.InitializeEventTypes() + return + } + sub.Status.Types = statusTypes + } +} + +func v2WithStatusJetStreamTypes(types []v1alpha2.JetStreamTypes) eventingtesting.SubscriptionOpt { + return func(sub *v1alpha2.Subscription) { + sub.Status.Backend.Types = types + } +} diff --git a/api/eventing/v1alpha1/groupversion_info.go b/api/eventing/v1alpha1/groupversion_info.go new file mode 100644 index 00000000..8f4291fe --- /dev/null +++ b/api/eventing/v1alpha1/groupversion_info.go @@ -0,0 +1,20 @@ +// Package v1alpha1 contains API Schema definitions for the eventing v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=eventing.kyma-project.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "eventing.kyma-project.io", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/eventing/v1alpha1/subscription_conversion.go b/api/eventing/v1alpha1/subscription_conversion.go new file mode 100644 index 00000000..f6d8205e --- /dev/null +++ b/api/eventing/v1alpha1/subscription_conversion.go @@ -0,0 +1,320 @@ +package v1alpha1 + +import ( + "fmt" + "strconv" + "strings" + + "github.com/kyma-project/eventing-manager/pkg/backend/eventtype" + + "github.com/pkg/errors" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" +) + +const ( + ErrorHubVersionMsg = "hub version is not the expected v1alpha2 version" + ErrorMultipleSourceMsg = "subscription contains more than 1 eventSource" +) + +var v1alpha1TypeCleaner eventtype.Cleaner //nolint:gochecknoglobals // using global var because there is no runtime +// object to hold this instance. + +func InitializeEventTypeCleaner(cleaner eventtype.Cleaner) { + v1alpha1TypeCleaner = cleaner +} + +// ConvertTo converts this Subscription in version v1 to the Hub version v2. +func (src *Subscription) ConvertTo(dstRaw conversion.Hub) error { + dst, ok := dstRaw.(*v1alpha2.Subscription) + if !ok { + return errors.Errorf(ErrorHubVersionMsg) + } + return V1ToV2(src, dst) +} + +// V1ToV2 copies the v1alpha1-type field values into v1alpha2-type field values. +func V1ToV2(src *Subscription, dst *v1alpha2.Subscription) error { + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + // SPEC fields + + dst.Spec.ID = src.Spec.ID + dst.Spec.Sink = src.Spec.Sink + dst.Spec.Source = "" + + src.setV2TypeMatching(dst) + + // protocol fields + src.setV2ProtocolFields(dst) + + // Types + if err := src.setV2SpecTypes(dst); err != nil { + return err + } + + // Config + src.natsSpecConfigToV2(dst) + + return nil +} + +// ConvertFrom converts this Subscription from the Hub version (v2) to v1. +func (dst *Subscription) ConvertFrom(srcRaw conversion.Hub) error { //nolint:revive + src, ok := srcRaw.(*v1alpha2.Subscription) + if !ok { + return errors.Errorf(ErrorHubVersionMsg) + } + return V2ToV1(dst, src) +} + +// V2ToV1 copies the v1alpha2-type field values into v1alpha1-type field values. +func V2ToV1(dst *Subscription, src *v1alpha2.Subscription) error { + // ObjectMeta + dst.ObjectMeta = src.ObjectMeta + + dst.Spec.ID = src.Spec.ID + dst.Spec.Sink = src.Spec.Sink + + dst.setV1ProtocolFields(src) + + dst.Spec.Filter = &BEBFilters{ + Filters: []*EventMeshFilter{}, + } + + for _, eventType := range src.Spec.Types { + filter := &EventMeshFilter{ + EventSource: &Filter{ + Property: "source", + Type: fmt.Sprint(v1alpha2.TypeMatchingExact), + Value: src.Spec.Source, + }, + EventType: &Filter{ + Type: fmt.Sprint(v1alpha2.TypeMatchingExact), + Property: "type", + Value: eventType, + }, + } + dst.Spec.Filter.Filters = append(dst.Spec.Filter.Filters, filter) + } + + if src.Spec.Config != nil { + if err := dst.natsSpecConfigToV1(src); err != nil { + return err + } + } + + // Conditions + for _, condition := range src.Status.Conditions { + dst.Status.Conditions = append(dst.Status.Conditions, ConditionV2ToV1(condition)) + } + + dst.Status.Ready = src.Status.Ready + + dst.setV1CleanEvenTypes(src) + dst.bebBackendStatusToV1(src) + dst.natsBackendStatusToV1(src) + + return nil +} + +// setV2TypeMatching sets the default typeMatching on the v1alpha2 Subscription version. +func (src *Subscription) setV2TypeMatching(dst *v1alpha2.Subscription) { + dst.Spec.TypeMatching = v1alpha2.TypeMatchingExact +} + +// setV2ProtocolFields converts the protocol-related fields from v1alpha1 to v1alpha2 Subscription version. +func (src *Subscription) setV2ProtocolFields(dst *v1alpha2.Subscription) { + dst.Spec.Config = map[string]string{} + if src.Spec.Protocol != "" { + dst.Spec.Config[v1alpha2.Protocol] = src.Spec.Protocol + } + // protocol settings + if src.Spec.ProtocolSettings != nil { + if src.Spec.ProtocolSettings.ContentMode != nil { + dst.Spec.Config[v1alpha2.ProtocolSettingsContentMode] = *src.Spec.ProtocolSettings.ContentMode + } + if src.Spec.ProtocolSettings.ExemptHandshake != nil { + dst.Spec.Config[v1alpha2.ProtocolSettingsExemptHandshake] = fmt.Sprint(*src.Spec.ProtocolSettings.ExemptHandshake) + } + if src.Spec.ProtocolSettings.Qos != nil { + dst.Spec.Config[v1alpha2.ProtocolSettingsQos] = *src.Spec.ProtocolSettings.Qos + } + // webhookAuth fields + if src.Spec.ProtocolSettings.WebhookAuth != nil { + if src.Spec.ProtocolSettings.WebhookAuth.Type != "" { + dst.Spec.Config[v1alpha2.WebhookAuthType] = src.Spec.ProtocolSettings.WebhookAuth.Type + } + dst.Spec.Config[v1alpha2.WebhookAuthGrantType] = src.Spec.ProtocolSettings.WebhookAuth.GrantType + dst.Spec.Config[v1alpha2.WebhookAuthClientID] = src.Spec.ProtocolSettings.WebhookAuth.ClientID + dst.Spec.Config[v1alpha2.WebhookAuthClientSecret] = src.Spec.ProtocolSettings.WebhookAuth.ClientSecret + dst.Spec.Config[v1alpha2.WebhookAuthTokenURL] = src.Spec.ProtocolSettings.WebhookAuth.TokenURL + if src.Spec.ProtocolSettings.WebhookAuth.Scope != nil { + dst.Spec.Config[v1alpha2.WebhookAuthScope] = strings.Join(src.Spec.ProtocolSettings.WebhookAuth.Scope, ",") + } + } + } +} + +func (src *Subscription) initializeProtocolSettingsIfNil() { + if src.Spec.ProtocolSettings == nil { + src.Spec.ProtocolSettings = &ProtocolSettings{} + } +} + +func (src *Subscription) initializeWebhookAuthIfNil() { + src.initializeProtocolSettingsIfNil() + if src.Spec.ProtocolSettings.WebhookAuth == nil { + src.Spec.ProtocolSettings.WebhookAuth = &WebhookAuth{} + } +} + +// setV1ProtocolFields converts the protocol-related fields from v1alpha1 to v1alpha2 Subscription version. +func (src *Subscription) setV1ProtocolFields(dst *v1alpha2.Subscription) { + if protocol, ok := dst.Spec.Config[v1alpha2.Protocol]; ok { + src.Spec.Protocol = protocol + } + + if currentMode, ok := dst.Spec.Config[v1alpha2.ProtocolSettingsContentMode]; ok { + src.initializeProtocolSettingsIfNil() + src.Spec.ProtocolSettings.ContentMode = ¤tMode + } + if qos, ok := dst.Spec.Config[v1alpha2.ProtocolSettingsQos]; ok { + src.initializeProtocolSettingsIfNil() + src.Spec.ProtocolSettings.Qos = &qos + } + if exemptHandshake, ok := dst.Spec.Config[v1alpha2.ProtocolSettingsExemptHandshake]; ok { + handshake, err := strconv.ParseBool(exemptHandshake) + if err != nil { + handshake = true + } + src.initializeProtocolSettingsIfNil() + src.Spec.ProtocolSettings.ExemptHandshake = &handshake + } + + if authType, ok := dst.Spec.Config[v1alpha2.WebhookAuthType]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.Type = authType + } + if grantType, ok := dst.Spec.Config[v1alpha2.WebhookAuthGrantType]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.GrantType = grantType + } + if clientID, ok := dst.Spec.Config[v1alpha2.WebhookAuthClientID]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.ClientID = clientID + } + if secret, ok := dst.Spec.Config[v1alpha2.WebhookAuthClientSecret]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.ClientSecret = secret + } + if token, ok := dst.Spec.Config[v1alpha2.WebhookAuthTokenURL]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.TokenURL = token + } + if scope, ok := dst.Spec.Config[v1alpha2.WebhookAuthScope]; ok { + src.initializeWebhookAuthIfNil() + src.Spec.ProtocolSettings.WebhookAuth.Scope = strings.Split(scope, ",") + } +} + +// setV2SpecTypes sets event types in the Subscription Spec in the v1alpha2 way. +func (src *Subscription) setV2SpecTypes(dst *v1alpha2.Subscription) error { + if v1alpha1TypeCleaner == nil { + return errors.New("event type cleaner is not initialized") + } + + if src.Spec.Filter != nil { + for _, filter := range src.Spec.Filter.Filters { + if dst.Spec.Source == "" { + dst.Spec.Source = filter.EventSource.Value + } + if dst.Spec.Source != "" && filter.EventSource.Value != dst.Spec.Source { + return errors.New(ErrorMultipleSourceMsg) + } + // clean the type and merge segments if needed + cleanedType, err := v1alpha1TypeCleaner.Clean(filter.EventType.Value) + if err != nil { + return err + } + + // add the type to spec + dst.Spec.Types = append(dst.Spec.Types, cleanedType) + } + } + return nil +} + +// natsSpecConfigToV2 converts the v1alpha2 Spec config to v1alpha1. +func (src *Subscription) natsSpecConfigToV1(dst *v1alpha2.Subscription) error { + if maxInFlightMessages, ok := dst.Spec.Config[v1alpha2.MaxInFlightMessages]; ok { + intVal, err := strconv.Atoi(maxInFlightMessages) + if err != nil { + return err + } + src.Spec.Config = &SubscriptionConfig{ + MaxInFlightMessages: intVal, + } + } + return nil +} + +// natsSpecConfigToV2 converts the hardcoded v1alpha1 Spec config to v1alpha2 generic config version. +func (src *Subscription) natsSpecConfigToV2(dst *v1alpha2.Subscription) { + if src.Spec.Config != nil { + if dst.Spec.Config == nil { + dst.Spec.Config = map[string]string{} + } + dst.Spec.Config[v1alpha2.MaxInFlightMessages] = fmt.Sprint(src.Spec.Config.MaxInFlightMessages) + } +} + +// setBEBBackendStatus moves the BEB-related to Backend fields of the Status in the v1alpha2. +func (src *Subscription) bebBackendStatusToV1(dst *v1alpha2.Subscription) { + src.Status.Ev2hash = dst.Status.Backend.Ev2hash + src.Status.Emshash = dst.Status.Backend.EventMeshHash + src.Status.ExternalSink = dst.Status.Backend.ExternalSink + src.Status.FailedActivation = dst.Status.Backend.FailedActivation + src.Status.APIRuleName = dst.Status.Backend.APIRuleName + if dst.Status.Backend.EventMeshSubscriptionStatus != nil { + src.Status.EmsSubscriptionStatus = &EmsSubscriptionStatus{ + SubscriptionStatus: dst.Status.Backend.EventMeshSubscriptionStatus.Status, + SubscriptionStatusReason: dst.Status.Backend.EventMeshSubscriptionStatus.StatusReason, + LastSuccessfulDelivery: dst.Status.Backend.EventMeshSubscriptionStatus.LastSuccessfulDelivery, + LastFailedDelivery: dst.Status.Backend.EventMeshSubscriptionStatus.LastFailedDelivery, + LastFailedDeliveryReason: dst.Status.Backend.EventMeshSubscriptionStatus.LastFailedDeliveryReason, + } + } +} + +// natsBackendStatusToV1 moves the NATS-related to Backend fields of the Status in the v1alpha2. +func (src *Subscription) natsBackendStatusToV1(dst *v1alpha2.Subscription) { + if maxInFlightMessages, ok := dst.Spec.Config[v1alpha2.MaxInFlightMessages]; ok { + intVal, err := strconv.Atoi(maxInFlightMessages) + if err == nil { + src.Status.Config = &SubscriptionConfig{} + src.Status.Config.MaxInFlightMessages = intVal + } + } +} + +// setV1CleanEvenTypes sets the clean event types to v1alpha1 Subscription Status. +func (src *Subscription) setV1CleanEvenTypes(dst *v1alpha2.Subscription) { + src.Status.InitializeCleanEventTypes() + for _, eventType := range dst.Status.Types { + src.Status.CleanEventTypes = append(src.Status.CleanEventTypes, eventType.CleanType) + } +} + +// ConditionV2ToV1 converts the v1alpha2 Condition to v1alpha1 version. +func ConditionV2ToV1(condition v1alpha2.Condition) Condition { + return Condition{ + Type: ConditionType(condition.Type), + Status: condition.Status, + LastTransitionTime: condition.LastTransitionTime, + Reason: ConditionReason(condition.Reason), + Message: condition.Message, + } +} diff --git a/api/eventing/v1alpha1/subscription_conversion_unit_test.go b/api/eventing/v1alpha1/subscription_conversion_unit_test.go new file mode 100644 index 00000000..563caf94 --- /dev/null +++ b/api/eventing/v1alpha1/subscription_conversion_unit_test.go @@ -0,0 +1,409 @@ +package v1alpha1_test + +import ( + "testing" + + "github.com/kyma-project/eventing-manager/pkg/logger" + + "github.com/kyma-project/eventing-manager/pkg/backend/eventtype" + + "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" + + eventingtesting "github.com/kyma-project/eventing-manager/testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" +) + +func Test_Conversion(t *testing.T) { + type TestCase struct { + name string + alpha1Sub *v1alpha1.Subscription + alpha2Sub *v1alpha2.Subscription + wantErrMsgV1toV2 string + wantErrMsgV2toV1 string + } + + testCases := []TestCase{ + { + name: "Converting NATS Subscription with empty Status", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1EmptyFilter(), + eventingtesting.WithV1alpha1EmptyConfig(), + eventingtesting.WithV1alpha1EmptyStatus(), + ), + alpha2Sub: newV2DefaultSubscription( + eventingtesting.WithEmptyStatus(), + eventingtesting.WithEmptyConfig(), + ), + }, + { + name: "Converting NATS Subscription with empty Filters", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1EmptyFilter(), + eventingtesting.WithStatusCleanEventTypes(nil), + ), + alpha2Sub: newV2DefaultSubscription(), + }, + { + name: "Converting NATS Subscription with multiple source which should result in a conversion error", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter("app", orderUpdatedEventType), + eventingtesting.WithV1alpha1Filter("", orderDeletedEventTypeNonClean), + ), + alpha2Sub: newV2DefaultSubscription(), + wantErrMsgV1toV2: v1alpha1.ErrorMultipleSourceMsg, + }, + { + name: "Converting NATS Subscription with non-convertable maxInFlight in the config which should result in a conversion error", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter("", orderUpdatedEventType), + ), + alpha2Sub: newV2DefaultSubscription( + eventingtesting.WithMaxInFlightMessages("nonint"), + ), + wantErrMsgV2toV1: "strconv.Atoi: parsing \"nonint\": invalid syntax", + }, + { + name: "Converting NATS Subscription with Filters", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, orderCreatedEventType), + eventingtesting.WithV1alpha1Filter(eventSource, orderUpdatedEventType), + eventingtesting.WithV1alpha1Filter(eventSource, orderDeletedEventTypeNonClean), + eventingtesting.WithStatusCleanEventTypes([]string{ + orderCreatedEventType, + orderUpdatedEventType, + orderDeletedEventType, + }), + ), + alpha2Sub: newV2DefaultSubscription( + eventingtesting.WithEventSource(eventSource), + eventingtesting.WithTypes([]string{ + orderCreatedEventType, + orderUpdatedEventType, + orderDeletedEventTypeNonClean, + }), + v2WithStatusTypes([]v1alpha2.EventType{ + { + OriginalType: orderCreatedEventType, + CleanType: orderCreatedEventType, + }, + { + OriginalType: orderUpdatedEventType, + CleanType: orderUpdatedEventType, + }, + { + OriginalType: orderDeletedEventTypeNonClean, + CleanType: orderDeletedEventType, + }, + }), + v2WithStatusJetStreamTypes([]v1alpha2.JetStreamTypes{ + { + OriginalType: orderCreatedEventType, + ConsumerName: "", + }, + { + OriginalType: orderUpdatedEventType, + ConsumerName: "", + }, + { + OriginalType: orderDeletedEventTypeNonClean, + ConsumerName: "", + }, + }), + ), + }, + { + name: "Converting BEB Subscription", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1ProtocolEventMesh(), + v1WithWebhookAuthForBEB(), + eventingtesting.WithV1alpha1Filter(eventSource, orderCreatedEventType), + eventingtesting.WithV1alpha1Filter(eventSource, orderUpdatedEventType), + eventingtesting.WithV1alpha1Filter(eventSource, orderDeletedEventTypeNonClean), + eventingtesting.WithStatusCleanEventTypes([]string{ + orderCreatedEventType, + orderUpdatedEventType, + orderDeletedEventType, + }), + v1WithBEBStatusFields(), + ), + alpha2Sub: newV2DefaultSubscription( + eventingtesting.WithEventSource(eventSource), + eventingtesting.WithTypes([]string{ + orderCreatedEventType, + orderUpdatedEventType, + orderDeletedEventTypeNonClean, + }), + eventingtesting.WithProtocolEventMesh(), + eventingtesting.WithWebhookAuthForEventMesh(), + v2WithStatusTypes([]v1alpha2.EventType{ + { + OriginalType: orderCreatedEventType, + CleanType: orderCreatedEventType, + }, + { + OriginalType: orderUpdatedEventType, + CleanType: orderUpdatedEventType, + }, + { + OriginalType: orderDeletedEventTypeNonClean, + CleanType: orderDeletedEventType, + }, + }), + v2WithBEBStatusFields(), + ), + }, + { + name: "Converting Subscription with Protocol, ProtocolSettings and WebhookAuth", + alpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1ProtocolEventMesh(), + eventingtesting.WithV1alpha1ProtocolSettings( + eventingtesting.NewProtocolSettings( + eventingtesting.WithAtLeastOnceQOS(), + eventingtesting.WithRequiredWebhookAuth())), + eventingtesting.WithV1alpha1Filter(eventSource, orderCreatedEventType), + eventingtesting.WithStatusCleanEventTypes([]string{ + orderCreatedEventType, + }), + ), + alpha2Sub: newV2DefaultSubscription( + eventingtesting.WithEventSource(eventSource), + eventingtesting.WithTypes([]string{ + orderCreatedEventType, + }), + eventingtesting.WithProtocolEventMesh(), + eventingtesting.WithConfigValue(v1alpha2.ProtocolSettingsQos, + string(types.QosAtLeastOnce)), + eventingtesting.WithConfigValue(v1alpha2.WebhookAuthGrantType, + "client_credentials"), + eventingtesting.WithConfigValue(v1alpha2.WebhookAuthClientID, + "xxx"), + eventingtesting.WithConfigValue(v1alpha2.WebhookAuthClientSecret, + "xxx"), + eventingtesting.WithConfigValue(v1alpha2.WebhookAuthTokenURL, + "https://oauth2.xxx.com/oauth2/token"), + v2WithStatusTypes([]v1alpha2.EventType{ + { + OriginalType: orderCreatedEventType, + CleanType: orderCreatedEventType, + }, + }), + ), + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + // WHEN + t.Run("Test v1 to v2 conversion", func(t *testing.T) { + // skip the conversion if the backwards conversion cannot succeed + if testCase.wantErrMsgV2toV1 != "" { + return + } + + // initialize dummy cleaner + cleaner := eventtype.CleanerFunc(func(et string) (string, error) { return et, nil }) + v1alpha1.InitializeEventTypeCleaner(cleaner) + + convertedV1Alpha2 := &v1alpha2.Subscription{} + err := v1alpha1.V1ToV2(testCase.alpha1Sub, convertedV1Alpha2) + if err != nil && testCase.wantErrMsgV1toV2 != "" { + require.Equal(t, err.Error(), testCase.wantErrMsgV1toV2) + } else { + require.NoError(t, err) + v1ToV2Assertions(t, testCase.alpha2Sub, convertedV1Alpha2) + } + }) + + // test ConvertFrom + t.Run("Test v2 to v1 conversion", func(t *testing.T) { + // skip the backwards conversion if the initial one cannot succeed + if testCase.wantErrMsgV1toV2 != "" { + return + } + convertedV1Alpha1 := &v1alpha1.Subscription{} + err := v1alpha1.V2ToV1(convertedV1Alpha1, testCase.alpha2Sub) + if err != nil && testCase.wantErrMsgV2toV1 != "" { + require.Equal(t, err.Error(), testCase.wantErrMsgV2toV1) + } else { + require.NoError(t, err) + v2ToV1Assertions(t, testCase.alpha1Sub, convertedV1Alpha1) + } + }) + }) + } +} + +// Test_CleanupInV1ToV2Conversion test the cleaning from non-alphanumeric characters +// and also merging of segments in event types if they exceed the limit. +func Test_CleanupInV1ToV2Conversion(t *testing.T) { + type TestCase struct { + name string + givenAlpha1Sub *v1alpha1.Subscription + givenPrefix string + wantTypes []string + wantError bool + } + + testCases := []TestCase{ + { + name: "success if prefix is empty", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "testapp.Segment1-Part1-Part2-Ä.Segment2-Part1-Part2-Ä.v1"), + ), + givenPrefix: "", + wantTypes: []string{ + "testapp.Segment1Part1Part2.Segment2Part1Part2.v1", + }, + }, + { + name: "success if the given event has more than two segments", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.testapp.Segment1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + ), + wantTypes: []string{ + "prefix.testapp.Segment1Segment2Segment3Segment4Part1Part2.Segment5Part1Part2.v1", + }, + wantError: false, + }, + { + name: "success if the application name needs to be cleaned", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.te--s__t!!a@@p##p%%.Segment1-Part1-Part2-Ä."+ + "Segment2-Part1-Part2-Ä.v1"), + ), + wantTypes: []string{ + "prefix.testapp.Segment1Part1Part2.Segment2Part1Part2.v1", + }, + wantError: false, + }, + { + name: "success if the application name needs to be cleaned and event has more than two segments", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.te--s__t!!a@@p##p%%.Segment1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + ), + wantTypes: []string{ + "prefix.testapp.Segment1Segment2Segment3Segment4Part1Part2.Segment5Part1Part2.v1", + }, + wantError: false, + }, + { + name: "success if there are multiple filters", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.test-app.Segme@@nt1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.testapp.Segment1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + ), + wantTypes: []string{ + "prefix.testapp.Segment1Segment2Segment3Segment4Part1Part2.Segment5Part1Part2.v1", + "prefix.testapp.Segment1Segment2Segment3Segment4Part1Part2.Segment5Part1Part2.v1", + }, + wantError: false, + }, + // invalid even-types + { + name: "fail if the prefix is invalid", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "invalid.test-app.Segme@@nt1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + ), + wantError: true, + }, + { + name: "fail if the prefix is missing", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "test-app.Segme@@nt1.Segment2.Segment3."+ + "Segment4-Part1-Part2-Ä.Segment5-Part1-Part2-Ä.v1"), + ), + wantError: true, + }, + { + name: "fail if the event-type is incomplete", + givenPrefix: "prefix", + givenAlpha1Sub: newDefaultSubscription( + eventingtesting.WithV1alpha1Filter(eventSource, "prefix.testapp.Segment1-Part1-Part2-Ä.v1"), + ), + wantError: true, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + // given + testLogger, err := logger.New("json", "info") + require.NoError(t, err) + + // initialize dummy cleaner + cleaner := eventtype.NewSimpleCleaner(tc.givenPrefix, testLogger) + v1alpha1.InitializeEventTypeCleaner(cleaner) + + // initialize v1alpha2 Subscription instance + convertedV1Alpha2 := &v1alpha2.Subscription{} + + // when + err = v1alpha1.V1ToV2(tc.givenAlpha1Sub, convertedV1Alpha2) + + // then + if tc.wantError { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tc.wantTypes, convertedV1Alpha2.Spec.Types) + } + }) + } +} + +func v1ToV2Assertions(t *testing.T, wantSub, convertedSub *v1alpha2.Subscription) { + assert.Equal(t, wantSub.ObjectMeta, convertedSub.ObjectMeta) + + // Spec + assert.Equal(t, wantSub.Spec.ID, convertedSub.Spec.ID) + assert.Equal(t, wantSub.Spec.Sink, convertedSub.Spec.Sink) + assert.Equal(t, wantSub.Spec.TypeMatching, convertedSub.Spec.TypeMatching) + assert.Equal(t, wantSub.Spec.Source, convertedSub.Spec.Source) + assert.Equal(t, wantSub.Spec.Types, convertedSub.Spec.Types) + assert.Equal(t, wantSub.Spec.Config, convertedSub.Spec.Config) +} + +func v2ToV1Assertions(t *testing.T, wantSub, convertedSub *v1alpha1.Subscription) { + assert.Equal(t, wantSub.ObjectMeta, convertedSub.ObjectMeta) + + // Spec + assert.Equal(t, wantSub.Spec.ID, convertedSub.Spec.ID) + assert.Equal(t, wantSub.Spec.Sink, convertedSub.Spec.Sink) + assert.Equal(t, wantSub.Spec.Protocol, convertedSub.Spec.Protocol) + assert.Equal(t, wantSub.Spec.ProtocolSettings, convertedSub.Spec.ProtocolSettings) + + assert.Equal(t, wantSub.Spec.Filter, convertedSub.Spec.Filter) + assert.Equal(t, wantSub.Spec.Config, convertedSub.Spec.Config) + + // Status + assert.Equal(t, wantSub.Status.Ready, convertedSub.Status.Ready) + assert.Equal(t, wantSub.Status.Conditions, convertedSub.Status.Conditions) + assert.Equal(t, wantSub.Status.CleanEventTypes, convertedSub.Status.CleanEventTypes) + + // BEB fields + assert.Equal(t, wantSub.Status.Ev2hash, convertedSub.Status.Ev2hash) + assert.Equal(t, wantSub.Status.Emshash, convertedSub.Status.Emshash) + assert.Equal(t, wantSub.Status.ExternalSink, convertedSub.Status.ExternalSink) + assert.Equal(t, wantSub.Status.FailedActivation, convertedSub.Status.FailedActivation) + assert.Equal(t, wantSub.Status.APIRuleName, convertedSub.Status.APIRuleName) + assert.Equal(t, wantSub.Status.EmsSubscriptionStatus, convertedSub.Status.EmsSubscriptionStatus) + + assert.Equal(t, wantSub.Status.Config, convertedSub.Status.Config) +} diff --git a/api/eventing/v1alpha1/subscription_types.go b/api/eventing/v1alpha1/subscription_types.go new file mode 100644 index 00000000..6c49daf0 --- /dev/null +++ b/api/eventing/v1alpha1/subscription_types.go @@ -0,0 +1,280 @@ +package v1alpha1 + +import ( + "encoding/json" + + "github.com/mitchellh/hashstructure/v2" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/eventing-manager/pkg/env" +) + +type BackendType string + +const ( + BEBBackendType BackendType = "BEB" + NatsBackendType BackendType = "NATS" +) + +var Finalizer = GroupVersion.Group + +// WebhookAuth defines the Webhook called by an active subscription in BEB. +// TODO: Remove it when depreciating code of v1alpha1 +type WebhookAuth struct { + // Defines the authentication type. + // +optional + Type string `json:"type,omitempty"` + + // Defines the grant type for OAuth2. + GrantType string `json:"grantType"` + + // Defines the clientID for OAuth2. + ClientID string `json:"clientId"` + + // Defines the Client Secret for OAuth2. + ClientSecret string `json:"clientSecret"` + + // Defines the token URL for OAuth2. + TokenURL string `json:"tokenUrl"` + + // Defines the scope for OAuth2. + Scope []string `json:"scope,omitempty"` +} + +// ProtocolSettings defines the CE protocol setting specification implementation. +// TODO: Remove it when depreciating code of v1alpha1 +type ProtocolSettings struct { + // Defines the content mode for eventing based on BEB. + // The value is either `BINARY`, or `STRUCTURED`. + // +optional + ContentMode *string `json:"contentMode,omitempty"` + + // Defines if the exempt handshake for eventing is based on BEB. + // +optional + ExemptHandshake *bool `json:"exemptHandshake,omitempty"` + + // Defines the quality of service for eventing based on BEB. + // +optional + Qos *string `json:"qos,omitempty"` + + // Defines the Webhook called by an active subscription on BEB. + // +optional + WebhookAuth *WebhookAuth `json:"webhookAuth,omitempty"` +} + +// TODO: Remove it when depreciating code of v1alpha1 +const ( + ProtocolSettingsContentModeBinary string = "BINARY" + ProtocolSettingsContentModeStructured string = "STRUCTURED" +) + +// Filter defines the CE filter element. +type Filter struct { + // Defines the type of the filter. + // +optional + Type string `json:"type,omitempty"` + + // Defines the property of the filter. + Property string `json:"property"` + + // Defines the value of the filter. + Value string `json:"value"` +} + +// Defines the BEB filter element as a combination of two CE filter elements. +type EventMeshFilter struct { + // Defines the source of the CE filter. + EventSource *Filter `json:"eventSource"` + + // Defines the type of the CE filter. + EventType *Filter `json:"eventType"` +} + +func (bf *EventMeshFilter) hash() (uint64, error) { + return hashstructure.Hash(bf, hashstructure.FormatV2, nil) +} + +// BEBFilters defines the list of BEB filters. +type BEBFilters struct { + // Contains a `URI-reference` to the CloudEvent filter dialect. See + // [here](https://github.com/cloudevents/spec/blob/main/subscriptions/spec.md#3241-filter-dialects) for more details. + // +optional + Dialect string `json:"dialect,omitempty"` + + Filters []*EventMeshFilter `json:"filters"` +} + +// Deduplicate returns a deduplicated copy of BEBFilters. +func (bf *BEBFilters) Deduplicate() (*BEBFilters, error) { + seen := map[uint64]struct{}{} + result := &BEBFilters{ + Dialect: bf.Dialect, + } + for _, f := range bf.Filters { + h, err := f.hash() + if err != nil { + return nil, err + } + if _, exists := seen[h]; !exists { + result.Filters = append(result.Filters, f) + seen[h] = struct{}{} + } + } + return result, nil +} + +type SubscriptionConfig struct { + // Defines how many not-ACKed messages can be in flight simultaneously. + // +optional + // +kubebuilder:validation:Minimum=1 + MaxInFlightMessages int `json:"maxInFlightMessages,omitempty"` +} + +// MergeSubsConfigs returns a valid subscription config object based on the provided config, +// complemented with default values, if necessary. +func MergeSubsConfigs(config *SubscriptionConfig, defaults *env.DefaultSubscriptionConfig) *SubscriptionConfig { + merged := &SubscriptionConfig{ + MaxInFlightMessages: defaults.MaxInFlightMessages, + } + if config == nil { + return merged + } + if config.MaxInFlightMessages >= 1 { + merged.MaxInFlightMessages = config.MaxInFlightMessages + } + return merged +} + +// SubscriptionSpec defines the desired state of Subscription. +type SubscriptionSpec struct { + // Unique identifier of the Subscription, read-only. + // +optional + ID string `json:"id,omitempty"` + + // Defines the CE protocol specification implementation. + // +optional + Protocol string `json:"protocol,omitempty"` + + // Defines the CE protocol settings specification implementation. + // +optional + ProtocolSettings *ProtocolSettings `json:"protocolsettings,omitempty"` + + // Kubernetes Service that should be used as a target for the events that match the Subscription. + // Must exist in the same Namespace as the Subscription. + Sink string `json:"sink"` + + // Defines which events will be sent to the sink. + Filter *BEBFilters `json:"filter"` + + // Defines additional configuration for the active backend. + // +optional + Config *SubscriptionConfig `json:"config,omitempty"` +} + +type EmsSubscriptionStatus struct { + // Status of the Subscription as reported by EventMesh. + // +optional + SubscriptionStatus string `json:"subscriptionStatus,omitempty"` + + // Reason for the current status. + // +optional + SubscriptionStatusReason string `json:"subscriptionStatusReason,omitempty"` + + // Timestamp of the last successful delivery. + // +optional + LastSuccessfulDelivery string `json:"lastSuccessfulDelivery,omitempty"` + + // Timestamp of the last failed delivery. + // +optional + LastFailedDelivery string `json:"lastFailedDelivery,omitempty"` + + // Reason for the last failed delivery. + // +optional + LastFailedDeliveryReason string `json:"lastFailedDeliveryReason,omitempty"` +} + +// SubscriptionStatus defines the observed state of the Subscription. +type SubscriptionStatus struct { + // Current state of the Subscription. + // +optional + Conditions []Condition `json:"conditions,omitempty"` + + // Overall readiness of the Subscription. + Ready bool `json:"ready"` + + // CleanEventTypes defines the filter's event types after cleanup to use it with the configured backend. + CleanEventTypes []string `json:"cleanEventTypes"` + + // Defines the checksum for the Subscription custom resource. + // +optional + Ev2hash int64 `json:"ev2hash,omitempty"` + + // Defines the checksum for the Subscription in EventMesh. + // +optional + Emshash int64 `json:"emshash,omitempty"` + + // Defines the webhook URL which is used by EventMesh to trigger subscribers. + // +optional + ExternalSink string `json:"externalSink,omitempty"` + + // Defines the reason if a Subscription failed activation in EventMesh. + // +optional + FailedActivation string `json:"failedActivation,omitempty"` + + // Defines the name of the APIRule which is used by the Subscription. + // +optional + APIRuleName string `json:"apiRuleName,omitempty"` + + // Defines the status of the Subscription in EventMesh. + // +optional + EmsSubscriptionStatus *EmsSubscriptionStatus `json:"emsSubscriptionStatus,omitempty"` + + // Defines the configurations that have been applied to the eventing backend when creating this Subscription. + // +optional + Config *SubscriptionConfig `json:"config,omitempty"` +} + +// Subscription is the Schema for the subscriptions API. +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:deprecatedversion:warning=The v1alpha1 API version is deprecated as of Kyma 2.14.X. +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:printcolumn:name="Clean Event Types",type="string",JSONPath=".status.cleanEventTypes" +type Subscription struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SubscriptionSpec `json:"spec,omitempty"` + Status SubscriptionStatus `json:"status,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +// If the SubscriptionStatus.CleanEventTypes is nil, it will be initialized to an empty slice of stings. +// It is needed because the Kubernetes APIServer will reject requests containing null in the JSON payload. +func (s Subscription) MarshalJSON() ([]byte, error) { + // Use type alias to copy the subscription without causing an infinite recursion when calling json.Marshal. + type Alias Subscription + a := Alias(s) + if a.Status.CleanEventTypes == nil { + a.Status.InitializeCleanEventTypes() + } + return json.Marshal(a) +} + +// SubscriptionList contains a list of Subscription. +// +kubebuilder:object:root=true +type SubscriptionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Subscription `json:"items"` +} + +// InitializeCleanEventTypes initializes the SubscriptionStatus.CleanEventTypes with an empty slice of strings. +func (s *SubscriptionStatus) InitializeCleanEventTypes() { + s.CleanEventTypes = []string{} +} + +func init() { //nolint:gochecknoinits + SchemeBuilder.Register(&Subscription{}, &SubscriptionList{}) +} diff --git a/api/eventing/v1alpha1/subscription_types_unit_test.go b/api/eventing/v1alpha1/subscription_types_unit_test.go new file mode 100644 index 00000000..ce2f62be --- /dev/null +++ b/api/eventing/v1alpha1/subscription_types_unit_test.go @@ -0,0 +1,150 @@ +package v1alpha1_test + +import ( + "reflect" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/kyma-project/eventing-manager/pkg/env" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" +) + +func TestBEBFilters_Deduplicate(t *testing.T) { + filter1 := &v1alpha1.EventMeshFilter{ + EventSource: &v1alpha1.Filter{ + Type: "exact", + Property: "source", + Value: "", + }, + EventType: &v1alpha1.Filter{ + Type: "exact", + Property: "type", + Value: orderCreatedEventType, + }, + } + filter2 := &v1alpha1.EventMeshFilter{ + EventSource: &v1alpha1.Filter{ + Type: "exact", + Property: "source", + Value: "", + }, + EventType: &v1alpha1.Filter{ + Type: "exact", + Property: "type", + Value: orderProcessedEventType, + }, + } + filter3 := &v1alpha1.EventMeshFilter{ + EventSource: &v1alpha1.Filter{ + Type: "exact", + Property: "source", + Value: "/external/system/id", + }, + EventType: &v1alpha1.Filter{ + Type: "exact", + Property: "type", + Value: orderCreatedEventType, + }, + } + tests := []struct { + caseName string + input *v1alpha1.BEBFilters + expected *v1alpha1.BEBFilters + expectErr bool + }{ + { + caseName: "Only one filter", + input: &v1alpha1.BEBFilters{ + Dialect: "beb", + Filters: []*v1alpha1.EventMeshFilter{filter1}, + }, + expected: &v1alpha1.BEBFilters{ + Dialect: "beb", + Filters: []*v1alpha1.EventMeshFilter{filter1}, + }, + expectErr: false, + }, + { + caseName: "Filters with duplicate", + input: &v1alpha1.BEBFilters{ + Dialect: "nats", + Filters: []*v1alpha1.EventMeshFilter{filter1, filter1}, + }, + expected: &v1alpha1.BEBFilters{ + Dialect: "nats", + Filters: []*v1alpha1.EventMeshFilter{filter1}, + }, + expectErr: false, + }, + { + caseName: "Filters without duplicate", + input: &v1alpha1.BEBFilters{ + Filters: []*v1alpha1.EventMeshFilter{filter1, filter2, filter3}, + }, + expected: &v1alpha1.BEBFilters{ + Filters: []*v1alpha1.EventMeshFilter{filter1, filter2, filter3}, + }, + expectErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.caseName, func(t *testing.T) { + got, err := tt.input.Deduplicate() + if (err != nil) != tt.expectErr { + t.Errorf("Deduplicate() error = %v, expectErr %v", err, tt.expected) + return + } + if !reflect.DeepEqual(got, tt.expected) { + t.Errorf("Deduplicate() got = %v, want %v", got, tt.expected) + } + }) + } +} + +func TestMergeSubsConfigs(t *testing.T) { + defaultConf := &env.DefaultSubscriptionConfig{MaxInFlightMessages: 4} + tests := []struct { + caseName string + inputConf *v1alpha1.SubscriptionConfig + inputDefaults *env.DefaultSubscriptionConfig + expectedOutput *v1alpha1.SubscriptionConfig + }{ + { + caseName: "nil input config", + inputConf: nil, + inputDefaults: defaultConf, + expectedOutput: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: 4}, + }, + { + caseName: "default is overridden", + inputConf: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: 10}, + inputDefaults: defaultConf, + expectedOutput: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: 10}, + }, + { + caseName: "provided input is invalid", + inputConf: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: 0}, + inputDefaults: defaultConf, + expectedOutput: &v1alpha1.SubscriptionConfig{MaxInFlightMessages: 4}, + }, + } + + for _, tt := range tests { + t.Run(tt.caseName, func(t *testing.T) { + got := v1alpha1.MergeSubsConfigs(tt.inputConf, tt.inputDefaults) + if !reflect.DeepEqual(got, tt.expectedOutput) { + t.Errorf("MergeSubsConfigs() got = %v, want = %v", got, tt.expectedOutput) + } + }) + } +} + +func TestInitializeCleanEventTypes(t *testing.T) { + s := v1alpha1.Subscription{} + require.Nil(t, s.Status.CleanEventTypes) + + s.Status.InitializeCleanEventTypes() + require.NotNil(t, s.Status.CleanEventTypes) +} diff --git a/api/eventing/v1alpha1/subscription_webhook.go b/api/eventing/v1alpha1/subscription_webhook.go new file mode 100644 index 00000000..e4988c49 --- /dev/null +++ b/api/eventing/v1alpha1/subscription_webhook.go @@ -0,0 +1,13 @@ +package v1alpha1 + +import ( + ctrl "sigs.k8s.io/controller-runtime" +) + +func (r *Subscription) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! diff --git a/api/eventing/v1alpha1/zz_generated.deepcopy.go b/api/eventing/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..f53715e8 --- /dev/null +++ b/api/eventing/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,319 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BEBFilters) DeepCopyInto(out *BEBFilters) { + *out = *in + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]*EventMeshFilter, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(EventMeshFilter) + (*in).DeepCopyInto(*out) + } + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BEBFilters. +func (in *BEBFilters) DeepCopy() *BEBFilters { + if in == nil { + return nil + } + out := new(BEBFilters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EmsSubscriptionStatus) DeepCopyInto(out *EmsSubscriptionStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmsSubscriptionStatus. +func (in *EmsSubscriptionStatus) DeepCopy() *EmsSubscriptionStatus { + if in == nil { + return nil + } + out := new(EmsSubscriptionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventMeshFilter) DeepCopyInto(out *EventMeshFilter) { + *out = *in + if in.EventSource != nil { + in, out := &in.EventSource, &out.EventSource + *out = new(Filter) + **out = **in + } + if in.EventType != nil { + in, out := &in.EventType, &out.EventType + *out = new(Filter) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventMeshFilter. +func (in *EventMeshFilter) DeepCopy() *EventMeshFilter { + if in == nil { + return nil + } + out := new(EventMeshFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Filter) DeepCopyInto(out *Filter) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Filter. +func (in *Filter) DeepCopy() *Filter { + if in == nil { + return nil + } + out := new(Filter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProtocolSettings) DeepCopyInto(out *ProtocolSettings) { + *out = *in + if in.ContentMode != nil { + in, out := &in.ContentMode, &out.ContentMode + *out = new(string) + **out = **in + } + if in.ExemptHandshake != nil { + in, out := &in.ExemptHandshake, &out.ExemptHandshake + *out = new(bool) + **out = **in + } + if in.Qos != nil { + in, out := &in.Qos, &out.Qos + *out = new(string) + **out = **in + } + if in.WebhookAuth != nil { + in, out := &in.WebhookAuth, &out.WebhookAuth + *out = new(WebhookAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProtocolSettings. +func (in *ProtocolSettings) DeepCopy() *ProtocolSettings { + if in == nil { + return nil + } + out := new(ProtocolSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionConfig) DeepCopyInto(out *SubscriptionConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionConfig. +func (in *SubscriptionConfig) DeepCopy() *SubscriptionConfig { + if in == nil { + return nil + } + out := new(SubscriptionConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + if in.ProtocolSettings != nil { + in, out := &in.ProtocolSettings, &out.ProtocolSettings + *out = new(ProtocolSettings) + (*in).DeepCopyInto(*out) + } + if in.Filter != nil { + in, out := &in.Filter, &out.Filter + *out = new(BEBFilters) + (*in).DeepCopyInto(*out) + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(SubscriptionConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CleanEventTypes != nil { + in, out := &in.CleanEventTypes, &out.CleanEventTypes + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.EmsSubscriptionStatus != nil { + in, out := &in.EmsSubscriptionStatus, &out.EmsSubscriptionStatus + *out = new(EmsSubscriptionStatus) + **out = **in + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = new(SubscriptionConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionStatus. +func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus { + if in == nil { + return nil + } + out := new(SubscriptionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebhookAuth) DeepCopyInto(out *WebhookAuth) { + *out = *in + if in.Scope != nil { + in, out := &in.Scope, &out.Scope + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebhookAuth. +func (in *WebhookAuth) DeepCopy() *WebhookAuth { + if in == nil { + return nil + } + out := new(WebhookAuth) + in.DeepCopyInto(out) + return out +} diff --git a/api/eventing/v1alpha2/condition.go b/api/eventing/v1alpha2/condition.go new file mode 100644 index 00000000..50d33005 --- /dev/null +++ b/api/eventing/v1alpha2/condition.go @@ -0,0 +1,289 @@ +package v1alpha2 + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type ConditionType string + +const ( + ConditionSubscribed ConditionType = "Subscribed" + ConditionSubscriptionActive ConditionType = "Subscription active" + ConditionAPIRuleStatus ConditionType = "APIRule status" + ConditionWebhookCallStatus ConditionType = "Webhook call status" + + ConditionPublisherProxyReady ConditionType = "Publisher Proxy Ready" + ConditionControllerReady ConditionType = "Subscription Controller Ready" +) + +var allSubscriptionConditions = MakeSubscriptionConditions() + +type Condition struct { + // Short description of the condition. + Type ConditionType `json:"type,omitempty"` + + // Status of the condition. The value is either `True`, `False`, or `Unknown`. + Status corev1.ConditionStatus `json:"status"` + + // Defines the date of the last condition status change. + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + // Defines the reason for the condition status change. + Reason ConditionReason `json:"reason,omitempty"` + // Provides more details about the condition status change. + Message string `json:"message,omitempty"` +} + +type ConditionReason string + +const ( + // JetStream Conditions. + ConditionReasonNATSSubscriptionActive ConditionReason = "NATS Subscription active" + ConditionReasonNATSSubscriptionNotActive ConditionReason = "NATS Subscription not active" + + // EventMesh Conditions. + ConditionReasonSubscriptionCreated ConditionReason = "EventMesh Subscription created" + ConditionReasonSubscriptionCreationFailed ConditionReason = "EventMesh Subscription creation failed" + ConditionReasonSubscriptionActive ConditionReason = "EventMesh Subscription active" + ConditionReasonSubscriptionNotActive ConditionReason = "EventMesh Subscription not active" + ConditionReasonSubscriptionDeleted ConditionReason = "EventMesh Subscription deleted" + ConditionReasonAPIRuleStatusReady ConditionReason = "APIRule status ready" + ConditionReasonAPIRuleStatusNotReady ConditionReason = "APIRule status not ready" + ConditionReasonWebhookCallStatus ConditionReason = "EventMesh Subscription webhook call no errors status" +) + +// initializeConditions sets unset conditions to Unknown. +func initializeConditions(initialConditions, currentConditions []Condition) []Condition { + givenConditions := make(map[ConditionType]Condition) + + // Create map of Condition per ConditionType. + for _, condition := range currentConditions { + givenConditions[condition.Type] = condition + } + + finalConditions := currentConditions + // Check if every Condition is present in the current Conditions. + for _, expectedCondition := range initialConditions { + if _, ok := givenConditions[expectedCondition.Type]; !ok { + // and add it if it is missing + finalConditions = append(finalConditions, expectedCondition) + } + } + return finalConditions +} + +// InitializeConditions sets unset Subscription conditions to Unknown. +func (s *SubscriptionStatus) InitializeConditions() { + initialConditions := MakeSubscriptionConditions() + s.Conditions = initializeConditions(initialConditions, s.Conditions) +} + +func (s SubscriptionStatus) IsReady() bool { + if !ContainSameConditionTypes(allSubscriptionConditions, s.Conditions) { + return false + } + + // The Subscription is ready if all its conditions are evaluated to true. + for _, c := range s.Conditions { + if c.Status != corev1.ConditionTrue { + return false + } + } + return true +} + +func (s SubscriptionStatus) FindCondition(conditionType ConditionType) *Condition { + for _, condition := range s.Conditions { + if conditionType == condition.Type { + return &condition + } + } + return nil +} + +// ShouldUpdateReadyStatus checks if there is a mismatch between the +// Subscription Ready status and the Ready status of all the conditions. +func (s SubscriptionStatus) ShouldUpdateReadyStatus() bool { + if !s.Ready && s.IsReady() || s.Ready && !s.IsReady() { + return true + } + return false +} + +// MakeSubscriptionConditions creates a map of all conditions which the Subscription should have. +func MakeSubscriptionConditions() []Condition { + conditions := []Condition{ + { + Type: ConditionAPIRuleStatus, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionSubscribed, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionSubscriptionActive, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + { + Type: ConditionWebhookCallStatus, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + } + return conditions +} + +func ContainSameConditionTypes(conditions1, conditions2 []Condition) bool { + if len(conditions1) != len(conditions2) { + return false + } + + for _, condition := range conditions1 { + if !containConditionType(conditions2, condition.Type) { + return false + } + } + + return true +} + +func containConditionType(conditions []Condition, conditionType ConditionType) bool { + for _, condition := range conditions { + if condition.Type == conditionType { + return true + } + } + + return false +} + +func MakeCondition(conditionType ConditionType, reason ConditionReason, status corev1.ConditionStatus, message string) Condition { + return Condition{ + Type: conditionType, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + } +} + +func (s *SubscriptionStatus) IsConditionSubscribed() bool { + for _, condition := range s.Conditions { + if condition.Type == ConditionSubscribed && condition.Status == corev1.ConditionTrue { + return true + } + } + return false +} + +func (s *SubscriptionStatus) IsConditionWebhookCall() bool { + for _, condition := range s.Conditions { + if condition.Type == ConditionWebhookCallStatus && + (condition.Status == corev1.ConditionTrue || condition.Status == corev1.ConditionUnknown) { + return true + } + } + return false +} + +func (s *SubscriptionStatus) GetConditionAPIRuleStatus() corev1.ConditionStatus { + for _, condition := range s.Conditions { + if condition.Type == ConditionAPIRuleStatus { + return condition.Status + } + } + return corev1.ConditionUnknown +} + +func (s *SubscriptionStatus) SetConditionAPIRuleStatus(err error) { + reason := ConditionReasonAPIRuleStatusReady + status := corev1.ConditionTrue + message := "" + if err != nil { + reason = ConditionReasonAPIRuleStatusNotReady + status = corev1.ConditionFalse + message = err.Error() + } + + newConditions := []Condition{MakeCondition(ConditionAPIRuleStatus, reason, status, message)} + for _, condition := range s.Conditions { + if condition.Type == ConditionAPIRuleStatus { + continue + } + newConditions = append(newConditions, condition) + } + s.Conditions = newConditions +} + +// ConditionsEquals checks if two list of conditions are equal. +func ConditionsEquals(existing, expected []Condition) bool { + // not equal if length is different + if len(existing) != len(expected) { + return false + } + + // compile map of Conditions per ConditionType + existingMap := make(map[ConditionType]Condition, len(existing)) + for _, value := range existing { + existingMap[value.Type] = value + } + + for _, value := range expected { + if !ConditionEquals(existingMap[value.Type], value) { + return false + } + } + + return true +} + +// ConditionsEquals checks if two conditions are equal. +func ConditionEquals(existing, expected Condition) bool { + isTypeEqual := existing.Type == expected.Type + isStatusEqual := existing.Status == expected.Status + isReasonEqual := existing.Reason == expected.Reason + isMessageEqual := existing.Message == expected.Message + + if !isStatusEqual || !isReasonEqual || !isMessageEqual || !isTypeEqual { + return false + } + + return true +} + +func CreateMessageForConditionReasonSubscriptionCreated(eventMeshName string) string { + return fmt.Sprintf("EventMesh subscription name is: %s", eventMeshName) +} + +// GetSubscriptionActiveCondition updates the ConditionSubscriptionActive condition based on the given error value. +func GetSubscriptionActiveCondition(sub *Subscription, err error) []Condition { + subscriptionActiveCondition := Condition{ + Type: ConditionSubscriptionActive, + LastTransitionTime: metav1.Now(), + } + if err == nil { + subscriptionActiveCondition.Status = corev1.ConditionTrue + subscriptionActiveCondition.Reason = ConditionReasonNATSSubscriptionActive + } else { + subscriptionActiveCondition.Message = err.Error() + subscriptionActiveCondition.Reason = ConditionReasonNATSSubscriptionNotActive + subscriptionActiveCondition.Status = corev1.ConditionFalse + } + for _, activeCond := range sub.Status.Conditions { + if activeCond.Type == ConditionSubscriptionActive { + if subscriptionActiveCondition.Status == activeCond.Status && + subscriptionActiveCondition.Reason == activeCond.Reason && + subscriptionActiveCondition.Message == activeCond.Message { + return []Condition{activeCond} + } + } + } + + return []Condition{subscriptionActiveCondition} +} diff --git a/api/eventing/v1alpha2/condition_unit_test.go b/api/eventing/v1alpha2/condition_unit_test.go new file mode 100644 index 00000000..86368d02 --- /dev/null +++ b/api/eventing/v1alpha2/condition_unit_test.go @@ -0,0 +1,553 @@ +package v1alpha2_test + +import ( + "reflect" + "testing" + "time" + + eventingtesting "github.com/kyma-project/eventing-manager/testing" + "github.com/pkg/errors" + + "github.com/stretchr/testify/require" + + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" +) + +func Test_InitializeSubscriptionConditions(t *testing.T) { + var tests = []struct { + name string + givenConditions []v1alpha2.Condition + }{ + { + name: "Conditions empty", + givenConditions: v1alpha2.MakeSubscriptionConditions(), + }, + { + name: "Conditions partially initialized", + givenConditions: []v1alpha2.Condition{ + { + Type: v1alpha2.ConditionSubscribed, + LastTransitionTime: metav1.Now(), + Status: corev1.ConditionUnknown, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // given + g := NewGomegaWithT(t) + s := v1alpha2.SubscriptionStatus{} + s.Conditions = tt.givenConditions + wantConditionTypes := []v1alpha2.ConditionType{ + v1alpha2.ConditionSubscribed, + v1alpha2.ConditionSubscriptionActive, + v1alpha2.ConditionAPIRuleStatus, + v1alpha2.ConditionWebhookCallStatus, + } + + // when + s.InitializeConditions() + + // then + g.Expect(s.Conditions).To(HaveLen(len(wantConditionTypes))) + foundConditionTypes := make([]v1alpha2.ConditionType, 0) + for _, condition := range s.Conditions { + g.Expect(condition.Status).To(BeEquivalentTo(corev1.ConditionUnknown)) + foundConditionTypes = append(foundConditionTypes, condition.Type) + } + g.Expect(wantConditionTypes).To(ConsistOf(foundConditionTypes)) + }) + } +} + +func Test_IsReady(t *testing.T) { + testCases := []struct { + name string + givenConditions []v1alpha2.Condition + wantReadyStatus bool + }{ + { + name: "should not be ready if conditions are nil", + givenConditions: nil, + wantReadyStatus: false, + }, + { + name: "should not be ready if conditions are empty", + givenConditions: []v1alpha2.Condition{{}}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionSubscribed is available and true", + givenConditions: []v1alpha2.Condition{{ + Type: v1alpha2.ConditionSubscribed, + Status: corev1.ConditionTrue, + }}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionSubscriptionActive is available and true", + givenConditions: []v1alpha2.Condition{{ + Type: v1alpha2.ConditionSubscriptionActive, + Status: corev1.ConditionTrue, + }}, + wantReadyStatus: false, + }, + { + name: "should not be ready if only ConditionAPIRuleStatus is available and true", + givenConditions: []v1alpha2.Condition{{ + Type: v1alpha2.ConditionAPIRuleStatus, + Status: corev1.ConditionTrue, + }}, + wantReadyStatus: false, + }, + { + name: "should not be ready if all conditions are unknown", + givenConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionUnknown}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionUnknown}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionUnknown}, + }, + wantReadyStatus: false, + }, + { + name: "should not be ready if all conditions are false", + givenConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + }, + wantReadyStatus: false, + }, + { + name: "should be ready if all conditions are true", + givenConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantReadyStatus: true, + }, + } + + status := v1alpha2.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.givenConditions + if gotReadyStatus := status.IsReady(); tc.wantReadyStatus != gotReadyStatus { + t.Errorf("Subscription status is not valid, want: %v but got: %v", tc.wantReadyStatus, gotReadyStatus) + } + }) + } +} + +func Test_FindCondition(t *testing.T) { + currentTime := metav1.NewTime(time.Now()) + + testCases := []struct { + name string + givenConditions []v1alpha2.Condition + findConditionType v1alpha2.ConditionType + wantCondition *v1alpha2.Condition + }{ + { + name: "should be able to find the present condition", + givenConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + }, + findConditionType: v1alpha2.ConditionSubscriptionActive, + wantCondition: &v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscriptionActive, + Status: corev1.ConditionTrue, LastTransitionTime: currentTime, + }, + }, + { + name: "should not be able to find the non-present condition", + givenConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue, LastTransitionTime: currentTime}, + }, + findConditionType: v1alpha2.ConditionSubscriptionActive, + wantCondition: nil, + }, + } + + status := v1alpha2.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.givenConditions + + if gotCondition := status.FindCondition(tc.findConditionType); !reflect.DeepEqual(tc.wantCondition, gotCondition) { + t.Errorf("Subscription FindCondition failed, want: %v but got: %v", tc.wantCondition, gotCondition) + } + }) + } +} + +func Test_ShouldUpdateReadyStatus(t *testing.T) { + testCases := []struct { + name string + subscriptionReady bool + subscriptionConditions []v1alpha2.Condition + wantStatus bool + }{ + { + name: "should not update if the subscription is ready and the conditions are ready", + subscriptionReady: true, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantStatus: false, + }, + { + name: "should not update if the subscription is not ready and the conditions are not ready", + subscriptionReady: false, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionFalse}, + }, + wantStatus: false, + }, + { + name: "should update if the subscription is not ready and the conditions are ready", + subscriptionReady: false, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + }, + wantStatus: true, + }, + { + name: "should update if the subscription is ready and the conditions are not ready", + subscriptionReady: true, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionFalse}, + }, + wantStatus: true, + }, + { + name: "should update if the subscription is ready and some of the conditions are missing", + subscriptionReady: true, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionUnknown}, + }, + wantStatus: true, + }, + { + name: "should not update if the subscription is not ready and some of the conditions are missing", + subscriptionReady: false, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionUnknown}, + }, + wantStatus: false, + }, + { + name: "should update if the subscription is ready and the status of the conditions are unknown", + subscriptionReady: true, + subscriptionConditions: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionUnknown}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionUnknown}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionUnknown}, + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionUnknown}, + }, + wantStatus: true, + }, + } + + status := v1alpha2.SubscriptionStatus{} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + status.Conditions = tc.subscriptionConditions + status.Ready = tc.subscriptionReady + if gotStatus := status.ShouldUpdateReadyStatus(); tc.wantStatus != gotStatus { + t.Errorf("ShouldUpdateReadyStatus is not valid, want: %v but got: %v", tc.wantStatus, gotStatus) + } + }) + } +} + +func Test_conditionsEquals(t *testing.T) { + testCases := []struct { + name string + conditionsSet1 []v1alpha2.Condition + conditionsSet2 []v1alpha2.Condition + wantEqualStatus bool + }{ + { + name: "should not be equal if the number of conditions are not equal", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha2.Condition{}, + wantEqualStatus: false, + }, + { + name: "should be equal if the conditions are the same", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: true, + }, + { + name: "should not be equal if the condition types are different", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionWebhookCallStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionSubscriptionActive, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are the same but the status is different", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionFalse}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are different but the status is the same", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionFalse}, + }, + conditionsSet2: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the condition types are different and an empty key is referenced", + conditionsSet1: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + }, + conditionsSet2: []v1alpha2.Condition{ + {Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue}, + {Type: v1alpha2.ConditionControllerReady, Status: corev1.ConditionTrue}, + }, + wantEqualStatus: false, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if gotEqualStatus := v1alpha2.ConditionsEquals(tc.conditionsSet1, tc.conditionsSet2); tc.wantEqualStatus != gotEqualStatus { + t.Errorf("The list of conditions are not equal, want: %v but got: %v", tc.wantEqualStatus, gotEqualStatus) + } + }) + } +} + +func Test_conditionEquals(t *testing.T) { + testCases := []struct { + name string + condition1 v1alpha2.Condition + condition2 v1alpha2.Condition + wantEqualStatus bool + }{ + { + name: "should not be equal if the types are the same but the status is different", + condition1: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, + }, + + condition2: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionUnknown, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the types are different but the status is the same", + condition1: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, + }, + + condition2: v1alpha2.Condition{ + Type: v1alpha2.ConditionAPIRuleStatus, Status: corev1.ConditionTrue, + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the message fields are different", + condition1: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, Message: "", + }, + + condition2: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, Status: corev1.ConditionTrue, Message: "some message", + }, + wantEqualStatus: false, + }, + { + name: "should not be equal if the reason fields are different", + condition1: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, + Status: corev1.ConditionTrue, + Reason: v1alpha2.ConditionReasonSubscriptionDeleted, + }, + + condition2: v1alpha2.Condition{ + Type: v1alpha2.ConditionSubscribed, + Status: corev1.ConditionTrue, + Reason: v1alpha2.ConditionReasonSubscriptionActive, + }, + wantEqualStatus: false, + }, + { + name: "should be equal if all the fields are the same", + condition1: v1alpha2.Condition{ + Type: v1alpha2.ConditionAPIRuleStatus, + Status: corev1.ConditionFalse, + Reason: v1alpha2.ConditionReasonAPIRuleStatusNotReady, + Message: "API Rule is not ready", + }, + condition2: v1alpha2.Condition{ + Type: v1alpha2.ConditionAPIRuleStatus, + Status: corev1.ConditionFalse, + Reason: v1alpha2.ConditionReasonAPIRuleStatusNotReady, + Message: "API Rule is not ready", + }, + wantEqualStatus: true, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if gotEqualStatus := v1alpha2.ConditionEquals(tc.condition1, tc.condition2); tc.wantEqualStatus != gotEqualStatus { + t.Errorf("The conditions are not equal, want: %v but got: %v", tc.wantEqualStatus, gotEqualStatus) + } + }) + } +} + +func Test_CreateMessageForConditionReasonSubscriptionCreated(t *testing.T) { + testCases := []struct { + name string + givenName string + wantName string + }{ + { + name: "with name 1", + givenName: "test-one", + wantName: "EventMesh subscription name is: test-one", + }, + { + name: "with name 2", + givenName: "test-second", + wantName: "EventMesh subscription name is: test-second", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + require.Equal(t, tc.wantName, v1alpha2.CreateMessageForConditionReasonSubscriptionCreated(tc.givenName)) + }) + } +} + +func Test_SetConditionSubscriptionActive(t *testing.T) { + err := errors.New("some error") + conditionReady := v1alpha2.MakeCondition( + v1alpha2.ConditionSubscriptionActive, + v1alpha2.ConditionReasonNATSSubscriptionActive, + corev1.ConditionTrue, "") + conditionReady.LastTransitionTime = metav1.NewTime(time.Now().AddDate(0, 0, -1)) + conditionNotReady := v1alpha2.MakeCondition( + v1alpha2.ConditionSubscriptionActive, + v1alpha2.ConditionReasonNATSSubscriptionNotActive, + corev1.ConditionFalse, err.Error()) + conditionNotReady.LastTransitionTime = metav1.NewTime(time.Now().AddDate(0, 0, -2)) + sub := eventingtesting.NewSubscription("test", "test") + + testCases := []struct { + name string + givenConditions []v1alpha2.Condition + givenError error + wantConditions []v1alpha2.Condition + wantLastTransitionTime *metav1.Time + }{ + { + name: "no error should set the condition to ready", + givenError: nil, + givenConditions: []v1alpha2.Condition{conditionNotReady}, + wantConditions: []v1alpha2.Condition{conditionReady}, + }, + { + name: "error should set the condition to not ready", + givenError: err, + givenConditions: []v1alpha2.Condition{conditionReady}, + wantConditions: []v1alpha2.Condition{conditionNotReady}, + }, + { + name: "the same condition should not change the lastTransitionTime in case of Sub active", + givenError: nil, + givenConditions: []v1alpha2.Condition{conditionReady}, + wantConditions: []v1alpha2.Condition{{ + Type: v1alpha2.ConditionSubscriptionActive, + Reason: v1alpha2.ConditionReasonNATSSubscriptionActive, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + }}, + wantLastTransitionTime: &conditionReady.LastTransitionTime, + }, + { + name: "the same condition should not change the lastTransitionTime in case of error", + givenError: err, + givenConditions: []v1alpha2.Condition{conditionNotReady}, + wantConditions: []v1alpha2.Condition{{ + Type: v1alpha2.ConditionSubscriptionActive, + Reason: v1alpha2.ConditionReasonNATSSubscriptionNotActive, + Status: corev1.ConditionFalse, + Message: err.Error(), + LastTransitionTime: metav1.Now(), + }}, + wantLastTransitionTime: &conditionNotReady.LastTransitionTime, + }, + } + for _, testCase := range testCases { + tc := testCase + t.Run(tc.name, func(t *testing.T) { + // given + sub.Status.Conditions = tc.givenConditions + + // when + conditions := v1alpha2.GetSubscriptionActiveCondition(sub, tc.givenError) + + // then + require.True(t, v1alpha2.ConditionsEquals(conditions, tc.wantConditions)) + if tc.wantLastTransitionTime != nil { + require.Equal(t, *tc.wantLastTransitionTime, conditions[0].LastTransitionTime) + } + }) + } +} diff --git a/api/eventing/v1alpha2/constants.go b/api/eventing/v1alpha2/constants.go new file mode 100644 index 00000000..3536f72d --- /dev/null +++ b/api/eventing/v1alpha2/constants.go @@ -0,0 +1,23 @@ +package v1alpha2 + +const ( + TypeMatchingStandard TypeMatching = "standard" + TypeMatchingExact TypeMatching = "exact" + + // config fields. + MaxInFlightMessages = "maxInFlightMessages" + + // protocol settings. + Protocol = "protocol" + ProtocolSettingsContentMode = "contentMode" + ProtocolSettingsExemptHandshake = "exemptHandshake" + ProtocolSettingsQos = "qos" + + // webhook auth fields. + WebhookAuthType = "type" + WebhookAuthGrantType = "grantType" + WebhookAuthClientID = "clientId" + WebhookAuthClientSecret = "clientSecret" + WebhookAuthTokenURL = "tokenUrl" + WebhookAuthScope = "scope" +) diff --git a/api/eventing/v1alpha2/errors.go b/api/eventing/v1alpha2/errors.go new file mode 100644 index 00000000..09fe2668 --- /dev/null +++ b/api/eventing/v1alpha2/errors.go @@ -0,0 +1,41 @@ +package v1alpha2 + +import ( + "fmt" + "strconv" + + "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" + + "k8s.io/apimachinery/pkg/util/validation/field" +) + +//nolint:gochecknoglobals // these are required for testing +var ( + SourcePath = field.NewPath("spec").Child("source") + TypesPath = field.NewPath("spec").Child("types") + ConfigPath = field.NewPath("spec").Child("config") + SinkPath = field.NewPath("spec").Child("sink") + NSPath = field.NewPath("metadata").Child("namespace") + + EmptyErrDetail = "must not be empty" + InvalidURIErrDetail = "must be valid as per RFC 3986" + DuplicateTypesErrDetail = "must not have duplicate types" + LengthErrDetail = "must not be of length zero" + MinSegmentErrDetail = fmt.Sprintf("must have minimum %s segments", strconv.Itoa(minEventTypeSegments)) + InvalidPrefixErrDetail = fmt.Sprintf("must not have %s as type prefix", InvalidPrefix) + StringIntErrDetail = fmt.Sprintf("%s must be a stringified int value", MaxInFlightMessages) + + InvalidQosErrDetail = fmt.Sprintf("must be a valid QoS value %s or %s", + types.QosAtLeastOnce, types.QosAtMostOnce) + InvalidAuthTypeErrDetail = fmt.Sprintf("must be a valid Auth Type value %s", types.AuthTypeClientCredentials) + InvalidGrantTypeErrDetail = fmt.Sprintf("must be a valid Grant Type value %s", types.GrantTypeClientCredentials) + + MissingSchemeErrDetail = "must have URL scheme 'http' or 'https'" + SuffixMissingErrDetail = fmt.Sprintf("must have valid sink URL suffix %s", ClusterLocalURLSuffix) + SubDomainsErrDetail = fmt.Sprintf("must have sink URL with %d sub-domains: ", subdomainSegments) + NSMismatchErrDetail = "must have the same namespace as the subscriber: " +) + +func MakeInvalidFieldError(path *field.Path, subName, detail string) *field.Error { + return field.Invalid(path, subName, detail) +} diff --git a/api/eventing/v1alpha2/groupversion_info.go b/api/eventing/v1alpha2/groupversion_info.go new file mode 100644 index 00000000..bb2cb894 --- /dev/null +++ b/api/eventing/v1alpha2/groupversion_info.go @@ -0,0 +1,24 @@ +// Package v1alpha2 contains API Schema definitions for the eventing v1alpha2 API group. +// +kubebuilder:object:generate=true +// +groupName=eventing.kyma-project.io +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "eventing.kyma-project.io", Version: "v1alpha2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme + + //nolint:gochecknoglobals // required for tests + // GroupKind is group kind to identify these objects. + GroupKind = schema.GroupKind{Group: "eventing.kyma-project.io", Kind: "Subscription"} +) diff --git a/api/eventing/v1alpha2/status_types.go b/api/eventing/v1alpha2/status_types.go new file mode 100644 index 00000000..5ce64c7a --- /dev/null +++ b/api/eventing/v1alpha2/status_types.go @@ -0,0 +1,97 @@ +package v1alpha2 + +type EventType struct { + // Event type as specified in the Subscription spec. + OriginalType string `json:"originalType"` + // Event type after it was cleaned up from backend compatible characters. + CleanType string `json:"cleanType"` +} + +// Backend contains Backend-specific fields. +type Backend struct { + // EventMesh-specific fields + + // Checksum for the Subscription custom resource. + // +optional + Ev2hash int64 `json:"ev2hash,omitempty"` + + // Hash used to identify an EventMesh Subscription retrieved from the server without the WebhookAuth config. + // +optional + EventMeshHash int64 `json:"emshash,omitempty"` + + // Hash used to identify an EventMesh Subscription posted to the server without the WebhookAuth config. + // +optional + EventMeshLocalHash int64 `json:"eventMeshLocalHash,omitempty"` + + // Hash used to identify the WebhookAuth of an EventMesh Subscription existing on the server. + // +optional + WebhookAuthHash int64 `json:"webhookAuthHash,omitempty"` + + // Webhook URL used by EventMesh to trigger subscribers. + // +optional + ExternalSink string `json:"externalSink,omitempty"` + + // Provides the reason if a Subscription failed activation in EventMesh. + // +optional + FailedActivation string `json:"failedActivation,omitempty"` + + // Name of the APIRule which is used by the Subscription. + // +optional + APIRuleName string `json:"apiRuleName,omitempty"` + + // Status of the Subscription as reported by EventMesh. + // +optional + EventMeshSubscriptionStatus *EventMeshSubscriptionStatus `json:"emsSubscriptionStatus,omitempty"` + + // List of event type to consumer name mappings for the NATS backend. + // +optional + Types []JetStreamTypes `json:"types,omitempty"` + + // List of mappings from event type to EventMesh compatible types. Used only with EventMesh as the backend. + // +optional + EmsTypes []EventMeshTypes `json:"emsTypes,omitempty"` +} + +type EventMeshSubscriptionStatus struct { + // Status of the Subscription as reported by the backend. + // +optional + Status string `json:"status,omitempty"` + + // Reason for the current status. + // +optional + StatusReason string `json:"statusReason,omitempty"` + + // Timestamp of the last successful delivery. + // +optional + LastSuccessfulDelivery string `json:"lastSuccessfulDelivery,omitempty"` + + // Timestamp of the last failed delivery. + // +optional + LastFailedDelivery string `json:"lastFailedDelivery,omitempty"` + + // Reason for the last failed delivery. + // +optional + LastFailedDeliveryReason string `json:"lastFailedDeliveryReason,omitempty"` +} + +type JetStreamTypes struct { + // Event type that was originally used to subscribe. + OriginalType string `json:"originalType"` + // Name of the JetStream consumer created for the event type. + ConsumerName string `json:"consumerName,omitempty"` +} + +type EventMeshTypes struct { + // Event type that was originally used to subscribe. + OriginalType string `json:"originalType"` + // Event type that is used on the EventMesh backend. + EventMeshType string `json:"eventMeshType"` +} + +// CopyHashes copies the precomputed hashes from the given backend. +func (b *Backend) CopyHashes(src Backend) { + b.Ev2hash = src.Ev2hash + b.EventMeshHash = src.EventMeshHash + b.WebhookAuthHash = src.WebhookAuthHash + b.EventMeshLocalHash = src.EventMeshLocalHash +} diff --git a/api/eventing/v1alpha2/status_types_test.go b/api/eventing/v1alpha2/status_types_test.go new file mode 100644 index 00000000..d3fbe441 --- /dev/null +++ b/api/eventing/v1alpha2/status_types_test.go @@ -0,0 +1,35 @@ +package v1alpha2 + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBackend_CopyHashes(t *testing.T) { + // given + b := Backend{} + + // then + require.Equal(t, int64(0), b.Ev2hash) + require.Equal(t, int64(0), b.EventMeshHash) + require.Equal(t, int64(0), b.WebhookAuthHash) + require.Equal(t, int64(0), b.EventMeshLocalHash) + + // given + src := Backend{ + Ev2hash: int64(1118518533334734626), + EventMeshHash: int64(1748405436686967274), + WebhookAuthHash: int64(1118518533334734627), + EventMeshLocalHash: int64(1883494500014499539), + } + + // when + b.CopyHashes(src) + + // then + require.Equal(t, src.Ev2hash, b.Ev2hash) + require.Equal(t, src.EventMeshHash, b.EventMeshHash) + require.Equal(t, src.WebhookAuthHash, b.WebhookAuthHash) + require.Equal(t, src.EventMeshLocalHash, b.EventMeshLocalHash) +} diff --git a/api/eventing/v1alpha2/subscription_types.go b/api/eventing/v1alpha2/subscription_types.go new file mode 100644 index 00000000..ff5f28c0 --- /dev/null +++ b/api/eventing/v1alpha2/subscription_types.go @@ -0,0 +1,146 @@ +package v1alpha2 + +import ( + "encoding/json" + "strconv" + + "github.com/kyma-project/eventing-manager/pkg/env" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + k8sruntime "k8s.io/apimachinery/pkg/runtime" + + "github.com/kyma-project/eventing-manager/pkg/utils" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type TypeMatching string + +var Finalizer = GroupVersion.Group + +// Defines the desired state of the Subscription. +type SubscriptionSpec struct { + // Unique identifier of the Subscription, read-only. + // +optional + ID string `json:"id,omitempty"` + + // Kubernetes Service that should be used as a target for the events that match the Subscription. + // Must exist in the same Namespace as the Subscription. + Sink string `json:"sink"` + + // Defines how types should be handled.
+ // - `standard`: backend-specific logic will be applied to the configured source and types.
+ // - `exact`: no further processing will be applied to the configured source and types. + TypeMatching TypeMatching `json:"typeMatching,omitempty"` + + // Defines the origin of the event. + Source string `json:"source"` + + // List of event types that will be used for subscribing on the backend. + Types []string `json:"types"` + + // Map of configuration options that will be applied on the backend. + // +optional + Config map[string]string `json:"config,omitempty"` +} + +// SubscriptionStatus defines the observed state of Subscription. +// +kubebuilder:subresource:status +type SubscriptionStatus struct { + // Current state of the Subscription. + // +optional + Conditions []Condition `json:"conditions,omitempty"` + + // Overall readiness of the Subscription. + Ready bool `json:"ready"` + + // List of event types after cleanup for use with the configured backend. + Types []EventType `json:"types"` + + // Backend-specific status which is applicable to the active backend only. + Backend Backend `json:"backend,omitempty"` +} + +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.ready" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// Subscription is the Schema for the subscriptions API. +type Subscription struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SubscriptionSpec `json:"spec,omitempty"` + Status SubscriptionStatus `json:"status,omitempty"` +} + +// MarshalJSON implements the json.Marshaler interface. +// If the SubscriptionStatus.CleanEventTypes is nil, it will be initialized to an empty slice of stings. +// It is needed because the Kubernetes APIServer will reject requests containing null in the JSON payload. +func (s Subscription) MarshalJSON() ([]byte, error) { + // Use type alias to copy the subscription without causing an infinite recursion when calling json.Marshal. + type Alias Subscription + a := Alias(s) + if a.Status.Types == nil { + a.Status.InitializeEventTypes() + } + return json.Marshal(a) +} + +// GetMaxInFlightMessages tries to convert the string-type maxInFlight to the integer. +func (s *Subscription) GetMaxInFlightMessages(defaults *env.DefaultSubscriptionConfig) int { + val, err := strconv.Atoi(s.Spec.Config[MaxInFlightMessages]) + if err != nil { + return defaults.MaxInFlightMessages + } + return val +} + +// InitializeEventTypes initializes the SubscriptionStatus.Types with an empty slice of EventType. +func (s *SubscriptionStatus) InitializeEventTypes() { + s.Types = []EventType{} +} + +// GetUniqueTypes returns the de-duplicated types from subscription spec. +func (s *Subscription) GetUniqueTypes() []string { + result := make([]string, 0, len(s.Spec.Types)) + for _, t := range s.Spec.Types { + if !utils.ContainsString(result, t) { + result = append(result, t) + } + } + + return result +} + +func (s *Subscription) DuplicateWithStatusDefaults() *Subscription { + desiredSub := s.DeepCopy() + desiredSub.Status = SubscriptionStatus{} + return desiredSub +} + +func (s *Subscription) ToUnstructuredSub() (*unstructured.Unstructured, error) { + object, err := k8sruntime.DefaultUnstructuredConverter.ToUnstructured(&s) + if err != nil { + return nil, err + } + return &unstructured.Unstructured{Object: object}, nil +} + +// +kubebuilder:object:root=true + +// SubscriptionList contains a list of Subscription. +type SubscriptionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Subscription `json:"items"` +} + +func init() { //nolint:gochecknoinits + SchemeBuilder.Register(&Subscription{}, &SubscriptionList{}) +} + +// Hub marks this type as a conversion hub. +func (*Subscription) Hub() {} diff --git a/api/eventing/v1alpha2/subscription_types_test.go b/api/eventing/v1alpha2/subscription_types_test.go new file mode 100644 index 00000000..78610994 --- /dev/null +++ b/api/eventing/v1alpha2/subscription_types_test.go @@ -0,0 +1,68 @@ +package v1alpha2_test + +import ( + "testing" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" + + "github.com/kyma-project/eventing-manager/pkg/env" + "github.com/stretchr/testify/assert" +) + +func TestGetMaxInFlightMessages(t *testing.T) { + defaultSubConfig := env.DefaultSubscriptionConfig{MaxInFlightMessages: 5} + testCases := []struct { + name string + givenSubscription *v1alpha2.Subscription + wantResult int + }{ + { + name: "function should give the default MaxInFlight if the Subscription config is missing", + givenSubscription: &v1alpha2.Subscription{ + Spec: v1alpha2.SubscriptionSpec{ + Config: nil, + }, + }, + wantResult: defaultSubConfig.MaxInFlightMessages, + }, + { + name: "function should give the default MaxInFlight if it is missing in the Subscription config", + givenSubscription: &v1alpha2.Subscription{ + Spec: v1alpha2.SubscriptionSpec{ + Config: map[string]string{ + "otherConfigKey": "20"}, + }, + }, + wantResult: defaultSubConfig.MaxInFlightMessages, + }, + { + name: "function should give the expectedConfig", + givenSubscription: &v1alpha2.Subscription{ + Spec: v1alpha2.SubscriptionSpec{ + Config: map[string]string{ + v1alpha2.MaxInFlightMessages: "20"}, + }, + }, + wantResult: 20, + }, + { + name: "function should result into an error", + givenSubscription: &v1alpha2.Subscription{ + Spec: v1alpha2.SubscriptionSpec{ + Config: map[string]string{ + v1alpha2.MaxInFlightMessages: "nonInt"}, + }, + }, + wantResult: defaultSubConfig.MaxInFlightMessages, + }, + } + + for _, testCase := range testCases { + tc := testCase + t.Run(tc.name, func(t *testing.T) { + result := tc.givenSubscription.GetMaxInFlightMessages(&defaultSubConfig) + + assert.Equal(t, tc.wantResult, result) + }) + } +} diff --git a/api/eventing/v1alpha2/subscription_webhook.go b/api/eventing/v1alpha2/subscription_webhook.go new file mode 100644 index 00000000..5b03e393 --- /dev/null +++ b/api/eventing/v1alpha2/subscription_webhook.go @@ -0,0 +1,200 @@ +package v1alpha2 + +import ( + "strconv" + "strings" + + "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" + + "github.com/kyma-project/eventing-manager/pkg/utils" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +const ( + DefaultMaxInFlightMessages = "10" + minEventTypeSegments = 2 + subdomainSegments = 5 + InvalidPrefix = "sap.kyma.custom" + ClusterLocalURLSuffix = "svc.cluster.local" + ValidSource = "source" +) + +func (s *Subscription) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(s). + Complete() +} + +//nolint: lll +//+kubebuilder:webhook:path=/mutate-eventing-kyma-project-io-v1alpha2-subscription,mutating=true,failurePolicy=fail,sideEffects=None,groups=eventing.kyma-project.io,resources=subscriptions,verbs=create;update,versions=v1alpha2,name=msubscription.kb.io,admissionReviewVersions=v1beta1 + +var _ webhook.Defaulter = &Subscription{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type. +func (s *Subscription) Default() { + if s.Spec.TypeMatching == "" { + s.Spec.TypeMatching = TypeMatchingStandard + } + if s.Spec.Config[MaxInFlightMessages] == "" { + if s.Spec.Config == nil { + s.Spec.Config = map[string]string{} + } + s.Spec.Config[MaxInFlightMessages] = DefaultMaxInFlightMessages + } +} + +//nolint: lll +//+kubebuilder:webhook:path=/validate-eventing-kyma-project-io-v1alpha2-subscription,mutating=false,failurePolicy=fail,sideEffects=None,groups=eventing.kyma-project.io,resources=subscriptions,verbs=create;update,versions=v1alpha2,name=vsubscription.kb.io,admissionReviewVersions=v1beta1 + +var _ webhook.Validator = &Subscription{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type. +func (s *Subscription) ValidateCreate() (admission.Warnings, error) { + return s.ValidateSubscription() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type. +func (s *Subscription) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) { + return s.ValidateSubscription() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type. +func (s *Subscription) ValidateDelete() (admission.Warnings, error) { + return nil, nil +} + +func (s *Subscription) ValidateSubscription() (admission.Warnings, error) { + var allErrs field.ErrorList + + if err := s.validateSubscriptionSource(); err != nil { + allErrs = append(allErrs, err) + } + if err := s.validateSubscriptionTypes(); err != nil { + allErrs = append(allErrs, err) + } + if err := s.validateSubscriptionConfig(); err != nil { + allErrs = append(allErrs, err...) + } + if err := s.validateSubscriptionSink(); err != nil { + allErrs = append(allErrs, err) + } + if len(allErrs) == 0 { + return nil, nil + } + + return nil, apierrors.NewInvalid(GroupKind, s.Name, allErrs) +} + +func (s *Subscription) validateSubscriptionSource() *field.Error { + if s.Spec.Source == "" && s.Spec.TypeMatching != TypeMatchingExact { + return MakeInvalidFieldError(SourcePath, s.Name, EmptyErrDetail) + } + // Check only if the source is valid for the cloud event, with a valid event type. + if IsInvalidCE(s.Spec.Source, "") { + return MakeInvalidFieldError(SourcePath, s.Name, InvalidURIErrDetail) + } + return nil +} + +func (s *Subscription) validateSubscriptionTypes() *field.Error { + if s.Spec.Types == nil || len(s.Spec.Types) == 0 { + return MakeInvalidFieldError(TypesPath, s.Name, EmptyErrDetail) + } + if len(s.GetUniqueTypes()) != len(s.Spec.Types) { + return MakeInvalidFieldError(TypesPath, s.Name, DuplicateTypesErrDetail) + } + for _, etype := range s.Spec.Types { + if len(etype) == 0 { + return MakeInvalidFieldError(TypesPath, s.Name, LengthErrDetail) + } + if segments := strings.Split(etype, "."); len(segments) < minEventTypeSegments { + return MakeInvalidFieldError(TypesPath, s.Name, MinSegmentErrDetail) + } + if s.Spec.TypeMatching != TypeMatchingExact && strings.HasPrefix(etype, InvalidPrefix) { + return MakeInvalidFieldError(TypesPath, s.Name, InvalidPrefixErrDetail) + } + // Check only is the event type is valid for the cloud event, with a valid source. + if IsInvalidCE(ValidSource, etype) { + return MakeInvalidFieldError(TypesPath, s.Name, InvalidURIErrDetail) + } + } + return nil +} + +func (s *Subscription) validateSubscriptionConfig() field.ErrorList { + var allErrs field.ErrorList + if isNotInt(s.Spec.Config[MaxInFlightMessages]) { + allErrs = append(allErrs, MakeInvalidFieldError(ConfigPath, s.Name, StringIntErrDetail)) + } + if s.ifKeyExistsInConfig(ProtocolSettingsQos) && types.IsInvalidQoS(s.Spec.Config[ProtocolSettingsQos]) { + allErrs = append(allErrs, MakeInvalidFieldError(ConfigPath, s.Name, InvalidQosErrDetail)) + } + if s.ifKeyExistsInConfig(WebhookAuthType) && types.IsInvalidAuthType(s.Spec.Config[WebhookAuthType]) { + allErrs = append(allErrs, MakeInvalidFieldError(ConfigPath, s.Name, InvalidAuthTypeErrDetail)) + } + if s.ifKeyExistsInConfig(WebhookAuthGrantType) && types.IsInvalidGrantType(s.Spec.Config[WebhookAuthGrantType]) { + allErrs = append(allErrs, MakeInvalidFieldError(ConfigPath, s.Name, InvalidGrantTypeErrDetail)) + } + return allErrs +} + +func (s *Subscription) validateSubscriptionSink() *field.Error { + if s.Spec.Sink == "" { + return MakeInvalidFieldError(SinkPath, s.Name, EmptyErrDetail) + } + + if !utils.IsValidScheme(s.Spec.Sink) { + return MakeInvalidFieldError(SinkPath, s.Name, MissingSchemeErrDetail) + } + + trimmedHost, subDomains, err := utils.GetSinkData(s.Spec.Sink) + if err != nil { + return MakeInvalidFieldError(SinkPath, s.Name, err.Error()) + } + + // Validate sink URL is a cluster local URL. + if !strings.HasSuffix(trimmedHost, ClusterLocalURLSuffix) { + return MakeInvalidFieldError(SinkPath, s.Name, SuffixMissingErrDetail) + } + + // We expected a sink in the format "service.namespace.svc.cluster.local". + if len(subDomains) != subdomainSegments { + return MakeInvalidFieldError(SinkPath, s.Name, SubDomainsErrDetail+trimmedHost) + } + + // Assumption: Subscription CR and Subscriber should be deployed in the same namespace. + svcNs := subDomains[1] + if s.Namespace != svcNs { + return MakeInvalidFieldError(NSPath, s.Name, NSMismatchErrDetail+svcNs) + } + + return nil +} + +func (s *Subscription) ifKeyExistsInConfig(key string) bool { + _, ok := s.Spec.Config[key] + return ok +} + +func isNotInt(value string) bool { + if _, err := strconv.Atoi(value); err != nil { + return true + } + return false +} + +func IsInvalidCE(source, eventType string) bool { + if source == "" { + return false + } + newEvent := utils.GetCloudEvent(eventType) + newEvent.SetSource(source) + err := newEvent.Validate() + return err != nil +} diff --git a/api/eventing/v1alpha2/subscription_webhook_unit_test.go b/api/eventing/v1alpha2/subscription_webhook_unit_test.go new file mode 100644 index 00000000..5fb87974 --- /dev/null +++ b/api/eventing/v1alpha2/subscription_webhook_unit_test.go @@ -0,0 +1,473 @@ +package v1alpha2_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/util/validation/field" + + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" + eventingtesting "github.com/kyma-project/eventing-manager/testing" +) + +const ( + subName = "sub" + subNamespace = "test" + sink = "https://eventing-nats.test.svc.cluster.local:8080" +) + +func Test_Default(t *testing.T) { + t.Parallel() + type TestCase struct { + name string + givenSub *v1alpha2.Subscription + wantSub *v1alpha2.Subscription + } + + testCases := []TestCase{ + { + name: "Add TypeMatching Standard and default MaxInFlightMessages value", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + ), + wantSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + ), + }, + { + name: "Add TypeMatching Standard only", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages("20"), + ), + wantSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages("20"), + eventingtesting.WithTypeMatchingStandard(), + ), + }, + { + name: "Add default MaxInFlightMessages value only", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithTypeMatchingExact(), + ), + wantSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithTypeMatchingExact(), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + ), + }, + } + + for _, testCase := range testCases { + tc := testCase + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + tc.givenSub.Default() + require.Equal(t, tc.givenSub, tc.wantSub) + }) + } +} + +func Test_validateSubscription(t *testing.T) { + t.Parallel() + type TestCase struct { + name string + givenSub *v1alpha2.Subscription + wantErr error + } + + testCases := []TestCase{ + { + name: "A valid subscription should not have errors", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithWebhookAuthForEventMesh(), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: nil, + }, + { + name: "empty source and TypeMatching Standard should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SourcePath, + subName, v1alpha2.EmptyErrDetail)}), + }, + { + name: "valid source and TypeMatching Standard should not return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: nil, + }, + { + name: "empty source and TypeMatching Exact should not return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingExact(), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: nil, + }, + { + name: "invalid URI reference as source should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource("s%ourc%e"), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SourcePath, + subName, v1alpha2.InvalidURIErrDetail)}), + }, + { + name: "nil types field should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.EmptyErrDetail)}), + }, + { + name: "empty types field should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.EmptyErrDetail)}), + }, + { + name: "duplicate types should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{eventingtesting.OrderCreatedV1Event, + eventingtesting.OrderCreatedV1Event}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.DuplicateTypesErrDetail)}), + }, + { + name: "empty event type should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{eventingtesting.OrderCreatedV1Event, ""}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.LengthErrDetail)}), + }, + { + name: "lower than min segments should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{"order"}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.MinSegmentErrDetail)}), + }, + { + name: "invalid prefix should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{v1alpha2.InvalidPrefix}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.TypesPath, + subName, v1alpha2.InvalidPrefixErrDetail)}), + }, + { + name: "invalid prefix with exact should not return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingExact(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithTypes([]string{v1alpha2.InvalidPrefix}), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(sink), + ), + wantErr: nil, + }, + { + name: "invalid maxInFlight value should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages("invalid"), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.ConfigPath, + subName, v1alpha2.StringIntErrDetail)}), + }, + { + name: "invalid QoS value should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithInvalidProtocolSettingsQos(), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.ConfigPath, + subName, v1alpha2.InvalidQosErrDetail)}), + }, + { + name: "invalid webhook auth type value should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithInvalidWebhookAuthType(), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.ConfigPath, + subName, v1alpha2.InvalidAuthTypeErrDetail)}), + }, + { + name: "invalid webhook grant type value should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithInvalidWebhookAuthGrantType(), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.ConfigPath, + subName, v1alpha2.InvalidGrantTypeErrDetail)}), + }, + { + name: "missing sink should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, v1alpha2.EmptyErrDetail)}), + }, + { + name: "sink with invalid scheme should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink(subNamespace), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, v1alpha2.MissingSchemeErrDetail)}), + }, + { + name: "sink with invalid URL should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink("http://invalid Sink"), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, "failed to parse subscription sink URL: "+ + "parse \"http://invalid Sink\": invalid character \" \" in host name")}), + }, + { + name: "sink with invalid suffix should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink("https://svc2.test.local"), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, v1alpha2.SuffixMissingErrDetail)}), + }, + { + name: "sink with invalid suffix and port should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink("https://svc2.test.local:8080"), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, v1alpha2.SuffixMissingErrDetail)}), + }, + { + name: "sink with invalid number of subdomains should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink("https://svc.cluster.local:8080"), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SinkPath, + subName, v1alpha2.SubDomainsErrDetail+"svc.cluster.local")}), + }, + { + name: "sink with different namespace should return error", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithSource(eventingtesting.EventSourceClean), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages(v1alpha2.DefaultMaxInFlightMessages), + eventingtesting.WithSink("https://eventing-nats.kyma-system.svc.cluster.local"), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.NSPath, + subName, v1alpha2.NSMismatchErrDetail+"kyma-system")}), + }, + { + name: "multiple errors should be reported if exists", + givenSub: eventingtesting.NewSubscription(subName, subNamespace, + eventingtesting.WithTypeMatchingStandard(), + eventingtesting.WithEventType(eventingtesting.OrderCreatedV1Event), + eventingtesting.WithMaxInFlightMessages("invalid"), + eventingtesting.WithSink(sink), + ), + wantErr: apierrors.NewInvalid( + v1alpha2.GroupKind, subName, + field.ErrorList{v1alpha2.MakeInvalidFieldError(v1alpha2.SourcePath, + subName, v1alpha2.EmptyErrDetail), + v1alpha2.MakeInvalidFieldError(v1alpha2.ConfigPath, + subName, v1alpha2.StringIntErrDetail)}), + }, + } + + for _, testCase := range testCases { + tc := testCase + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + _, err := tc.givenSub.ValidateSubscription() + require.Equal(t, err, tc.wantErr) + }) + } +} + +func Test_IsInvalidCESource(t *testing.T) { + t.Parallel() + type TestCase struct { + name string + givenSource string + givenType string + wantIsInvalid bool + } + + testCases := []TestCase{ + { + name: "invalid URI Path source should be invalid", + givenSource: "app%%type", + givenType: "order.created.v1", + wantIsInvalid: true, + }, + { + name: "valid URI Path source should not be invalid", + givenSource: "t..e--s__t!!a@@**p##p&&", + givenType: "", + wantIsInvalid: false, + }, + { + name: "should ignore check if the source is empty", + givenSource: "", + givenType: "", + wantIsInvalid: false, + }, + { + name: "invalid type should be invalid", + givenSource: "source", + givenType: " ", // space is an invalid type for cloud event + wantIsInvalid: true, + }, + } + + for _, testCase := range testCases { + tc := testCase + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + gotIsInvalid := v1alpha2.IsInvalidCE(tc.givenSource, tc.givenType) + require.Equal(t, tc.wantIsInvalid, gotIsInvalid) + }) + } +} diff --git a/api/eventing/v1alpha2/utils.go b/api/eventing/v1alpha2/utils.go new file mode 100644 index 00000000..d16dfc66 --- /dev/null +++ b/api/eventing/v1alpha2/utils.go @@ -0,0 +1,29 @@ +package v1alpha2 + +import ( + "encoding/json" + + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +func SubscriptionGroupVersionResource() schema.GroupVersionResource { + return schema.GroupVersionResource{ + Version: GroupVersion.Version, + Group: GroupVersion.Group, + Resource: "subscriptions", + } +} + +func ConvertUnstructListToSubList(unstructuredList *unstructured.UnstructuredList) (*SubscriptionList, error) { + subscriptionList := new(SubscriptionList) + subscriptionListBytes, err := unstructuredList.MarshalJSON() + if err != nil { + return nil, err + } + err = json.Unmarshal(subscriptionListBytes, subscriptionList) + if err != nil { + return nil, err + } + return subscriptionList, nil +} diff --git a/api/eventing/v1alpha2/zz_generated.deepcopy.go b/api/eventing/v1alpha2/zz_generated.deepcopy.go new file mode 100644 index 00000000..194c3af6 --- /dev/null +++ b/api/eventing/v1alpha2/zz_generated.deepcopy.go @@ -0,0 +1,246 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2023. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha2 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Backend) DeepCopyInto(out *Backend) { + *out = *in + if in.EventMeshSubscriptionStatus != nil { + in, out := &in.EventMeshSubscriptionStatus, &out.EventMeshSubscriptionStatus + *out = new(EventMeshSubscriptionStatus) + **out = **in + } + if in.Types != nil { + in, out := &in.Types, &out.Types + *out = make([]JetStreamTypes, len(*in)) + copy(*out, *in) + } + if in.EmsTypes != nil { + in, out := &in.EmsTypes, &out.EmsTypes + *out = make([]EventMeshTypes, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backend. +func (in *Backend) DeepCopy() *Backend { + if in == nil { + return nil + } + out := new(Backend) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventMeshSubscriptionStatus) DeepCopyInto(out *EventMeshSubscriptionStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventMeshSubscriptionStatus. +func (in *EventMeshSubscriptionStatus) DeepCopy() *EventMeshSubscriptionStatus { + if in == nil { + return nil + } + out := new(EventMeshSubscriptionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventMeshTypes) DeepCopyInto(out *EventMeshTypes) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventMeshTypes. +func (in *EventMeshTypes) DeepCopy() *EventMeshTypes { + if in == nil { + return nil + } + out := new(EventMeshTypes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EventType) DeepCopyInto(out *EventType) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventType. +func (in *EventType) DeepCopy() *EventType { + if in == nil { + return nil + } + out := new(EventType) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JetStreamTypes) DeepCopyInto(out *JetStreamTypes) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JetStreamTypes. +func (in *JetStreamTypes) DeepCopy() *JetStreamTypes { + if in == nil { + return nil + } + out := new(JetStreamTypes) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + if in.Types != nil { + in, out := &in.Types, &out.Types + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Config != nil { + in, out := &in.Config, &out.Config + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionStatus) DeepCopyInto(out *SubscriptionStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Types != nil { + in, out := &in.Types, &out.Types + *out = make([]EventType, len(*in)) + copy(*out, *in) + } + in.Backend.DeepCopyInto(&out.Backend) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionStatus. +func (in *SubscriptionStatus) DeepCopy() *SubscriptionStatus { + if in == nil { + return nil + } + out := new(SubscriptionStatus) + in.DeepCopyInto(out) + return out +} diff --git a/api/operator.kyma-project.io/v1alpha1/eventing_types.go b/api/operator/v1alpha1/eventing_types.go similarity index 100% rename from api/operator.kyma-project.io/v1alpha1/eventing_types.go rename to api/operator/v1alpha1/eventing_types.go diff --git a/api/operator.kyma-project.io/v1alpha1/eventing_types_test.go b/api/operator/v1alpha1/eventing_types_test.go similarity index 100% rename from api/operator.kyma-project.io/v1alpha1/eventing_types_test.go rename to api/operator/v1alpha1/eventing_types_test.go diff --git a/api/operator.kyma-project.io/v1alpha1/groupversion_info.go b/api/operator/v1alpha1/groupversion_info.go similarity index 100% rename from api/operator.kyma-project.io/v1alpha1/groupversion_info.go rename to api/operator/v1alpha1/groupversion_info.go diff --git a/api/operator.kyma-project.io/v1alpha1/status.go b/api/operator/v1alpha1/status.go similarity index 100% rename from api/operator.kyma-project.io/v1alpha1/status.go rename to api/operator/v1alpha1/status.go diff --git a/api/operator.kyma-project.io/v1alpha1/status_test.go b/api/operator/v1alpha1/status_test.go similarity index 100% rename from api/operator.kyma-project.io/v1alpha1/status_test.go rename to api/operator/v1alpha1/status_test.go diff --git a/api/operator.kyma-project.io/v1alpha1/zz_generated.deepcopy.go b/api/operator/v1alpha1/zz_generated.deepcopy.go similarity index 99% rename from api/operator.kyma-project.io/v1alpha1/zz_generated.deepcopy.go rename to api/operator/v1alpha1/zz_generated.deepcopy.go index 99b1cdc5..28204a61 100644 --- a/api/operator.kyma-project.io/v1alpha1/zz_generated.deepcopy.go +++ b/api/operator/v1alpha1/zz_generated.deepcopy.go @@ -22,7 +22,7 @@ limitations under the License. package v1alpha1 import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) diff --git a/cmd/main.go b/cmd/main.go index 38df4ee3..114b27da 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,13 +22,13 @@ import ( "log" "os" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" istiopeerauthentication "github.com/kyma-project/eventing-manager/pkg/istio/peerauthentication" "github.com/go-logr/zapr" - subscriptionv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - subscriptionv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + subscriptionv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + subscriptionv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" apiclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -58,7 +58,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" //+kubebuilder:scaffold:imports ) @@ -78,6 +78,8 @@ func init() { utilruntime.Must(jetstream.AddToScheme(scheme)) utilruntime.Must(jetstream.AddV1Alpha2ToScheme(scheme)) + utilruntime.Must(subscriptionv1alpha1.AddToScheme(scheme)) + utilruntime.Must(subscriptionv1alpha2.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/config/crd/external/subscriptions.eventing.kyma-project.io.crd.yaml b/config/crd/bases/eventing.kyma-project.io_subscriptions.yaml similarity index 98% rename from config/crd/external/subscriptions.eventing.kyma-project.io.crd.yaml rename to config/crd/bases/eventing.kyma-project.io_subscriptions.yaml index eeef8c34..b980cd35 100644 --- a/config/crd/external/subscriptions.eventing.kyma-project.io.crd.yaml +++ b/config/crd/bases/eventing.kyma-project.io_subscriptions.yaml @@ -1,20 +1,12 @@ +--- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null name: subscriptions.eventing.kyma-project.io spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - name: eventing-controller-webhook-service - namespace: kyma-system - path: /convert - conversionReviewVersions: - - v1 group: eventing.kyma-project.io names: kind: Subscription diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index fb52b857..0955426d 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -3,7 +3,7 @@ # It should be run by config/default resources: - bases/operator.kyma-project.io_eventings.yaml -- external/subscriptions.eventing.kyma-project.io.crd.yaml +- bases/eventing.kyma-project.io_subscriptions.yaml #+kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -11,11 +11,13 @@ patchesStrategicMerge: # patches here are for enabling the conversion webhook for each CRD #- patches/webhook_in_eventings.yaml - patches/webhook_in_subscriptions.yaml +#- patches/webhook_in_subscriptions.yaml #+kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD #- patches/cainjection_in_eventings.yaml +#- patches/cainjection_in_subscriptions.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/samples/subscription_v1alpha1_js.yaml b/config/samples/subscription_v1alpha1_js.yaml new file mode 100644 index 00000000..86840626 --- /dev/null +++ b/config/samples/subscription_v1alpha1_js.yaml @@ -0,0 +1,27 @@ +apiVersion: eventing.kyma-project.io/v1alpha1 +kind: Subscription +metadata: + name: test-noapp1 + namespace: tunas-testing +spec: + filter: + filters: + - eventSource: + property: source + type: exact + value: "noapp" + eventType: + property: type + type: exact + value: sap.kyma.custom.noapp.order.created.v1 + - eventSource: + property: source + type: exact + value: "noapp" + eventType: + property: type + type: exact + value: sap.kyma.custom.noapp.order.created.v2 + protocol: "" + protocolsettings: {} + sink: http://test.tunas-testing.svc.cluster.local \ No newline at end of file diff --git a/config/samples/subscription_v1alpha2_exact_eventmesh.yaml b/config/samples/subscription_v1alpha2_exact_eventmesh.yaml new file mode 100644 index 00000000..9b1f57c5 --- /dev/null +++ b/config/samples/subscription_v1alpha2_exact_eventmesh.yaml @@ -0,0 +1,12 @@ +apiVersion: eventing.kyma-project.io/v1alpha2 +kind: Subscription +metadata: + name: test-noapp-exact + namespace: tunas-testing +spec: + sink: http://test.tunas-testing.svc.cluster.local + typeMatching: exact + source: "/default/sap.kyma/tunas-develop" + types: + - sap.kyma.custom.noapp.order.created.v1 + diff --git a/config/samples/subscription_v1alpha2_standard.yaml b/config/samples/subscription_v1alpha2_standard.yaml new file mode 100644 index 00000000..3de98a14 --- /dev/null +++ b/config/samples/subscription_v1alpha2_standard.yaml @@ -0,0 +1,12 @@ +apiVersion: eventing.kyma-project.io/v1alpha2 +kind: Subscription +metadata: + name: test-noapp + namespace: tunas-testing +spec: + sink: http://test.tunas-testing.svc.cluster.local + typeMatching: standard + source: "noapp" + types: + - order.created.v1 + diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 00000000..3698c7dc --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + creationTimestamp: null + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-eventing-kyma-project-io-v1alpha2-subscription + failurePolicy: Fail + name: msubscription.kb.io + rules: + - apiGroups: + - eventing.kyma-project.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - subscriptions + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-eventing-kyma-project-io-v1alpha2-subscription + failurePolicy: Fail + name: vsubscription.kb.io + rules: + - apiGroups: + - eventing.kyma-project.io + apiVersions: + - v1alpha2 + operations: + - CREATE + - UPDATE + resources: + - subscriptions + sideEffects: None diff --git a/docs/user/02-configuration.md b/docs/user/02-configuration.md index da4db46f..65a72b6d 100644 --- a/docs/user/02-configuration.md +++ b/docs/user/02-configuration.md @@ -70,4 +70,4 @@ Use the following sample CRs as guidance. Each can be applied immediately when y | **specHash** (required) | integer | | | **state** (required) | string | | - + \ No newline at end of file diff --git a/go.mod b/go.mod index ce343f69..c1d324e4 100644 --- a/go.mod +++ b/go.mod @@ -12,7 +12,6 @@ require ( github.com/kelseyhightower/envconfig v1.4.0 github.com/kyma-incubator/api-gateway v0.0.0-20220819093753-296e6704d413 github.com/kyma-project/kyma/common/logging v0.0.0-20231113125307-562a57ab5198 - github.com/kyma-project/kyma/components/eventing-controller 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.5 @@ -84,6 +83,7 @@ require ( github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/zerolog v1.29.0 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect diff --git a/go.sum b/go.sum index 93455f8f..a9ccacf0 100644 --- a/go.sum +++ b/go.sum @@ -220,12 +220,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kyma-project/api-gateway v0.0.0-20220819093753-296e6704d413 h1:fkGKNOFbltycpdQ7yCGfa+7MpH9X18F09x+n7Tgfp7A= github.com/kyma-project/api-gateway v0.0.0-20220819093753-296e6704d413/go.mod h1:5kBV6C2JEaapjTAn10Mo81Te4e6LN3epexUCSLXgQLI= -github.com/kyma-project/api-gateway v0.0.0-20231025094533-b7f4433b5cac h1:1lgrll58pt2J3KmgaxuhxmQ5S5pmRHd5Ecd0R/jtuGU= -github.com/kyma-project/api-gateway v0.0.0-20231025094533-b7f4433b5cac/go.mod h1:liAdIi2zvHbrK4K6Xi+pHUz2cnU70QRkhuUqhVF6Hmo= github.com/kyma-project/kyma/common/logging v0.0.0-20231113125307-562a57ab5198 h1:xz4kPj7u51OgP+0f58OeaQlyiGm6AwEHALjbiLeK3Ec= github.com/kyma-project/kyma/common/logging v0.0.0-20231113125307-562a57ab5198/go.mod h1:JGb5RBi8Uz+RZ/jf54+qA+RqY6uPQBJ8pO1w3KSwm1Q= -github.com/kyma-project/kyma/components/eventing-controller v0.0.0-20231113125307-562a57ab5198 h1:/o4jabncHPmpvgFzGQ6TBzjbHmf111FDkOzgmdH3L4I= -github.com/kyma-project/kyma/components/eventing-controller v0.0.0-20231113125307-562a57ab5198/go.mod h1:myk9NTLyoeWE5uo5y9oECUJqBkwcWPWW/8jq5g6EPy8= github.com/kyma-project/nats-manager v1.0.3-0.20231124103356-1904d89ab2b2 h1:P8SMLPxQMCnPlwGMpqid5ofHPO2dvybu94F8K32GNmw= github.com/kyma-project/nats-manager v1.0.3-0.20231124103356-1904d89ab2b2/go.mod h1:asVMhM0flO8aRcllmgABSuoPL+X9kdJ7tp8JPSPzpkk= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= diff --git a/hack/e2e/cleanup/cleanup_test.go b/hack/e2e/cleanup/cleanup_test.go index d98c388f..4ca6b1a2 100644 --- a/hack/e2e/cleanup/cleanup_test.go +++ b/hack/e2e/cleanup/cleanup_test.go @@ -17,7 +17,7 @@ import ( k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/hack/e2e/common/testenvironment" "github.com/kyma-project/eventing-manager/pkg/eventing" diff --git a/hack/e2e/common/eventing/testsubscriptioninfo.go b/hack/e2e/common/eventing/testsubscriptioninfo.go index 9d10b5b8..0a261bdd 100644 --- a/hack/e2e/common/eventing/testsubscriptioninfo.go +++ b/hack/e2e/common/eventing/testsubscriptioninfo.go @@ -1,8 +1,8 @@ package eventing import ( - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - ecv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + ecv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + ecv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/hack/e2e/common/fixtures/fixtures.go b/hack/e2e/common/fixtures/fixtures.go index f09e1895..37a57127 100644 --- a/hack/e2e/common/fixtures/fixtures.go +++ b/hack/e2e/common/fixtures/fixtures.go @@ -12,7 +12,7 @@ import ( "github.com/kyma-project/eventing-manager/hack/e2e/common/eventing" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/hack/e2e/common/k8s.go b/hack/e2e/common/k8s.go index 7039dc54..ddc94c3d 100644 --- a/hack/e2e/common/k8s.go +++ b/hack/e2e/common/k8s.go @@ -6,10 +6,10 @@ import ( "k8s.io/client-go/dynamic" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - ecv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + ecv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + ecv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" diff --git a/hack/e2e/common/testenvironment/test_environment.go b/hack/e2e/common/testenvironment/test_environment.go index f118580c..fac19e06 100644 --- a/hack/e2e/common/testenvironment/test_environment.go +++ b/hack/e2e/common/testenvironment/test_environment.go @@ -15,9 +15,9 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/cloudevents/sdk-go/v2/binding" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" - ecv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + ecv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "go.uber.org/zap" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" diff --git a/hack/e2e/env/env.go b/hack/e2e/env/env.go index 802fb64f..f2363912 100644 --- a/hack/e2e/env/env.go +++ b/hack/e2e/env/env.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/kelseyhightower/envconfig" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // E2EConfig represents the environment config for the end-to-end tests for eventing-manager. diff --git a/hack/e2e/setup/setup_test.go b/hack/e2e/setup/setup_test.go index e7c5d7a7..60c38c0b 100644 --- a/hack/e2e/setup/setup_test.go +++ b/hack/e2e/setup/setup_test.go @@ -19,7 +19,7 @@ import ( "github.com/pkg/errors" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/eventing" "github.com/stretchr/testify/require" diff --git a/internal/controller/subscription/eventmesh/reconciler.go b/internal/controller/eventing/subscription/eventmesh/reconciler.go similarity index 99% rename from internal/controller/subscription/eventmesh/reconciler.go rename to internal/controller/eventing/subscription/eventmesh/reconciler.go index 8649f310..b5763c42 100644 --- a/internal/controller/subscription/eventmesh/reconciler.go +++ b/internal/controller/eventing/subscription/eventmesh/reconciler.go @@ -30,8 +30,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/source" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "go.uber.org/zap" diff --git a/internal/controller/subscription/eventmesh/reconciler_internal_integration_test.go b/internal/controller/eventing/subscription/eventmesh/reconciler_internal_integration_test.go similarity index 99% rename from internal/controller/subscription/eventmesh/reconciler_internal_integration_test.go rename to internal/controller/eventing/subscription/eventmesh/reconciler_internal_integration_test.go index a3bff798..81674c5a 100644 --- a/internal/controller/subscription/eventmesh/reconciler_internal_integration_test.go +++ b/internal/controller/eventing/subscription/eventmesh/reconciler_internal_integration_test.go @@ -22,6 +22,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh/mocks" @@ -35,7 +36,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/object" "github.com/kyma-project/eventing-manager/test/utils" reconcilertesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // TestReconciler_Reconcile tests the return values of the Reconcile() method of the reconciler. diff --git a/internal/controller/subscription/eventmesh/test/assertions.go b/internal/controller/eventing/subscription/eventmesh/test/assertions.go similarity index 95% rename from internal/controller/subscription/eventmesh/test/assertions.go rename to internal/controller/eventing/subscription/eventmesh/test/assertions.go index 8fd52c27..e24bf8ba 100644 --- a/internal/controller/subscription/eventmesh/test/assertions.go +++ b/internal/controller/eventing/subscription/eventmesh/test/assertions.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/types" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // getSubscriptionAssert fetches a subscription using the lookupKey and allows making assertions on it. diff --git a/internal/controller/subscription/eventmesh/test/reconciler_integration_test.go b/internal/controller/eventing/subscription/eventmesh/test/reconciler_integration_test.go similarity index 99% rename from internal/controller/subscription/eventmesh/test/reconciler_integration_test.go rename to internal/controller/eventing/subscription/eventmesh/test/reconciler_integration_test.go index 808d6556..3d492f32 100644 --- a/internal/controller/subscription/eventmesh/test/reconciler_integration_test.go +++ b/internal/controller/eventing/subscription/eventmesh/test/reconciler_integration_test.go @@ -16,7 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" eventMeshtypes "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" "github.com/kyma-project/eventing-manager/pkg/object" diff --git a/internal/controller/subscription/eventmesh/test/utils.go b/internal/controller/eventing/subscription/eventmesh/test/utils.go similarity index 97% rename from internal/controller/subscription/eventmesh/test/utils.go rename to internal/controller/eventing/subscription/eventmesh/test/utils.go index 33f201a1..537aa814 100644 --- a/internal/controller/subscription/eventmesh/test/utils.go +++ b/internal/controller/eventing/subscription/eventmesh/test/utils.go @@ -13,6 +13,8 @@ import ( "testing" "time" + eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/eventmesh" + "github.com/avast/retry-go/v3" "github.com/go-logr/zapr" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" @@ -35,9 +37,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" - eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/subscription/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendeventmesh "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" @@ -204,14 +205,13 @@ func startTestEnv() (*rest.Config, error) { useExistingCluster := useExistingCluster emTestEnsemble.testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../../", "config", "crd", "bases"), - filepath.Join("../../../../../", "config", "crd", "external"), - filepath.Join("../../../../../", "config", "crd", "for-tests"), + filepath.Join("../../../../../../", "config", "crd", "bases"), + filepath.Join("../../../../../../", "config", "crd", "for-tests"), }, AttachControlPlaneOutput: attachControlPlaneOutput, UseExistingCluster: &useExistingCluster, WebhookInstallOptions: envtest.WebhookInstallOptions{ - Paths: []string{filepath.Join("../../../../../", "config", "webhook")}, + Paths: []string{filepath.Join("../../../../../../", "config", "webhook")}, }, } diff --git a/internal/controller/subscription/eventmesh/testwebhookauth/assertions.go b/internal/controller/eventing/subscription/eventmesh/testwebhookauth/assertions.go similarity index 93% rename from internal/controller/subscription/eventmesh/testwebhookauth/assertions.go rename to internal/controller/eventing/subscription/eventmesh/testwebhookauth/assertions.go index cf48b2c1..67ff903b 100644 --- a/internal/controller/subscription/eventmesh/testwebhookauth/assertions.go +++ b/internal/controller/eventing/subscription/eventmesh/testwebhookauth/assertions.go @@ -8,7 +8,7 @@ import ( "k8s.io/apimachinery/pkg/types" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // getSubscriptionAssert fetches a subscription using the lookupKey and allows making assertions on it. diff --git a/internal/controller/subscription/eventmesh/testwebhookauth/reconciler_integration_test.go b/internal/controller/eventing/subscription/eventmesh/testwebhookauth/reconciler_integration_test.go similarity index 100% rename from internal/controller/subscription/eventmesh/testwebhookauth/reconciler_integration_test.go rename to internal/controller/eventing/subscription/eventmesh/testwebhookauth/reconciler_integration_test.go diff --git a/internal/controller/subscription/eventmesh/testwebhookauth/utils.go b/internal/controller/eventing/subscription/eventmesh/testwebhookauth/utils.go similarity index 96% rename from internal/controller/subscription/eventmesh/testwebhookauth/utils.go rename to internal/controller/eventing/subscription/eventmesh/testwebhookauth/utils.go index 2f5a85c4..6f95ca53 100644 --- a/internal/controller/subscription/eventmesh/testwebhookauth/utils.go +++ b/internal/controller/eventing/subscription/eventmesh/testwebhookauth/utils.go @@ -11,6 +11,8 @@ import ( "testing" "time" + eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/eventmesh" + "github.com/avast/retry-go/v3" "github.com/go-logr/zapr" "github.com/stretchr/testify/require" @@ -32,7 +34,7 @@ import ( apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" kymalogger "github.com/kyma-project/kyma/common/logging/logger" - eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/subscription/eventmesh" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendeventmesh "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" @@ -45,7 +47,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/utils" testutils "github.com/kyma-project/eventing-manager/test/utils" reconcilertesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) type eventMeshTestEnsemble struct { @@ -199,14 +200,13 @@ func startAndWaitForWebhookServer(manager manager.Manager, installOpts *envtest. func startTestEnv() (*rest.Config, error) { emTestEnsemble.testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../../", "config", "crd", "bases"), - filepath.Join("../../../../../", "config", "crd", "external"), - filepath.Join("../../../../../", "config", "crd", "for-tests"), + filepath.Join("../../../../../../", "config", "crd", "bases"), + filepath.Join("../../../../../../", "config", "crd", "for-tests"), }, AttachControlPlaneOutput: attachControlPlaneOutput, UseExistingCluster: utils.BoolPtr(useExistingCluster), WebhookInstallOptions: envtest.WebhookInstallOptions{ - Paths: []string{filepath.Join("../../../../../", "config", "webhook")}, + Paths: []string{filepath.Join("../../../../../../", "config", "webhook")}, }, } diff --git a/internal/controller/subscription/eventmesh/testwithory/assertions.go b/internal/controller/eventing/subscription/eventmesh/testwithory/assertions.go similarity index 95% rename from internal/controller/subscription/eventmesh/testwithory/assertions.go rename to internal/controller/eventing/subscription/eventmesh/testwithory/assertions.go index e872778a..e14fbbed 100644 --- a/internal/controller/subscription/eventmesh/testwithory/assertions.go +++ b/internal/controller/eventing/subscription/eventmesh/testwithory/assertions.go @@ -9,7 +9,7 @@ import ( "k8s.io/apimachinery/pkg/types" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // getSubscriptionAssert fetches a subscription using the lookupKey and allows making assertions on it. diff --git a/internal/controller/subscription/eventmesh/testwithory/reconciler_integration_test.go b/internal/controller/eventing/subscription/eventmesh/testwithory/reconciler_integration_test.go similarity index 99% rename from internal/controller/subscription/eventmesh/testwithory/reconciler_integration_test.go rename to internal/controller/eventing/subscription/eventmesh/testwithory/reconciler_integration_test.go index 3e11e7b6..83cebad4 100644 --- a/internal/controller/subscription/eventmesh/testwithory/reconciler_integration_test.go +++ b/internal/controller/eventing/subscription/eventmesh/testwithory/reconciler_integration_test.go @@ -16,7 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" eventMeshtypes "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" "github.com/kyma-project/eventing-manager/pkg/object" diff --git a/internal/controller/subscription/eventmesh/testwithory/utils.go b/internal/controller/eventing/subscription/eventmesh/testwithory/utils.go similarity index 97% rename from internal/controller/subscription/eventmesh/testwithory/utils.go rename to internal/controller/eventing/subscription/eventmesh/testwithory/utils.go index 7147114a..cce3adcb 100644 --- a/internal/controller/subscription/eventmesh/testwithory/utils.go +++ b/internal/controller/eventing/subscription/eventmesh/testwithory/utils.go @@ -13,6 +13,8 @@ import ( "testing" "time" + eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/eventmesh" + "github.com/avast/retry-go/v3" "github.com/go-logr/zapr" "github.com/stretchr/testify/require" @@ -36,7 +38,7 @@ import ( apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" kymalogger "github.com/kyma-project/kyma/common/logging/logger" - eventmeshreconciler "github.com/kyma-project/eventing-manager/internal/controller/subscription/eventmesh" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendeventmesh "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" @@ -50,7 +52,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/utils" testutils "github.com/kyma-project/eventing-manager/test/utils" reconcilertesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) type eventMeshTestEnsemble struct { @@ -203,14 +204,13 @@ func startTestEnv() (*rest.Config, error) { useExistingCluster := useExistingCluster emTestEnsemble.testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../../", "config", "crd", "bases"), - filepath.Join("../../../../../", "config", "crd", "external"), - filepath.Join("../../../../../", "config", "crd", "for-tests"), + filepath.Join("../../../../../../", "config", "crd", "bases"), + filepath.Join("../../../../../../", "config", "crd", "for-tests"), }, AttachControlPlaneOutput: attachControlPlaneOutput, UseExistingCluster: &useExistingCluster, WebhookInstallOptions: envtest.WebhookInstallOptions{ - Paths: []string{filepath.Join("../../../../../", "config", "webhook")}, + Paths: []string{filepath.Join("../../../../../../", "config", "webhook")}, }, } diff --git a/internal/controller/subscription/eventmesh/utils.go b/internal/controller/eventing/subscription/eventmesh/utils.go similarity index 97% rename from internal/controller/subscription/eventmesh/utils.go rename to internal/controller/eventing/subscription/eventmesh/utils.go index f7c236fa..f1c104a8 100644 --- a/internal/controller/subscription/eventmesh/utils.go +++ b/internal/controller/eventing/subscription/eventmesh/utils.go @@ -6,7 +6,7 @@ import ( "strings" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/pkg/errors" "go.uber.org/zap" "golang.org/x/xerrors" diff --git a/internal/controller/subscription/eventmesh/utils_test.go b/internal/controller/eventing/subscription/eventmesh/utils_test.go similarity index 98% rename from internal/controller/subscription/eventmesh/utils_test.go rename to internal/controller/eventing/subscription/eventmesh/utils_test.go index ac1681b5..81c38079 100644 --- a/internal/controller/subscription/eventmesh/utils_test.go +++ b/internal/controller/eventing/subscription/eventmesh/utils_test.go @@ -9,10 +9,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" eventinglogger "github.com/kyma-project/eventing-manager/pkg/logger" reconcilertesting "github.com/kyma-project/eventing-manager/testing" kymalogger "github.com/kyma-project/kyma/common/logging/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) func Test_isInDeletion(t *testing.T) { diff --git a/internal/controller/subscription/jetstream/errors.go b/internal/controller/eventing/subscription/jetstream/errors.go similarity index 100% rename from internal/controller/subscription/jetstream/errors.go rename to internal/controller/eventing/subscription/jetstream/errors.go diff --git a/internal/controller/subscription/jetstream/matchers_test.go b/internal/controller/eventing/subscription/jetstream/matchers_test.go similarity index 94% rename from internal/controller/subscription/jetstream/matchers_test.go rename to internal/controller/eventing/subscription/jetstream/matchers_test.go index a0428860..1448ddd4 100644 --- a/internal/controller/subscription/jetstream/matchers_test.go +++ b/internal/controller/eventing/subscription/jetstream/matchers_test.go @@ -5,8 +5,8 @@ import ( "github.com/kyma-project/eventing-manager/pkg/env" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/jetstream" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" ) diff --git a/internal/controller/subscription/jetstream/reconciler.go b/internal/controller/eventing/subscription/jetstream/reconciler.go similarity index 99% rename from internal/controller/subscription/jetstream/reconciler.go rename to internal/controller/eventing/subscription/jetstream/reconciler.go index 060bf528..487f9953 100644 --- a/internal/controller/subscription/jetstream/reconciler.go +++ b/internal/controller/eventing/subscription/jetstream/reconciler.go @@ -32,9 +32,9 @@ import ( backendutils "github.com/kyma-project/eventing-manager/pkg/backend/utils" "github.com/kyma-project/eventing-manager/pkg/utils" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/jetstream" "github.com/kyma-project/eventing-manager/pkg/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/internal/controller/subscription/jetstream/reconciler_integration_test.go b/internal/controller/eventing/subscription/jetstream/reconciler_integration_test.go similarity index 99% rename from internal/controller/subscription/jetstream/reconciler_integration_test.go rename to internal/controller/eventing/subscription/jetstream/reconciler_integration_test.go index 96c24065..ebc2a331 100644 --- a/internal/controller/subscription/jetstream/reconciler_integration_test.go +++ b/internal/controller/eventing/subscription/jetstream/reconciler_integration_test.go @@ -14,7 +14,7 @@ import ( eventingtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // TestMain pre-hook and post-hook to run before and after all tests. diff --git a/internal/controller/subscription/jetstream/reconciler_internal_unit_test.go b/internal/controller/eventing/subscription/jetstream/reconciler_internal_unit_test.go similarity index 99% rename from internal/controller/subscription/jetstream/reconciler_internal_unit_test.go rename to internal/controller/eventing/subscription/jetstream/reconciler_internal_unit_test.go index c5e0b7a9..02d337d3 100644 --- a/internal/controller/subscription/jetstream/reconciler_internal_unit_test.go +++ b/internal/controller/eventing/subscription/jetstream/reconciler_internal_unit_test.go @@ -18,6 +18,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/jetstream" "github.com/kyma-project/eventing-manager/pkg/backend/jetstream/mocks" @@ -26,7 +27,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/logger" controllertesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/internal/controller/subscription/jetstream/test_utils_test.go b/internal/controller/eventing/subscription/jetstream/test_utils_test.go similarity index 98% rename from internal/controller/subscription/jetstream/test_utils_test.go rename to internal/controller/eventing/subscription/jetstream/test_utils_test.go index 371ce64c..5fd626b7 100644 --- a/internal/controller/subscription/jetstream/test_utils_test.go +++ b/internal/controller/eventing/subscription/jetstream/test_utils_test.go @@ -10,9 +10,9 @@ import ( "testing" "time" - "github.com/kyma-project/eventing-manager/pkg/backend/sink" + ctrljetstream "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/jetstream" - ctrljetstream "github.com/kyma-project/eventing-manager/internal/controller/subscription/jetstream" + "github.com/kyma-project/eventing-manager/pkg/backend/sink" "github.com/avast/retry-go/v3" "github.com/kyma-project/eventing-manager/internal/controller/events" @@ -31,6 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" cleanerv1alpha2 "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/jetstream" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" @@ -38,7 +39,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/logger" eventingtesting "github.com/kyma-project/eventing-manager/testing" kymalogger "github.com/kyma-project/kyma/common/logging/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" "k8s.io/client-go/kubernetes/scheme" @@ -113,14 +113,13 @@ func setupSuite() error { NatsServer: natsServer, TestEnv: &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../", "config", "crd", "bases"), - filepath.Join("../../../../", "config", "crd", "external"), + filepath.Join("../../../../../", "config", "crd", "bases"), }, AttachControlPlaneOutput: attachControlPlaneOutput, UseExistingCluster: &useExistingCluster, WebhookInstallOptions: envtest.WebhookInstallOptions{ Paths: []string{ - filepath.Join("../../../../", "config", "webhook", "webhook_configs.yaml"), + filepath.Join("../../../../../", "config", "webhook", "webhook_configs.yaml"), }, }, }, diff --git a/internal/controller/subscription/jetstream/utils.go b/internal/controller/eventing/subscription/jetstream/utils.go similarity index 84% rename from internal/controller/subscription/jetstream/utils.go rename to internal/controller/eventing/subscription/jetstream/utils.go index 0878ad33..f2ef95e5 100644 --- a/internal/controller/subscription/jetstream/utils.go +++ b/internal/controller/eventing/subscription/jetstream/utils.go @@ -1,8 +1,8 @@ package jetstream import ( + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/utils" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // isInDeletion checks if the subscription needs to be deleted. diff --git a/internal/controller/subscription/jetstream/utils_unit_test.go b/internal/controller/eventing/subscription/jetstream/utils_unit_test.go similarity index 95% rename from internal/controller/subscription/jetstream/utils_unit_test.go rename to internal/controller/eventing/subscription/jetstream/utils_unit_test.go index 9e21135a..e4d4a666 100644 --- a/internal/controller/subscription/jetstream/utils_unit_test.go +++ b/internal/controller/eventing/subscription/jetstream/utils_unit_test.go @@ -3,8 +3,8 @@ package jetstream import ( "testing" + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" subtesting "github.com/kyma-project/eventing-manager/testing" - "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "github.com/stretchr/testify/require" ) diff --git a/internal/controller/operator.kyma-project.io/eventing/controller.go b/internal/controller/operator/eventing/controller.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/controller.go rename to internal/controller/operator/eventing/controller.go index 96fc645e..286031ac 100644 --- a/internal/controller/operator.kyma-project.io/eventing/controller.go +++ b/internal/controller/operator/eventing/controller.go @@ -43,7 +43,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/options" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/eventing" diff --git a/internal/controller/operator.kyma-project.io/eventing/controller_test.go b/internal/controller/operator/eventing/controller_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/controller_test.go rename to internal/controller/operator/eventing/controller_test.go index 337e1aca..1955da7d 100644 --- a/internal/controller/operator.kyma-project.io/eventing/controller_test.go +++ b/internal/controller/operator/eventing/controller_test.go @@ -9,7 +9,7 @@ import ( "github.com/kyma-project/eventing-manager/pkg/watcher" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" submanagermocks "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager/mocks" watchmock "github.com/kyma-project/eventing-manager/pkg/watcher/mocks" testutils "github.com/kyma-project/eventing-manager/test/utils" diff --git a/internal/controller/operator.kyma-project.io/eventing/domain.go b/internal/controller/operator/eventing/domain.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/domain.go rename to internal/controller/operator/eventing/domain.go diff --git a/internal/controller/operator.kyma-project.io/eventing/domain_test.go b/internal/controller/operator/eventing/domain_test.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/domain_test.go rename to internal/controller/operator/eventing/domain_test.go diff --git a/internal/controller/operator.kyma-project.io/eventing/eventmesh.go b/internal/controller/operator/eventing/eventmesh.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/eventmesh.go rename to internal/controller/operator/eventing/eventmesh.go index a6770875..d84440a0 100644 --- a/internal/controller/operator.kyma-project.io/eventing/eventmesh.go +++ b/internal/controller/operator/eventing/eventmesh.go @@ -14,7 +14,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/internal/label" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/eventing" diff --git a/internal/controller/operator.kyma-project.io/eventing/eventmesh_test.go b/internal/controller/operator/eventing/eventmesh_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/eventmesh_test.go rename to internal/controller/operator/eventing/eventmesh_test.go index 28ed9cdf..2a82354f 100644 --- a/internal/controller/operator.kyma-project.io/eventing/eventmesh_test.go +++ b/internal/controller/operator/eventing/eventmesh_test.go @@ -5,6 +5,12 @@ import ( "errors" "testing" + "github.com/kyma-project/eventing-manager/pkg/eventing" + + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" + "github.com/kyma-project/eventing-manager/pkg/k8s" + k8smocks "github.com/kyma-project/eventing-manager/pkg/k8s/mocks" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -13,13 +19,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" "github.com/kyma-project/eventing-manager/internal/label" "github.com/kyma-project/eventing-manager/pkg/env" - "github.com/kyma-project/eventing-manager/pkg/eventing" managermocks "github.com/kyma-project/eventing-manager/pkg/eventing/mocks" - "github.com/kyma-project/eventing-manager/pkg/k8s" - k8smocks "github.com/kyma-project/eventing-manager/pkg/k8s/mocks" "github.com/kyma-project/eventing-manager/pkg/logger" submanagermocks "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager/mocks" subscriptionmanagermocks "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/mocks" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controller/integration_test.go b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/controller/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controller/integration_test.go index c87daf3a..489f9500 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controller/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go @@ -7,7 +7,7 @@ import ( "os" "testing" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" @@ -17,11 +17,11 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - eventinv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventinv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" natstestutils "github.com/kyma-project/nats-manager/testutils" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/eventing" "github.com/kyma-project/eventing-manager/pkg/k8s" "github.com/kyma-project/eventing-manager/test/matchers" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controller_switching/integration_test.go b/internal/controller/operator/eventing/integrationtests/controller_switching/integration_test.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/controller_switching/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controller_switching/integration_test.go index a35a9406..9786283a 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controller_switching/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller_switching/integration_test.go @@ -5,9 +5,9 @@ import ( "os" "testing" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/eventing" "github.com/kyma-project/eventing-manager/test/matchers" "github.com/kyma-project/eventing-manager/test/utils" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controllersinglecr/integration_test.go b/internal/controller/operator/eventing/integrationtests/controllersinglecr/integration_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/controllersinglecr/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controllersinglecr/integration_test.go index bab75f13..b82d1528 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/controllersinglecr/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controllersinglecr/integration_test.go @@ -7,7 +7,7 @@ import ( natstestutils "github.com/kyma-project/nats-manager/testutils" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/test/matchers" testutils "github.com/kyma-project/eventing-manager/test/utils" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/nats_disabled/integration_test.go b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/nats_disabled/integration_test.go rename to internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go index 6b250c94..ff62eb80 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/nats_disabled/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" "github.com/kyma-project/eventing-manager/pkg/k8s" "github.com/kyma-project/eventing-manager/test/matchers" @@ -13,7 +13,7 @@ import ( natstestutils "github.com/kyma-project/nats-manager/testutils" "github.com/onsi/gomega" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/eventing" testutils "github.com/kyma-project/eventing-manager/test/utils/integration" "github.com/stretchr/testify/require" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/validation/integration_test.go b/internal/controller/operator/eventing/integrationtests/validation/integration_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/validation/integration_test.go rename to internal/controller/operator/eventing/integrationtests/validation/integration_test.go index 0bae7405..5e010e59 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/validation/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/validation/integration_test.go @@ -5,7 +5,7 @@ import ( "os" "testing" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/test" eventingMatchers "github.com/kyma-project/eventing-manager/test/matchers" "github.com/kyma-project/eventing-manager/test/utils/integration" diff --git a/internal/controller/operator.kyma-project.io/eventing/integrationtests/without_apirule_crd/integration_test.go b/internal/controller/operator/eventing/integrationtests/without_apirule_crd/integration_test.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/integrationtests/without_apirule_crd/integration_test.go rename to internal/controller/operator/eventing/integrationtests/without_apirule_crd/integration_test.go index 584d62d0..fbbf4fd6 100644 --- a/internal/controller/operator.kyma-project.io/eventing/integrationtests/without_apirule_crd/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/without_apirule_crd/integration_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/test/matchers" "github.com/kyma-project/eventing-manager/test/utils" testutils "github.com/kyma-project/eventing-manager/test/utils/integration" diff --git a/internal/controller/operator.kyma-project.io/eventing/mocks/controller.go b/internal/controller/operator/eventing/mocks/controller.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/mocks/controller.go rename to internal/controller/operator/eventing/mocks/controller.go diff --git a/internal/controller/operator.kyma-project.io/eventing/mocks/manager.go b/internal/controller/operator/eventing/mocks/manager.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/mocks/manager.go rename to internal/controller/operator/eventing/mocks/manager.go diff --git a/internal/controller/operator.kyma-project.io/eventing/mocks/nats_config_handler.go b/internal/controller/operator/eventing/mocks/nats_config_handler.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/mocks/nats_config_handler.go rename to internal/controller/operator/eventing/mocks/nats_config_handler.go index c1e1c6c0..adc5591a 100644 --- a/internal/controller/operator.kyma-project.io/eventing/mocks/nats_config_handler.go +++ b/internal/controller/operator/eventing/mocks/nats_config_handler.go @@ -9,7 +9,7 @@ import ( mock "github.com/stretchr/testify/mock" - v1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // NatsConfigHandler is an autogenerated mock type for the NatsConfigHandler type diff --git a/internal/controller/operator.kyma-project.io/eventing/nats.go b/internal/controller/operator/eventing/nats.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/nats.go rename to internal/controller/operator/eventing/nats.go index 621f3c47..cd3d18a1 100644 --- a/internal/controller/operator.kyma-project.io/eventing/nats.go +++ b/internal/controller/operator/eventing/nats.go @@ -6,7 +6,7 @@ import ( "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/options" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/k8s" diff --git a/internal/controller/operator.kyma-project.io/eventing/nats_test.go b/internal/controller/operator/eventing/nats_test.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/nats_test.go rename to internal/controller/operator/eventing/nats_test.go index 388a8942..bf86aa86 100644 --- a/internal/controller/operator.kyma-project.io/eventing/nats_test.go +++ b/internal/controller/operator/eventing/nats_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" - "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing/mocks" + "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing/mocks" submanagermocks "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager/mocks" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/options" "github.com/kyma-project/eventing-manager/pkg/env" managermocks "github.com/kyma-project/eventing-manager/pkg/eventing/mocks" diff --git a/internal/controller/operator.kyma-project.io/eventing/service_instance_secret.go b/internal/controller/operator/eventing/service_instance_secret.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/service_instance_secret.go rename to internal/controller/operator/eventing/service_instance_secret.go diff --git a/internal/controller/operator.kyma-project.io/eventing/status.go b/internal/controller/operator/eventing/status.go similarity index 99% rename from internal/controller/operator.kyma-project.io/eventing/status.go rename to internal/controller/operator/eventing/status.go index 2182ea0d..deb918c5 100644 --- a/internal/controller/operator.kyma-project.io/eventing/status.go +++ b/internal/controller/operator/eventing/status.go @@ -5,7 +5,7 @@ import ( "errors" "time" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "go.uber.org/zap" v1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/internal/controller/operator.kyma-project.io/eventing/unit_test.go b/internal/controller/operator/eventing/unit_test.go similarity index 97% rename from internal/controller/operator.kyma-project.io/eventing/unit_test.go rename to internal/controller/operator/eventing/unit_test.go index 1a49086f..b6dbb9c3 100644 --- a/internal/controller/operator.kyma-project.io/eventing/unit_test.go +++ b/internal/controller/operator/eventing/unit_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - ctrlmocks "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing/mocks" + ctrlmocks "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing/mocks" apiclientsetfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" @@ -20,7 +20,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" managermocks "github.com/kyma-project/eventing-manager/pkg/eventing/mocks" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" "github.com/stretchr/testify/require" diff --git a/internal/controller/operator.kyma-project.io/eventing/utils.go b/internal/controller/operator/eventing/utils.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/utils.go rename to internal/controller/operator/eventing/utils.go index e6234c12..1c010ea6 100644 --- a/internal/controller/operator.kyma-project.io/eventing/utils.go +++ b/internal/controller/operator/eventing/utils.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/mitchellh/hashstructure/v2" ctrl "sigs.k8s.io/controller-runtime" diff --git a/internal/controller/operator.kyma-project.io/eventing/utils_test.go b/internal/controller/operator/eventing/utils_test.go similarity index 98% rename from internal/controller/operator.kyma-project.io/eventing/utils_test.go rename to internal/controller/operator/eventing/utils_test.go index 1172930d..2489b9aa 100644 --- a/internal/controller/operator.kyma-project.io/eventing/utils_test.go +++ b/internal/controller/operator/eventing/utils_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/test/utils" "github.com/stretchr/testify/require" ) diff --git a/internal/controller/operator.kyma-project.io/eventing/webhook.go b/internal/controller/operator/eventing/webhook.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/webhook.go rename to internal/controller/operator/eventing/webhook.go diff --git a/internal/controller/operator.kyma-project.io/eventing/webhook_test.go b/internal/controller/operator/eventing/webhook_test.go similarity index 100% rename from internal/controller/operator.kyma-project.io/eventing/webhook_test.go rename to internal/controller/operator/eventing/webhook_test.go diff --git a/pkg/backend/eventmesh/eventmesh.go b/pkg/backend/eventmesh/eventmesh.go index 18f1682f..bd09b480 100644 --- a/pkg/backend/eventmesh/eventmesh.go +++ b/pkg/backend/eventmesh/eventmesh.go @@ -8,6 +8,7 @@ import ( "go.uber.org/zap" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendutils "github.com/kyma-project/eventing-manager/pkg/backend/utils" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/client" @@ -17,7 +18,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/featureflags" "github.com/kyma-project/eventing-manager/pkg/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/backend/eventmesh/eventmesh_integration_test.go b/pkg/backend/eventmesh/eventmesh_integration_test.go index 7ff656e7..1ee71d60 100644 --- a/pkg/backend/eventmesh/eventmesh_integration_test.go +++ b/pkg/backend/eventmesh/eventmesh_integration_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendutils "github.com/kyma-project/eventing-manager/pkg/backend/utils" PublisherManagerMock "github.com/kyma-project/eventing-manager/pkg/ems/api/events/client/mocks" @@ -15,7 +16,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/logger" controllertesting "github.com/kyma-project/eventing-manager/testing" kymalogger "github.com/kyma-project/kyma/common/logging/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) func Test_getProcessedEventTypes(t *testing.T) { diff --git a/pkg/backend/eventmesh/mocks/Backend.go b/pkg/backend/eventmesh/mocks/Backend.go index 9e40283e..18d512c0 100644 --- a/pkg/backend/eventmesh/mocks/Backend.go +++ b/pkg/backend/eventmesh/mocks/Backend.go @@ -8,7 +8,7 @@ import ( mock "github.com/stretchr/testify/mock" - v1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + v1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" v1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" ) diff --git a/pkg/backend/eventmesh/utils.go b/pkg/backend/eventmesh/utils.go index fc732713..950033ec 100644 --- a/pkg/backend/eventmesh/utils.go +++ b/pkg/backend/eventmesh/utils.go @@ -4,9 +4,9 @@ import ( "fmt" "strings" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" backendutils "github.com/kyma-project/eventing-manager/pkg/backend/utils" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // getEventMeshSubject appends the prefix to subject. diff --git a/pkg/backend/eventmesh/utils_unit_test.go b/pkg/backend/eventmesh/utils_unit_test.go index 556ac1ae..521470fc 100644 --- a/pkg/backend/eventmesh/utils_unit_test.go +++ b/pkg/backend/eventmesh/utils_unit_test.go @@ -6,9 +6,9 @@ import ( "github.com/stretchr/testify/require" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" backendutils "github.com/kyma-project/eventing-manager/pkg/backend/utils" eventingtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) func Test_IsEventTypeSegmentsOverLimit(t *testing.T) { diff --git a/pkg/backend/jetstream/jetstream.go b/pkg/backend/jetstream/jetstream.go index ded9e7ac..aeeafb83 100644 --- a/pkg/backend/jetstream/jetstream.go +++ b/pkg/backend/jetstream/jetstream.go @@ -19,8 +19,8 @@ import ( "github.com/pkg/errors" "go.uber.org/zap" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" - ecenv "github.com/kyma-project/kyma/components/eventing-controller/pkg/env" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" + ecenv "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendmetrics "github.com/kyma-project/eventing-manager/pkg/backend/metrics" diff --git a/pkg/backend/jetstream/jetstream_integration_test.go b/pkg/backend/jetstream/jetstream_integration_test.go index 6cab3e64..d8bd38e0 100644 --- a/pkg/backend/jetstream/jetstream_integration_test.go +++ b/pkg/backend/jetstream/jetstream_integration_test.go @@ -13,13 +13,13 @@ import ( kymalogger "github.com/kyma-project/kyma/common/logging/logger" "github.com/stretchr/testify/require" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/logger" evtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // TestJetStreamSubAfterSync_SinkChange tests the SyncSubscription method diff --git a/pkg/backend/jetstream/jetstream_internal_unit_test.go b/pkg/backend/jetstream/jetstream_internal_unit_test.go index 71874ae0..fb617701 100644 --- a/pkg/backend/jetstream/jetstream_internal_unit_test.go +++ b/pkg/backend/jetstream/jetstream_internal_unit_test.go @@ -13,10 +13,10 @@ import ( "github.com/stretchr/testify/assert" + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" subtesting "github.com/kyma-project/eventing-manager/testing" - "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) diff --git a/pkg/backend/jetstream/mocks/Backend.go b/pkg/backend/jetstream/mocks/Backend.go index 1dab8391..c3e98314 100644 --- a/pkg/backend/jetstream/mocks/Backend.go +++ b/pkg/backend/jetstream/mocks/Backend.go @@ -11,7 +11,7 @@ import ( utils "github.com/kyma-project/eventing-manager/pkg/backend/utils" - v1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + v1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // Backend is an autogenerated mock type for the Backend type diff --git a/pkg/backend/jetstream/test_helpers.go b/pkg/backend/jetstream/test_helpers.go index f5e2de9c..3d024e1a 100644 --- a/pkg/backend/jetstream/test_helpers.go +++ b/pkg/backend/jetstream/test_helpers.go @@ -18,9 +18,9 @@ import ( v2 "github.com/cloudevents/sdk-go/v2" "github.com/cloudevents/sdk-go/v2/binding" cev2http "github.com/cloudevents/sdk-go/v2/protocol/http" + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" evtesting "github.com/kyma-project/eventing-manager/testing" - "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/backend/jetstream/types.go b/pkg/backend/jetstream/types.go index f4f29cbe..62c94f5b 100644 --- a/pkg/backend/jetstream/types.go +++ b/pkg/backend/jetstream/types.go @@ -9,11 +9,11 @@ import ( "github.com/nats-io/nats.go" cev2 "github.com/cloudevents/sdk-go/v2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendmetrics "github.com/kyma-project/eventing-manager/pkg/backend/metrics" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/logger" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/backend/jetstream/utils.go b/pkg/backend/jetstream/utils.go index bcdb2fdf..8371812f 100644 --- a/pkg/backend/jetstream/utils.go +++ b/pkg/backend/jetstream/utils.go @@ -15,8 +15,8 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/backend/jetstream/utils_internal_integration_test.go b/pkg/backend/jetstream/utils_internal_integration_test.go index 72883fcd..a0fd0e22 100644 --- a/pkg/backend/jetstream/utils_internal_integration_test.go +++ b/pkg/backend/jetstream/utils_internal_integration_test.go @@ -3,8 +3,8 @@ package jetstream import ( "testing" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" evtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "github.com/stretchr/testify/require" ) diff --git a/pkg/backend/jetstream/utils_internal_unit_test.go b/pkg/backend/jetstream/utils_internal_unit_test.go index 8b08c72c..519d6f96 100644 --- a/pkg/backend/jetstream/utils_internal_unit_test.go +++ b/pkg/backend/jetstream/utils_internal_unit_test.go @@ -11,10 +11,10 @@ import ( kymalogger "github.com/kyma-project/kyma/common/logging/logger" "github.com/stretchr/testify/require" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/logger" evtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // maxJetStreamConsumerNameLength is the maximum preferred length for the JetStream consumer names diff --git a/pkg/backend/sink/validator.go b/pkg/backend/sink/validator.go index a84bccbe..5171a528 100644 --- a/pkg/backend/sink/validator.go +++ b/pkg/backend/sink/validator.go @@ -12,8 +12,8 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/internal/controller/events" - "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) type Validator interface { diff --git a/pkg/backend/sink/validator_test.go b/pkg/backend/sink/validator_test.go index 63046f42..de3f4f5c 100644 --- a/pkg/backend/sink/validator_test.go +++ b/pkg/backend/sink/validator_test.go @@ -12,8 +12,8 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client/fake" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" controllertesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) func TestSinkValidator(t *testing.T) { diff --git a/pkg/backend/utils/eventmesh_utils.go b/pkg/backend/utils/eventmesh_utils.go index e772cef4..d9ac30d7 100644 --- a/pkg/backend/utils/eventmesh_utils.go +++ b/pkg/backend/utils/eventmesh_utils.go @@ -9,9 +9,9 @@ import ( "github.com/pkg/errors" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" "github.com/kyma-project/eventing-manager/pkg/featureflags" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) // eventMeshSubscriptionNameMapper maps a Kyma subscription to an ID that can be used on the EventMesh backend, diff --git a/pkg/backend/utils/eventmesh_utils_test.go b/pkg/backend/utils/eventmesh_utils_test.go index a4fdd251..4f63de10 100644 --- a/pkg/backend/utils/eventmesh_utils_test.go +++ b/pkg/backend/utils/eventmesh_utils_test.go @@ -15,9 +15,9 @@ import ( . "github.com/onsi/gomega" v1meta "k8s.io/apimachinery/pkg/apis/meta/v1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" eventingtesting "github.com/kyma-project/eventing-manager/testing" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) func TestConvertKymaSubToEventMeshSub(t *testing.T) { diff --git a/pkg/backend/utils/utils.go b/pkg/backend/utils/utils.go index 4f906ef5..e2e32449 100644 --- a/pkg/backend/utils/utils.go +++ b/pkg/backend/utils/utils.go @@ -6,7 +6,7 @@ import ( "fmt" "net/url" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/pkg/errors" "go.uber.org/zap" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/env/nats_config.go b/pkg/env/nats_config.go index 6ab9a8a3..4029cf6f 100644 --- a/pkg/env/nats_config.go +++ b/pkg/env/nats_config.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kelseyhightower/envconfig" ) diff --git a/pkg/env/nats_config_test.go b/pkg/env/nats_config_test.go index 67c9c1a6..fdddc0ad 100644 --- a/pkg/env/nats_config_test.go +++ b/pkg/env/nats_config_test.go @@ -7,7 +7,10 @@ import ( "testing" "time" - "github.com/kyma-project/eventing-manager/test/utils" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/stretchr/testify/require" ) @@ -29,10 +32,29 @@ func Test_GetNewNATSConfig(t *testing.T) { JSConsumerDeliverPolicy: "DeliverNew", } - givenEventing := utils.NewEventingCR( - utils.WithEventingStreamData("Memory", "650M", 5, 5000), - utils.WithEventingEventTypePrefix("sap.kyma.custom"), - ) + givenEventing := &v1alpha1.Eventing{ + TypeMeta: metav1.TypeMeta{ + Kind: "Eventing", + APIVersion: "operator.kyma-project.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test-ns", + UID: "1234-5678-1234-5678", + }, + Spec: v1alpha1.EventingSpec{ + Backend: v1alpha1.Backend{ + Type: v1alpha1.NatsBackendType, + Config: v1alpha1.BackendConfig{ + EventTypePrefix: "sap.kyma.custom", + NATSStreamStorageType: "Memory", + NATSStreamMaxSize: resource.MustParse("650M"), + NATSStreamReplicas: 5, + NATSMaxMsgsPerTopic: 5000, + }, + }, + }, + } // when result := givenConfig.GetNewNATSConfig(*givenEventing) diff --git a/pkg/eventing/deployment.go b/pkg/eventing/deployment.go index 02cb425e..cc85e11c 100644 --- a/pkg/eventing/deployment.go +++ b/pkg/eventing/deployment.go @@ -11,7 +11,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/internal/label" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/utils" diff --git a/pkg/eventing/deployment_test.go b/pkg/eventing/deployment_test.go index f3bd413d..dc25ce10 100644 --- a/pkg/eventing/deployment_test.go +++ b/pkg/eventing/deployment_test.go @@ -11,7 +11,7 @@ import ( appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/internal/label" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/test" @@ -376,7 +376,7 @@ func Test_getLabels(t *testing.T) { label.KeyManagedBy: label.ValueEventingManager, label.KeyName: publisherName, label.KeyPartOf: label.ValueEventingManager, - label.KeyBackend: "BEB", + label.KeyBackend: "EventMesh", label.KeyDashboard: label.ValueEventing, }, }, diff --git a/pkg/eventing/manager.go b/pkg/eventing/manager.go index da5f79d8..bb2b86b4 100644 --- a/pkg/eventing/manager.go +++ b/pkg/eventing/manager.go @@ -4,18 +4,18 @@ import ( "context" "fmt" + ecv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/k8s" "github.com/kyma-project/eventing-manager/pkg/logger" "github.com/kyma-project/eventing-manager/pkg/object" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" ) const ( diff --git a/pkg/eventing/manager_test.go b/pkg/eventing/manager_test.go index 2423bbac..70f6fddc 100644 --- a/pkg/eventing/manager_test.go +++ b/pkg/eventing/manager_test.go @@ -17,15 +17,15 @@ import ( "k8s.io/apimachinery/pkg/runtime" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + ecv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" natstestutils "github.com/kyma-project/nats-manager/testutils" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/env" k8smocks "github.com/kyma-project/eventing-manager/pkg/k8s/mocks" testutils "github.com/kyma-project/eventing-manager/test/utils" diff --git a/pkg/eventing/mocks/manager.go b/pkg/eventing/mocks/manager.go index 3d927b26..276ce666 100644 --- a/pkg/eventing/mocks/manager.go +++ b/pkg/eventing/mocks/manager.go @@ -11,7 +11,7 @@ import ( v1 "k8s.io/api/apps/v1" - v1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // Manager is an autogenerated mock type for the Manager type diff --git a/pkg/eventing/utils.go b/pkg/eventing/utils.go index 2a63cd07..a3dd22d7 100644 --- a/pkg/eventing/utils.go +++ b/pkg/eventing/utils.go @@ -2,9 +2,7 @@ package eventing import ( "fmt" - - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" autoscalingv2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -243,9 +241,9 @@ func newPublisherProxyHealthService(name, namespace string, labels map[string]st } } -func getECBackendType(backendType v1alpha1.BackendType) ecv1alpha1.BackendType { +func getECBackendType(backendType v1alpha1.BackendType) v1alpha1.BackendType { if backendType == v1alpha1.EventMeshBackendType { - return ecv1alpha1.BEBBackendType + return v1alpha1.EventMeshBackendType } - return ecv1alpha1.NatsBackendType + return v1alpha1.NatsBackendType } diff --git a/pkg/eventing/utils_test.go b/pkg/eventing/utils_test.go index 6aad0559..fa992e4d 100644 --- a/pkg/eventing/utils_test.go +++ b/pkg/eventing/utils_test.go @@ -3,11 +3,9 @@ package eventing import ( "testing" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" ) func Test_EPPResourcesNames(t *testing.T) { @@ -34,7 +32,7 @@ func Test_getECBackendType(t *testing.T) { tests := []struct { name string args args - want ecv1alpha1.BackendType + want v1alpha1.BackendType }{ { name: "should return the correct backend type for NATS", @@ -48,7 +46,7 @@ func Test_getECBackendType(t *testing.T) { args: args{ backendType: "EventMesh", }, - want: "BEB", + want: "EventMesh", }, { name: "should return the default backend type for unsupported input", diff --git a/pkg/k8s/client.go b/pkg/k8s/client.go index ab39af5b..8d80982a 100644 --- a/pkg/k8s/client.go +++ b/pkg/k8s/client.go @@ -20,7 +20,7 @@ import ( "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" ) diff --git a/pkg/k8s/client_test.go b/pkg/k8s/client_test.go index a5a48135..493e58c1 100644 --- a/pkg/k8s/client_test.go +++ b/pkg/k8s/client_test.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" testutils "github.com/kyma-project/eventing-manager/test/utils" diff --git a/pkg/k8s/mocks/client.go b/pkg/k8s/mocks/client.go index 35c6ef5c..87946f13 100644 --- a/pkg/k8s/mocks/client.go +++ b/pkg/k8s/mocks/client.go @@ -18,7 +18,7 @@ import ( v1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" - v1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + v1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" v1beta1 "istio.io/client-go/pkg/apis/security/v1beta1" ) diff --git a/pkg/object/apirule.go b/pkg/object/apirule.go index 1237fd5b..0fbbb396 100644 --- a/pkg/object/apirule.go +++ b/pkg/object/apirule.go @@ -8,8 +8,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/featureflags" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/object/apirule_test.go b/pkg/object/apirule_test.go index 86315ee8..12c23616 100644 --- a/pkg/object/apirule_test.go +++ b/pkg/object/apirule_test.go @@ -2,14 +2,15 @@ package object import ( "fmt" + "reflect" + "testing" + "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/utils/ptr" - "reflect" - "testing" ) func TestApplyExistingAPIRuleAttributes(t *testing.T) { diff --git a/pkg/object/equality.go b/pkg/object/equality.go index 8851bc2a..eb34f719 100644 --- a/pkg/object/equality.go +++ b/pkg/object/equality.go @@ -11,15 +11,13 @@ import ( "k8s.io/apimachinery/pkg/conversion" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) // Semantic can do semantic deep equality checks for API objects. Fields which // are not relevant for the reconciliation logic are intentionally omitted. var Semantic = conversion.EqualitiesOrDie( apiRuleEqual, - eventingBackendEqual, publisherProxyDeploymentEqual, serviceAccountEqual, clusterRoleEqual, @@ -209,26 +207,6 @@ func ownerReferencesDeepEqual(ors1, ors2 []v1.OwnerReference) bool { return true } -// eventingBackendEqual asserts the equality of two EventingBackend objects. -func eventingBackendEqual(b1, b2 *eventingv1alpha1.EventingBackend) bool { - if b1 == nil || b2 == nil { - return false - } - if b1 == b2 { - return true - } - - if !reflect.DeepEqual(b1.Labels, b2.Labels) { - return false - } - - if !reflect.DeepEqual(b1.Spec, b2.Spec) { - return false - } - - return true -} - // publisherProxyDeploymentEqual asserts the equality of two Deployment objects // for event publisher proxy deployments. func publisherProxyDeploymentEqual(d1, d2 *appsv1.Deployment) bool { @@ -414,17 +392,6 @@ func realProto(pr corev1.Protocol) corev1.Protocol { return pr } -func IsBackendStatusEqual(oldStatus, newStatus eventingv1alpha1.EventingBackendStatus) bool { - oldStatusWithoutCond := oldStatus.DeepCopy() - newStatusWithoutCond := newStatus.DeepCopy() - - // remove conditions, so that we don't compare them - oldStatusWithoutCond.Conditions = []eventingv1alpha1.Condition{} - newStatusWithoutCond.Conditions = []eventingv1alpha1.Condition{} - - return reflect.DeepEqual(oldStatusWithoutCond, newStatusWithoutCond) && eventingv1alpha1.ConditionsEquals(oldStatus.Conditions, newStatus.Conditions) -} - func IsSubscriptionStatusEqual(oldStatus, newStatus eventingv1alpha2.SubscriptionStatus) bool { oldStatusWithoutCond := oldStatus.DeepCopy() newStatusWithoutCond := newStatus.DeepCopy() diff --git a/pkg/object/equality_test.go b/pkg/object/equality_test.go index ed2acda6..159aa3b1 100644 --- a/pkg/object/equality_test.go +++ b/pkg/object/equality_test.go @@ -1,12 +1,12 @@ package object import ( - "k8s.io/apimachinery/pkg/util/intstr" "net/http" "testing" + "k8s.io/apimachinery/pkg/util/intstr" + "github.com/stretchr/testify/require" - appsv1 "k8s.io/api/apps/v1" v2 "k8s.io/api/autoscaling/v2" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -16,12 +16,7 @@ import ( "k8s.io/utils/ptr" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" - "github.com/kyma-project/kyma/components/eventing-controller/pkg/deployment" - "github.com/kyma-project/kyma/components/eventing-controller/pkg/env" - - "github.com/kyma-project/eventing-manager/pkg/utils" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" ) func TestApiRuleEqual(t *testing.T) { @@ -187,202 +182,6 @@ func TestApiRuleEqual(t *testing.T) { } } -func TestEventingBackendEqual(t *testing.T) { - emptyBackend := eventingv1alpha1.EventingBackend{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "bar", - }, - Spec: eventingv1alpha1.EventingBackendSpec{}, - } - - testCases := map[string]struct { - getBackend1 func() *eventingv1alpha1.EventingBackend - getBackend2 func() *eventingv1alpha1.EventingBackend - expectedResult bool - }{ - "should be unequal if labels are different": { - getBackend1: func() *eventingv1alpha1.EventingBackend { - b := emptyBackend.DeepCopy() - b.Labels = map[string]string{"k1": "v1"} - return b - }, - getBackend2: func() *eventingv1alpha1.EventingBackend { - return emptyBackend.DeepCopy() - }, - expectedResult: false, - }, - "should be equal if labels are the same": { - getBackend1: func() *eventingv1alpha1.EventingBackend { - b := emptyBackend.DeepCopy() - b.Labels = map[string]string{"k1": "v1"} - return b - }, - getBackend2: func() *eventingv1alpha1.EventingBackend { - b := emptyBackend.DeepCopy() - b.Name = "bar" - b.Labels = map[string]string{"k1": "v1"} - return b - }, - expectedResult: true, - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - if eventingBackendEqual(tc.getBackend1(), tc.getBackend2()) != tc.expectedResult { - t.Errorf("expected output to be %t", tc.expectedResult) - } - }) - } -} - -func TestEventingBackendStatusEqual(t *testing.T) { - testCases := []struct { - name string - givenBackendStatus1 eventingv1alpha1.EventingBackendStatus - givenBackendStatus2 eventingv1alpha1.EventingBackendStatus - wantResult bool - }{ - { - name: "should be unequal if ready status is different", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(true), - }, - wantResult: false, - }, - { - name: "should be unequal if missing secret", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - BEBSecretName: "secret", - BEBSecretNamespace: "default", - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - }, - wantResult: false, - }, - { - name: "should be unequal if different secretName", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - BEBSecretName: "secret", - BEBSecretNamespace: "default", - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - BEBSecretName: "secretnew", - BEBSecretNamespace: "default", - }, - wantResult: false, - }, - { - name: "should be unequal if different secretNamespace", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - BEBSecretName: "secret", - BEBSecretNamespace: "default", - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - EventingReady: utils.BoolPtr(false), - BEBSecretName: "secret", - BEBSecretNamespace: "kyma-system", - }, - wantResult: false, - }, - { - name: "should be unequal if missing backend", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Backend: eventingv1alpha1.NatsBackendType, - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{}, - wantResult: false, - }, - { - name: "should be unequal if different backend", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Backend: eventingv1alpha1.NatsBackendType, - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - Backend: eventingv1alpha1.BEBBackendType, - }, - wantResult: false, - }, - { - name: "should be unequal if conditions different", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionTrue}, - }, - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionFalse}, - }, - }, - wantResult: false, - }, - { - name: "should be unequal if conditions missing", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionTrue}, - }, - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{}, - }, - wantResult: false, - }, - { - name: "should be unequal if conditions different", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionTrue}, - }, - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionControllerReady, Status: corev1.ConditionTrue}, - }, - }, - wantResult: false, - }, - { - name: "should be equal if the status are the same", - givenBackendStatus1: eventingv1alpha1.EventingBackendStatus{ - Backend: eventingv1alpha1.NatsBackendType, - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionControllerReady, Status: corev1.ConditionTrue}, - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionTrue}, - }, - EventingReady: utils.BoolPtr(true), - }, - givenBackendStatus2: eventingv1alpha1.EventingBackendStatus{ - Backend: eventingv1alpha1.NatsBackendType, - Conditions: []eventingv1alpha1.Condition{ - {Type: eventingv1alpha1.ConditionControllerReady, Status: corev1.ConditionTrue}, - {Type: eventingv1alpha1.ConditionPublisherProxyReady, Status: corev1.ConditionTrue}, - }, - EventingReady: utils.BoolPtr(true), - }, - wantResult: true, - }, - } - for _, tc := range testCases { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - if IsBackendStatusEqual(tc.givenBackendStatus1, tc.givenBackendStatus2) != tc.wantResult { - t.Errorf("expected output to be %t", tc.wantResult) - } - }) - } -} - func Test_isSubscriptionStatusEqual(t *testing.T) { testCases := []struct { name string @@ -455,252 +254,178 @@ func Test_isSubscriptionStatusEqual(t *testing.T) { } } -func TestPublisherProxyDeploymentEqual(t *testing.T) { - publisherCfg := env.PublisherConfig{ - Image: "publisher", - PortNum: 0, - MetricsPortNum: 0, - ServiceAccount: "publisher-sa", - Replicas: 1, - RequestsCPU: "32m", - RequestsMemory: "64Mi", - LimitsCPU: "64m", - LimitsMemory: "128Mi", - } - natsConfig := env.NATSConfig{ - EventTypePrefix: "prefix", - JSStreamName: "kyma", - } - defaultNATSPublisher := deployment.NewNATSPublisherDeployment(natsConfig, publisherCfg) - defaultBEBPublisher := deployment.NewBEBPublisherDeployment(publisherCfg) - - testCases := map[string]struct { - getPublisher1 func() *appsv1.Deployment - getPublisher2 func() *appsv1.Deployment - expectedResult bool - }{ - "should be equal if same default NATS publisher": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Name = "publisher1" - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Name = "publisher2" - return p - }, - expectedResult: true, - }, - "should be equal if same default BEB publisher": { - getPublisher1: func() *appsv1.Deployment { - p := defaultBEBPublisher.DeepCopy() - p.Name = "publisher1" - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultBEBPublisher.DeepCopy() - p.Name = "publisher2" - return p - }, - expectedResult: true, - }, - "should be unequal if publisher types are different": { - getPublisher1: func() *appsv1.Deployment { - return defaultBEBPublisher.DeepCopy() - }, - getPublisher2: func() *appsv1.Deployment { - return defaultNATSPublisher.DeepCopy() - }, - expectedResult: false, - }, - "should be unequal if publisher image changes": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Spec.Containers[0].Image = "new-publisher-img" - return p - }, - getPublisher2: func() *appsv1.Deployment { - return defaultNATSPublisher.DeepCopy() - }, - expectedResult: false, - }, - "should be unequal if env var changes": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Spec.Containers[0].Env[0].Value = "new-value" - return p - }, - getPublisher2: func() *appsv1.Deployment { - return defaultNATSPublisher.DeepCopy() - }, - expectedResult: false, - }, - "should be equal if replicas changes": { - getPublisher1: func() *appsv1.Deployment { - replicas := int32(1) - p := defaultNATSPublisher.DeepCopy() - p.Spec.Replicas = &replicas - return p - }, - getPublisher2: func() *appsv1.Deployment { - replicas := int32(2) - p := defaultNATSPublisher.DeepCopy() - p.Spec.Replicas = &replicas - return p - }, - expectedResult: true, - }, - "should be equal if replicas are the same": { - getPublisher1: func() *appsv1.Deployment { - replicas := int32(2) - p := defaultNATSPublisher.DeepCopy() - p.Spec.Replicas = &replicas - return p - }, - getPublisher2: func() *appsv1.Deployment { - replicas := int32(2) - p := defaultNATSPublisher.DeepCopy() - p.Spec.Replicas = &replicas - return p - }, - expectedResult: true, - }, - "should be equal if spec annotations are nil and empty": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Annotations = nil - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Annotations = map[string]string{} - return p - }, - expectedResult: true, - }, - "should be unequal if spec annotations changes": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Annotations = map[string]string{"key": "value1"} - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Annotations = map[string]string{"key": "value2"} - return p - }, - expectedResult: false, - }, - "should be equal if spec Labels are nil and empty": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = nil - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{} - return p - }, - expectedResult: true, - }, - "should be equal if spec Labels are equal with same order": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - "key2": "value2", - } - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - "key2": "value2", - } - return p - }, - expectedResult: true, - }, - "should be equal if spec Labels are equal with different order": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - "key2": "value2", - } - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key2": "value2", - "key1": "value1", - } - return p - }, - expectedResult: true, - }, - "should not be equal if spec Labels were added": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - } - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - "key2": "value2", - } - return p - }, - expectedResult: false, - }, - "should not be equal if spec Labels were removed": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - "key2": "value2", - } - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{ - "key1": "value1", - } - return p - }, - expectedResult: false, - }, - "should be unequal if spec Labels changes": { - getPublisher1: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{"key": "value1"} - return p - }, - getPublisher2: func() *appsv1.Deployment { - p := defaultNATSPublisher.DeepCopy() - p.Spec.Template.Labels = map[string]string{"key": "value2"} - return p - }, - expectedResult: false, - }, - } - for name, tc := range testCases { - t.Run(name, func(t *testing.T) { - if publisherProxyDeploymentEqual(tc.getPublisher1(), tc.getPublisher2()) != tc.expectedResult { - t.Errorf("expected output to be %t", tc.expectedResult) - } - }) - } -} +//func TestPublisherProxyDeploymentEqual(t *testing.T) { +// publisherCfg := env.PublisherConfig{ +// Image: "publisher", +// PortNum: 0, +// MetricsPortNum: 0, +// ServiceAccount: "publisher-sa", +// Replicas: 1, +// RequestsCPU: "32m", +// RequestsMemory: "64Mi", +// LimitsCPU: "64m", +// LimitsMemory: "128Mi", +// } +// natsConfig := env.NATSConfig{ +// EventTypePrefix: "prefix", +// JSStreamName: "kyma", +// } +// defaultNATSPublisher := eventingpkg.NewNATSPublisherDeployment(natsConfig, publisherCfg) +// defaultBEBPublisher := eventingpkg.NewBEBPublisherDeployment(publisherCfg) +// +// testCases := map[string]struct { +// getPublisher1 func() *appsv1.Deployment +// getPublisher2 func() *appsv1.Deployment +// expectedResult bool +// }{ +// "should be equal if same default NATS publisher": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Name = "publisher1" +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Name = "publisher2" +// return p +// }, +// expectedResult: true, +// }, +// "should be equal if same default BEB publisher": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultBEBPublisher.DeepCopy() +// p.Name = "publisher1" +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultBEBPublisher.DeepCopy() +// p.Name = "publisher2" +// return p +// }, +// expectedResult: true, +// }, +// "should be unequal if publisher types are different": { +// getPublisher1: func() *appsv1.Deployment { +// return defaultBEBPublisher.DeepCopy() +// }, +// getPublisher2: func() *appsv1.Deployment { +// return defaultNATSPublisher.DeepCopy() +// }, +// expectedResult: false, +// }, +// "should be unequal if publisher image changes": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Spec.Containers[0].Image = "new-publisher-img" +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// return defaultNATSPublisher.DeepCopy() +// }, +// expectedResult: false, +// }, +// "should be unequal if env var changes": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Spec.Containers[0].Env[0].Value = "new-value" +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// return defaultNATSPublisher.DeepCopy() +// }, +// expectedResult: false, +// }, +// "should be equal if replicas changes": { +// getPublisher1: func() *appsv1.Deployment { +// replicas := int32(1) +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Replicas = &replicas +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// replicas := int32(2) +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Replicas = &replicas +// return p +// }, +// expectedResult: true, +// }, +// "should be equal if replicas are the same": { +// getPublisher1: func() *appsv1.Deployment { +// replicas := int32(2) +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Replicas = &replicas +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// replicas := int32(2) +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Replicas = &replicas +// return p +// }, +// expectedResult: true, +// }, +// "should be equal if spec annotations are nil and empty": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Annotations = nil +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Annotations = map[string]string{} +// return p +// }, +// expectedResult: true, +// }, +// "should be unequal if spec annotations changes": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Annotations = map[string]string{"key": "value1"} +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Annotations = map[string]string{"key": "value2"} +// return p +// }, +// expectedResult: false, +// }, +// "should be equal if spec Labels are nil and empty": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Labels = nil +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Labels = map[string]string{} +// return p +// }, +// expectedResult: true, +// }, +// "should be unequal if spec Labels changes": { +// getPublisher1: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Labels = map[string]string{"key": "value1"} +// return p +// }, +// getPublisher2: func() *appsv1.Deployment { +// p := defaultNATSPublisher.DeepCopy() +// p.Spec.Template.Labels = map[string]string{"key": "value2"} +// return p +// }, +// expectedResult: false, +// }, +// } +// for name, tc := range testCases { +// t.Run(name, func(t *testing.T) { +// if publisherProxyDeploymentEqual(tc.getPublisher1(), tc.getPublisher2()) != tc.expectedResult { +// t.Errorf("expected output to be %t", tc.expectedResult) +// } +// }) +// } +//} func Test_ownerReferencesDeepEqual(t *testing.T) { ownerReference := func(version, kind, name, uid string, controller, block *bool) metav1.OwnerReference { diff --git a/pkg/subscriptionmanager/eventmesh/eventmesh.go b/pkg/subscriptionmanager/eventmesh/eventmesh.go index 772bfc43..60243ded 100644 --- a/pkg/subscriptionmanager/eventmesh/eventmesh.go +++ b/pkg/subscriptionmanager/eventmesh/eventmesh.go @@ -6,12 +6,14 @@ import ( "strings" "time" + "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/eventmesh" + "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" "github.com/kyma-project/eventing-manager/pkg/backend/metrics" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/pkg/errors" "go.uber.org/zap" @@ -25,7 +27,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/kyma-project/eventing-manager/internal/controller/subscription/eventmesh" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" backendeventmesh "github.com/kyma-project/eventing-manager/pkg/backend/eventmesh" "github.com/kyma-project/eventing-manager/pkg/backend/eventtype" "github.com/kyma-project/eventing-manager/pkg/backend/sink" @@ -33,7 +35,6 @@ import ( "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/logger" subscriptionmanager "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" ) const ( diff --git a/pkg/subscriptionmanager/eventmesh/eventmesh_test.go b/pkg/subscriptionmanager/eventmesh/eventmesh_test.go index 259a9256..20590027 100644 --- a/pkg/subscriptionmanager/eventmesh/eventmesh_test.go +++ b/pkg/subscriptionmanager/eventmesh/eventmesh_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/require" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" "k8s.io/client-go/dynamic" "sigs.k8s.io/controller-runtime/pkg/manager" diff --git a/pkg/subscriptionmanager/factory.go b/pkg/subscriptionmanager/factory.go index ba1db706..958988a1 100644 --- a/pkg/subscriptionmanager/factory.go +++ b/pkg/subscriptionmanager/factory.go @@ -6,7 +6,7 @@ import ( "github.com/kyma-project/eventing-manager/pkg/backend/metrics" "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/env" eclogger "github.com/kyma-project/eventing-manager/pkg/logger" "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/eventmesh" diff --git a/pkg/subscriptionmanager/jetstream/jetstream.go b/pkg/subscriptionmanager/jetstream/jetstream.go index 3ac015f1..878d63ca 100644 --- a/pkg/subscriptionmanager/jetstream/jetstream.go +++ b/pkg/subscriptionmanager/jetstream/jetstream.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/kyma-project/eventing-manager/internal/controller/eventing/subscription/jetstream" + manager2 "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" "github.com/kyma-project/eventing-manager/pkg/backend/sink" @@ -25,14 +27,13 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/manager" - "github.com/kyma-project/eventing-manager/internal/controller/subscription/jetstream" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/backend/eventtype" backendjetstream "github.com/kyma-project/eventing-manager/pkg/backend/jetstream" backendmetrics "github.com/kyma-project/eventing-manager/pkg/backend/metrics" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/logger" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) const ( diff --git a/pkg/subscriptionmanager/jetstream/jetstream_test.go b/pkg/subscriptionmanager/jetstream/jetstream_test.go index 0aaf6dc7..099a736a 100644 --- a/pkg/subscriptionmanager/jetstream/jetstream_test.go +++ b/pkg/subscriptionmanager/jetstream/jetstream_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" kymalogger "github.com/kyma-project/kyma/common/logging/logger" "github.com/nats-io/nats-server/v2/server" diff --git a/pkg/subscriptionmanager/mocks/ec/manager.go b/pkg/subscriptionmanager/mocks/ec/manager.go deleted file mode 100644 index 913f6b72..00000000 --- a/pkg/subscriptionmanager/mocks/ec/manager.go +++ /dev/null @@ -1,166 +0,0 @@ -// Code generated by mockery v2.30.16. DO NOT EDIT. - -package mocks - -import ( - env "github.com/kyma-project/kyma/components/eventing-controller/pkg/env" - manager "sigs.k8s.io/controller-runtime/pkg/manager" - - mock "github.com/stretchr/testify/mock" - - subscriptionmanager "github.com/kyma-project/kyma/components/eventing-controller/pkg/subscriptionmanager" -) - -// Manager is an autogenerated mock type for the Manager type -type Manager struct { - mock.Mock -} - -type Manager_Expecter struct { - mock *mock.Mock -} - -func (_m *Manager) EXPECT() *Manager_Expecter { - return &Manager_Expecter{mock: &_m.Mock} -} - -// Init provides a mock function with given fields: mgr -func (_m *Manager) Init(mgr manager.Manager) error { - ret := _m.Called(mgr) - - var r0 error - if rf, ok := ret.Get(0).(func(manager.Manager) error); ok { - r0 = rf(mgr) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Manager_Init_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Init' -type Manager_Init_Call struct { - *mock.Call -} - -// Init is a helper method to define mock.On call -// - mgr manager.Manager -func (_e *Manager_Expecter) Init(mgr interface{}) *Manager_Init_Call { - return &Manager_Init_Call{Call: _e.mock.On("Init", mgr)} -} - -func (_c *Manager_Init_Call) Run(run func(mgr manager.Manager)) *Manager_Init_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(manager.Manager)) - }) - return _c -} - -func (_c *Manager_Init_Call) Return(_a0 error) *Manager_Init_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Manager_Init_Call) RunAndReturn(run func(manager.Manager) error) *Manager_Init_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: defaultSubsConfig, params -func (_m *Manager) Start(defaultSubsConfig env.DefaultSubscriptionConfig, params subscriptionmanager.Params) error { - ret := _m.Called(defaultSubsConfig, params) - - var r0 error - if rf, ok := ret.Get(0).(func(env.DefaultSubscriptionConfig, subscriptionmanager.Params) error); ok { - r0 = rf(defaultSubsConfig, params) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Manager_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type Manager_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -// - defaultSubsConfig env.DefaultSubscriptionConfig -// - params subscriptionmanager.Params -func (_e *Manager_Expecter) Start(defaultSubsConfig interface{}, params interface{}) *Manager_Start_Call { - return &Manager_Start_Call{Call: _e.mock.On("Start", defaultSubsConfig, params)} -} - -func (_c *Manager_Start_Call) Run(run func(defaultSubsConfig env.DefaultSubscriptionConfig, params subscriptionmanager.Params)) *Manager_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(env.DefaultSubscriptionConfig), args[1].(subscriptionmanager.Params)) - }) - return _c -} - -func (_c *Manager_Start_Call) Return(_a0 error) *Manager_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Manager_Start_Call) RunAndReturn(run func(env.DefaultSubscriptionConfig, subscriptionmanager.Params) error) *Manager_Start_Call { - _c.Call.Return(run) - return _c -} - -// Stop provides a mock function with given fields: runCleanup -func (_m *Manager) Stop(runCleanup bool) error { - ret := _m.Called(runCleanup) - - var r0 error - if rf, ok := ret.Get(0).(func(bool) error); ok { - r0 = rf(runCleanup) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Manager_Stop_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Stop' -type Manager_Stop_Call struct { - *mock.Call -} - -// Stop is a helper method to define mock.On call -// - runCleanup bool -func (_e *Manager_Expecter) Stop(runCleanup interface{}) *Manager_Stop_Call { - return &Manager_Stop_Call{Call: _e.mock.On("Stop", runCleanup)} -} - -func (_c *Manager_Stop_Call) Run(run func(runCleanup bool)) *Manager_Stop_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(bool)) - }) - return _c -} - -func (_c *Manager_Stop_Call) Return(_a0 error) *Manager_Stop_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Manager_Stop_Call) RunAndReturn(run func(bool) error) *Manager_Stop_Call { - _c.Call.Return(run) - return _c -} - -// NewManager creates a new instance of Manager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewManager(t interface { - mock.TestingT - Cleanup(func()) -}) *Manager { - mock := &Manager{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/subscriptionmanager/mocks/manager_factory.go b/pkg/subscriptionmanager/mocks/manager_factory.go index 4477f8e7..1eb0e996 100644 --- a/pkg/subscriptionmanager/mocks/manager_factory.go +++ b/pkg/subscriptionmanager/mocks/manager_factory.go @@ -7,7 +7,7 @@ import ( manager "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" mock "github.com/stretchr/testify/mock" - v1alpha1 "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // ManagerFactory is an autogenerated mock type for the ManagerFactory type diff --git a/test/matchers/matchers.go b/test/matchers/matchers.go index 67de9ec5..c9f46741 100644 --- a/test/matchers/matchers.go +++ b/test/matchers/matchers.go @@ -1,8 +1,8 @@ package matchers import ( - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" - "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" + "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" "github.com/onsi/gomega" "github.com/onsi/gomega/gstruct" gomegatypes "github.com/onsi/gomega/types" diff --git a/test/utils/integration/integration.go b/test/utils/integration/integration.go index a5b5ea31..ed8c5135 100644 --- a/test/utils/integration/integration.go +++ b/test/utils/integration/integration.go @@ -11,7 +11,7 @@ import ( "testing" "time" - eventing2 "github.com/kyma-project/eventing-manager/internal/controller/operator.kyma-project.io/eventing" + eventing2 "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager" @@ -43,7 +43,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1" "github.com/kyma-project/nats-manager/testutils" admissionv1 "k8s.io/api/admissionregistration/v1" @@ -53,7 +53,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/kyma-project/eventing-manager/options" "github.com/kyma-project/eventing-manager/pkg/env" "github.com/kyma-project/eventing-manager/pkg/eventing" @@ -299,7 +299,6 @@ func StartEnvTest(config TestEnvironmentConfig) (*envtest.Environment, *rest.Con // define CRDs to include. includedCRDs := []string{ filepath.Join(config.ProjectRootDir, "config", "crd", "bases"), - filepath.Join(config.ProjectRootDir, "config", "crd", "external"), } if config.ApplicationRuleCRDEnabled { includedCRDs = append(includedCRDs, diff --git a/test/utils/options.go b/test/utils/options.go index ea9cca2d..20478109 100644 --- a/test/utils/options.go +++ b/test/utils/options.go @@ -1,7 +1,7 @@ package utils import ( - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/test/utils/utils.go b/test/utils/utils.go index 7f70223a..849c9f44 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -11,7 +11,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" - eventinv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" + eventinv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -20,7 +20,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "sigs.k8s.io/controller-runtime/pkg/client" - "github.com/kyma-project/eventing-manager/api/operator.kyma-project.io/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/testing/matchers.go b/testing/matchers.go index e2224f15..85fd00d4 100644 --- a/testing/matchers.go +++ b/testing/matchers.go @@ -13,34 +13,11 @@ import ( "k8s.io/apimachinery/pkg/types" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/constants" "github.com/kyma-project/eventing-manager/pkg/object" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" ) -// -// string matchers -// - -func HaveEventingBackendReady() gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) bool { - return *s.EventingReady - }, BeTrue()) -} - -func HaveEventingBackendNotReady() gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) bool { - return *s.EventingReady - }, BeFalse()) -} - -func HaveBackendType(backendType eventingv1alpha1.BackendType) gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) eventingv1alpha1.BackendType { - return s.Backend - }, Equal(backendType)) -} - // // APIRule matchers // @@ -114,20 +91,6 @@ func HaveAPIRuleOwnersRefs(uids ...types.UID) gomegatypes.GomegaMatcher { }, Equal(uids)) } -// -// Subscription matchers -// - -func HaveBackendCondition(condition eventingv1alpha1.Condition) gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) []eventingv1alpha1.Condition { - return s.Conditions - }, ContainElement(MatchFields(IgnoreExtras|IgnoreMissing, Fields{ - "Type": Equal(condition.Type), - "Reason": Equal(condition.Reason), - "Status": Equal(condition.Status), - }))) -} - // // int matchers // @@ -177,18 +140,6 @@ func HaveValidBEBNamespace(bebNamespaceKey, namespace string) gomegatypes.Gomega }, BeTrue()) } -func HaveNoBEBSecretNameAndNamespace() gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) bool { - return s.BEBSecretName == "" && s.BEBSecretNamespace == "" - }, BeTrue()) -} - -func HaveBEBSecretNameAndNamespace(bebSecretName, namespace string) gomegatypes.GomegaMatcher { - return WithTransform(func(s *eventingv1alpha1.EventingBackendStatus) bool { - return s.BEBSecretName == bebSecretName && s.BEBSecretNamespace == namespace - }, BeTrue()) -} - func HaveSubscriptionName(name string) gomegatypes.GomegaMatcher { return WithTransform(func(s *eventingv1alpha2.Subscription) string { return s.Name }, Equal(name)) } diff --git a/testing/test_helpers.go b/testing/test_helpers.go index bc62c389..f44576a1 100644 --- a/testing/test_helpers.go +++ b/testing/test_helpers.go @@ -9,8 +9,8 @@ import ( "k8s.io/client-go/dynamic" dynamicfake "k8s.io/client-go/dynamic/fake" + eventingv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" "github.com/kyma-project/eventing-manager/pkg/object" - eventingv1alpha2 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha2" apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" corev1 "k8s.io/api/core/v1" @@ -19,9 +19,9 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" "github.com/kyma-project/eventing-manager/pkg/ems/api/events/types" "github.com/kyma-project/eventing-manager/pkg/utils" - eventingv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" ) const ( @@ -257,17 +257,6 @@ func NewNamespace(name string) *corev1.Namespace { return &namespace } -func NewEventingBackend(name, namespace string) *eventingv1alpha1.EventingBackend { - return &eventingv1alpha1.EventingBackend{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: eventingv1alpha1.EventingBackendSpec{}, - Status: eventingv1alpha1.EventingBackendStatus{}, - } -} - func GetStructuredMessageHeaders() http.Header { return http.Header{"Content-Type": []string{"application/cloudevents+json"}} }