diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 7ab976fa..c9d3343d 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -7,11 +7,13 @@ env: on: pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" jobs: nats: @@ -59,7 +61,7 @@ jobs: - name: Setup and test the eventing-manager run: | - make e2e-setup + make e2e-setup - name: Setup eventing run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 02e1aadf..f884dc41 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,11 +2,13 @@ name: golangci-lint on: pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" permissions: contents: read @@ -19,7 +21,7 @@ jobs: steps: - uses: actions/setup-go@v4 with: - go-version: '1.21' + go-version: "1.21" cache: false - uses: actions/checkout@v4 - name: golangci-lint diff --git a/.github/workflows/sink.yml b/.github/workflows/sink.yml index 28105645..5fbb74bb 100644 --- a/.github/workflows/sink.yml +++ b/.github/workflows/sink.yml @@ -10,17 +10,19 @@ env: on: push: branches: - - main - tags: [ '*.*.*' ] + - main + - "release-*" + tags: ["*.*.*"] paths: - - 'hack/e2e/sink/**' - - '.github/workflows/sink.yml' + - "hack/e2e/sink/**" + - ".github/workflows/sink.yml" pull_request: branches: - - main + - main + - "release-*" paths: - - 'hack/e2e/sink/**' - - '.github/workflows/sink.yml' + - "hack/e2e/sink/**" + - ".github/workflows/sink.yml" jobs: build: @@ -32,51 +34,51 @@ jobs: working-directory: ${{ env.E2E_SINK_DIR }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: 1.19 - cache: true + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: 1.19 + cache: true - - name: Build - run: go build -v ./... + - name: Build + run: go build -v ./... - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - # Login against a Docker registry except on PR - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - # if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + # if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract Docker metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=sha - type=semver,pattern={{version}},event=tag - labels: | - org.opencontainers.image.title=E2E Tests Sink - org.opencontainers.image.description=A webserver imitating an eventing sink that receives events and stores in memory - org.opencontainers.image.url=https://github.com/kyma-project/eventing-manager/${{ env.E2E_SINK_DIR }} + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=sha + type=semver,pattern={{version}},event=tag + labels: | + org.opencontainers.image.title=E2E Tests Sink + org.opencontainers.image.description=A webserver imitating an eventing sink that receives events and stores in memory + org.opencontainers.image.url=https://github.com/kyma-project/eventing-manager/${{ env.E2E_SINK_DIR }} - - name: Build Docker image - id: build-and-push - uses: docker/build-push-action@v5 - with: - context: ${{ env.E2E_SINK_DIR }} - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - load: ${{ github.event_name == 'pull_request' }} - cache-from: type=gha - cache-to: type=gha,mode=max + - name: Build Docker image + id: build-and-push + uses: docker/build-push-action@v5 + with: + context: ${{ env.E2E_SINK_DIR }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + load: ${{ github.event_name == 'pull_request' }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a706597e..df589a44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,17 +6,21 @@ env: on: push: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths-ignore: - - 'docs/**' - - '**.md' - - 'sec-scanners-config.yaml' + - "docs/**" + - "**.md" + - "sec-scanners-config.yaml" jobs: unit: @@ -26,7 +30,7 @@ jobs: uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: - go-version: '1.21' + go-version: "1.21" cache: false - name: Sync GO dependencies run: | diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 6243ffa0..db16acbf 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -6,15 +6,19 @@ env: on: push: - branches: [ "main" ] + branches: + - main + - "release-*" paths: - - 'api/**' - - 'config/crd/**' + - "api/**" + - "config/crd/**" pull_request: - branches: [ "main" ] + branches: + - main + - "release-*" paths: - - 'api/**' - - 'config/crd/**' + - "api/**" + - "config/crd/**" jobs: crd: diff --git a/.version b/.version index 8759f86b..0eb00612 100644 --- a/.version +++ b/.version @@ -1,2 +1,2 @@ # next version to be released -MODULE_VERSION=1.0.1 +MODULE_VERSION=1.0.2 diff --git a/Dockerfile b/Dockerfile index dd11fe28..61c8d74b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,7 @@ RUN go mod download COPY cmd/main.go cmd/main.go COPY api/ api/ COPY internal/controller/ internal/controller/ +COPY internal/label/ internal/label/ COPY pkg/ pkg/ COPY testing/ testing/ COPY options/ options/ 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 a0826064..172a089f 100644 --- a/PROJECT +++ b/PROJECT @@ -5,6 +5,7 @@ domain: kyma-project.io layout: - go.kubebuilder.io/v4 +multigroup: true projectName: eventing-manager repo: github.com/kyma-project/eventing-manager resources: @@ -15,6 +16,31 @@ resources: domain: kyma-project.io group: operator kind: Eventing - path: github.com/kyma-project/eventing-manager/api/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/v1alpha1/eventing_types.go b/api/operator/v1alpha1/eventing_types.go similarity index 100% rename from api/v1alpha1/eventing_types.go rename to api/operator/v1alpha1/eventing_types.go diff --git a/api/v1alpha1/eventing_types_test.go b/api/operator/v1alpha1/eventing_types_test.go similarity index 100% rename from api/v1alpha1/eventing_types_test.go rename to api/operator/v1alpha1/eventing_types_test.go diff --git a/api/v1alpha1/groupversion_info.go b/api/operator/v1alpha1/groupversion_info.go similarity index 100% rename from api/v1alpha1/groupversion_info.go rename to api/operator/v1alpha1/groupversion_info.go diff --git a/api/v1alpha1/status.go b/api/operator/v1alpha1/status.go similarity index 100% rename from api/v1alpha1/status.go rename to api/operator/v1alpha1/status.go diff --git a/api/v1alpha1/status_test.go b/api/operator/v1alpha1/status_test.go similarity index 100% rename from api/v1alpha1/status_test.go rename to api/operator/v1alpha1/status_test.go diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/operator/v1alpha1/zz_generated.deepcopy.go similarity index 100% rename from api/v1alpha1/zz_generated.deepcopy.go rename to api/operator/v1alpha1/zz_generated.deepcopy.go diff --git a/cmd/main.go b/cmd/main.go index d289baa0..9dfbdd77 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -22,25 +22,24 @@ import ( "log" "os" - 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" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" - - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/eventing" + apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" + subscriptionv1alpha1 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha1" + subscriptionv1alpha2 "github.com/kyma-project/eventing-manager/api/eventing/v1alpha2" + controllercache "github.com/kyma-project/eventing-manager/internal/controller/cache" + controllerclient "github.com/kyma-project/eventing-manager/internal/controller/client" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" "github.com/kyma-project/eventing-manager/options" 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/eventing" + istiopeerauthentication "github.com/kyma-project/eventing-manager/pkg/istio/peerauthentication" "github.com/kyma-project/eventing-manager/pkg/k8s" "github.com/kyma-project/eventing-manager/pkg/logger" "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager" @@ -57,7 +56,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/v1alpha1" + eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" //+kubebuilder:scaffold:imports ) @@ -77,6 +76,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 } @@ -122,6 +123,8 @@ func main() { //nolint:funlen // main function needs to initialize many object WebhookServer: webhook.NewServer(webhook.Options{Port: 9443}), Cache: cache.Options{SyncPeriod: &opts.ReconcilePeriod}, Metrics: server.Options{BindAddress: opts.MetricsAddr}, + NewCache: controllercache.New, + NewClient: controllerclient.New, }) if err != nil { setupLog.Error(err, "unable to start manager") 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/default/kustomization.yaml b/config/default/kustomization.yaml index 67c5a254..01a91ee9 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -9,10 +9,16 @@ namespace: kyma-system #namePrefix: eventing- # Labels to add to all resources and selectors. -#labels: -#- includeSelectors: true -# pairs: -# someName: someValue +labels: + - includeSelectors: false + pairs: + app.kubernetes.io/component: eventing-manager + app.kubernetes.io/created-by: eventing-manager + app.kubernetes.io/instance: eventing-manager + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: eventing-manager + app.kubernetes.io/part-of: Kyma + control-plane: eventing-manager resources: - ../crd 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/ui-extensions/eventing/kustomization.yaml b/config/ui-extensions/eventing/kustomization.yaml index a5f043f8..9175e1a1 100644 --- a/config/ui-extensions/eventing/kustomization.yaml +++ b/config/ui-extensions/eventing/kustomization.yaml @@ -9,6 +9,7 @@ configMapGenerator: options: disableNameSuffixHash: true labels: + app.kubernetes.io/created-by: eventing-manager app.kubernetes.io/name: eventings.operator.kyma-project.io busola.io/extension: resource busola.io/extension-version: "0.5" diff --git a/config/ui-extensions/subscriptions/subscriptions.yaml b/config/ui-extensions/subscriptions/subscriptions.yaml index f0bb09d5..2ac13b62 100644 --- a/config/ui-extensions/subscriptions/subscriptions.yaml +++ b/config/ui-extensions/subscriptions/subscriptions.yaml @@ -4,6 +4,7 @@ metadata: name: subscriptions namespace: kube-public labels: + app.kubernetes.io/created-by: eventing-manager app.kubernetes.io/name: subscriptions busola.io/extension: resource busola.io/extension-version: '0.5' 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/docs/user/resources/_sidebar.md b/docs/user/resources/_sidebar.md new file mode 100644 index 00000000..60cea1af --- /dev/null +++ b/docs/user/resources/_sidebar.md @@ -0,0 +1,3 @@ +- [Eventing module](../README.md) +- Resources + - [Subscription](evnt-cr-subscription.md) \ No newline at end of file diff --git a/go.mod b/go.mod index 8fb47e9f..dc4b9e0e 100644 --- a/go.mod +++ b/go.mod @@ -7,33 +7,32 @@ require ( github.com/cloudevents/sdk-go/protocol/nats/v2 v2.14.0 github.com/cloudevents/sdk-go/v2 v2.14.0 github.com/go-logr/logr v1.3.0 - github.com/go-logr/zapr v1.2.4 - github.com/google/uuid v1.4.0 + github.com/go-logr/zapr v1.3.0 + github.com/google/uuid v1.5.0 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.2 + github.com/kyma-project/kyma/common/logging v0.0.0-20231213062924-40b7754f6246 + 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 + github.com/nats-io/nats-server/v2 v2.10.7 github.com/nats-io/nats.go v1.31.0 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.30.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/stretchr/testify v1.8.4 - github.com/vektra/mockery/v2 v2.36.1 + github.com/vektra/mockery/v2 v2.38.0 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/oauth2 v0.14.0 + golang.org/x/oauth2 v0.15.0 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 - istio.io/api v1.20.0-rc.0 - istio.io/client-go v1.20.0-rc.0 - k8s.io/api v0.28.3 + istio.io/api v1.20.1 + istio.io/client-go v1.20.1 + k8s.io/api v0.28.4 k8s.io/apiextensions-apiserver v0.28.3 - k8s.io/apimachinery v0.28.3 - k8s.io/client-go v0.28.3 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/apimachinery v0.28.4 + k8s.io/client-go v0.28.4 + k8s.io/utils v0.0.0-20231127182322-b307cd553661 sigs.k8s.io/controller-runtime v0.16.3 ) @@ -63,7 +62,7 @@ require ( github.com/jinzhu/copier v0.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.17.2 // indirect + github.com/klauspost/compress v1.17.4 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -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 @@ -94,15 +94,15 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.15.0 // indirect + golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.18.0 // indirect - golang.org/x/sys v0.14.0 // indirect - golang.org/x/term v0.14.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.4.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/time v0.5.0 // indirect + golang.org/x/tools v0.14.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect @@ -118,7 +118,7 @@ require ( k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace github.com/kyma-incubator/api-gateway => github.com/kyma-project/api-gateway v0.0.0-20220819093753-296e6704d413 diff --git a/go.sum b/go.sum index c4224e73..dc6d820e 100644 --- a/go.sum +++ b/go.sum @@ -40,7 +40,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/avast/retry-go/v3 v3.1.1 h1:49Scxf4v8PmiQ/nY0aY3p0hDueqSmc7++cBbtiDGu2g= github.com/avast/retry-go/v3 v3.1.1/go.mod h1:6cXRK369RpzFL3UQGqIUp9Q7GDrams+KsYWrfNA1/nQ= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -89,11 +88,10 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= @@ -174,8 +172,8 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJY github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= @@ -207,8 +205,8 @@ github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dv github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -220,14 +218,10 @@ 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.2 h1:uJiVrLFFqnOsnz1IGNn76fm5cQoK+4L8GxP829mX2C8= -github.com/kyma-project/nats-manager v1.0.2/go.mod h1:gC0W/C2NgpmVnG/5v5f76ijNw5aloQLEkSuVOElB9gk= +github.com/kyma-project/kyma/common/logging v0.0.0-20231213062924-40b7754f6246 h1:BxMd3yY1znt2dCG1fiWw2UqQKKMwzRI7MQ/yqqq5L9s= +github.com/kyma-project/kyma/common/logging v0.0.0-20231213062924-40b7754f6246/go.mod h1:JGb5RBi8Uz+RZ/jf54+qA+RqY6uPQBJ8pO1w3KSwm1Q= +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= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -258,8 +252,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nats-io/jwt/v2 v2.5.3 h1:/9SWvzc6hTfamcgXJ3uYRpgj+QuY2aLNqRiqrKcrpEo= github.com/nats-io/jwt/v2 v2.5.3/go.mod h1:iysuPemFcc7p4IoYots3IuELSI4EDe9Y0bQMe+I3Bf4= -github.com/nats-io/nats-server/v2 v2.10.5 h1:hhWt6m9ja/mNnm6ixc85jCthDaiUFPaeJI79K/MD980= -github.com/nats-io/nats-server/v2 v2.10.5/go.mod h1:xUMTU4kS//SDkJCSvFwN9SyJ9nUuLhSkzB/Qz0dvjjg= +github.com/nats-io/nats-server/v2 v2.10.7 h1:f5VDy+GMu7JyuFA0Fef+6TfulfCs5nBTgq7MMkFJx5Y= +github.com/nats-io/nats-server/v2 v2.10.7/go.mod h1:V2JHOvPiPdtfDXTuEUsthUnCvSDeFrK4Xn9hRo6du7c= github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= @@ -273,8 +267,8 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= -github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU= +github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= @@ -333,13 +327,12 @@ github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8 github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/vektra/mockery/v2 v2.36.1 h1:F/2tEFFRWdHe36smr+e6YIiKzXTZVd0cCAUqG0GTw1s= -github.com/vektra/mockery/v2 v2.36.1/go.mod h1:diB13hxXG6QrTR0ol2Rk8s2dRMftzvExSvPDKr+IYKk= +github.com/vektra/mockery/v2 v2.38.0 h1:I0LBuUzZHqAU4d1DknW0DTFBPO6n8TaD38WL2KJf3yI= +github.com/vektra/mockery/v2 v2.38.0/go.mod h1:diB13hxXG6QrTR0ol2Rk8s2dRMftzvExSvPDKr+IYKk= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= @@ -347,16 +340,12 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -367,8 +356,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= -golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -404,10 +393,9 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -441,10 +429,9 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -454,8 +441,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= -golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -466,10 +453,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -508,9 +494,7 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -518,12 +502,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= -golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -537,8 +521,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= -golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -589,10 +573,9 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -727,26 +710,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -istio.io/api v1.20.0-rc.0 h1:iRe7ZSS98bCKqXPZLkc0nYbTZefs69VjdDppR865Fsg= -istio.io/api v1.20.0-rc.0/go.mod h1:hm1PE/mGdIAsjCDkTIAplP53H7TjO5LUQCiVvF26SVg= -istio.io/client-go v1.20.0-rc.0 h1:Dm2YNG/RBFnuMpfQGEPEp6bVTPFKxWlDYVSsuR15tSs= -istio.io/client-go v1.20.0-rc.0/go.mod h1:6D76gZsdjz8JtVeIarUYdOn3WA8Zh+j8fIv2+2K3M+Q= -k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= -k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= +istio.io/api v1.20.1 h1:Itku+LK5FwNzkKJY+5BGRCTRimVA5gShwFXdNNXtAHk= +istio.io/api v1.20.1/go.mod h1:hm1PE/mGdIAsjCDkTIAplP53H7TjO5LUQCiVvF26SVg= +istio.io/client-go v1.20.1 h1:0kObqt2b6mJ1lM+PEOWQ9/MQbhJFMBZ2K7krAz/Qrto= +istio.io/client-go v1.20.1/go.mod h1:5Je53KEbCFhBedeu1wIf02ekK2v7bAQEAfR9e0/u1LI= +k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= +k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= -k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= -k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= -k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= -k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= +k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= +k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= +k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= +k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= k8s.io/component-base v0.28.3 h1:rDy68eHKxq/80RiMb2Ld/tbH8uAE75JdCqJyi6lXMzI= k8s.io/component-base v0.28.3/go.mod h1:fDJ6vpVNSk6cRo5wmDa6eKIG7UlIQkaFmZN2fYgIUD8= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20231127182322-b307cd553661 h1:FepOBzJ0GXm8t0su67ln2wAZjbQ6RxQGZDnzuLcrUTI= +k8s.io/utils v0.0.0-20231127182322-b307cd553661/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -756,5 +739,5 @@ sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMm sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/hack/e2e/cleanup/cleanup_test.go b/hack/e2e/cleanup/cleanup_test.go index 779ce23b..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/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 c520920e..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/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 e25be2a3..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/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 508abff5..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/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 bc1d05d3..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/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 d30387a4..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/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/cache/cache.go b/internal/controller/cache/cache.go new file mode 100644 index 00000000..3a6ef1f1 --- /dev/null +++ b/internal/controller/cache/cache.go @@ -0,0 +1,36 @@ +package cache + +import ( + appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/kyma-project/eventing-manager/internal/label" +) + +func New(config *rest.Config, options cache.Options) (cache.Cache, error) { + return cache.New(config, applySelectors(options)) +} + +// applySelectors applies label selectors to runtime objects created by the EventingManager. +func applySelectors(options cache.Options) cache.Options { + // TODO(marcobebway) filter by label "app.kubernetes.io/created-by=eventing-manager" when it is released + instanceEventing := fromLabelSelector(label.SelectorInstanceEventing()) + options.ByObject = map[client.Object]cache.ByObject{ + &appsv1.Deployment{}: instanceEventing, + &corev1.ServiceAccount{}: instanceEventing, + &rbacv1.ClusterRole{}: instanceEventing, + &rbacv1.ClusterRoleBinding{}: instanceEventing, + &autoscalingv1.HorizontalPodAutoscaler{}: instanceEventing, + } + return options +} + +func fromLabelSelector(selector labels.Selector) cache.ByObject { + return cache.ByObject{Label: selector} +} diff --git a/internal/controller/cache/cache_test.go b/internal/controller/cache/cache_test.go new file mode 100644 index 00000000..0e921241 --- /dev/null +++ b/internal/controller/cache/cache_test.go @@ -0,0 +1,134 @@ +package cache + +import ( + "fmt" + "reflect" + "testing" + + "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" + autoscalingv1 "k8s.io/api/autoscaling/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + "k8s.io/apimachinery/pkg/labels" + "sigs.k8s.io/controller-runtime/pkg/cache" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func Test_applySelectors(t *testing.T) { + // given + selector := cache.ByObject{ + Label: labels.SelectorFromSet( + map[string]string{ + "app.kubernetes.io/instance": "eventing", + }, + ), + } + type args struct { + options cache.Options + } + tests := []struct { + name string + args args + want cache.Options + }{ + { + name: "should apply the correct selectors", + args: args{ + options: cache.Options{}, + }, + want: cache.Options{ + ByObject: map[client.Object]cache.ByObject{ + &appsv1.Deployment{}: selector, + &corev1.ServiceAccount{}: selector, + &rbacv1.ClusterRole{}: selector, + &rbacv1.ClusterRoleBinding{}: selector, + &autoscalingv1.HorizontalPodAutoscaler{}: selector, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := applySelectors(tt.args.options) + + // then + require.True(t, deepEqualOptions(tt.want, got)) + }) + } +} + +func deepEqualOptions(a, b cache.Options) bool { + // we only care about the ByObject comparison + return deepEqualByObject(a.ByObject, b.ByObject) +} + +func deepEqualByObject(a, b map[client.Object]cache.ByObject) bool { + if len(a) != len(b) { + return false + } + + aTypeMap := make(map[string]cache.ByObject, len(a)) + bTypeMap := make(map[string]cache.ByObject, len(a)) + computeTypeMap(a, aTypeMap) + computeTypeMap(b, bTypeMap) + return reflect.DeepEqual(aTypeMap, bTypeMap) +} + +func computeTypeMap(byObjectMap map[client.Object]cache.ByObject, typeMap map[string]cache.ByObject) { + keyOf := func(i interface{}) string { return fmt.Sprintf(">>> %T", i) } + for k, v := range byObjectMap { + if obj, ok := k.(*appsv1.Deployment); ok { + key := keyOf(obj) + typeMap[key] = v + } + if obj, ok := k.(*corev1.ServiceAccount); ok { + key := keyOf(obj) + typeMap[key] = v + } + if obj, ok := k.(*rbacv1.ClusterRole); ok { + key := keyOf(obj) + typeMap[key] = v + } + if obj, ok := k.(*rbacv1.ClusterRoleBinding); ok { + key := keyOf(obj) + typeMap[key] = v + } + if obj, ok := k.(*autoscalingv1.HorizontalPodAutoscaler); ok { + key := keyOf(obj) + typeMap[key] = v + } + } +} + +func Test_fromLabelSelector(t *testing.T) { + // given + type args struct { + label labels.Selector + } + tests := []struct { + name string + args args + want cache.ByObject + }{ + { + name: "should return the correct selector", + args: args{ + label: labels.SelectorFromSet(map[string]string{"key": "value"}), + }, + want: cache.ByObject{ + Label: labels.SelectorFromSet(map[string]string{"key": "value"}), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := fromLabelSelector(tt.args.label) + + // then + require.Equal(t, tt.want, got) + }) + } +} diff --git a/internal/controller/client/client.go b/internal/controller/client/client.go new file mode 100644 index 00000000..861c204c --- /dev/null +++ b/internal/controller/client/client.go @@ -0,0 +1,23 @@ +package client + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func New(config *rest.Config, options client.Options) (client.Client, error) { + return client.New(config, disableCacheForObjects(options)) +} + +// disableCacheForObjects disables caching for runtime objects that are not created by the EventingManager. +func disableCacheForObjects(options client.Options) client.Options { + options.Cache = &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.Secret{}, + &corev1.Service{}, + &corev1.ConfigMap{}, + }, + } + return options +} diff --git a/internal/controller/client/client_test.go b/internal/controller/client/client_test.go new file mode 100644 index 00000000..84e7eec6 --- /dev/null +++ b/internal/controller/client/client_test.go @@ -0,0 +1,92 @@ +package client + +import ( + "fmt" + "reflect" + "testing" + + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func Test_disableCacheForObjects(t *testing.T) { + // given + type args struct { + options client.Options + } + tests := []struct { + name string + args args + want client.Options + }{ + { + name: "should disable cache for the correct objects", + args: args{ + options: client.Options{}, + }, + want: client.Options{ + Cache: &client.CacheOptions{ + DisableFor: []client.Object{ + &corev1.Secret{}, + &corev1.Service{}, + &corev1.ConfigMap{}, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := disableCacheForObjects(tt.args.options) + + // then + require.True(t, deepEqualOptions(tt.want, got)) + }) + } +} + +func deepEqualOptions(a, b client.Options) bool { + // we only care about the Cache comparison + return deepEqualCacheOptions(a.Cache, b.Cache) +} + +func deepEqualCacheOptions(a, b *client.CacheOptions) bool { + if a == b { + return true + } + + if a == nil || b == nil { + return false + } + + // we only care about the DisableFor comparison + if len(a.DisableFor) != len(b.DisableFor) { + return false + } + + aTypeMap := make(map[string]interface{}, len(a.DisableFor)) + bTypeMap := make(map[string]interface{}, len(a.DisableFor)) + computeDisableForMap(a, aTypeMap) + computeDisableForMap(b, bTypeMap) + return reflect.DeepEqual(aTypeMap, bTypeMap) +} + +func computeDisableForMap(cacheOptions *client.CacheOptions, disableForMap map[string]interface{}) { + keyOf := func(i interface{}) string { return fmt.Sprintf(">>> %T", i) } + for _, obj := range cacheOptions.DisableFor { + if obj, ok := obj.(*corev1.Secret); ok { + key := keyOf(obj) + disableForMap[key] = nil + } + if obj, ok := obj.(*corev1.Service); ok { + key := keyOf(obj) + disableForMap[key] = nil + } + if obj, ok := obj.(*corev1.ConfigMap); ok { + key := keyOf(obj) + disableForMap[key] = nil + } + } +} 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/eventing/controller.go b/internal/controller/operator/eventing/controller.go similarity index 98% rename from internal/controller/eventing/controller.go rename to internal/controller/operator/eventing/controller.go index b87908e1..286031ac 100644 --- a/internal/controller/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/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" @@ -61,7 +61,6 @@ const ( NatsServerNotAvailableMsg = "NATS server is not available" natsClientPort = 4222 - AppLabelValue = eventing.PublisherName PublisherSecretEMSHostKey = "ems-publish-host" TokenEndpointFormat = "%s?grant_type=%s&response_type=token" @@ -74,8 +73,8 @@ const ( // Reconciler reconciles an Eventing object // -//go:generate go run github.com/vektra/mockery/v2 --name=Controller --dir=../../../vendor/sigs.k8s.io/controller-runtime/pkg/controller --outpkg=mocks --case=underscore -//go:generate go run github.com/vektra/mockery/v2 --name=Manager --dir=../../../vendor/sigs.k8s.io/controller-runtime/pkg/manager --outpkg=mocks --case=underscore +//go:generate go run github.com/vektra/mockery/v2 --name=Controller --dir=../../../../vendor/sigs.k8s.io/controller-runtime/pkg/controller --outpkg=mocks --case=underscore +//go:generate go run github.com/vektra/mockery/v2 --name=Manager --dir=../../../../vendor/sigs.k8s.io/controller-runtime/pkg/manager --outpkg=mocks --case=underscore type Reconciler struct { client.Client logger *logger.Logger diff --git a/internal/controller/eventing/controller_test.go b/internal/controller/operator/eventing/controller_test.go similarity index 99% rename from internal/controller/eventing/controller_test.go rename to internal/controller/operator/eventing/controller_test.go index fe41b8d2..1955da7d 100644 --- a/internal/controller/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/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/eventing/domain.go b/internal/controller/operator/eventing/domain.go similarity index 100% rename from internal/controller/eventing/domain.go rename to internal/controller/operator/eventing/domain.go diff --git a/internal/controller/eventing/domain_test.go b/internal/controller/operator/eventing/domain_test.go similarity index 100% rename from internal/controller/eventing/domain_test.go rename to internal/controller/operator/eventing/domain_test.go diff --git a/internal/controller/eventing/eventmesh.go b/internal/controller/operator/eventing/eventmesh.go similarity index 98% rename from internal/controller/eventing/eventmesh.go rename to internal/controller/operator/eventing/eventmesh.go index 8b11802d..d84440a0 100644 --- a/internal/controller/eventing/eventmesh.go +++ b/internal/controller/operator/eventing/eventmesh.go @@ -14,7 +14,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/kyma-project/eventing-manager/api/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" subscriptionmanager "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" @@ -297,7 +298,7 @@ func getSecretForPublisher(eventMeshSecret *corev1.Secret) (*corev1.Secret, erro secret := newSecret(eventing.PublisherName, eventMeshSecret.Namespace) secret.Labels = map[string]string{ - eventing.AppLabelKey: AppLabelValue, + label.KeyName: label.ValueEventingPublisherProxy, } if _, ok := eventMeshSecret.Data["messaging"]; !ok { diff --git a/internal/controller/eventing/eventmesh_test.go b/internal/controller/operator/eventing/eventmesh_test.go similarity index 99% rename from internal/controller/eventing/eventmesh_test.go rename to internal/controller/operator/eventing/eventmesh_test.go index ac890e0f..2a82354f 100644 --- a/internal/controller/eventing/eventmesh_test.go +++ b/internal/controller/operator/eventing/eventmesh_test.go @@ -7,7 +7,7 @@ import ( "github.com/kyma-project/eventing-manager/pkg/eventing" - "github.com/kyma-project/eventing-manager/api/v1alpha1" + "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" @@ -19,6 +19,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "github.com/kyma-project/eventing-manager/internal/label" "github.com/kyma-project/eventing-manager/pkg/env" managermocks "github.com/kyma-project/eventing-manager/pkg/eventing/mocks" "github.com/kyma-project/eventing-manager/pkg/logger" @@ -628,7 +629,7 @@ func Test_GetSecretForPublisher(t *testing.T) { Name: eventing.PublisherName, Namespace: "test-namespace", Labels: map[string]string{ - eventing.AppLabelKey: eventing.PublisherName, + label.KeyName: label.ValueEventingPublisherProxy, }, }, StringData: map[string]string{ diff --git a/internal/controller/eventing/integrationtests/controller/integration_test.go b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go similarity index 99% rename from internal/controller/eventing/integrationtests/controller/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controller/integration_test.go index 21eb17dc..489f9500 100644 --- a/internal/controller/eventing/integrationtests/controller/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller/integration_test.go @@ -7,6 +7,8 @@ import ( "os" "testing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" + "github.com/onsi/gomega" gomegatypes "github.com/onsi/gomega/types" "github.com/stretchr/testify/require" @@ -15,12 +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/v1alpha1" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/eventing" + 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" @@ -29,7 +30,7 @@ import ( ) const ( - projectRootDir = "../../../../../" + projectRootDir = "../../../../../../" eventTypePrefix = "test-prefix" ) diff --git a/internal/controller/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/eventing/integrationtests/controller_switching/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controller_switching/integration_test.go index 6cebfc2a..9786283a 100644 --- a/internal/controller/eventing/integrationtests/controller_switching/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/controller_switching/integration_test.go @@ -5,8 +5,9 @@ import ( "os" "testing" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/v1alpha1" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/eventing" + eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing" + + 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" @@ -20,7 +21,7 @@ import ( ) const ( - projectRootDir = "../../../../../" + projectRootDir = "../../../../../../" ) var testEnvironment *testutils.TestEnvironment //nolint:gochecknoglobals // used in tests diff --git a/internal/controller/eventing/integrationtests/controllersinglecr/integration_test.go b/internal/controller/operator/eventing/integrationtests/controllersinglecr/integration_test.go similarity index 98% rename from internal/controller/eventing/integrationtests/controllersinglecr/integration_test.go rename to internal/controller/operator/eventing/integrationtests/controllersinglecr/integration_test.go index c0c2e38e..b82d1528 100644 --- a/internal/controller/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/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" @@ -17,7 +17,7 @@ import ( ) const ( - projectRootDir = "../../../../../" + projectRootDir = "../../../../../../" ) var testEnvironment *integrationutils.TestEnvironment //nolint:gochecknoglobals // used in tests diff --git a/internal/controller/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/eventing/integrationtests/nats_disabled/integration_test.go rename to internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go index 34900aed..ff62eb80 100644 --- a/internal/controller/eventing/integrationtests/nats_disabled/integration_test.go +++ b/internal/controller/operator/eventing/integrationtests/nats_disabled/integration_test.go @@ -5,14 +5,15 @@ import ( "os" "testing" - eventingcontroller "github.com/kyma-project/eventing-manager/internal/controller/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" "github.com/kyma-project/eventing-manager/test/utils" natstestutils "github.com/kyma-project/nats-manager/testutils" "github.com/onsi/gomega" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/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" @@ -20,7 +21,7 @@ import ( ) const ( - projectRootDir = "../../../../../" + projectRootDir = "../../../../../../" ) var testEnvironment *testutils.TestEnvironment //nolint:gochecknoglobals // used in tests diff --git a/internal/controller/eventing/integrationtests/validation/integration_test.go b/internal/controller/operator/eventing/integrationtests/validation/integration_test.go similarity index 99% rename from internal/controller/eventing/integrationtests/validation/integration_test.go rename to internal/controller/operator/eventing/integrationtests/validation/integration_test.go index 30eb069e..5e010e59 100644 --- a/internal/controller/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/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" @@ -18,7 +18,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -const projectRootDir = "../../../../../" +const projectRootDir = "../../../../../../" const noError = "" diff --git a/internal/controller/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/eventing/integrationtests/without_apirule_crd/integration_test.go rename to internal/controller/operator/eventing/integrationtests/without_apirule_crd/integration_test.go index 15df3e46..fbbf4fd6 100644 --- a/internal/controller/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/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" @@ -13,7 +13,7 @@ import ( ) const ( - projectRootDir = "../../../../../" + projectRootDir = "../../../../../../" ) var testEnvironment *testutils.TestEnvironment //nolint:gochecknoglobals // used in tests diff --git a/internal/controller/eventing/mocks/controller.go b/internal/controller/operator/eventing/mocks/controller.go similarity index 95% rename from internal/controller/eventing/mocks/controller.go rename to internal/controller/operator/eventing/mocks/controller.go index 62573857..ecb91c2e 100644 --- a/internal/controller/eventing/mocks/controller.go +++ b/internal/controller/operator/eventing/mocks/controller.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -35,6 +35,10 @@ func (_m *Controller) EXPECT() *Controller_Expecter { func (_m *Controller) GetLogger() logr.Logger { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetLogger") + } + var r0 logr.Logger if rf, ok := ret.Get(0).(func() logr.Logger); ok { r0 = rf() @@ -76,6 +80,10 @@ func (_c *Controller_GetLogger_Call) RunAndReturn(run func() logr.Logger) *Contr func (_m *Controller) Reconcile(_a0 context.Context, _a1 reconcile.Request) (reconcile.Result, error) { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for Reconcile") + } + var r0 reconcile.Result var r1 error if rf, ok := ret.Get(0).(func(context.Context, reconcile.Request) (reconcile.Result, error)); ok { @@ -129,6 +137,10 @@ func (_c *Controller_Reconcile_Call) RunAndReturn(run func(context.Context, reco func (_m *Controller) Start(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) @@ -178,6 +190,10 @@ func (_m *Controller) Watch(src source.Source, eventhandler handler.EventHandler _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Watch") + } + var r0 error if rf, ok := ret.Get(0).(func(source.Source, handler.EventHandler, ...predicate.Predicate) error); ok { r0 = rf(src, eventhandler, predicates...) diff --git a/internal/controller/eventing/mocks/manager.go b/internal/controller/operator/eventing/mocks/manager.go similarity index 93% rename from internal/controller/eventing/mocks/manager.go rename to internal/controller/operator/eventing/mocks/manager.go index dc7b9157..12739e00 100644 --- a/internal/controller/eventing/mocks/manager.go +++ b/internal/controller/operator/eventing/mocks/manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -48,6 +48,10 @@ func (_m *Manager) EXPECT() *Manager_Expecter { func (_m *Manager) Add(_a0 manager.Runnable) error { ret := _m.Called(_a0) + if len(ret) == 0 { + panic("no return value specified for Add") + } + var r0 error if rf, ok := ret.Get(0).(func(manager.Runnable) error); ok { r0 = rf(_a0) @@ -90,6 +94,10 @@ func (_c *Manager_Add_Call) RunAndReturn(run func(manager.Runnable) error) *Mana func (_m *Manager) AddHealthzCheck(name string, check healthz.Checker) error { ret := _m.Called(name, check) + if len(ret) == 0 { + panic("no return value specified for AddHealthzCheck") + } + var r0 error if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { r0 = rf(name, check) @@ -133,6 +141,10 @@ func (_c *Manager_AddHealthzCheck_Call) RunAndReturn(run func(string, healthz.Ch func (_m *Manager) AddReadyzCheck(name string, check healthz.Checker) error { ret := _m.Called(name, check) + if len(ret) == 0 { + panic("no return value specified for AddReadyzCheck") + } + var r0 error if rf, ok := ret.Get(0).(func(string, healthz.Checker) error); ok { r0 = rf(name, check) @@ -176,6 +188,10 @@ func (_c *Manager_AddReadyzCheck_Call) RunAndReturn(run func(string, healthz.Che func (_m *Manager) Elected() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for Elected") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -219,6 +235,10 @@ func (_c *Manager_Elected_Call) RunAndReturn(run func() <-chan struct{}) *Manage func (_m *Manager) GetAPIReader() client.Reader { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetAPIReader") + } + var r0 client.Reader if rf, ok := ret.Get(0).(func() client.Reader); ok { r0 = rf() @@ -262,6 +282,10 @@ func (_c *Manager_GetAPIReader_Call) RunAndReturn(run func() client.Reader) *Man func (_m *Manager) GetCache() cache.Cache { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetCache") + } + var r0 cache.Cache if rf, ok := ret.Get(0).(func() cache.Cache); ok { r0 = rf() @@ -305,6 +329,10 @@ func (_c *Manager_GetCache_Call) RunAndReturn(run func() cache.Cache) *Manager_G func (_m *Manager) GetClient() client.Client { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetClient") + } + var r0 client.Client if rf, ok := ret.Get(0).(func() client.Client); ok { r0 = rf() @@ -348,6 +376,10 @@ func (_c *Manager_GetClient_Call) RunAndReturn(run func() client.Client) *Manage func (_m *Manager) GetConfig() *rest.Config { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetConfig") + } + var r0 *rest.Config if rf, ok := ret.Get(0).(func() *rest.Config); ok { r0 = rf() @@ -391,6 +423,10 @@ func (_c *Manager_GetConfig_Call) RunAndReturn(run func() *rest.Config) *Manager func (_m *Manager) GetControllerOptions() config.Controller { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetControllerOptions") + } + var r0 config.Controller if rf, ok := ret.Get(0).(func() config.Controller); ok { r0 = rf() @@ -432,6 +468,10 @@ func (_c *Manager_GetControllerOptions_Call) RunAndReturn(run func() config.Cont func (_m *Manager) GetEventRecorderFor(name string) record.EventRecorder { ret := _m.Called(name) + if len(ret) == 0 { + panic("no return value specified for GetEventRecorderFor") + } + var r0 record.EventRecorder if rf, ok := ret.Get(0).(func(string) record.EventRecorder); ok { r0 = rf(name) @@ -476,6 +516,10 @@ func (_c *Manager_GetEventRecorderFor_Call) RunAndReturn(run func(string) record func (_m *Manager) GetFieldIndexer() client.FieldIndexer { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetFieldIndexer") + } + var r0 client.FieldIndexer if rf, ok := ret.Get(0).(func() client.FieldIndexer); ok { r0 = rf() @@ -519,6 +563,10 @@ func (_c *Manager_GetFieldIndexer_Call) RunAndReturn(run func() client.FieldInde func (_m *Manager) GetHTTPClient() *http.Client { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetHTTPClient") + } + var r0 *http.Client if rf, ok := ret.Get(0).(func() *http.Client); ok { r0 = rf() @@ -562,6 +610,10 @@ func (_c *Manager_GetHTTPClient_Call) RunAndReturn(run func() *http.Client) *Man func (_m *Manager) GetLogger() logr.Logger { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetLogger") + } + var r0 logr.Logger if rf, ok := ret.Get(0).(func() logr.Logger); ok { r0 = rf() @@ -603,6 +655,10 @@ func (_c *Manager_GetLogger_Call) RunAndReturn(run func() logr.Logger) *Manager_ func (_m *Manager) GetRESTMapper() meta.RESTMapper { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetRESTMapper") + } + var r0 meta.RESTMapper if rf, ok := ret.Get(0).(func() meta.RESTMapper); ok { r0 = rf() @@ -646,6 +702,10 @@ func (_c *Manager_GetRESTMapper_Call) RunAndReturn(run func() meta.RESTMapper) * func (_m *Manager) GetScheme() *runtime.Scheme { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetScheme") + } + var r0 *runtime.Scheme if rf, ok := ret.Get(0).(func() *runtime.Scheme); ok { r0 = rf() @@ -689,6 +749,10 @@ func (_c *Manager_GetScheme_Call) RunAndReturn(run func() *runtime.Scheme) *Mana func (_m *Manager) GetWebhookServer() webhook.Server { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetWebhookServer") + } + var r0 webhook.Server if rf, ok := ret.Get(0).(func() webhook.Server); ok { r0 = rf() @@ -732,6 +796,10 @@ func (_c *Manager_GetWebhookServer_Call) RunAndReturn(run func() webhook.Server) func (_m *Manager) Start(ctx context.Context) error { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context) error); ok { r0 = rf(ctx) diff --git a/internal/controller/eventing/mocks/nats_config_handler.go b/internal/controller/operator/eventing/mocks/nats_config_handler.go similarity index 93% rename from internal/controller/eventing/mocks/nats_config_handler.go rename to internal/controller/operator/eventing/mocks/nats_config_handler.go index 08941244..b6403fb0 100644 --- a/internal/controller/eventing/mocks/nats_config_handler.go +++ b/internal/controller/operator/eventing/mocks/nats_config_handler.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -9,7 +9,7 @@ import ( mock "github.com/stretchr/testify/mock" - v1alpha1 "github.com/kyma-project/eventing-manager/api/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // NatsConfigHandler is an autogenerated mock type for the NatsConfigHandler type @@ -29,6 +29,10 @@ func (_m *NatsConfigHandler) EXPECT() *NatsConfigHandler_Expecter { func (_m *NatsConfigHandler) GetNatsConfig(ctx context.Context, _a1 v1alpha1.Eventing) (*env.NATSConfig, error) { ret := _m.Called(ctx, _a1) + if len(ret) == 0 { + panic("no return value specified for GetNatsConfig") + } + var r0 *env.NATSConfig var r1 error if rf, ok := ret.Get(0).(func(context.Context, v1alpha1.Eventing) (*env.NATSConfig, error)); ok { diff --git a/internal/controller/eventing/nats.go b/internal/controller/operator/eventing/nats.go similarity index 94% rename from internal/controller/eventing/nats.go rename to internal/controller/operator/eventing/nats.go index 65031b37..cd3d18a1 100644 --- a/internal/controller/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/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" @@ -34,6 +34,10 @@ func (r *Reconciler) reconcileNATSSubManager(ctx context.Context, eventing *v1al if err := r.stopNATSSubManager(false, log); err != nil { return err } + } else if eventing.Status.BackendConfigHash != specHash { + // in case spec is change and subManager is not started yet (e.g. due to error) + // make natsSubManager nil to create a subManager with new values + r.natsSubManager = nil } if r.natsSubManager == nil { diff --git a/internal/controller/eventing/nats_test.go b/internal/controller/operator/eventing/nats_test.go similarity index 91% rename from internal/controller/eventing/nats_test.go rename to internal/controller/operator/eventing/nats_test.go index ced1a7b6..bf86aa86 100644 --- a/internal/controller/eventing/nats_test.go +++ b/internal/controller/operator/eventing/nats_test.go @@ -7,10 +7,11 @@ import ( "testing" "time" + "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/v1alpha1" - "github.com/kyma-project/eventing-manager/internal/controller/eventing/mocks" + "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" @@ -131,7 +132,7 @@ func Test_reconcileNATSSubManager(t *testing.T) { name: "it should retry to start subscription manager when subscription manager was " + "successfully initialized but failed to start", givenIsNATSSubManagerStarted: false, - givenHashBefore: int64(0), + givenHashBefore: int64(-7550677537009891034), givenNATSSubManagerMock: func() *submanagermocks.Manager { jetStreamSubManagerMock := new(submanagermocks.Manager) jetStreamSubManagerMock.On("Init", mock.Anything).Return(nil).Once() @@ -156,7 +157,7 @@ func Test_reconcileNATSSubManager(t *testing.T) { wantAssertCheck: true, givenShouldRetry: true, wantError: errors.New("failed to start"), - wantHashAfter: int64(0), + wantHashAfter: int64(-7550677537009891034), }, { name: "it should update the subscription manager when the backend config changes", @@ -188,6 +189,36 @@ func Test_reconcileNATSSubManager(t *testing.T) { wantAssertCheck: true, wantHashAfter: int64(-7550677537009891034), }, + { + name: "it should update the subscription manager when the backend config changes" + + "but subscription manager failed to start", + givenIsNATSSubManagerStarted: false, + givenHashBefore: int64(-8550677537009891034), + givenUpdateTest: true, + givenNATSSubManagerMock: func() *submanagermocks.Manager { + jetStreamSubManagerMock := new(submanagermocks.Manager) + jetStreamSubManagerMock.On("Init", mock.Anything).Return(nil).Once() + jetStreamSubManagerMock.On("Start", mock.Anything, mock.Anything).Return(nil).Once() + return jetStreamSubManagerMock + }, + givenEventingManagerMock: func() *managermocks.Manager { + emMock := new(managermocks.Manager) + emMock.On("GetBackendConfig").Return(givenBackendConfig).Twice() + return emMock + }, + givenNatsConfigHandlerMock: func() *mocks.NatsConfigHandler { + nchMock := new(mocks.NatsConfigHandler) + nchMock.On("GetNatsConfig", mock.Anything, mock.Anything).Return(givenNATSConfig, nil) + return nchMock + }, + givenManagerFactoryMock: func(subManager *submanagermocks.Manager) *subscriptionmanagermocks.ManagerFactory { + subManagerFactoryMock := new(subscriptionmanagermocks.ManagerFactory) + subManagerFactoryMock.On("NewJetStreamManager", mock.Anything, mock.Anything).Return(subManager).Once() + return subManagerFactoryMock + }, + wantAssertCheck: true, + wantHashAfter: int64(-7550677537009891034), + }, } // run test cases diff --git a/internal/controller/eventing/service_instance_secret.go b/internal/controller/operator/eventing/service_instance_secret.go similarity index 100% rename from internal/controller/eventing/service_instance_secret.go rename to internal/controller/operator/eventing/service_instance_secret.go diff --git a/internal/controller/eventing/status.go b/internal/controller/operator/eventing/status.go similarity index 99% rename from internal/controller/eventing/status.go rename to internal/controller/operator/eventing/status.go index 39715cc6..deb918c5 100644 --- a/internal/controller/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/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/eventing/unit_test.go b/internal/controller/operator/eventing/unit_test.go similarity index 98% rename from internal/controller/eventing/unit_test.go rename to internal/controller/operator/eventing/unit_test.go index 200ca2e5..b6dbb9c3 100644 --- a/internal/controller/eventing/unit_test.go +++ b/internal/controller/operator/eventing/unit_test.go @@ -4,6 +4,8 @@ import ( "context" "testing" + ctrlmocks "github.com/kyma-project/eventing-manager/internal/controller/operator/eventing/mocks" + apiclientsetfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" "github.com/kyma-project/eventing-manager/pkg/k8s" @@ -16,11 +18,9 @@ import ( "github.com/kyma-project/eventing-manager/pkg/logger" - ctrlmocks "github.com/kyma-project/eventing-manager/internal/controller/eventing/mocks" - "k8s.io/apimachinery/pkg/runtime" - eventingv1alpha1 "github.com/kyma-project/eventing-manager/api/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/eventing/utils.go b/internal/controller/operator/eventing/utils.go similarity index 98% rename from internal/controller/eventing/utils.go rename to internal/controller/operator/eventing/utils.go index b895581b..1c010ea6 100644 --- a/internal/controller/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/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/eventing/utils_test.go b/internal/controller/operator/eventing/utils_test.go similarity index 99% rename from internal/controller/eventing/utils_test.go rename to internal/controller/operator/eventing/utils_test.go index 38f49b12..2489b9aa 100644 --- a/internal/controller/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/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/eventing/webhook.go b/internal/controller/operator/eventing/webhook.go similarity index 100% rename from internal/controller/eventing/webhook.go rename to internal/controller/operator/eventing/webhook.go diff --git a/internal/controller/eventing/webhook_test.go b/internal/controller/operator/eventing/webhook_test.go similarity index 100% rename from internal/controller/eventing/webhook_test.go rename to internal/controller/operator/eventing/webhook_test.go diff --git a/internal/label/label.go b/internal/label/label.go new file mode 100644 index 00000000..9eb900d7 --- /dev/null +++ b/internal/label/label.go @@ -0,0 +1,24 @@ +package label + +import ( + "k8s.io/apimachinery/pkg/labels" +) + +const ( + KeyComponent = "app.kubernetes.io/component" + KeyCreatedBy = "app.kubernetes.io/created-by" + KeyInstance = "app.kubernetes.io/instance" + KeyManagedBy = "app.kubernetes.io/managed-by" + KeyName = "app.kubernetes.io/name" + KeyPartOf = "app.kubernetes.io/part-of" + KeyBackend = "eventing.kyma-project.io/backend" + KeyDashboard = "kyma-project.io/dashboard" + + ValueEventingPublisherProxy = "eventing-publisher-proxy" + ValueEventingManager = "eventing-manager" + ValueEventing = "eventing" +) + +func SelectorInstanceEventing() labels.Selector { + return labels.SelectorFromSet(map[string]string{KeyInstance: ValueEventing}) +} diff --git a/internal/label/label_test.go b/internal/label/label_test.go new file mode 100644 index 00000000..23b0e203 --- /dev/null +++ b/internal/label/label_test.go @@ -0,0 +1,34 @@ +package label + +import ( + "testing" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/labels" +) + +func TestSelectorInstanceEventing(t *testing.T) { + // given + tests := []struct { + name string + want labels.Selector + }{ + { + name: "should return the correct selector", + want: labels.SelectorFromSet( + map[string]string{ + "app.kubernetes.io/instance": "eventing", + }, + ), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := SelectorInstanceEventing() + + // then + require.Equal(t, tt.want, got) + }) + } +} 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..72172606 100644 --- a/pkg/backend/jetstream/jetstream.go +++ b/pkg/backend/jetstream/jetstream.go @@ -19,8 +19,7 @@ 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" "github.com/kyma-project/eventing-manager/pkg/backend/cleaner" backendmetrics "github.com/kyma-project/eventing-manager/pkg/backend/metrics" @@ -43,7 +42,8 @@ const ( ) func NewJetStream(config env.NATSConfig, metricsCollector *backendmetrics.Collector, - cleaner cleaner.Cleaner, subsConfig env.DefaultSubscriptionConfig, logger *logger.Logger) *JetStream { + cleaner cleaner.Cleaner, subsConfig env.DefaultSubscriptionConfig, logger *logger.Logger, +) *JetStream { return &JetStream{ Config: config, logger: logger, @@ -161,7 +161,8 @@ func (js *JetStream) DeleteSubscriptionsOnly(subscription *eventingv1alpha2.Subs // GetJetStreamSubjects returns a list of subjects appended with prefix if needed. func (js *JetStream) GetJetStreamSubjects(source string, subjects []string, - typeMatching eventingv1alpha2.TypeMatching) []string { + typeMatching eventingv1alpha2.TypeMatching, +) []string { var result []string for _, subject := range subjects { result = append(result, js.GetJetStreamSubject(source, subject, typeMatching)) @@ -377,7 +378,8 @@ func (js *JetStream) syncSubscriptionEventTypes(subscription *eventingv1alpha2.S // syncSubscriptionEventType syncs controller runtime subscriptions to subscription CR event types and to JetStream // subscriptions/consumers. func (js *JetStream) syncSubscriptionEventType(key SubscriptionSubjectIdentifier, - subscription *eventingv1alpha2.Subscription, subscriber Subscriber) error { + subscription *eventingv1alpha2.Subscription, subscriber Subscriber, +) error { // don't try to delete invalid subscriber and its consumer if subscriber has type in subscription CR it belongs to. // This means that it will be bound to the existing JetStream consumer in later steps. if !subscriber.IsValid() && js.runtimeSubscriptionExistsInKymaSub(key, subscription) { @@ -392,7 +394,8 @@ func (js *JetStream) cleanupUnnecessaryJetStreamSubscribers( jsSub Subscriber, subscription *eventingv1alpha2.Subscription, log *zap.SugaredLogger, - key SubscriptionSubjectIdentifier) error { + key SubscriptionSubjectIdentifier, +) error { consumer, err := js.jsCtx.ConsumerInfo(js.Config.JSStreamName, key.ConsumerName()) if err != nil { if errors.Is(err, nats.ErrConsumerNotFound) { @@ -419,7 +422,8 @@ func (js *JetStream) cleanupUnnecessaryJetStreamSubscribers( // runtimeSubscriptionExistsInKymaSub returns true if runtime subscriber subject exists in subscription CR. func (js *JetStream) runtimeSubscriptionExistsInKymaSub(runtimeSubscriptionKey SubscriptionSubjectIdentifier, - subscription *eventingv1alpha2.Subscription) bool { + subscription *eventingv1alpha2.Subscription, +) bool { for _, subject := range subscription.Status.Types { jsSubject := js.getJetStreamSubject(subscription.Spec.Source, subject.CleanType, subscription.Spec.TypeMatching) jsSubKey := NewSubscriptionSubjectIdentifier(subscription, jsSubject) @@ -432,7 +436,8 @@ func (js *JetStream) runtimeSubscriptionExistsInKymaSub(runtimeSubscriptionKey S // consumerSubjectExistsInKymaSub checks if the specified consumer is used by the subscription. func (js *JetStream) consumerSubjectExistsInKymaSub(consumer *nats.ConsumerInfo, - subscription *eventingv1alpha2.Subscription) bool { + subscription *eventingv1alpha2.Subscription, +) bool { return utils.ContainsString( js.GetJetStreamSubjects( subscription.Spec.Source, @@ -463,7 +468,8 @@ func (js *JetStream) deleteSubscriptionFromJetStream(jsSub Subscriber, jsSubKey // deleteSubscriptionFromJetStreamOnly deletes the subscription from NATS server and from in-memory db. // Note: The consumer will not be deleted, meaning there should be no message loss. func (js *JetStream) deleteSubscriptionFromJetStreamOnly(jsSub Subscriber, - jsSubKey SubscriptionSubjectIdentifier) error { + jsSubKey SubscriptionSubjectIdentifier, +) error { if jsSub.IsValid() { // The Unsubscribe function should not delete the consumer because it was added manually. if err := jsSub.Unsubscribe(); err != nil { @@ -581,7 +587,8 @@ func (js *JetStream) deleteConsumerFromJetStream(name string) error { // syncConsumerAndSubscription makes sure there is a consumer and subscription created on the NATS Backend. // these also must be bound to each other to ensure that NATS JetStream eventing logic works as expected. func (js *JetStream) syncConsumerAndSubscription(subscription *eventingv1alpha2.Subscription, - asyncCallback func(m *nats.Msg)) error { + asyncCallback func(m *nats.Msg), +) error { for _, eventType := range subscription.Status.Types { jsSubject := js.GetJetStreamSubject(subscription.Spec.Source, eventType.CleanType, subscription.Spec.TypeMatching) jsSubKey := NewSubscriptionSubjectIdentifier(subscription, jsSubject) @@ -621,14 +628,15 @@ func (js *JetStream) syncConsumerAndSubscription(subscription *eventingv1alpha2. // getOrCreateConsumer fetches the ConsumerInfo from NATS Server or creates it in case it doesn't exist. func (js *JetStream) getOrCreateConsumer(subscription *eventingv1alpha2.Subscription, - subject eventingv1alpha2.EventType) (*nats.ConsumerInfo, error) { + subject eventingv1alpha2.EventType, +) (*nats.ConsumerInfo, error) { jsSubject := js.GetJetStreamSubject(subscription.Spec.Source, subject.CleanType, subscription.Spec.TypeMatching) jsSubKey := NewSubscriptionSubjectIdentifier(subscription, jsSubject) consumerInfo, err := js.jsCtx.ConsumerInfo(js.Config.JSStreamName, jsSubKey.ConsumerName()) if err != nil { if errors.Is(err, nats.ErrConsumerNotFound) { - ecSubsConfig := ecenv.DefaultSubscriptionConfig(js.subsConfig) + ecSubsConfig := env.DefaultSubscriptionConfig(js.subsConfig) consumerInfo, err = js.jsCtx.AddConsumer( js.Config.JSStreamName, js.getConsumerConfig(jsSubKey, jsSubject, subscription.GetMaxInFlightMessages(&ecSubsConfig)), @@ -645,11 +653,12 @@ func (js *JetStream) getOrCreateConsumer(subscription *eventingv1alpha2.Subscrip // createNATSSubscription creates a NATS Subscription and binds it to the already existing consumer. func (js *JetStream) createNATSSubscription(subscription *eventingv1alpha2.Subscription, - subject eventingv1alpha2.EventType, asyncCallback func(m *nats.Msg)) error { + subject eventingv1alpha2.EventType, asyncCallback func(m *nats.Msg), +) error { jsSubject := js.GetJetStreamSubject(subscription.Spec.Source, subject.CleanType, subscription.Spec.TypeMatching) jsSubKey := NewSubscriptionSubjectIdentifier(subscription, jsSubject) - ecSubsConfig := ecenv.DefaultSubscriptionConfig(js.subsConfig) + ecSubsConfig := env.DefaultSubscriptionConfig(js.subsConfig) jsSubscription, err := js.jsCtx.Subscribe( jsSubject, asyncCallback, @@ -672,7 +681,8 @@ func (js *JetStream) createNATSSubscription(subscription *eventingv1alpha2.Subsc // bindInvalidSubscriptions tries to bind the invalid NATS Subscription to the existing consumer. func (js *JetStream) bindInvalidSubscriptions(subscription *eventingv1alpha2.Subscription, - subject eventingv1alpha2.EventType, asyncCallback func(m *nats.Msg)) error { + subject eventingv1alpha2.EventType, asyncCallback func(m *nats.Msg), +) error { jsSubject := js.GetJetStreamSubject(subscription.Spec.Source, subject.CleanType, subscription.Spec.TypeMatching) jsSubKey := NewSubscriptionSubjectIdentifier(subscription, jsSubject) // bind the existing consumer to a new subscription on JetStream @@ -692,8 +702,9 @@ func (js *JetStream) bindInvalidSubscriptions(subscription *eventingv1alpha2.Sub // syncConsumerMaxInFlight checks that the latest Subscription's maxInFlight value // is propagated to the NATS consumer as MaxAckPending. func (js *JetStream) syncConsumerMaxInFlight(subscription *eventingv1alpha2.Subscription, - consumerInfo nats.ConsumerInfo) error { - ecSubsConfig := ecenv.DefaultSubscriptionConfig(js.subsConfig) + consumerInfo nats.ConsumerInfo, +) error { + ecSubsConfig := env.DefaultSubscriptionConfig(js.subsConfig) maxInFlight := subscription.GetMaxInFlightMessages(&ecSubsConfig) if consumerInfo.Config.MaxAckPending == maxInFlight { 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 a161155d..74fd1a32 100644 --- a/pkg/backend/jetstream/mocks/Backend.go +++ b/pkg/backend/jetstream/mocks/Backend.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -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 @@ -31,6 +31,10 @@ func (_m *Backend) EXPECT() *Backend_Expecter { func (_m *Backend) DeleteInvalidConsumers(subscriptions []v1alpha2.Subscription) error { ret := _m.Called(subscriptions) + if len(ret) == 0 { + panic("no return value specified for DeleteInvalidConsumers") + } + var r0 error if rf, ok := ret.Get(0).(func([]v1alpha2.Subscription) error); ok { r0 = rf(subscriptions) @@ -73,6 +77,10 @@ func (_c *Backend_DeleteInvalidConsumers_Call) RunAndReturn(run func([]v1alpha2. func (_m *Backend) DeleteSubscription(subscription *v1alpha2.Subscription) error { ret := _m.Called(subscription) + if len(ret) == 0 { + panic("no return value specified for DeleteSubscription") + } + var r0 error if rf, ok := ret.Get(0).(func(*v1alpha2.Subscription) error); ok { r0 = rf(subscription) @@ -115,6 +123,10 @@ func (_c *Backend_DeleteSubscription_Call) RunAndReturn(run func(*v1alpha2.Subsc func (_m *Backend) DeleteSubscriptionsOnly(subscription *v1alpha2.Subscription) error { ret := _m.Called(subscription) + if len(ret) == 0 { + panic("no return value specified for DeleteSubscriptionsOnly") + } + var r0 error if rf, ok := ret.Get(0).(func(*v1alpha2.Subscription) error); ok { r0 = rf(subscription) @@ -157,6 +169,10 @@ func (_c *Backend_DeleteSubscriptionsOnly_Call) RunAndReturn(run func(*v1alpha2. func (_m *Backend) GetConfig() env.NATSConfig { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetConfig") + } + var r0 env.NATSConfig if rf, ok := ret.Get(0).(func() env.NATSConfig); ok { r0 = rf() @@ -198,6 +214,10 @@ func (_c *Backend_GetConfig_Call) RunAndReturn(run func() env.NATSConfig) *Backe func (_m *Backend) GetJetStreamContext() nats.JetStreamContext { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetJetStreamContext") + } + var r0 nats.JetStreamContext if rf, ok := ret.Get(0).(func() nats.JetStreamContext); ok { r0 = rf() @@ -241,6 +261,10 @@ func (_c *Backend_GetJetStreamContext_Call) RunAndReturn(run func() nats.JetStre func (_m *Backend) GetJetStreamSubjects(source string, subjects []string, typeMatching v1alpha2.TypeMatching) []string { ret := _m.Called(source, subjects, typeMatching) + if len(ret) == 0 { + panic("no return value specified for GetJetStreamSubjects") + } + var r0 []string if rf, ok := ret.Get(0).(func(string, []string, v1alpha2.TypeMatching) []string); ok { r0 = rf(source, subjects, typeMatching) @@ -287,6 +311,10 @@ func (_c *Backend_GetJetStreamSubjects_Call) RunAndReturn(run func(string, []str func (_m *Backend) Initialize(connCloseHandler utils.ConnClosedHandler) error { ret := _m.Called(connCloseHandler) + if len(ret) == 0 { + panic("no return value specified for Initialize") + } + var r0 error if rf, ok := ret.Get(0).(func(utils.ConnClosedHandler) error); ok { r0 = rf(connCloseHandler) @@ -361,6 +389,10 @@ func (_c *Backend_Shutdown_Call) RunAndReturn(run func()) *Backend_Shutdown_Call func (_m *Backend) SyncSubscription(subscription *v1alpha2.Subscription) error { ret := _m.Called(subscription) + if len(ret) == 0 { + panic("no return value specified for SyncSubscription") + } + var r0 error if rf, ok := ret.Get(0).(func(*v1alpha2.Subscription) error); ok { r0 = rf(subscription) diff --git a/pkg/backend/jetstream/mocks/JetStreamContext.go b/pkg/backend/jetstream/mocks/JetStreamContext.go index 51395680..c23f16b2 100644 --- a/pkg/backend/jetstream/mocks/JetStreamContext.go +++ b/pkg/backend/jetstream/mocks/JetStreamContext.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -30,6 +30,10 @@ func (_m *JetStreamContext) AccountInfo(opts ...nats.JSOpt) (*nats.AccountInfo, _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for AccountInfo") + } + var r0 *nats.AccountInfo var r1 error if rf, ok := ret.Get(0).(func(...nats.JSOpt) (*nats.AccountInfo, error)); ok { @@ -98,6 +102,10 @@ func (_m *JetStreamContext) AddConsumer(stream string, cfg *nats.ConsumerConfig, _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for AddConsumer") + } + var r0 *nats.ConsumerInfo var r1 error if rf, ok := ret.Get(0).(func(string, *nats.ConsumerConfig, ...nats.JSOpt) (*nats.ConsumerInfo, error)); ok { @@ -168,6 +176,10 @@ func (_m *JetStreamContext) AddStream(cfg *nats.StreamConfig, opts ...nats.JSOpt _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for AddStream") + } + var r0 *nats.StreamInfo var r1 error if rf, ok := ret.Get(0).(func(*nats.StreamConfig, ...nats.JSOpt) (*nats.StreamInfo, error)); ok { @@ -237,6 +249,10 @@ func (_m *JetStreamContext) ChanQueueSubscribe(subj string, queue string, ch cha _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ChanQueueSubscribe") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, string, chan *nats.Msg, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -308,6 +324,10 @@ func (_m *JetStreamContext) ChanSubscribe(subj string, ch chan *nats.Msg, opts . _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ChanSubscribe") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, chan *nats.Msg, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -378,6 +398,10 @@ func (_m *JetStreamContext) ConsumerInfo(stream string, name string, opts ...nat _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ConsumerInfo") + } + var r0 *nats.ConsumerInfo var r1 error if rf, ok := ret.Get(0).(func(string, string, ...nats.JSOpt) (*nats.ConsumerInfo, error)); ok { @@ -448,6 +472,10 @@ func (_m *JetStreamContext) ConsumerNames(stream string, opts ...nats.JSOpt) <-c _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ConsumerNames") + } + var r0 <-chan string if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) <-chan string); ok { r0 = rf(stream, opts...) @@ -507,6 +535,10 @@ func (_m *JetStreamContext) Consumers(stream string, opts ...nats.JSOpt) <-chan _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Consumers") + } + var r0 <-chan *nats.ConsumerInfo if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) <-chan *nats.ConsumerInfo); ok { r0 = rf(stream, opts...) @@ -566,6 +598,10 @@ func (_m *JetStreamContext) ConsumersInfo(stream string, opts ...nats.JSOpt) <-c _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ConsumersInfo") + } + var r0 <-chan *nats.ConsumerInfo if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) <-chan *nats.ConsumerInfo); ok { r0 = rf(stream, opts...) @@ -618,6 +654,10 @@ func (_c *JetStreamContext_ConsumersInfo_Call) RunAndReturn(run func(string, ... func (_m *JetStreamContext) CreateKeyValue(cfg *nats.KeyValueConfig) (nats.KeyValue, error) { ret := _m.Called(cfg) + if len(ret) == 0 { + panic("no return value specified for CreateKeyValue") + } + var r0 nats.KeyValue var r1 error if rf, ok := ret.Get(0).(func(*nats.KeyValueConfig) (nats.KeyValue, error)); ok { @@ -672,6 +712,10 @@ func (_c *JetStreamContext_CreateKeyValue_Call) RunAndReturn(run func(*nats.KeyV func (_m *JetStreamContext) CreateObjectStore(cfg *nats.ObjectStoreConfig) (nats.ObjectStore, error) { ret := _m.Called(cfg) + if len(ret) == 0 { + panic("no return value specified for CreateObjectStore") + } + var r0 nats.ObjectStore var r1 error if rf, ok := ret.Get(0).(func(*nats.ObjectStoreConfig) (nats.ObjectStore, error)); ok { @@ -733,6 +777,10 @@ func (_m *JetStreamContext) DeleteConsumer(stream string, consumer string, opts _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for DeleteConsumer") + } + var r0 error if rf, ok := ret.Get(0).(func(string, string, ...nats.JSOpt) error); ok { r0 = rf(stream, consumer, opts...) @@ -784,6 +832,10 @@ func (_c *JetStreamContext_DeleteConsumer_Call) RunAndReturn(run func(string, st func (_m *JetStreamContext) DeleteKeyValue(bucket string) error { ret := _m.Called(bucket) + if len(ret) == 0 { + panic("no return value specified for DeleteKeyValue") + } + var r0 error if rf, ok := ret.Get(0).(func(string) error); ok { r0 = rf(bucket) @@ -833,6 +885,10 @@ func (_m *JetStreamContext) DeleteMsg(name string, seq uint64, opts ...nats.JSOp _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for DeleteMsg") + } + var r0 error if rf, ok := ret.Get(0).(func(string, uint64, ...nats.JSOpt) error); ok { r0 = rf(name, seq, opts...) @@ -884,6 +940,10 @@ func (_c *JetStreamContext_DeleteMsg_Call) RunAndReturn(run func(string, uint64, func (_m *JetStreamContext) DeleteObjectStore(bucket string) error { ret := _m.Called(bucket) + if len(ret) == 0 { + panic("no return value specified for DeleteObjectStore") + } + var r0 error if rf, ok := ret.Get(0).(func(string) error); ok { r0 = rf(bucket) @@ -933,6 +993,10 @@ func (_m *JetStreamContext) DeleteStream(name string, opts ...nats.JSOpt) error _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for DeleteStream") + } + var r0 error if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) error); ok { r0 = rf(name, opts...) @@ -990,6 +1054,10 @@ func (_m *JetStreamContext) GetLastMsg(name string, subject string, opts ...nats _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for GetLastMsg") + } + var r0 *nats.RawStreamMsg var r1 error if rf, ok := ret.Get(0).(func(string, string, ...nats.JSOpt) (*nats.RawStreamMsg, error)); ok { @@ -1060,6 +1128,10 @@ func (_m *JetStreamContext) GetMsg(name string, seq uint64, opts ...nats.JSOpt) _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for GetMsg") + } + var r0 *nats.RawStreamMsg var r1 error if rf, ok := ret.Get(0).(func(string, uint64, ...nats.JSOpt) (*nats.RawStreamMsg, error)); ok { @@ -1123,6 +1195,10 @@ func (_c *JetStreamContext_GetMsg_Call) RunAndReturn(run func(string, uint64, .. func (_m *JetStreamContext) KeyValue(bucket string) (nats.KeyValue, error) { ret := _m.Called(bucket) + if len(ret) == 0 { + panic("no return value specified for KeyValue") + } + var r0 nats.KeyValue var r1 error if rf, ok := ret.Get(0).(func(string) (nats.KeyValue, error)); ok { @@ -1177,6 +1253,10 @@ func (_c *JetStreamContext_KeyValue_Call) RunAndReturn(run func(string) (nats.Ke func (_m *JetStreamContext) KeyValueStoreNames() <-chan string { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for KeyValueStoreNames") + } + var r0 <-chan string if rf, ok := ret.Get(0).(func() <-chan string); ok { r0 = rf() @@ -1220,6 +1300,10 @@ func (_c *JetStreamContext_KeyValueStoreNames_Call) RunAndReturn(run func() <-ch func (_m *JetStreamContext) KeyValueStores() <-chan nats.KeyValueStatus { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for KeyValueStores") + } + var r0 <-chan nats.KeyValueStatus if rf, ok := ret.Get(0).(func() <-chan nats.KeyValueStatus); ok { r0 = rf() @@ -1263,6 +1347,10 @@ func (_c *JetStreamContext_KeyValueStores_Call) RunAndReturn(run func() <-chan n func (_m *JetStreamContext) ObjectStore(bucket string) (nats.ObjectStore, error) { ret := _m.Called(bucket) + if len(ret) == 0 { + panic("no return value specified for ObjectStore") + } + var r0 nats.ObjectStore var r1 error if rf, ok := ret.Get(0).(func(string) (nats.ObjectStore, error)); ok { @@ -1323,6 +1411,10 @@ func (_m *JetStreamContext) ObjectStoreNames(opts ...nats.ObjectOpt) <-chan stri _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ObjectStoreNames") + } + var r0 <-chan string if rf, ok := ret.Get(0).(func(...nats.ObjectOpt) <-chan string); ok { r0 = rf(opts...) @@ -1380,6 +1472,10 @@ func (_m *JetStreamContext) ObjectStores(opts ...nats.ObjectOpt) <-chan nats.Obj _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for ObjectStores") + } + var r0 <-chan nats.ObjectStoreStatus if rf, ok := ret.Get(0).(func(...nats.ObjectOpt) <-chan nats.ObjectStoreStatus); ok { r0 = rf(opts...) @@ -1438,6 +1534,10 @@ func (_m *JetStreamContext) Publish(subj string, data []byte, opts ...nats.PubOp _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Publish") + } + var r0 *nats.PubAck var r1 error if rf, ok := ret.Get(0).(func(string, []byte, ...nats.PubOpt) (*nats.PubAck, error)); ok { @@ -1508,6 +1608,10 @@ func (_m *JetStreamContext) PublishAsync(subj string, data []byte, opts ...nats. _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for PublishAsync") + } + var r0 nats.PubAckFuture var r1 error if rf, ok := ret.Get(0).(func(string, []byte, ...nats.PubOpt) (nats.PubAckFuture, error)); ok { @@ -1571,6 +1675,10 @@ func (_c *JetStreamContext_PublishAsync_Call) RunAndReturn(run func(string, []by func (_m *JetStreamContext) PublishAsyncComplete() <-chan struct{} { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for PublishAsyncComplete") + } + var r0 <-chan struct{} if rf, ok := ret.Get(0).(func() <-chan struct{}); ok { r0 = rf() @@ -1614,6 +1722,10 @@ func (_c *JetStreamContext_PublishAsyncComplete_Call) RunAndReturn(run func() <- func (_m *JetStreamContext) PublishAsyncPending() int { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for PublishAsyncPending") + } + var r0 int if rf, ok := ret.Get(0).(func() int); ok { r0 = rf() @@ -1662,6 +1774,10 @@ func (_m *JetStreamContext) PublishMsg(m *nats.Msg, opts ...nats.PubOpt) (*nats. _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for PublishMsg") + } + var r0 *nats.PubAck var r1 error if rf, ok := ret.Get(0).(func(*nats.Msg, ...nats.PubOpt) (*nats.PubAck, error)); ok { @@ -1731,6 +1847,10 @@ func (_m *JetStreamContext) PublishMsgAsync(m *nats.Msg, opts ...nats.PubOpt) (n _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for PublishMsgAsync") + } + var r0 nats.PubAckFuture var r1 error if rf, ok := ret.Get(0).(func(*nats.Msg, ...nats.PubOpt) (nats.PubAckFuture, error)); ok { @@ -1800,6 +1920,10 @@ func (_m *JetStreamContext) PullSubscribe(subj string, durable string, opts ...n _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for PullSubscribe") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, string, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -1870,6 +1994,10 @@ func (_m *JetStreamContext) PurgeStream(name string, opts ...nats.JSOpt) error { _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for PurgeStream") + } + var r0 error if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) error); ok { r0 = rf(name, opts...) @@ -1927,6 +2055,10 @@ func (_m *JetStreamContext) QueueSubscribe(subj string, queue string, cb nats.Ms _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for QueueSubscribe") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, string, nats.MsgHandler, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -1998,6 +2130,10 @@ func (_m *JetStreamContext) QueueSubscribeSync(subj string, queue string, opts . _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for QueueSubscribeSync") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, string, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -2068,6 +2204,10 @@ func (_m *JetStreamContext) SecureDeleteMsg(name string, seq uint64, opts ...nat _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for SecureDeleteMsg") + } + var r0 error if rf, ok := ret.Get(0).(func(string, uint64, ...nats.JSOpt) error); ok { r0 = rf(name, seq, opts...) @@ -2126,6 +2266,10 @@ func (_m *JetStreamContext) StreamInfo(stream string, opts ...nats.JSOpt) (*nats _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for StreamInfo") + } + var r0 *nats.StreamInfo var r1 error if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) (*nats.StreamInfo, error)); ok { @@ -2195,6 +2339,10 @@ func (_m *JetStreamContext) StreamNameBySubject(_a0 string, _a1 ...nats.JSOpt) ( _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for StreamNameBySubject") + } + var r0 string var r1 error if rf, ok := ret.Get(0).(func(string, ...nats.JSOpt) (string, error)); ok { @@ -2261,6 +2409,10 @@ func (_m *JetStreamContext) StreamNames(opts ...nats.JSOpt) <-chan string { _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for StreamNames") + } + var r0 <-chan string if rf, ok := ret.Get(0).(func(...nats.JSOpt) <-chan string); ok { r0 = rf(opts...) @@ -2318,6 +2470,10 @@ func (_m *JetStreamContext) Streams(opts ...nats.JSOpt) <-chan *nats.StreamInfo _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Streams") + } + var r0 <-chan *nats.StreamInfo if rf, ok := ret.Get(0).(func(...nats.JSOpt) <-chan *nats.StreamInfo); ok { r0 = rf(opts...) @@ -2375,6 +2531,10 @@ func (_m *JetStreamContext) StreamsInfo(opts ...nats.JSOpt) <-chan *nats.StreamI _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for StreamsInfo") + } + var r0 <-chan *nats.StreamInfo if rf, ok := ret.Get(0).(func(...nats.JSOpt) <-chan *nats.StreamInfo); ok { r0 = rf(opts...) @@ -2433,6 +2593,10 @@ func (_m *JetStreamContext) Subscribe(subj string, cb nats.MsgHandler, opts ...n _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for Subscribe") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, nats.MsgHandler, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -2503,6 +2667,10 @@ func (_m *JetStreamContext) SubscribeSync(subj string, opts ...nats.SubOpt) (*na _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for SubscribeSync") + } + var r0 *nats.Subscription var r1 error if rf, ok := ret.Get(0).(func(string, ...nats.SubOpt) (*nats.Subscription, error)); ok { @@ -2572,6 +2740,10 @@ func (_m *JetStreamContext) UpdateConsumer(stream string, cfg *nats.ConsumerConf _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for UpdateConsumer") + } + var r0 *nats.ConsumerInfo var r1 error if rf, ok := ret.Get(0).(func(string, *nats.ConsumerConfig, ...nats.JSOpt) (*nats.ConsumerInfo, error)); ok { @@ -2642,6 +2814,10 @@ func (_m *JetStreamContext) UpdateStream(cfg *nats.StreamConfig, opts ...nats.JS _ca = append(_ca, _va...) ret := _m.Called(_ca...) + if len(ret) == 0 { + panic("no return value specified for UpdateStream") + } + var r0 *nats.StreamInfo var r1 error if rf, ok := ret.Get(0).(func(*nats.StreamConfig, ...nats.JSOpt) (*nats.StreamInfo, error)); ok { 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/ems/api/events/client/mocks/PublisherManager.go b/pkg/ems/api/events/client/mocks/PublisherManager.go index f9209293..a10f800a 100644 --- a/pkg/ems/api/events/client/mocks/PublisherManager.go +++ b/pkg/ems/api/events/client/mocks/PublisherManager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -26,6 +26,10 @@ func (_m *PublisherManager) EXPECT() *PublisherManager_Expecter { func (_m *PublisherManager) Create(subscription *types.Subscription) (*types.CreateResponse, error) { ret := _m.Called(subscription) + if len(ret) == 0 { + panic("no return value specified for Create") + } + var r0 *types.CreateResponse var r1 error if rf, ok := ret.Get(0).(func(*types.Subscription) (*types.CreateResponse, error)); ok { @@ -80,6 +84,10 @@ func (_c *PublisherManager_Create_Call) RunAndReturn(run func(*types.Subscriptio func (_m *PublisherManager) Delete(name string) (*types.DeleteResponse, error) { ret := _m.Called(name) + if len(ret) == 0 { + panic("no return value specified for Delete") + } + var r0 *types.DeleteResponse var r1 error if rf, ok := ret.Get(0).(func(string) (*types.DeleteResponse, error)); ok { @@ -134,6 +142,10 @@ func (_c *PublisherManager_Delete_Call) RunAndReturn(run func(string) (*types.De func (_m *PublisherManager) Get(name string) (*types.Subscription, *types.Response, error) { ret := _m.Called(name) + if len(ret) == 0 { + panic("no return value specified for Get") + } + var r0 *types.Subscription var r1 *types.Response var r2 error @@ -197,6 +209,10 @@ func (_c *PublisherManager_Get_Call) RunAndReturn(run func(string) (*types.Subsc func (_m *PublisherManager) List() (*types.Subscriptions, *types.Response, error) { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for List") + } + var r0 *types.Subscriptions var r1 *types.Response var r2 error @@ -259,6 +275,10 @@ func (_c *PublisherManager_List_Call) RunAndReturn(run func() (*types.Subscripti func (_m *PublisherManager) Publish(cloudEvent event.Event, qos types.Qos) (*types.PublishResponse, error) { ret := _m.Called(cloudEvent, qos) + if len(ret) == 0 { + panic("no return value specified for Publish") + } + var r0 *types.PublishResponse var r1 error if rf, ok := ret.Get(0).(func(event.Event, types.Qos) (*types.PublishResponse, error)); ok { @@ -314,6 +334,10 @@ func (_c *PublisherManager_Publish_Call) RunAndReturn(run func(event.Event, type func (_m *PublisherManager) TriggerHandshake(name string) (*types.TriggerHandshake, error) { ret := _m.Called(name) + if len(ret) == 0 { + panic("no return value specified for TriggerHandshake") + } + var r0 *types.TriggerHandshake var r1 error if rf, ok := ret.Get(0).(func(string) (*types.TriggerHandshake, error)); ok { @@ -368,6 +392,10 @@ func (_c *PublisherManager_TriggerHandshake_Call) RunAndReturn(run func(string) func (_m *PublisherManager) Update(name string, webhookAuth *types.WebhookAuth) (*types.UpdateResponse, error) { ret := _m.Called(name, webhookAuth) + if len(ret) == 0 { + panic("no return value specified for Update") + } + var r0 *types.UpdateResponse var r1 error if rf, ok := ret.Get(0).(func(string, *types.WebhookAuth) (*types.UpdateResponse, error)); ok { @@ -423,6 +451,10 @@ func (_c *PublisherManager_Update_Call) RunAndReturn(run func(string, *types.Web func (_m *PublisherManager) UpdateState(name string, state types.State) (*types.UpdateStateResponse, error) { ret := _m.Called(name, state) + if len(ret) == 0 { + panic("no return value specified for UpdateState") + } + var r0 *types.UpdateStateResponse var r1 error if rf, ok := ret.Get(0).(func(string, types.State) (*types.UpdateStateResponse, error)); ok { diff --git a/pkg/env/nats_config.go b/pkg/env/nats_config.go index c38088e6..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/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 a12dd234..cc85e11c 100644 --- a/pkg/eventing/deployment.go +++ b/pkg/eventing/deployment.go @@ -11,7 +11,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "github.com/kyma-project/eventing-manager/api/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" ) @@ -21,18 +22,12 @@ const ( livenessTimeoutSecs = int32(1) livenessPeriodSecs = int32(2) eventMeshNamespacePrefix = "/" - InstanceLabelKey = "app.kubernetes.io/instance" - InstanceLabelValue = "eventing" - DashboardLabelKey = "kyma-project.io/dashboard" - DashboardLabelValue = "eventing" - BackendLabelKey = "eventing.kyma-project.io/backend" publisherPortName = "http" publisherPortNum = int32(8080) publisherMetricsPortName = "http-metrics" publisherMetricsPortNum = int32(9090) PublisherName = "eventing-publisher-proxy" - AppLabelKey = "app.kubernetes.io/name" PublisherSecretClientIDKey = "client-id" PublisherSecretClientSecretKey = "client-secret" PublisherSecretTokenEndpointKey = "token-endpoint" @@ -56,6 +51,7 @@ func newNATSPublisherDeployment( eventing, publisherConfig, WithLabels(GetPublisherDeploymentName(*eventing), v1alpha1.NatsBackendType), + WithSelector(GetPublisherDeploymentName(*eventing)), WithContainers(publisherConfig, eventing), WithNATSEnvVars(natsConfig, publisherConfig, eventing), WithLogEnvVars(publisherConfig, eventing), @@ -72,6 +68,7 @@ func newEventMeshPublisherDeployment( eventing, publisherConfig, WithLabels(GetPublisherDeploymentName(*eventing), v1alpha1.EventMeshBackendType), + WithSelector(GetPublisherDeploymentName(*eventing)), WithContainers(publisherConfig, eventing), WithBEBEnvVars(GetPublisherDeploymentName(*eventing), publisherConfig, eventing), WithLogEnvVars(publisherConfig, eventing), @@ -126,19 +123,39 @@ func getPodSecurityContext() *v1.PodSecurityContext { } } -func WithLabels(publisherName string, backendType v1alpha1.BackendType) DeployOpt { - labels := map[string]string{ - AppLabelKey: publisherName, - InstanceLabelKey: InstanceLabelValue, - DashboardLabelKey: DashboardLabelValue, +func getLabels(publisherName string, backendType v1alpha1.BackendType) map[string]string { + return map[string]string{ + label.KeyComponent: label.ValueEventingManager, + label.KeyCreatedBy: label.ValueEventingManager, + label.KeyInstance: label.ValueEventing, + label.KeyManagedBy: label.ValueEventingManager, + label.KeyName: publisherName, + label.KeyPartOf: label.ValueEventingManager, + label.KeyBackend: fmt.Sprint(getECBackendType(backendType)), + label.KeyDashboard: label.ValueEventing, } +} + +func WithLabels(publisherName string, backendType v1alpha1.BackendType) DeployOpt { return func(d *appsv1.Deployment) { - d.Spec.Selector = metav1.SetAsLabelSelector(labels) + labels := getLabels(publisherName, backendType) + d.ObjectMeta.Labels = labels d.Spec.Template.ObjectMeta.Labels = labels + } +} - // label the event-publisher proxy with the backendType label - labels[BackendLabelKey] = fmt.Sprint(getECBackendType(backendType)) - d.ObjectMeta.Labels = labels +func getSelector(publisherName string) *metav1.LabelSelector { + labels := map[string]string{ + label.KeyInstance: label.ValueEventing, + label.KeyName: publisherName, + label.KeyDashboard: label.ValueEventing, + } + return metav1.SetAsLabelSelector(labels) +} + +func WithSelector(publisherName string) DeployOpt { + return func(d *appsv1.Deployment) { + d.Spec.Selector = getSelector(publisherName) } } @@ -157,7 +174,7 @@ func WithAffinity(publisherName string) DeployOpt { Weight: 100, PodAffinityTerm: v1.PodAffinityTerm{ LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{AppLabelKey: publisherName}, + MatchLabels: map[string]string{label.KeyName: publisherName}, }, TopologyKey: "kubernetes.io/hostname", }, diff --git a/pkg/eventing/deployment_test.go b/pkg/eventing/deployment_test.go index d136c720..dc25ce10 100644 --- a/pkg/eventing/deployment_test.go +++ b/pkg/eventing/deployment_test.go @@ -2,16 +2,17 @@ package eventing import ( "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "strings" "testing" - appsv1 "k8s.io/api/apps/v1" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + appsv1 "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" - "github.com/kyma-project/eventing-manager/api/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" testutils "github.com/kyma-project/eventing-manager/test/utils" @@ -77,9 +78,9 @@ func TestNewDeployment(t *testing.T) { t.Errorf("Invalid backend!") } - // the tight backenType should be set - assert.Equal(t, deployment.ObjectMeta.Labels[BackendLabelKey], string(getECBackendType(tc.givenBackendType))) - assert.Equal(t, deployment.ObjectMeta.Labels[AppLabelKey], publisherName) + // the right backendType should be set + assert.Equal(t, deployment.ObjectMeta.Labels[label.KeyBackend], string(getECBackendType(tc.givenBackendType))) + assert.Equal(t, deployment.ObjectMeta.Labels[label.KeyName], publisherName) // check the container properties were set properly container := findPublisherContainer(publisherName, *deployment) @@ -327,3 +328,121 @@ func findPublisherContainer(publisherName string, deployment appsv1.Deployment) } return container } + +func Test_getLabels(t *testing.T) { + // given + const ( + publisherName = "test-publisher" + backendTypeUnsupported = "Unsupported" + backendTypeEventMesh = "EventMesh" + backendTypeNATS = "NATS" + ) + type args struct { + publisherName string + backendType v1alpha1.BackendType + } + tests := []struct { + name string + args args + want map[string]string + }{ + { + name: "should return the correct labels for backend NATS", + args: args{ + publisherName: publisherName, + backendType: backendTypeNATS, + }, + want: map[string]string{ + label.KeyComponent: label.ValueEventingManager, + label.KeyCreatedBy: label.ValueEventingManager, + label.KeyInstance: label.ValueEventing, + label.KeyManagedBy: label.ValueEventingManager, + label.KeyName: publisherName, + label.KeyPartOf: label.ValueEventingManager, + label.KeyBackend: "NATS", + label.KeyDashboard: label.ValueEventing, + }, + }, + { + name: "should return the correct labels for backend EventMesh", + args: args{ + publisherName: publisherName, + backendType: backendTypeEventMesh, + }, + want: map[string]string{ + label.KeyComponent: label.ValueEventingManager, + label.KeyCreatedBy: label.ValueEventingManager, + label.KeyInstance: label.ValueEventing, + label.KeyManagedBy: label.ValueEventingManager, + label.KeyName: publisherName, + label.KeyPartOf: label.ValueEventingManager, + label.KeyBackend: "EventMesh", + label.KeyDashboard: label.ValueEventing, + }, + }, + { + name: "should return the correct labels for unsupported backend", + args: args{ + publisherName: publisherName, + backendType: backendTypeUnsupported, + }, + want: map[string]string{ + label.KeyComponent: label.ValueEventingManager, + label.KeyCreatedBy: label.ValueEventingManager, + label.KeyInstance: label.ValueEventing, + label.KeyManagedBy: label.ValueEventingManager, + label.KeyName: publisherName, + label.KeyPartOf: label.ValueEventingManager, + label.KeyBackend: "NATS", + label.KeyDashboard: label.ValueEventing, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := getLabels(tt.args.publisherName, tt.args.backendType) + + // then + require.Equal(t, tt.want, got) + }) + } +} + +func Test_getSelector(t *testing.T) { + // given + const ( + publisherName = "test-publisher" + ) + type args struct { + publisherName string + } + tests := []struct { + name string + args args + want *metav1.LabelSelector + }{ + { + name: "should return the correct selector", + args: args{ + publisherName: publisherName, + }, + want: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + label.KeyInstance: label.ValueEventing, + label.KeyName: publisherName, + label.KeyDashboard: label.ValueEventing, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := getSelector(tt.args.publisherName) + + // then + require.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/eventing/manager.go b/pkg/eventing/manager.go index 06e2ac8b..6d1389e0 100644 --- a/pkg/eventing/manager.go +++ b/pkg/eventing/manager.go @@ -4,14 +4,14 @@ import ( "context" "fmt" - ecv1alpha1 "github.com/kyma-project/kyma/components/eventing-controller/api/v1alpha1" + 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/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" @@ -210,7 +210,7 @@ func (em EventingManager) DeployPublisherProxyResources( publisherDeployment.Spec.Template.Labels), // HPA to auto-scale publisher proxy. newHorizontalPodAutoscaler(publisherDeployment.Name, publisherDeployment.Namespace, int32(eventing.Spec.Publisher.Min), - int32(eventing.Spec.Publisher.Max), cpuUtilization, memoryUtilization), + int32(eventing.Spec.Publisher.Max), cpuUtilization, memoryUtilization, publisherDeployment.Labels), } // create the resources on k8s. @@ -254,13 +254,13 @@ func (em EventingManager) DeletePublisherProxyResources(ctx context.Context, eve // Service to expose health endpoint of EPP. newPublisherProxyHealthService(GetPublisherHealthServiceName(*eventing), eventing.Namespace, map[string]string{}, map[string]string{}), // HPA to auto-scale publisher proxy. - newHorizontalPodAutoscaler(publisherDeployment.Name, eventing.Namespace, 0, 0, 0, 0), + newHorizontalPodAutoscaler(publisherDeployment.Name, eventing.Namespace, 0, 0, 0, 0, map[string]string{}), } // delete the resources on k8s. - for _, object := range resources { + for _, obj := range resources { // delete the object. - if err := em.kubeClient.DeleteResource(ctx, object); err != nil { + if err := em.kubeClient.DeleteResource(ctx, obj); err != nil { return err } } diff --git a/pkg/eventing/manager_test.go b/pkg/eventing/manager_test.go index 3facc851..3e8632f6 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/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 e6331173..3d3ca7e0 100644 --- a/pkg/eventing/mocks/manager.go +++ b/pkg/eventing/mocks/manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -11,7 +11,7 @@ import ( v1 "k8s.io/api/apps/v1" - v1alpha1 "github.com/kyma-project/eventing-manager/api/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // Manager is an autogenerated mock type for the Manager type @@ -31,6 +31,10 @@ func (_m *Manager) EXPECT() *Manager_Expecter { func (_m *Manager) DeletePublisherProxyResources(ctx context.Context, _a1 *v1alpha1.Eventing) error { ret := _m.Called(ctx, _a1) + if len(ret) == 0 { + panic("no return value specified for DeletePublisherProxyResources") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Eventing) error); ok { r0 = rf(ctx, _a1) @@ -74,6 +78,10 @@ func (_c *Manager_DeletePublisherProxyResources_Call) RunAndReturn(run func(cont func (_m *Manager) DeployPublisherProxy(ctx context.Context, _a1 *v1alpha1.Eventing, natsConfig *env.NATSConfig, backendType v1alpha1.BackendType) (*v1.Deployment, error) { ret := _m.Called(ctx, _a1, natsConfig, backendType) + if len(ret) == 0 { + panic("no return value specified for DeployPublisherProxy") + } + var r0 *v1.Deployment var r1 error if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Eventing, *env.NATSConfig, v1alpha1.BackendType) (*v1.Deployment, error)); ok { @@ -131,6 +139,10 @@ func (_c *Manager_DeployPublisherProxy_Call) RunAndReturn(run func(context.Conte func (_m *Manager) DeployPublisherProxyResources(_a0 context.Context, _a1 *v1alpha1.Eventing, _a2 *v1.Deployment) error { ret := _m.Called(_a0, _a1, _a2) + if len(ret) == 0 { + panic("no return value specified for DeployPublisherProxyResources") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Eventing, *v1.Deployment) error); ok { r0 = rf(_a0, _a1, _a2) @@ -175,6 +187,10 @@ func (_c *Manager_DeployPublisherProxyResources_Call) RunAndReturn(run func(cont func (_m *Manager) GetBackendConfig() *env.BackendConfig { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetBackendConfig") + } + var r0 *env.BackendConfig if rf, ok := ret.Get(0).(func() *env.BackendConfig); ok { r0 = rf() @@ -218,6 +234,10 @@ func (_c *Manager_GetBackendConfig_Call) RunAndReturn(run func() *env.BackendCon func (_m *Manager) IsNATSAvailable(ctx context.Context, namespace string) (bool, error) { ret := _m.Called(ctx, namespace) + if len(ret) == 0 { + panic("no return value specified for IsNATSAvailable") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (bool, error)); ok { @@ -304,6 +324,10 @@ func (_c *Manager_SetBackendConfig_Call) RunAndReturn(run func(env.BackendConfig func (_m *Manager) SubscriptionExists(ctx context.Context) (bool, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for SubscriptionExists") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { diff --git a/pkg/eventing/utils.go b/pkg/eventing/utils.go index 1fd200ee..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/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" @@ -42,7 +40,8 @@ func GetPublisherClusterRoleBindingName(eventing v1alpha1.Eventing) string { return fmt.Sprintf("%s-%s", eventing.GetName(), publisherProxySuffix) } -func newHorizontalPodAutoscaler(name, namespace string, min int32, max int32, cpuUtilization, memoryUtilization int32) *autoscalingv2.HorizontalPodAutoscaler { +func newHorizontalPodAutoscaler(name, namespace string, min, max, cpuUtilization, memoryUtilization int32, + labels map[string]string) *autoscalingv2.HorizontalPodAutoscaler { return &autoscalingv2.HorizontalPodAutoscaler{ TypeMeta: metav1.TypeMeta{ Kind: "HorizontalPodAutoscaler", @@ -51,6 +50,7 @@ func newHorizontalPodAutoscaler(name, namespace string, min int32, max int32, cp ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, + Labels: labels, }, Spec: autoscalingv2.HorizontalPodAutoscalerSpec{ ScaleTargetRef: autoscalingv2.CrossVersionObjectReference{ @@ -241,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 19f74eab..fa992e4d 100644 --- a/pkg/eventing/utils_test.go +++ b/pkg/eventing/utils_test.go @@ -3,7 +3,7 @@ package eventing import ( "testing" - "github.com/kyma-project/eventing-manager/api/v1alpha1" + "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -23,3 +23,46 @@ func Test_EPPResourcesNames(t *testing.T) { require.Equal(t, "test1-publisher-proxy", GetPublisherClusterRoleName(eventingCR)) require.Equal(t, "test1-publisher-proxy", GetPublisherClusterRoleBindingName(eventingCR)) } + +func Test_getECBackendType(t *testing.T) { + // given + type args struct { + backendType v1alpha1.BackendType + } + tests := []struct { + name string + args args + want v1alpha1.BackendType + }{ + { + name: "should return the correct backend type for NATS", + args: args{ + backendType: "NATS", + }, + want: "NATS", + }, + { + name: "should return the correct backend type for EventMesh", + args: args{ + backendType: "EventMesh", + }, + want: "EventMesh", + }, + { + name: "should return the default backend type for unsupported input", + args: args{ + backendType: "Unsupported", + }, + want: "NATS", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + got := getECBackendType(tt.args.backendType) + + // then + require.Equal(t, tt.want, got) + }) + } +} 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 3711ed0d..b05dd234 100644 --- a/pkg/k8s/mocks/client.go +++ b/pkg/k8s/mocks/client.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -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" ) @@ -40,6 +40,10 @@ func (_m *Client) EXPECT() *Client_Expecter { func (_m *Client) APIRuleCRDExists(ctx context.Context) (bool, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for APIRuleCRDExists") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { @@ -92,6 +96,10 @@ func (_c *Client_APIRuleCRDExists_Call) RunAndReturn(run func(context.Context) ( func (_m *Client) ApplicationCRDExists(ctx context.Context) (bool, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for ApplicationCRDExists") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { @@ -144,6 +152,10 @@ func (_c *Client_ApplicationCRDExists_Call) RunAndReturn(run func(context.Contex func (_m *Client) DeleteClusterRole(ctx context.Context, name string, namespace string) error { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for DeleteClusterRole") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { r0 = rf(ctx, name, namespace) @@ -188,6 +200,10 @@ func (_c *Client_DeleteClusterRole_Call) RunAndReturn(run func(context.Context, func (_m *Client) DeleteClusterRoleBinding(ctx context.Context, name string, namespace string) error { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for DeleteClusterRoleBinding") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { r0 = rf(ctx, name, namespace) @@ -232,6 +248,10 @@ func (_c *Client_DeleteClusterRoleBinding_Call) RunAndReturn(run func(context.Co func (_m *Client) DeleteDeployment(ctx context.Context, name string, namespace string) error { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for DeleteDeployment") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { r0 = rf(ctx, name, namespace) @@ -276,6 +296,10 @@ func (_c *Client_DeleteDeployment_Call) RunAndReturn(run func(context.Context, s func (_m *Client) DeleteResource(ctx context.Context, object client.Object) error { ret := _m.Called(ctx, object) + if len(ret) == 0 { + panic("no return value specified for DeleteResource") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, client.Object) error); ok { r0 = rf(ctx, object) @@ -319,6 +343,10 @@ func (_c *Client_DeleteResource_Call) RunAndReturn(run func(context.Context, cli func (_m *Client) GetCRD(ctx context.Context, name string) (*v1.CustomResourceDefinition, error) { ret := _m.Called(ctx, name) + if len(ret) == 0 { + panic("no return value specified for GetCRD") + } + var r0 *v1.CustomResourceDefinition var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*v1.CustomResourceDefinition, error)); ok { @@ -374,6 +402,10 @@ func (_c *Client_GetCRD_Call) RunAndReturn(run func(context.Context, string) (*v func (_m *Client) GetConfigMap(ctx context.Context, name string, namespace string) (*corev1.ConfigMap, error) { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for GetConfigMap") + } + var r0 *corev1.ConfigMap var r1 error if rf, ok := ret.Get(0).(func(context.Context, string, string) (*corev1.ConfigMap, error)); ok { @@ -430,6 +462,10 @@ func (_c *Client_GetConfigMap_Call) RunAndReturn(run func(context.Context, strin func (_m *Client) GetDeployment(ctx context.Context, name string, namespace string) (*appsv1.Deployment, error) { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for GetDeployment") + } + var r0 *appsv1.Deployment var r1 error if rf, ok := ret.Get(0).(func(context.Context, string, string) (*appsv1.Deployment, error)); ok { @@ -486,6 +522,10 @@ func (_c *Client_GetDeployment_Call) RunAndReturn(run func(context.Context, stri func (_m *Client) GetDeploymentDynamic(ctx context.Context, name string, namespace string) (*appsv1.Deployment, error) { ret := _m.Called(ctx, name, namespace) + if len(ret) == 0 { + panic("no return value specified for GetDeploymentDynamic") + } + var r0 *appsv1.Deployment var r1 error if rf, ok := ret.Get(0).(func(context.Context, string, string) (*appsv1.Deployment, error)); ok { @@ -542,6 +582,10 @@ func (_c *Client_GetDeploymentDynamic_Call) RunAndReturn(run func(context.Contex func (_m *Client) GetMutatingWebHookConfiguration(ctx context.Context, name string) (*admissionregistrationv1.MutatingWebhookConfiguration, error) { ret := _m.Called(ctx, name) + if len(ret) == 0 { + panic("no return value specified for GetMutatingWebHookConfiguration") + } + var r0 *admissionregistrationv1.MutatingWebhookConfiguration var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*admissionregistrationv1.MutatingWebhookConfiguration, error)); ok { @@ -597,6 +641,10 @@ func (_c *Client_GetMutatingWebHookConfiguration_Call) RunAndReturn(run func(con func (_m *Client) GetNATSResources(ctx context.Context, namespace string) (*v1alpha1.NATSList, error) { ret := _m.Called(ctx, namespace) + if len(ret) == 0 { + panic("no return value specified for GetNATSResources") + } + var r0 *v1alpha1.NATSList var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*v1alpha1.NATSList, error)); ok { @@ -652,6 +700,10 @@ func (_c *Client_GetNATSResources_Call) RunAndReturn(run func(context.Context, s func (_m *Client) GetSecret(ctx context.Context, namespacedName string) (*corev1.Secret, error) { ret := _m.Called(ctx, namespacedName) + if len(ret) == 0 { + panic("no return value specified for GetSecret") + } + var r0 *corev1.Secret var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*corev1.Secret, error)); ok { @@ -707,6 +759,10 @@ func (_c *Client_GetSecret_Call) RunAndReturn(run func(context.Context, string) func (_m *Client) GetSubscriptions(ctx context.Context) (*v1alpha2.SubscriptionList, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for GetSubscriptions") + } + var r0 *v1alpha2.SubscriptionList var r1 error if rf, ok := ret.Get(0).(func(context.Context) (*v1alpha2.SubscriptionList, error)); ok { @@ -761,6 +817,10 @@ func (_c *Client_GetSubscriptions_Call) RunAndReturn(run func(context.Context) ( func (_m *Client) GetValidatingWebHookConfiguration(ctx context.Context, name string) (*admissionregistrationv1.ValidatingWebhookConfiguration, error) { ret := _m.Called(ctx, name) + if len(ret) == 0 { + panic("no return value specified for GetValidatingWebHookConfiguration") + } + var r0 *admissionregistrationv1.ValidatingWebhookConfiguration var r1 error if rf, ok := ret.Get(0).(func(context.Context, string) (*admissionregistrationv1.ValidatingWebhookConfiguration, error)); ok { @@ -816,6 +876,10 @@ func (_c *Client_GetValidatingWebHookConfiguration_Call) RunAndReturn(run func(c func (_m *Client) PatchApply(ctx context.Context, object client.Object) error { ret := _m.Called(ctx, object) + if len(ret) == 0 { + panic("no return value specified for PatchApply") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, client.Object) error); ok { r0 = rf(ctx, object) @@ -859,6 +923,10 @@ func (_c *Client_PatchApply_Call) RunAndReturn(run func(context.Context, client. func (_m *Client) PatchApplyPeerAuthentication(ctx context.Context, authentication *v1beta1.PeerAuthentication) error { ret := _m.Called(ctx, authentication) + if len(ret) == 0 { + panic("no return value specified for PatchApplyPeerAuthentication") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *v1beta1.PeerAuthentication) error); ok { r0 = rf(ctx, authentication) @@ -902,6 +970,10 @@ func (_c *Client_PatchApplyPeerAuthentication_Call) RunAndReturn(run func(contex func (_m *Client) PeerAuthenticationCRDExists(ctx context.Context) (bool, error) { ret := _m.Called(ctx) + if len(ret) == 0 { + panic("no return value specified for PeerAuthenticationCRDExists") + } + var r0 bool var r1 error if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { @@ -954,6 +1026,10 @@ func (_c *Client_PeerAuthenticationCRDExists_Call) RunAndReturn(run func(context func (_m *Client) UpdateDeployment(ctx context.Context, deployment *appsv1.Deployment) error { ret := _m.Called(ctx, deployment) + if len(ret) == 0 { + panic("no return value specified for UpdateDeployment") + } + var r0 error if rf, ok := ret.Get(0).(func(context.Context, *appsv1.Deployment) error); ok { r0 = rf(ctx, deployment) diff --git a/pkg/object/apirule.go b/pkg/object/apirule.go index 3ff18e31..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 ( @@ -64,19 +64,17 @@ func GetService(svcName string, port uint32) apigatewayv1beta1.Service { // WithService sets the Service of an APIRule. func WithService(host, svcName string, port uint32) Option { - return func(o metav1.Object) { - d := o.(*apigatewayv1beta1.APIRule) + return func(r *apigatewayv1beta1.APIRule) { apiService := GetService(svcName, port) - d.Spec.Service = &apiService - d.Spec.Host = &host + r.Spec.Service = &apiService + r.Spec.Host = &host } } // WithGateway sets the gateway of an APIRule. func WithGateway(gw string) Option { - return func(o metav1.Object) { - d := o.(*apigatewayv1beta1.APIRule) - d.Spec.Gateway = &gw + return func(r *apigatewayv1beta1.APIRule) { + r.Spec.Gateway = &gw } } @@ -97,40 +95,34 @@ func RemoveDuplicateValues(values []string) []string { // WithLabels sets the labels for an APIRule. func WithLabels(labels map[string]string) Option { - return func(o metav1.Object) { - d := o.(*apigatewayv1beta1.APIRule) //nolint:errcheck // object is APIRule. - d.Labels = labels + return func(r *apigatewayv1beta1.APIRule) { + r.SetLabels(labels) } } // WithOwnerReference sets the OwnerReferences of an APIRule. func WithOwnerReference(subs []eventingv1alpha2.Subscription) Option { - return func(o metav1.Object) { - d := o.(*apigatewayv1beta1.APIRule) + return func(r *apigatewayv1beta1.APIRule) { ownerRefs := make([]metav1.OwnerReference, 0) - if len(subs) > 0 { - for _, sub := range subs { - blockOwnerDeletion := true - ownerRef := metav1.OwnerReference{ - APIVersion: sub.APIVersion, - Kind: sub.Kind, - Name: sub.Name, - UID: sub.UID, - BlockOwnerDeletion: &blockOwnerDeletion, - } - ownerRefs = append(ownerRefs, ownerRef) + for _, sub := range subs { + blockOwnerDeletion := true + ownerRef := metav1.OwnerReference{ + APIVersion: sub.APIVersion, + Kind: sub.Kind, + Name: sub.Name, + UID: sub.UID, + BlockOwnerDeletion: &blockOwnerDeletion, } + ownerRefs = append(ownerRefs, ownerRef) } - - d.OwnerReferences = ownerRefs + r.SetOwnerReferences(ownerRefs) } } // WithRules sets the rules of an APIRule for all Subscriptions for a subscriber. func WithRules(certsURL string, subs []eventingv1alpha2.Subscription, svc apigatewayv1beta1.Service, methods ...string) Option { - return func(o metav1.Object) { - d := o.(*apigatewayv1beta1.APIRule) + return func(r *apigatewayv1beta1.APIRule) { var handler apigatewayv1beta1.Handler if featureflags.IsEventingWebhookAuthEnabled() { handler.Name = OAuthHandlerNameJWT @@ -170,6 +162,6 @@ func WithRules(certsURL string, subs []eventingv1alpha2.Subscription, svc apigat } rules = append(rules, rule) } - d.Spec.Rules = rules + r.Spec.Rules = rules } } diff --git a/pkg/object/apirule_test.go b/pkg/object/apirule_test.go new file mode 100644 index 00000000..12c23616 --- /dev/null +++ b/pkg/object/apirule_test.go @@ -0,0 +1,718 @@ +package object + +import ( + "fmt" + "reflect" + "testing" + + "github.com/kyma-incubator/api-gateway/api/v1beta1" + 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" +) + +func TestApplyExistingAPIRuleAttributes(t *testing.T) { + // given + const ( + name = "name-0" + generateName = "0123" + resourceVersion = "4567" + ) + + var ( + host = ptr.To("some.host") + status = v1beta1.APIRuleStatus{ + LastProcessedTime: ptr.To(metav1.Time{}), + ObservedGeneration: 512, + APIRuleStatus: nil, + VirtualServiceStatus: nil, + AccessRuleStatus: nil, + } + ) + + type args struct { + givenSrc *v1beta1.APIRule + givenDst *v1beta1.APIRule + wantDst *v1beta1.APIRule + } + tests := []struct { + name string + args args + }{ + { + name: "ApiRule attributes are applied from src to dst", + args: args{ + givenSrc: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + GenerateName: generateName, + ResourceVersion: resourceVersion, + }, + Spec: v1beta1.APIRuleSpec{Host: host}, + Status: status, + }, + givenDst: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + GenerateName: generateName, + ResourceVersion: resourceVersion, + }, + Spec: v1beta1.APIRuleSpec{Host: host}, + Status: status, + }, + wantDst: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + GenerateName: "", + ResourceVersion: resourceVersion, + }, + Spec: v1beta1.APIRuleSpec{Host: host}, + Status: status, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + ApplyExistingAPIRuleAttributes(tt.args.givenSrc, tt.args.givenDst) + + // then + require.Equal(t, tt.args.wantDst.Name, tt.args.givenDst.Name) + require.Equal(t, tt.args.wantDst.GenerateName, tt.args.givenDst.GenerateName) + require.Equal(t, tt.args.wantDst.ResourceVersion, tt.args.givenDst.ResourceVersion) + require.Equal(t, tt.args.wantDst.Spec, tt.args.givenDst.Spec) + require.Equal(t, tt.args.wantDst.Status, tt.args.givenDst.Status) + }) + } +} + +func TestGetService(t *testing.T) { + // given + const ( + name = "name-0" + port = uint32(9080) + isExternal = true + ) + + type args struct { + svcName string + port uint32 + } + tests := []struct { + name string + args args + want v1beta1.Service + }{ + { + name: "get service with the given properties", + args: args{ + svcName: name, + port: port, + }, + want: v1beta1.Service{ + Name: ptr.To(name), + Port: ptr.To(port), + IsExternal: ptr.To(isExternal), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + if got := GetService(tt.args.svcName, tt.args.port); !reflect.DeepEqual(got, tt.want) { + // then + t.Errorf("GetService() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNewAPIRule(t *testing.T) { + // given + const ( + namespace = "namespace-0" + namePrefix = "name-0" + ) + + type args struct { + ns string + namePrefix string + opts []Option + } + tests := []struct { + name string + args args + want *v1beta1.APIRule + }{ + { + name: "get APIRule with the given properties", + args: args{ + ns: namespace, + namePrefix: namePrefix, + opts: nil, + }, + want: &v1beta1.APIRule{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + GenerateName: namePrefix, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + if got := NewAPIRule(tt.args.ns, tt.args.namePrefix, tt.args.opts...); !reflect.DeepEqual(got, tt.want) { + // then + t.Errorf("NewAPIRule() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestRemoveDuplicateValues(t *testing.T) { + // given + type args struct { + values []string + } + tests := []struct { + name string + args args + want []string + }{ + { + name: "list without duplicates", + args: args{ + values: []string{ + "1", "2", "3", + }, + }, + want: []string{ + "1", "2", "3", + }, + }, + { + name: "list with duplicates", + args: args{ + values: []string{ + "1", "2", "3", + "3", "2", "1", + }, + }, + want: []string{ + "1", "2", "3", + }, + }, + { + name: "empty list", + args: args{ + values: []string{}, + }, + want: []string{}, + }, + { + name: "nil list", + args: args{ + values: nil, + }, + want: []string{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + if got := RemoveDuplicateValues(tt.args.values); !reflect.DeepEqual(got, tt.want) { + // then + t.Errorf("RemoveDuplicateValues() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestWithGateway(t *testing.T) { + // given + const ( + gateway = "some.gateway" + ) + + type args struct { + givenGateway string + givenObject *v1beta1.APIRule + } + tests := []struct { + name string + args args + wantObject *v1beta1.APIRule + }{ + { + name: "apply gateway to object", + args: args{ + givenGateway: gateway, + givenObject: &v1beta1.APIRule{}, + }, + wantObject: &v1beta1.APIRule{ + Spec: v1beta1.APIRuleSpec{ + Gateway: ptr.To(gateway), + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + WithGateway(tt.args.givenGateway)(tt.args.givenObject) + + // then + require.Equal(t, tt.wantObject.Spec.Gateway, tt.args.givenObject.Spec.Gateway) + }) + } +} + +func TestWithLabels(t *testing.T) { + // given + type args struct { + givenLabels map[string]string + givenObject *v1beta1.APIRule + } + tests := []struct { + name string + args args + wantObject *v1beta1.APIRule + }{ + { + name: "object with nil labels", + args: args{ + givenLabels: map[string]string{ + "key-0": "val-0", + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: nil, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "key-0": "val-0", + }, + }, + }, + }, + { + name: "object with empty labels", + args: args{ + givenLabels: map[string]string{ + "key-0": "val-0", + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{}, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "key-0": "val-0", + }, + }, + }, + }, + { + name: "object with labels", + args: args{ + givenLabels: map[string]string{ + "key-0": "val-0", + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "key-1": "val-1", + "key-2": "val-2", + }, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + "key-0": "val-0", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + WithLabels(tt.args.givenLabels)(tt.args.givenObject) + + // then + require.Equal(t, tt.wantObject.GetLabels(), tt.args.givenObject.GetLabels()) + }) + } +} + +func TestWithOwnerReference(t *testing.T) { + // given + const ( + kind0 = "kind-0" + kind1 = "kind-1" + kind2 = "kind-2" + + apiVersion0 = "version-0" + apiVersion1 = "version-1" + apiVersion2 = "version-2" + + name0 = "name-0" + name1 = "name-1" + name2 = "name-2" + + uid0 = "000000" + uid1 = "111111" + uid2 = "222222" + + blockOwnerDeletion = true + ) + + var ( + sub0 = eventingv1alpha2.Subscription{ + TypeMeta: metav1.TypeMeta{Kind: kind0, APIVersion: apiVersion0}, + ObjectMeta: metav1.ObjectMeta{Name: name0, UID: uid0}, + } + sub1 = eventingv1alpha2.Subscription{ + TypeMeta: metav1.TypeMeta{Kind: kind1, APIVersion: apiVersion1}, + ObjectMeta: metav1.ObjectMeta{Name: name1, UID: uid1}, + } + ) + + type args struct { + givenSubs []eventingv1alpha2.Subscription + givenObject *v1beta1.APIRule + } + tests := []struct { + name string + args args + wantObject *v1beta1.APIRule + }{ + { + name: "nil Subscriptions", + args: args{ + givenSubs: nil, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: nil, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{}, + }, + }, + }, + { + name: "empty Subscriptions", + args: args{ + givenSubs: []eventingv1alpha2.Subscription{}, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: nil, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{}, + }, + }, + }, + { + name: "object with nil OwnerReferences", + args: args{ + givenSubs: []eventingv1alpha2.Subscription{ + sub0, + sub1, + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: nil, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: apiVersion0, + Kind: kind0, + Name: name0, + UID: uid0, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + { + APIVersion: apiVersion1, + Kind: kind1, + Name: name1, + UID: uid1, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + }, + }, + }, + }, + { + name: "object with empty OwnerReferences", + args: args{ + givenSubs: []eventingv1alpha2.Subscription{ + sub0, + sub1, + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{}, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: apiVersion0, + Kind: kind0, + Name: name0, + UID: uid0, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + { + APIVersion: apiVersion1, + Kind: kind1, + Name: name1, + UID: uid1, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + }, + }, + }, + }, + { + name: "object with OwnerReferences", + args: args{ + givenSubs: []eventingv1alpha2.Subscription{ + sub0, + sub1, + }, + givenObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: apiVersion2, + Kind: kind2, + Name: name2, + UID: uid2, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + }, + }, + }, + }, + wantObject: &v1beta1.APIRule{ + ObjectMeta: metav1.ObjectMeta{ + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: apiVersion0, + Kind: kind0, + Name: name0, + UID: uid0, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + { + APIVersion: apiVersion1, + Kind: kind1, + Name: name1, + UID: uid1, + BlockOwnerDeletion: ptr.To(blockOwnerDeletion), + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + WithOwnerReference(tt.args.givenSubs)(tt.args.givenObject) + gotOwnerReferences := tt.args.givenObject.GetOwnerReferences() + + // then + require.Equal(t, tt.wantObject.GetOwnerReferences(), gotOwnerReferences) + }) + } +} + +func TestWithRules(t *testing.T) { + // given + const ( + endpoint0 = "/endpoint0" + endpoint1 = "/endpoint1" + + sink0 = "https://sink0.com" + endpoint0 + sink1 = "https://sink1.com" + endpoint1 + + certsURL = "some.url" + name = "name-0" + port = uint32(9999) + external = true + ) + + var ( + sub0 = eventingv1alpha2.Subscription{ + Spec: eventingv1alpha2.SubscriptionSpec{Sink: sink0}, + } + sub1 = eventingv1alpha2.Subscription{ + Spec: eventingv1alpha2.SubscriptionSpec{Sink: sink1}, + } + + methods = []string{"some.method"} + ) + + type args struct { + givenCertsURL string + givenSubs []eventingv1alpha2.Subscription + givenSvc v1beta1.Service + givenMethods []string + givenObject *v1beta1.APIRule + } + tests := []struct { + name string + args args + wantObject *v1beta1.APIRule + }{ + { + name: "apply properties to object", + args: args{ + givenCertsURL: certsURL, + givenSubs: []eventingv1alpha2.Subscription{ + sub0, + sub1, + }, + givenSvc: v1beta1.Service{ + Name: ptr.To(name), + Port: ptr.To(port), + IsExternal: ptr.To(external), + }, + givenMethods: methods, + givenObject: &v1beta1.APIRule{}, + }, + wantObject: &v1beta1.APIRule{ + Spec: v1beta1.APIRuleSpec{ + Rules: []v1beta1.Rule{ + { + Path: endpoint0, + Service: &v1beta1.Service{ + Name: ptr.To(name), + Port: ptr.To(port), + IsExternal: ptr.To(external), + }, + Methods: methods, + AccessStrategies: []*v1beta1.Authenticator{ + { + Handler: &v1beta1.Handler{ + Name: OAuthHandlerNameJWT, + Config: &runtime.RawExtension{ + Raw: []byte(fmt.Sprintf(JWKSURLFormat, certsURL)), + }, + }, + }, + }, + }, + { + Path: endpoint1, + Service: &v1beta1.Service{ + Name: ptr.To(name), + Port: ptr.To(port), + IsExternal: ptr.To(external), + }, + Methods: methods, + AccessStrategies: []*v1beta1.Authenticator{ + { + Handler: &v1beta1.Handler{ + Name: OAuthHandlerNameJWT, + Config: &runtime.RawExtension{ + Raw: []byte(fmt.Sprintf(JWKSURLFormat, certsURL)), + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + WithRules(tt.args.givenCertsURL, tt.args.givenSubs, tt.args.givenSvc, tt.args.givenMethods...)(tt.args.givenObject) + + // then + require.Equal(t, tt.wantObject.Spec.Rules, tt.args.givenObject.Spec.Rules) + }) + } +} + +func TestWithService(t *testing.T) { + // given + const ( + host = "host0" + name = "name-0" + port = uint32(9999) + external = true + ) + + type args struct { + givenHost string + givenSvcName string + givenPort uint32 + givenObject *v1beta1.APIRule + } + tests := []struct { + name string + args args + wantObject *v1beta1.APIRule + }{ + { + name: "apply properties to object", + args: args{ + givenHost: host, + givenSvcName: name, + givenPort: port, + givenObject: &v1beta1.APIRule{}, + }, + wantObject: &v1beta1.APIRule{ + Spec: v1beta1.APIRuleSpec{ + Host: ptr.To(host), + Service: &v1beta1.Service{ + Name: ptr.To(name), + Port: ptr.To(port), + IsExternal: ptr.To(external), + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // when + WithService(tt.args.givenHost, tt.args.givenSvcName, tt.args.givenPort)(tt.args.givenObject) + + // then + require.Equal(t, tt.wantObject, tt.args.givenObject) + }) + } +} diff --git a/pkg/object/equality.go b/pkg/object/equality.go index 92a67f86..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 { @@ -357,14 +335,14 @@ func envEqual(e1, e2 []corev1.EnvVar) bool { // probeEqual asserts the equality of two Probe objects. It's used by // containerEqual. func probeEqual(p1, p2 *corev1.Probe) bool { - if p1 == nil || p2 == nil { - return false - } - if p1 == p2 { return true } + if p1 == nil || p2 == nil { + return false + } + isInitialDelaySecondsEqual := p1.InitialDelaySeconds != p2.InitialDelaySeconds isTimeoutSecondsEqual := p1.TimeoutSeconds != p2.TimeoutSeconds && p1.TimeoutSeconds != 0 && p2.TimeoutSeconds != 0 isPeriodSecondsEqual := p1.PeriodSeconds != p2.PeriodSeconds && p1.PeriodSeconds != 0 && p2.PeriodSeconds != 0 @@ -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 8452e7dc..159aa3b1 100644 --- a/pkg/object/equality_test.go +++ b/pkg/object/equality_test.go @@ -7,7 +7,6 @@ import ( "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" @@ -17,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) { @@ -188,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 @@ -456,178 +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 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 { @@ -836,6 +634,72 @@ func Test_containerEqual(t *testing.T) { }, want: true, }, + { + name: "ContainerPort are not equal", + args: args{ + c1: &corev1.Container{ + Name: "test", + Image: "bla", + Command: []string{"1", "2"}, + Args: []string{"a", "b"}, + WorkingDir: "foodir", + Ports: []corev1.ContainerPort{{ + Name: "testport", + HostPort: 1, + ContainerPort: 2, + Protocol: "http", + HostIP: "192.168.1.1", + }}, + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + "cpu": quantityA, + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + "mem": quantityA, + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{}, + InitialDelaySeconds: 0, + TimeoutSeconds: 0, + PeriodSeconds: 0, + SuccessThreshold: 0, + FailureThreshold: 0, + }, + }, + c2: &corev1.Container{ + Name: "test", + Image: "bla", + Command: []string{"1", "2"}, + Args: []string{"a", "b"}, + WorkingDir: "foodir", + Ports: []corev1.ContainerPort{{ + Name: "testport", + HostPort: 1, + ContainerPort: 3, + Protocol: "http", + HostIP: "192.168.1.1", + }}, + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + "cpu": quantityA, + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + "mem": quantityA, + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{}, + InitialDelaySeconds: 0, + TimeoutSeconds: 0, + PeriodSeconds: 0, + SuccessThreshold: 0, + FailureThreshold: 0, + }, + }, + }, + want: false, + }, { name: "resources are not equal", args: args{ @@ -902,6 +766,83 @@ func Test_containerEqual(t *testing.T) { }, want: false, }, + { + name: "ports are not equal", + args: args{ + c1: &corev1.Container{ + Name: "test", + Image: "bla", + Command: []string{"1", "2"}, + Args: []string{"a", "b"}, + WorkingDir: "foodir", + Ports: []corev1.ContainerPort{ + { + Name: "testport-0", + HostPort: 1, + ContainerPort: 2, + Protocol: "http", + HostIP: "192.168.1.1", + }, + }, + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + "cpu": quantityA, + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + "mem": quantityA, + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{}, + InitialDelaySeconds: 0, + TimeoutSeconds: 0, + PeriodSeconds: 0, + SuccessThreshold: 0, + FailureThreshold: 0, + }, + }, + c2: &corev1.Container{ + Name: "test", + Image: "bla", + Command: []string{"1", "2"}, + Args: []string{"a", "b"}, + WorkingDir: "foodir", + Ports: []corev1.ContainerPort{ + { + Name: "testport-0", + HostPort: 1, + ContainerPort: 2, + Protocol: "http", + HostIP: "192.168.1.1", + }, + { + Name: "testport-1", + HostPort: 1, + ContainerPort: 2, + Protocol: "http", + HostIP: "192.168.1.1", + }, + }, + Resources: corev1.ResourceRequirements{ + Limits: map[corev1.ResourceName]resource.Quantity{ + "cpu": quantityA, + }, + Requests: map[corev1.ResourceName]resource.Quantity{ + "mem": quantityA, + }, + }, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{}, + InitialDelaySeconds: 0, + TimeoutSeconds: 0, + PeriodSeconds: 0, + SuccessThreshold: 0, + FailureThreshold: 0, + }, + }, + }, + want: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -945,6 +886,15 @@ func Test_serviceAccountEqual(t *testing.T) { BlockOwnerDeletion: ptr.To(false), }, } + + serviceAccount = &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: name0, + Namespace: namespace0, + Labels: labels0, + OwnerReferences: ownerReferences0, + }, + } ) type args struct { @@ -956,6 +906,30 @@ func Test_serviceAccountEqual(t *testing.T) { args args want bool }{ + { + name: "ServiceAccount refs are equal", + args: args{ + a: serviceAccount, + b: serviceAccount, + }, + want: true, + }, + { + name: "one ServiceAccount is Nil", + args: args{ + a: nil, + b: serviceAccount, + }, + want: false, + }, + { + name: "both ServiceAccounts are Nil", + args: args{ + a: nil, + b: nil, + }, + want: true, + }, { name: "ServiceAccounts are equal", args: args{ @@ -1125,6 +1099,15 @@ func Test_clusterRoleEqual(t *testing.T) { NonResourceURLs: []string{"val-0"}, }, } + + clusterRole = &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{ + Name: name0, + Labels: labels0, + OwnerReferences: ownerReferences0, + }, + Rules: rules0, + } ) type args struct { @@ -1136,6 +1119,30 @@ func Test_clusterRoleEqual(t *testing.T) { args args want bool }{ + { + name: "ClusterRole refs are equal", + args: args{ + a: clusterRole, + b: clusterRole, + }, + want: true, + }, + { + name: "one ClusterRole is nil", + args: args{ + a: nil, + b: clusterRole, + }, + want: false, + }, + { + name: "both ClusterRoles are nil", + args: args{ + a: nil, + b: nil, + }, + want: true, + }, { name: "ClusterRoles are equal", args: args{ @@ -2103,3 +2110,63 @@ func Test_envEqual(t *testing.T) { }) } } + +func Test_probeEqual(t *testing.T) { + var ( + probe = &corev1.Probe{} + ) + + type args struct { + p1 *corev1.Probe + p2 *corev1.Probe + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "Probe refs are equal", + args: args{ + p1: probe, + p2: probe, + }, + want: true, + }, + { + name: "one Probe is Nil", + args: args{ + p1: nil, + p2: probe, + }, + want: false, + }, + { + name: "both Probes are Nil", + args: args{ + p1: nil, + p2: nil, + }, + want: true, + }, + { + name: "Probes are not equal", + args: args{ + p1: &corev1.Probe{ + InitialDelaySeconds: 1, + }, + p2: &corev1.Probe{ + InitialDelaySeconds: 2, + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := probeEqual(tt.args.p1, tt.args.p2); got != tt.want { + t.Errorf("probeEqual() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/object/object.go b/pkg/object/object.go index 09d468fb..7e6ce5af 100644 --- a/pkg/object/object.go +++ b/pkg/object/object.go @@ -1,6 +1,8 @@ package object -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +import ( + apigatewayv1beta1 "github.com/kyma-incubator/api-gateway/api/v1beta1" +) // Option is a functional option for API objects builders. -type Option func(metav1.Object) +type Option func(*apigatewayv1beta1.APIRule) 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 1eaa66f1..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/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/manager/mocks/manager.go b/pkg/subscriptionmanager/manager/mocks/manager.go index 98e52f51..b31299a2 100644 --- a/pkg/subscriptionmanager/manager/mocks/manager.go +++ b/pkg/subscriptionmanager/manager/mocks/manager.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -28,6 +28,10 @@ func (_m *Manager) EXPECT() *Manager_Expecter { func (_m *Manager) Init(mgr manager.Manager) error { ret := _m.Called(mgr) + if len(ret) == 0 { + panic("no return value specified for Init") + } + var r0 error if rf, ok := ret.Get(0).(func(manager.Manager) error); ok { r0 = rf(mgr) @@ -70,6 +74,10 @@ func (_c *Manager_Init_Call) RunAndReturn(run func(manager.Manager) error) *Mana func (_m *Manager) Start(defaultSubsConfig env.DefaultSubscriptionConfig, params subscriptionmanagermanager.Params) error { ret := _m.Called(defaultSubsConfig, params) + if len(ret) == 0 { + panic("no return value specified for Start") + } + var r0 error if rf, ok := ret.Get(0).(func(env.DefaultSubscriptionConfig, subscriptionmanagermanager.Params) error); ok { r0 = rf(defaultSubsConfig, params) @@ -113,6 +121,10 @@ func (_c *Manager_Start_Call) RunAndReturn(run func(env.DefaultSubscriptionConfi func (_m *Manager) Stop(runCleanup bool) error { ret := _m.Called(runCleanup) + if len(ret) == 0 { + panic("no return value specified for Stop") + } + var r0 error if rf, ok := ret.Get(0).(func(bool) error); ok { r0 = rf(runCleanup) 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 647192de..9e7d9b18 100644 --- a/pkg/subscriptionmanager/mocks/manager_factory.go +++ b/pkg/subscriptionmanager/mocks/manager_factory.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -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/v1alpha1" + v1alpha1 "github.com/kyma-project/eventing-manager/api/operator/v1alpha1" ) // ManagerFactory is an autogenerated mock type for the ManagerFactory type @@ -27,6 +27,10 @@ func (_m *ManagerFactory) EXPECT() *ManagerFactory_Expecter { func (_m *ManagerFactory) NewEventMeshManager(domain string) (manager.Manager, error) { ret := _m.Called(domain) + if len(ret) == 0 { + panic("no return value specified for NewEventMeshManager") + } + var r0 manager.Manager var r1 error if rf, ok := ret.Get(0).(func(string) (manager.Manager, error)); ok { @@ -81,6 +85,10 @@ func (_c *ManagerFactory_NewEventMeshManager_Call) RunAndReturn(run func(string) func (_m *ManagerFactory) NewJetStreamManager(_a0 v1alpha1.Eventing, _a1 env.NATSConfig) manager.Manager { ret := _m.Called(_a0, _a1) + if len(ret) == 0 { + panic("no return value specified for NewJetStreamManager") + } + var r0 manager.Manager if rf, ok := ret.Get(0).(func(v1alpha1.Eventing, env.NATSConfig) manager.Manager); ok { r0 = rf(_a0, _a1) diff --git a/pkg/watcher/mocks/watcher.go b/pkg/watcher/mocks/watcher.go index 3e9cb36d..96b0f584 100644 --- a/pkg/watcher/mocks/watcher.go +++ b/pkg/watcher/mocks/watcher.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.36.1. DO NOT EDIT. +// Code generated by mockery v2.38.0. DO NOT EDIT. package mocks @@ -24,6 +24,10 @@ func (_m *Watcher) EXPECT() *Watcher_Expecter { func (_m *Watcher) GetEventsChannel() <-chan event.GenericEvent { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for GetEventsChannel") + } + var r0 <-chan event.GenericEvent if rf, ok := ret.Get(0).(func() <-chan event.GenericEvent); ok { r0 = rf() @@ -67,6 +71,10 @@ func (_c *Watcher_GetEventsChannel_Call) RunAndReturn(run func() <-chan event.Ge func (_m *Watcher) IsStarted() bool { ret := _m.Called() + if len(ret) == 0 { + panic("no return value specified for IsStarted") + } + var r0 bool if rf, ok := ret.Get(0).(func() bool); ok { r0 = rf() diff --git a/sec-scanners-config.yaml b/sec-scanners-config.yaml index 7bf36c18..e9263382 100644 --- a/sec-scanners-config.yaml +++ b/sec-scanners-config.yaml @@ -1,7 +1,7 @@ module-name: eventing -rc-tag: 1.0.0 +rc-tag: 1.0.2 protecode: - - europe-docker.pkg.dev/kyma-project/prod/eventing-manager:v20231114-4bbffe1a + - europe-docker.pkg.dev/kyma-project/prod/eventing-manager:1.0.2 - europe-docker.pkg.dev/kyma-project/prod/event-publisher-proxy:v20231025-3f5d1600 - europe-docker.pkg.dev/kyma-project/prod/eventing-webhook-certificates:1.7.0 whitesource: diff --git a/test/matchers/matchers.go b/test/matchers/matchers.go index 311a39be..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/v1alpha1" - "github.com/kyma-project/eventing-manager/internal/controller/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 5515a56e..ed8c5135 100644 --- a/test/utils/integration/integration.go +++ b/test/utils/integration/integration.go @@ -5,13 +5,15 @@ import ( "context" "crypto/rand" "fmt" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "log" "path/filepath" "strings" "testing" "time" + 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" "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager" submanagermocks "github.com/kyma-project/eventing-manager/pkg/subscriptionmanager/manager/mocks" @@ -41,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" @@ -51,8 +53,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "github.com/kyma-project/eventing-manager/api/v1alpha1" - eventingctrl "github.com/kyma-project/eventing-manager/internal/controller/eventing" + "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" @@ -79,7 +80,7 @@ type TestEnvironment struct { k8sClient client.Client KubeClient k8s.Client K8sDynamicClient *dynamic.DynamicClient - Reconciler *eventingctrl.Reconciler + Reconciler *eventing2.Reconciler Logger *logger.Logger Recorder *record.EventRecorder TestCancelFn context.CancelFunc @@ -197,7 +198,7 @@ func NewTestEnvironment(config TestEnvironmentConfig) (*TestEnvironment, error) subManagerFactoryMock.On("NewEventMeshManager", mock.Anything).Return(eventMeshSubManagerMock, nil) // create a new watcher - eventingReconciler := eventingctrl.NewReconciler( + eventingReconciler := eventing2.NewReconciler( k8sClient, kubeClient, dynamicClient, @@ -298,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, @@ -854,12 +854,12 @@ func (env TestEnvironment) EnsureCABundleInjectedIntoWebhooks(t *testing.T) { return false } - if !bytes.Equal(mwh.Webhooks[0].ClientConfig.CABundle, certSecret.Data[eventingctrl.TLSCertField]) { + if !bytes.Equal(mwh.Webhooks[0].ClientConfig.CABundle, certSecret.Data[eventing2.TLSCertField]) { env.Logger.WithContext().Error("CABundle of mutating configuration is not correct") return false } - if !bytes.Equal(vwh.Webhooks[0].ClientConfig.CABundle, certSecret.Data[eventingctrl.TLSCertField]) { + if !bytes.Equal(vwh.Webhooks[0].ClientConfig.CABundle, certSecret.Data[eventing2.TLSCertField]) { env.Logger.WithContext().Error("CABundle of validating configuration is not correct") return false } @@ -992,7 +992,7 @@ func newSecretWithTLSSecret(dummyCABundle []byte) *corev1.Secret { Namespace: getTestBackendConfig().Namespace, }, Data: map[string][]byte{ - eventingctrl.TLSCertField: dummyCABundle, + eventing2.TLSCertField: dummyCABundle, }, } } diff --git a/test/utils/options.go b/test/utils/options.go index 1688e58e..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/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 0b36de56..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/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"}} }