[KOGITO-9321] Testing Operator using Order SWF example (#1707)

* [KOGITO-9321] Testing Operator using Order SWF example

Signed-off-by: Davide Salerno <dsalerno@redhat.com>

* Apply Ricardo's suggestions from code review

Co-authored-by: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com>

---------

Signed-off-by: Davide Salerno <dsalerno@redhat.com>
Co-authored-by: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com>
This commit is contained in:
Davide Salerno
2023-08-02 17:22:06 +02:00
committed by GitHub
parent 97a852dc2c
commit 7cc7fe9540
5 changed files with 317 additions and 0 deletions

View File

@ -0,0 +1,60 @@
# Serverless Operator - Inventory Example
## Description
This example is meant to let you understand how to deploy on Kubernetes the [Inventory Logic Tutorial](https://redhat-scholars.github.io/serverless-workflow/osl/index.html) using the [Operator](https://github.com/kiegroup/kogito-serverless-operator).
We'll report here for this reason only a short summary of the workflow use case, and we'd suggest you [read the complete documentation](https://redhat-scholars.github.io/serverless-workflow/osl/index.html) about this tutorial if you need more details about it.
### Use Case
An e-commerce company has to implement the following **order management** workflow:
* When a new order comes in, they need to **check the inventory** for the availability of the items. If the items are available the order will be **prepared for shipping** (picking, packaging, printing label, etc), when the shipping is completed, the shipping department sends an event back to the workflow, and the customer is **notified** about the shipping status with usual tracking information.
* If the item is out of stock, the order will be forwarded to an **external supplier** who will take care of the shipping procedure, when the **supplier ships** the order, it also sends an event back to the workflow, in such a way the workflow can continue and **send the notification** to the customer.
* As long as the order is not shipped, the customer has the option of **canceling the order** by also canceling the shipping.
The following picture shows a high-level design:
![Inventory Workflow](order.svg "Inventory Workflow")
## Deploy the Inventory workflow on Kubernetes
### Prepare your environment
1. Install [minikube](https://minikube.sigs.k8s.io/docs/start/)
2. Install the [Operator](https://kiegroup.github.io/kogito-docs/serverlessworkflow/latest/cloud/operator/install-serverless-operator.html)
### Deploy the Workflow with Quarkus in Dev Mode
In the [resources](./resources/) directory you can find the Kubernetes Custom Resources (CR) that you need in order to deploy this workflow on your cluster in dev mode.
To do this you only need to apply these resources using the following commands:
```bash
kubectl create namespace my-workflows
kubectl apply -f ./resources/ -n my-workflows
```
### Test that the workflow is running
Open a new terminal and start the flow with the following command:
```shell
#!/bin/sh
ADDRESS=$(kubectl get workflow -n my-workflows -o custom-columns="URL":.status.address.url --no-headers)
curl -X POST $ADDRESS \
-H 'Content-Type:application/json' -H 'Accept:application/json' \
-d '{ "orderId": "order-123" }'
```
You should get back the output which resembles the following:
```shell
{"id":"7484e05f-3b95-4ac7-8c09-a2c717a0293e","workflowdata":{"orderId":"order-123"}}
```
In the other terminal where the workflow is running you can spot the following message in the log:
```shell
Order received: order-123
```
**CONGRATULATION!!!** Your first workflow was executed as expected!

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -0,0 +1,62 @@
apiVersion: v1
data:
supplier.yaml: |
---
openapi: 3.0.3
info:
title: Supplier API
version: 1.0.0-SNAPSHOT
tags:
- name: supplier
description: Supplier Sample
paths:
/supplier/{supplier-id}:
post:
tags:
- Supplier
operationId: sendOrder
parameters:
- name: supplier-id
in: path
required: true
schema:
type: string
requestBody:
content:
text/plain:
schema:
type: string
responses:
"200":
description: OK
content:
text/plain:
schema:
type: string
delete:
tags:
- Supplier
operationId: cancelOrder
parameters:
- name: supplier-id
in: path
required: true
schema:
type: string
requestBody:
content:
text/plain:
schema:
type: string
responses:
"200":
description: OK
content:
text/plain:
schema:
type: string
kind: ConfigMap
metadata:
creationTimestamp: null
name: 01-order-resources
namespace: my-workflows

View File

@ -0,0 +1,179 @@
apiVersion: sonataflow.org/v1alpha08
kind: SonataFlow
metadata:
annotations:
sonataflow.org/description: Order Workflow Sample
sonataflow.org/expressionLang: jq
sonataflow.org/profile: dev
sonataflow.org/version: "1.0"
creationTimestamp: null
labels:
app: order
name: order
namespace: my-workflows
spec:
flow:
events:
- correlation:
- contextAttributeName: orderid
dataOnly: true
kind: consumed
name: orderEvent
source: Client
type: OrderEventType
- correlation:
- contextAttributeName: orderid
dataOnly: true
kind: consumed
name: shippingEvent
source: Shipper
type: ShippingEventType
- correlation:
- contextAttributeName: orderid
dataOnly: true
kind: consumed
name: cancelEvent
source: Client
type: CancelEventType
functions:
- name: printMessage
operation: sysout
type: custom
- name: sendOrder
operation: specs/supplier.yaml#sendOrder
type: rest
- name: cancelOrder
operation: specs/supplier.yaml#cancelOrder
type: rest
start:
stateName: Order Received
states:
- exclusive: true
name: Order Received
onEvents:
- actionMode: sequential
eventDataFilter:
useData: true
eventRefs:
- orderEvent
transition:
nextState: Check Inventory
type: event
- actionMode: sequential
actions:
- actionDataFilter:
fromStateData: .
results: '{inventory: .item | test("0+") }'
useResults: true
functionRef:
arguments:
message: '"Check Inventory " + .orderId'
invoke: sync
refName: printMessage
name: printAction
name: Check Inventory
transition:
nextState: Item Available?
type: operation
- dataConditions:
- condition: .inventory
transition:
nextState: Prepare for Shipping
defaultCondition:
transition:
nextState: Forward to External Supplier
name: Item Available?
type: switch
- actionMode: sequential
actions:
- actionDataFilter:
useResults: true
functionRef:
arguments:
message: '"Prepare for Shipping"'
invoke: sync
refName: printMessage
name: printAction
name: Prepare for Shipping
transition:
nextState: Order Shipped or Cancelled
type: operation
- actionMode: sequential
actions:
- actionDataFilter:
useResults: true
functionRef:
arguments:
content: .orderId
supplier-id: '"1"'
invoke: sync
refName: sendOrder
name: sendOrderRestCall
name: Forward to External Supplier
transition:
nextState: Order Shipped or Cancelled
type: operation
- exclusive: true
name: Order Shipped or Cancelled
onEvents:
- actionMode: sequential
eventDataFilter:
useData: true
eventRefs:
- shippingEvent
- actionMode: sequential
eventDataFilter:
data: '{cancel:true}'
useData: true
eventRefs:
- cancelEvent
transition:
nextState: Is Shipped?
type: event
- dataConditions:
- condition: .cancel == true
name: order cancelled
transition:
nextState: Compensate Order
defaultCondition:
transition:
nextState: Notify Customer
name: Is Shipped?
type: switch
- actionMode: sequential
actions:
- actionDataFilter:
useResults: true
functionRef:
arguments:
message: '"Compensate Order"'
invoke: sync
refName: printMessage
name: printAction
end:
compensate: true
terminate: true
name: Compensate Order
type: operation
- actionMode: sequential
actions:
- actionDataFilter:
useResults: true
functionRef:
arguments:
message: '"Notify Customer"'
invoke: sync
refName: printMessage
name: printAction
end:
terminate: true
name: Notify Customer
type: operation
resources:
configMaps:
- configMap:
name: 01-order-resources
workflowPath: specs
status:
address: {}
lastTimeRecoverAttempt: null

View File

@ -0,0 +1,15 @@
apiVersion: v1
data:
application.properties: |
# Generate OpenAPIs with operationId
mp.openapi.extensions.smallrye.operationIdStrategy=METHOD
# OpenAPIs endpoint
quarkus.rest-client.supplier_yaml.url=https://order-swf-supplier-kubesmarts.rhba-0ad6762cc85bcef5745bb684498c2436-0000.us-south.containers.appdomain.cloud
kind: ConfigMap
metadata:
creationTimestamp: null
labels:
app: order
name: order-props
namespace: my-workflows