From d6caf7670a501c1c754d9702799386dccafbda6d Mon Sep 17 00:00:00 2001 From: Davide Salerno Date: Mon, 26 Jun 2023 09:44:22 +0200 Subject: [PATCH 1/2] [KOGITO-9321] Testing Operator using Order SWF example Signed-off-by: Davide Salerno --- .../serverless-workflow-inventory/README.md | 60 ++++++ .../serverless-workflow-inventory/order.svg | 1 + .../01-configmap_01-order-resources.yaml | 62 ++++++ .../resources/01-sonataflow_order.yaml | 179 ++++++++++++++++++ .../resources/02-configmap_order-props.yaml | 15 ++ 5 files changed, 317 insertions(+) create mode 100644 serverless-operator-examples/serverless-workflow-inventory/README.md create mode 100644 serverless-operator-examples/serverless-workflow-inventory/order.svg create mode 100644 serverless-operator-examples/serverless-workflow-inventory/resources/01-configmap_01-order-resources.yaml create mode 100644 serverless-operator-examples/serverless-workflow-inventory/resources/01-sonataflow_order.yaml create mode 100644 serverless-operator-examples/serverless-workflow-inventory/resources/02-configmap_order-props.yaml diff --git a/serverless-operator-examples/serverless-workflow-inventory/README.md b/serverless-operator-examples/serverless-workflow-inventory/README.md new file mode 100644 index 0000000000..f932b1431a --- /dev/null +++ b/serverless-operator-examples/serverless-workflow-inventory/README.md @@ -0,0 +1,60 @@ +# Serverless Operator - Inventory Example + +## Description + +This example is meant to let you understand ho 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 will report here for this reason only a short summary about the workflow use case, and we kindly suggest you to read the full documentation 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 come 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 send 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 send 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 **cancelling the order** by also cancelling 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 Kubernete CustomResources 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 SonataFlow -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 '{ "workflowdata": { "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 Quarkus is running you can spot the following message in log: +```shell +Order received: order-123 +``` + +**CONGRATULATION!!!** Your first Serverless Workflow was executed as expected! diff --git a/serverless-operator-examples/serverless-workflow-inventory/order.svg b/serverless-operator-examples/serverless-workflow-inventory/order.svg new file mode 100644 index 0000000000..6549e4923c --- /dev/null +++ b/serverless-operator-examples/serverless-workflow-inventory/order.svg @@ -0,0 +1 @@ + Start Order ReceivedCheck InventoryItem Available?Prepare for Shipping Forward to External Supplier Order Shipped or Cancelled Is Shipped?Compensate Order End Notify Customer End order cance... order cance... .inventory .inventory \ No newline at end of file diff --git a/serverless-operator-examples/serverless-workflow-inventory/resources/01-configmap_01-order-resources.yaml b/serverless-operator-examples/serverless-workflow-inventory/resources/01-configmap_01-order-resources.yaml new file mode 100644 index 0000000000..c34e6f018c --- /dev/null +++ b/serverless-operator-examples/serverless-workflow-inventory/resources/01-configmap_01-order-resources.yaml @@ -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 diff --git a/serverless-operator-examples/serverless-workflow-inventory/resources/01-sonataflow_order.yaml b/serverless-operator-examples/serverless-workflow-inventory/resources/01-sonataflow_order.yaml new file mode 100644 index 0000000000..f994ff07d8 --- /dev/null +++ b/serverless-operator-examples/serverless-workflow-inventory/resources/01-sonataflow_order.yaml @@ -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 diff --git a/serverless-operator-examples/serverless-workflow-inventory/resources/02-configmap_order-props.yaml b/serverless-operator-examples/serverless-workflow-inventory/resources/02-configmap_order-props.yaml new file mode 100644 index 0000000000..87a490e40b --- /dev/null +++ b/serverless-operator-examples/serverless-workflow-inventory/resources/02-configmap_order-props.yaml @@ -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 From 796cdc52eeae5e25724bbf7021aa74f6ef461b13 Mon Sep 17 00:00:00 2001 From: Davide Salerno Date: Wed, 28 Jun 2023 21:38:58 +0200 Subject: [PATCH 2/2] Apply Ricardo's suggestions from code review Co-authored-by: Ricardo Zanini <1538000+ricardozanini@users.noreply.github.com> --- .../serverless-workflow-inventory/README.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/serverless-operator-examples/serverless-workflow-inventory/README.md b/serverless-operator-examples/serverless-workflow-inventory/README.md index f932b1431a..b847a6c948 100644 --- a/serverless-operator-examples/serverless-workflow-inventory/README.md +++ b/serverless-operator-examples/serverless-workflow-inventory/README.md @@ -2,18 +2,18 @@ ## Description -This example is meant to let you understand ho 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 will report here for this reason only a short summary about the workflow use case, and we kindly suggest you to read the full documentation about this tutorial if you need more details about it. +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 come 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 send 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 send 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 **cancelling the order** by also cancelling the shipping. +* 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: +The following picture shows a high-level design: ![Inventory Workflow](order.svg "Inventory Workflow") @@ -25,7 +25,7 @@ The following picture shows a high level design: 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 Kubernete CustomResources that you need in order to deploy this workflow on your cluster 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: @@ -40,10 +40,10 @@ Open a new terminal and start the flow with the following command: ```shell #!/bin/sh -ADDRESS=$(kubectl get SonataFlow -n my-workflows -o custom-columns="URL":.status.address.url --no-headers) +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 '{ "workflowdata": { "orderId": "order-123"} }' + -d '{ "orderId": "order-123" }' ``` You should get back the output which resembles the following: @@ -52,9 +52,9 @@ You should get back the output which resembles the following: {"id":"7484e05f-3b95-4ac7-8c09-a2c717a0293e","workflowdata":{"orderId":"order-123"}} ``` -In the other terminal where Quarkus is running you can spot the following message in log: +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 Serverless Workflow was executed as expected! +**CONGRATULATION!!!** Your first workflow was executed as expected!