choice documentation and samples (#1631)

* choice documentation and samples

* Update docs/eventing/samples/choice/_index.md

Co-Authored-By: Sam O'Dell <31352624+samodell@users.noreply.github.com>

* Update docs/eventing/choice.md

Co-Authored-By: Sam O'Dell <31352624+samodell@users.noreply.github.com>

* fix typo
This commit is contained in:
Lionel Villard 2019-08-02 14:34:44 -04:00 committed by Knative Prow Robot
parent 2e839ace71
commit 781a554626
17 changed files with 647 additions and 0 deletions

43
docs/eventing/choice.md Normal file
View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,8 @@
---
title: "Choice Example"
linkTitle: "Choice"
weight: 10
type: "docs"
---
{{% readfile file="README.md" relative="true" markdown="true" %}}

View File

@ -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!"
}
```

View File

@ -0,0 +1,8 @@
---
title: "Multiple Cases"
linkTitle: "Multiple Cases"
weight: 20
type: "docs"
---
{{% readfile file="README.md" relative="true" markdown="true" %}}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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!"})

View File

@ -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!"
}
```

View File

@ -0,0 +1,8 @@
---
title: "Mutual Exclusive Cases"
linkTitle: "Mutual Exclustivity"
weight: 20
type: "docs"
---
{{% readfile file="README.md" relative="true" markdown="true" %}}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]'

View File

@ -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!"})