diff --git a/docs/eventing/choice.md b/docs/eventing/choice.md new file mode 100644 index 000000000..78ed79a6e --- /dev/null +++ b/docs/eventing/choice.md @@ -0,0 +1,43 @@ +--- +title: "Choice" +weight: 20 +type: "docs" +--- + +Choice CRD provides a way to easily define a list of branches that will be +invoked. Each branch consists of a filter function guarding the execution of the +branch. When the filter passes, the rest of the branch is executed. + +Choice creates `Channel`s and `Subscription`s under the hood. + +## Usage + +### Choice Spec + +Choice has three parts for the Spec: + +1. `cases` defines the list of `filter` and `subscriber` pairs, one per + branch, and optionally a `reply` object. For each branch: + 1. the `filter` is evaluated and when it returns an event the `subscriber` is executed. + Both `filter` and `subscriber` must be `Callable`. + 1. the event returned by the `subscriber` is sent to the branch `reply` object. When + the `reply` is empty, the event is sent to the `spec.reply` object (see below). +1. (optional) `channelTemplate` defines the Template which will be used to create + `Channel`s. +1. (optional) `reply` defines where the result of each branch is sent to when the branch does + not have its own `reply` object. + +### Choice Status + +Choice has three parts for the Status: + +1. Conditions which detail the overall Status of the Choice object +1. IngressChannelStatus and CaseStatuses which convey the Status + of underlying `Channel` and `Subscription` resource that are created as part of this Choice. +1. AddressStatus which is exposed so that Choice can be used where Addressable + can be used. Sending to this address will target the `Channel` which is + fronting this Choice (same as `IngressChannelStatus`). + +## Examples + +Learn how to use Choice by following the [examples](./samples/choice/README.md) diff --git a/docs/eventing/samples/choice/README.md b/docs/eventing/samples/choice/README.md new file mode 100644 index 000000000..c8825d9ef --- /dev/null +++ b/docs/eventing/samples/choice/README.md @@ -0,0 +1,25 @@ +The following examples will help you understand how to use Choice +to describe various flows. + +## Prerequisites + +All examples require: +- A Kubernetes cluster with + - Knative Eventing v0.8+ + - Knative Service v0.8+ + +All examples are using the [default channel template](../../channels/default-channels.md). + +## Examples + +For each of these examples below, we'll use +[`CronJobSource`](../cronjob-source/README.md) as the source of events. + +We also use simple +[functions](https://github.com/lionelvillard/knative-functions) to perform trivial filtering, transformation and routing of the incoming events. + +The examples are: + +- [Choice with multiple cases and global reply](./multiple-cases/README.md) +- [Choice with mutually exclusive cases](./mutual-exclusivity/README.md) + diff --git a/docs/eventing/samples/choice/_index.md b/docs/eventing/samples/choice/_index.md new file mode 100644 index 000000000..96d9108ec --- /dev/null +++ b/docs/eventing/samples/choice/_index.md @@ -0,0 +1,8 @@ +--- +title: "Choice Example" +linkTitle: "Choice" +weight: 10 +type: "docs" +--- + +{{% readfile file="README.md" relative="true" markdown="true" %}} diff --git a/docs/eventing/samples/choice/multiple-cases/README.md b/docs/eventing/samples/choice/multiple-cases/README.md new file mode 100644 index 000000000..3c7066c8d --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/README.md @@ -0,0 +1,187 @@ +We are going to create a Choice with two cases: +- the first case accepts events with a time that is is even +- the second case accepts events with a time that is is odd + +The events produced by each case are then sent to the `event-display` service. + +## Prerequisites + +Please refer to the sample overview for the [prerequisites](../README.md). + +### Create the Knative Services + +Let's first create the filter and transformer services that we will use in our Choice. + +```yaml +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: even-filter +spec: + template: + spec: + containers: + - image: villardl/filter-nodejs + env: + - name: FILTER + value: | + Math.round(Date.parse(event.time) / 60000) % 2 === 0 +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: odd-filter +spec: + template: + spec: + containers: + - image: villardl/filter-nodejs + env: + - name: FILTER + value: | + Math.round(Date.parse(event.time) / 60000) % 2 !== 0 +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: even-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs + env: + - name: TRANSFORMER + value: | + ({"message": "we are even!"}) + +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: odd-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs + env: + - name: TRANSFORMER + value: | + ({"message": "this is odd!"}) +. +``` + +```shell +kubectl create -f ./filters.yaml -f ./transformers.yaml +``` + +### Create the Choice + +The `choice.yaml` file contains the specifications for creating the Choice. + +```yaml +apiVersion: messaging.knative.dev/v1alpha1 +kind: Choice +metadata: + name: odd-even-choice +spec: + channelTemplate: + apiVersion: messaging.knative.dev/v1alpha1 + kind: InMemoryChannel + cases: + - filter: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: even-filter + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: even-transformer + - filter: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: odd-filter + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: odd-transformer + reply: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: event-display +``` + +```shell +kubectl create -f ./choice.yaml +``` + +### Create the CronJobSource targeting the Choice + +This will create a CronJobSource which will send a CloudEvent with {"message": +"Even or odd?"} as the data payload every minute. + +```yaml +apiVersion: sources.eventing.knative.dev/v1alpha1 +kind: CronJobSource +metadata: + name: cronjob-source +spec: + schedule: "*/1 * * * *" + data: '{"message": "Even or odd?"}' + sink: + apiVersion: messaging.knative.dev/v1alpha1 + kind: Choice + name: odd-even-choice +``` + +```shell +kubectl create -f ./cron-source.yaml +``` + +### Inspecting the results + +You can now see the final output by inspecting the logs of the event-display +pods. Note that since we set the `CronJobSource` to emit every minute, it +might take some time for the events to show up in the logs. + +Let's look at the `event-display` log: + +```shell +kubectl logs -l serving.knative.dev/service=event-display --tail=30 -c user-container + +☁️ cloudevents.Event +Validation: valid +Context Attributes, + specversion: 0.3 + type: dev.knative.cronjob.event + source: /apis/v1/namespaces/default/cronjobsources/cronjob-source + id: 2884f4a3-53f2-4926-a32c-e696a6fb3697 + time: 2019-07-31T18:10:00.000309586Z + datacontenttype: application/json; charset=utf-8 +Extensions, + knativehistory: odd-even-choice-kn-choice-0-kn-channel.default.svc.cluster.local, odd-even-choice-kn-choice-kn-channel.default.svc.cluster.local +Data, + { + "message": "we are even!" + } +☁️ cloudevents.Event +Validation: valid +Context Attributes, + specversion: 0.3 + type: dev.knative.cronjob.event + source: /apis/v1/namespaces/default/cronjobsources/cronjob-source + id: 2e519f11-3b6f-401c-b196-73f8b235de58 + time: 2019-07-31T18:11:00.002649881Z + datacontenttype: application/json; charset=utf-8 +Extensions, + knativehistory: odd-even-choice-kn-choice-1-kn-channel.default.svc.cluster.local, odd-even-choice-kn-choice-kn-channel.default.svc.cluster.local +Data, + { + "message": "this is odd!" + } +``` \ No newline at end of file diff --git a/docs/eventing/samples/choice/multiple-cases/_index.md b/docs/eventing/samples/choice/multiple-cases/_index.md new file mode 100644 index 000000000..f8f362922 --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/_index.md @@ -0,0 +1,8 @@ +--- +title: "Multiple Cases" +linkTitle: "Multiple Cases" +weight: 20 +type: "docs" +--- + +{{% readfile file="README.md" relative="true" markdown="true" %}} diff --git a/docs/eventing/samples/choice/multiple-cases/choice.yaml b/docs/eventing/samples/choice/multiple-cases/choice.yaml new file mode 100644 index 000000000..de9214a03 --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/choice.yaml @@ -0,0 +1,33 @@ +apiVersion: messaging.knative.dev/v1alpha1 +kind: Choice +metadata: + name: odd-even-choice +spec: + channelTemplate: + apiVersion: messaging.knative.dev/v1alpha1 + kind: InMemoryChannel + cases: + - filter: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: even-filter + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: even-transformer + - filter: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: odd-filter + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: odd-transformer + reply: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: event-display \ No newline at end of file diff --git a/docs/eventing/samples/choice/multiple-cases/cron-source.yaml b/docs/eventing/samples/choice/multiple-cases/cron-source.yaml new file mode 100644 index 000000000..c328a32e1 --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/cron-source.yaml @@ -0,0 +1,11 @@ +apiVersion: sources.eventing.knative.dev/v1alpha1 +kind: CronJobSource +metadata: + name: cronjob-source +spec: + schedule: "*/1 * * * *" + data: '{"message": "Even or odd?"}' + sink: + apiVersion: messaging.knative.dev/v1alpha1 + kind: Choice + name: odd-even-choice diff --git a/docs/eventing/samples/choice/multiple-cases/event-display.yaml b/docs/eventing/samples/choice/multiple-cases/event-display.yaml new file mode 100644 index 000000000..2d374c853 --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/event-display.yaml @@ -0,0 +1,9 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: event-display +spec: + template: + spec: + containers: + - image: gcr.io/knative-releases/github.com/knative/eventing-sources/cmd/event_display diff --git a/docs/eventing/samples/choice/multiple-cases/filters.yaml b/docs/eventing/samples/choice/multiple-cases/filters.yaml new file mode 100644 index 000000000..f304cd367 --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/filters.yaml @@ -0,0 +1,27 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: even-filter +spec: + template: + spec: + containers: + - image: villardl/filter-nodejs:0.1 + env: + - name: FILTER + value: | + Math.round(Date.parse(event.time) / 60000) % 2 === 0 +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: odd-filter +spec: + template: + spec: + containers: + - image: villardl/filter-nodejs:0.1 + env: + - name: FILTER + value: | + Math.round(Date.parse(event.time) / 60000) % 2 !== 0 \ No newline at end of file diff --git a/docs/eventing/samples/choice/multiple-cases/transformers.yaml b/docs/eventing/samples/choice/multiple-cases/transformers.yaml new file mode 100644 index 000000000..b3972e33b --- /dev/null +++ b/docs/eventing/samples/choice/multiple-cases/transformers.yaml @@ -0,0 +1,28 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: even-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs:0.1 + env: + - name: TRANSFORMER + value: | + ({"message": "we are even!"}) + +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: odd-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs:0.1 + env: + - name: TRANSFORMER + value: | + ({"message": "this is odd!"}) diff --git a/docs/eventing/samples/choice/mutual-exclusivity/README.md b/docs/eventing/samples/choice/mutual-exclusivity/README.md new file mode 100644 index 000000000..ba9b2ac37 --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/README.md @@ -0,0 +1,171 @@ +In this example, we are going to see how we can create a Choice +with mutually exclusive cases. + +This example is the same as the [multiple cases example](../multiple-cases/README.md) except +that we are now going to rely on the Knative [switcher](https://github.com/lionelvillard/knative-functions#switcher) function to provide a soft mutual exclusivity guarantee. + +NOTE: this example has to be deployed in the default namespace. + +## Prerequisites + +Please refer to the sample overview for the [prerequisites](../README.md). + +### Create the Knative Services + +Let's first create the switcher and transformer services that we will use in our Choice. + +```yaml +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: me-even-odd-switcher +spec: + template: + spec: + containers: + - image: villardl/switcher-nodejs:0.1 + env: + - name: EXPRESSION + value: Math.round(Date.parse(event.time) / 60000) % 2 + - name: CASES + value: '[0, 1]' +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: even-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs + env: + - name: TRANSFORMER + value: | + ({"message": "we are even!"}) + +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: odd-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs + env: + - name: TRANSFORMER + value: | + ({"message": "this is odd!"}) +. +``` + +```shell +kubectl create -f ./switcher.yaml -f ./transformers.yaml +``` + +### Create the Choice + +The `choice.yaml` file contains the specifications for creating the Choice. + +```yaml +apiVersion: messaging.knative.dev/v1alpha1 +kind: Choice +metadata: + name: me-odd-even-choice +spec: + channelTemplate: + apiVersion: messaging.knative.dev/v1alpha1 + kind: InMemoryChannel + cases: + - filter: + uri: "http://me-even-odd-switcher.default.svc.cluster.local/0" + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-even-transformer + - filter: + uri: "http://me-even-odd-switcher.default.svc.cluster.local/1" + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-odd-transformer + reply: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-event-display +``` + +```shell +kubectl create -f ./choice.yaml +``` + +### Create the CronJobSource targeting the Choice + +This will create a CronJobSource which will send a CloudEvent with {"message": +"Even or odd?"} as the data payload every minute. + +```yaml +apiVersion: sources.eventing.knative.dev/v1alpha1 +kind: CronJobSource +metadata: + name: me-cronjob-source +spec: + schedule: "*/1 * * * *" + data: '{"message": "Even or odd?"}' + sink: + apiVersion: messaging.knative.dev/v1alpha1 + kind: Choice + name: me-odd-even-choice +``` + +```shell +kubectl create -f ./cron-source.yaml +``` + +### Inspecting the results + +You can now see the final output by inspecting the logs of the `me-event-display` +pods. Note that since we set the `CronJobSource` to emit every minute, it +might take some time for the events to show up in the logs. + +Let's look at the `me-event-display` log: + +```shell +kubectl logs -l serving.knative.dev/service=me-event-display --tail=30 -c user-container + +☁️ cloudevents.Event +Validation: valid +Context Attributes, + specversion: 0.3 + type: dev.knative.cronjob.event + source: /apis/v1/namespaces/default/cronjobsources/me-cronjob-source + id: 48eea348-8cfd-4aba-9ead-cb024ce16a48 + time: 2019-07-31T20:56:00.000477587Z + datacontenttype: application/json; charset=utf-8 +Extensions, + knativehistory: me-odd-even-choice-kn-choice-kn-channel.default.svc.cluster.local, me-odd-even-choice-kn-choice-0-kn-channel.default.svc.cluster.local +Data, + { + "message": "we are even!" + } +☁️ cloudevents.Event +Validation: valid +Context Attributes, + specversion: 0.3 + type: dev.knative.cronjob.event + source: /apis/v1/namespaces/default/cronjobsources/me-cronjob-source + id: 42717dcf-b194-4b36-a094-3ea20e565ad5 + time: 2019-07-31T20:57:00.000312243Z + datacontenttype: application/json; charset=utf-8 +Extensions, + knativehistory: me-odd-even-choice-kn-choice-1-kn-channel.default.svc.cluster.local, me-odd-even-choice-kn-choice-kn-channel.default.svc.cluster.local +Data, + { + "message": "this is odd!" + } +``` + diff --git a/docs/eventing/samples/choice/mutual-exclusivity/_index.md b/docs/eventing/samples/choice/mutual-exclusivity/_index.md new file mode 100644 index 000000000..791a92e18 --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/_index.md @@ -0,0 +1,8 @@ +--- +title: "Mutual Exclusive Cases" +linkTitle: "Mutual Exclustivity" +weight: 20 +type: "docs" +--- + +{{% readfile file="README.md" relative="true" markdown="true" %}} diff --git a/docs/eventing/samples/choice/mutual-exclusivity/choice.yaml b/docs/eventing/samples/choice/mutual-exclusivity/choice.yaml new file mode 100644 index 000000000..fdcc200cd --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/choice.yaml @@ -0,0 +1,27 @@ +apiVersion: messaging.knative.dev/v1alpha1 +kind: Choice +metadata: + name: me-odd-even-choice +spec: + channelTemplate: + apiVersion: messaging.knative.dev/v1alpha1 + kind: InMemoryChannel + cases: + - filter: + uri: "http://me-even-odd-switcher.default.svc.cluster.local/0" + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-even-transformer + - filter: + uri: "http://me-even-odd-switcher.default.svc.cluster.local/1" + subscriber: + ref: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-odd-transformer + reply: + apiVersion: serving.knative.dev/v1alpha1 + kind: Service + name: me-event-display \ No newline at end of file diff --git a/docs/eventing/samples/choice/mutual-exclusivity/cron-source.yaml b/docs/eventing/samples/choice/mutual-exclusivity/cron-source.yaml new file mode 100644 index 000000000..72478b130 --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/cron-source.yaml @@ -0,0 +1,11 @@ +apiVersion: sources.eventing.knative.dev/v1alpha1 +kind: CronJobSource +metadata: + name: me-cronjob-source +spec: + schedule: "*/1 * * * *" + data: '{"message": "Even or odd?"}' + sink: + apiVersion: messaging.knative.dev/v1alpha1 + kind: Choice + name: me-odd-even-choice diff --git a/docs/eventing/samples/choice/mutual-exclusivity/event-display.yaml b/docs/eventing/samples/choice/mutual-exclusivity/event-display.yaml new file mode 100644 index 000000000..c9f95c4a3 --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/event-display.yaml @@ -0,0 +1,9 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: me-event-display +spec: + template: + spec: + containers: + - image: gcr.io/knative-releases/github.com/knative/eventing-sources/cmd/event_display diff --git a/docs/eventing/samples/choice/mutual-exclusivity/switcher.yaml b/docs/eventing/samples/choice/mutual-exclusivity/switcher.yaml new file mode 100644 index 000000000..a4921af1e --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/switcher.yaml @@ -0,0 +1,14 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: me-even-odd-switcher +spec: + template: + spec: + containers: + - image: villardl/switcher-nodejs:0.1 + env: + - name: EXPRESSION + value: Math.round(Date.parse(event.time) / 60000) % 2 + - name: CASES + value: '[0, 1]' diff --git a/docs/eventing/samples/choice/mutual-exclusivity/transformers.yaml b/docs/eventing/samples/choice/mutual-exclusivity/transformers.yaml new file mode 100644 index 000000000..8a6e72bbd --- /dev/null +++ b/docs/eventing/samples/choice/mutual-exclusivity/transformers.yaml @@ -0,0 +1,28 @@ +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: me-even-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs:0.1 + env: + - name: TRANSFORMER + value: | + ({"message": "we are even!"}) + +--- +apiVersion: serving.knative.dev/v1alpha1 +kind: Service +metadata: + name: me-odd-transformer +spec: + template: + spec: + containers: + - image: villardl/transformer-nodejs:0.1 + env: + - name: TRANSFORMER + value: | + ({"message": "this is odd!"})