From 5aa5d795bae8e533ec403899e32e641e6a01027a Mon Sep 17 00:00:00 2001 From: nmirasch Date: Wed, 29 Nov 2023 15:22:04 +0100 Subject: [PATCH 1/6] KOGITO-9971: [Guides] Dataindex deployment use cases with operator --- serverlessworkflow/antora.yml | 1 + serverlessworkflow/modules/ROOT/nav.adoc | 3 + .../data-index/common/_prerequisites.adoc | 28 +++ .../common/_querying_dataindex.adoc | 105 +++++++++ .../data-index/data-index-usecase-multi.adoc | 221 ++++++++++++++++++ .../data-index-usecase-singleton.adoc | 206 ++++++++++++++++ .../modules/ROOT/pages/index.adoc | 8 + 7 files changed, 572 insertions(+) create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/common/_prerequisites.adoc create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/common/_querying_dataindex.adoc create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc diff --git a/serverlessworkflow/antora.yml b/serverlessworkflow/antora.yml index eb283e70b..c2f8c8685 100644 --- a/serverlessworkflow/antora.yml +++ b/serverlessworkflow/antora.yml @@ -109,6 +109,7 @@ asciidoc: kaoto_url: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-kaoto minikube_url: https://minikube.sigs.k8s.io kogito_serverless_operator_url: https://github.com/apache/incubator-kie-kogito-serverless-operator/ + flow_examples_operator_url: https://github.com/flows-examples/techpreview2/ docs_issues_url: https://github.com/apache/incubator-kie-kogito-docs/issues/new ocp_local_url: https://access.redhat.com/documentation/en-us/red_hat_openshift_local/2.17 ocp_knative_serving_url: https://docs.openshift.com/container-platform/4.12/serverless/install/installing-knative-serving.html diff --git a/serverlessworkflow/modules/ROOT/nav.adoc b/serverlessworkflow/modules/ROOT/nav.adoc index 7429f9d6f..1f8a3db4c 100644 --- a/serverlessworkflow/modules/ROOT/nav.adoc +++ b/serverlessworkflow/modules/ROOT/nav.adoc @@ -111,6 +111,9 @@ ** xref:data-index/data-index-core-concepts.adoc[Core concepts] ** xref:data-index/data-index-service.adoc[Standalone service] ** xref:data-index/data-index-quarkus-extension.adoc[Quarkus Extension] +** Operator +*** xref:data-index/data-index-usecase-singleton.adoc[] +*** xref:data-index/data-index-usecase-multi.adoc[] //** Quarkus Extensions TODO: https://issues.redhat.com/browse/KOGITO-9463 * Use Cases ** xref:use-cases/orchestration-based-saga-pattern.adoc[Saga Orchestration] diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/common/_prerequisites.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/common/_prerequisites.adoc new file mode 100644 index 000000000..80b3418e1 --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/common/_prerequisites.adoc @@ -0,0 +1,28 @@ + +.Prerequisites +* Minikube installed with `registry` addon enabled +* `kubectl` {kubectl_prereq} +* SonataFlow operator installed if workflows are deployed. To install the operator you can see xref:cloud/operator/install-serverless-operator.adoc[]. + +[NOTE] +==== +We recommend that you start Minikube with the following parameters, note that the `registry` addon must be enabled. + +[source,shell] +---- +minikube start --cpus 4 --memory 10240 --addons registry --addons metrics-server --insecure-registry "10.0.0.0/24" --insecure-registry "localhost:5000" +---- + +To verify that the registry addon was property added you can execute this command: + +[source,shell] +---- +minikube addons list | grep registry +---- + +---- +| registry | minikube | enabled ✅ | Google | +| registry-aliases | minikube | disabled | 3rd party (unknown) | +| registry-creds | minikube | disabled | 3rd party (UPMC Enterprises) | +---- +==== \ No newline at end of file diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/common/_querying_dataindex.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/common/_querying_dataindex.adoc new file mode 100644 index 000000000..7effdb6fe --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/common/_querying_dataindex.adoc @@ -0,0 +1,105 @@ +[[querying-dataindex-minikube]] +== Querying Data Index service on Minikube + +You can use the public Data Index endpoint to play around with the GraphiQL interface. + +.Procedure +This procedure apply to all use cases with that deploys the Data Index Service. + +* Get the Data Index Url: +[source,shell] +---- +minikube service data-index-service-postgresql --url -n my_usecase +---- + +* Open the GrahiqlUI + +Using the url returned, open a browser window in the following url http://192.168.49.2:32409/graphiql/, + +[NOTE] +==== +that IP and port will be different in your installation, and don't forget to add the last slash "/" to the url, otherwise the GraphiqlUI won't be opened. +==== + + +To see the process instances information you can execute this query: + +[source,shell] +---- +{ + ProcessInstances { + id, + processId, + processName, + variables, + state, + endpoint, + serviceUrl, + start, + end + } +} +---- + +The results should be something like: + +[source] +---- +{ + "data": { + "ProcessInstances": [ + { + "id": "3ed8bf63-85c9-425d-9099-49bfb63608cb", + "processId": "greeting", + "processName": "workflow", + "variables": "{\"workflowdata\":{\"name\":\"John\",\"greeting\":\"Hello from JSON Workflow, \",\"language\":\"English\"}}", + "state": "COMPLETED", + "endpoint": "/greeting", + "serviceUrl": "http://greeting", + "start": "2023-09-13T06:59:24.319Z", + "end": "2023-09-13T06:59:24.400Z" + } + ] + } +} +---- + +To see the jobs instances information, if any, you can execute this query: + +[source] +---- +{ + Jobs { + id, + processId, + processInstanceId, + status, + expirationTime, + retries, + endpoint, + callbackEndpoint + } +} +---- + +The results should be something like: + +[source] +---- +{ + "data": { + "Jobs": [ + { + "id": "55c7aadb-3dff-4b97-af8e-cc45014b1c0d", + "processId": "callbackstatetimeouts", + "processInstanceId": "299886b7-2b78-4965-a701-16783c4162d8", + "status": "EXECUTED", + "expirationTime": null, + "retries": 0, + "endpoint": "http://jobs-service-postgresql/jobs", + "callbackEndpoint": "http://callbackstatetimeouts:80/management/jobs/callbackstatetimeouts/instances/299886b7-2b78-4965-a701-16783c4162d8/timers/-1" + } + ] + } +} +---- \ No newline at end of file diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc new file mode 100644 index 000000000..078ffe22e --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc @@ -0,0 +1,221 @@ += Deploying Data Index and multiple {product_name} application on Minikube +:compat-mode!: +// Metadata: +:description: Deploying Multiple {product_name} pushing to single Data Index on Minikube +:keywords: kogito, workflow, quarkus, serverless, kubectl, minikube, operator, dataindex +:table-caption: Data Set +// envs for common content +:kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. +//Common constants +:data_index_ref: Data Index + + +This document describes how to deploy a multiple {product_name} workflow applications and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. + +For more information about Minikube and related system requirements, see link:{minikube_url}/docs/start/[Getting started with Minikube] documentation. + +This use case is intended to represent an installation with: + +* A singleton Data Index Service with PostgreSQL persistence +* The `greeting` workflow (no persistence), that is configured to register events to the Data Index Service. +* The `helloworld` workflow (no persistence), that is configured to register events to the Data Index Service. +* Both workflows are configured to register the process events on the {data_index_ref} Service. + +You can directly access the UseCase2 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Use Cases repository]. + +// shared pre req +include::common/_prerequisites.adoc[] + +You can check the Minikube installation by entering the following commands in a command terminal: + +.Verify Minikube version +[source,shell] +---- +minikube version +---- + +.Verify `kubectl` CLI version +[source,shell] +---- +kubectl version +---- + +[NOTE] +==== +If `kubectl` is not installed, then Minikube handles it when you execute the following command: + +.`kubectl` is available using Minikube +[source,shell] +---- +alias kubectl="minikube kubectl --" +---- +==== + +.Procedure +. After cloning the link:{flow_examples_operator_url}[SonataFlow Use Cases repository]. Open a terminal and run the following commands +. Create the namespace: ++ +-- +[source,shell] +---- +kubectl create namespace usecase2 +---- +-- + +. Deploy the {data_index_ref} Service and postgresql database: ++ +-- + +link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. + +.Use case kustomization.yaml resources that deploy {data_index_ref} deployment with persistence to a postgresql database +[source,yaml,subs="attributes+"] +---- +resources: +- 01-postgres.yaml <1> +- 02-dataindex.yaml <2> + +secretGenerator: + - name: postgres-secrets + literals: + - POSTGRES_USER=sonataflow + - POSTGRES_PASSWORD=sonataflow + - POSTGRES_DB=sonataflow + - PGDATA=/var/lib/postgresql/data/mydata + +configMapGenerator: + - name: dataindex-properties + files: + - application.properties +---- +<1> Postgres database deployment +<2> {data_index_ref} deployment + +Perform the deployments executing +[source,shell] +---- +kubectl kustomize infra/dataindex | kubectl apply -f - -n usecase2 +---- + +---- +configmap/dataindex-properties-hg9ff8bff5 created +secret/postgres-secrets-22tkgc2dt7 created +service/data-index-service-postgresql created +service/postgres created +persistentvolumeclaim/postgres-pvc created +deployment.apps/data-index-service-postgresql created +deployment.apps/postgres created +---- + +Give some time for the data index to start, you can check that it's running by executing. + +[source,shell] +---- +kubectl get pod -n usecase2 +---- + +---- +NAME READY STATUS RESTARTS AGE +data-index-service-postgresql-5d76dc4468-lb259 1/1 Running 0 2m11s +postgres-7f78499688-lc8n6 1/1 Running 0 2m11s +---- +-- +. Deploy the workflow: ++ +-- + +link:{flow_examples_operator_url}/tree/main/usecases/usecase2[Here] you can find the use case kustomization required to deploy the workflow + +.Use case kustomization.yaml resources that deploys the workflow +[source,yaml,subs="attributes+"] +---- +resources: +- ../../platforms/dataindex_platform +- ../../infra/service_discovery +- ../../workflows/sonataflow-greeting +- ../../workflows/sonataflow-helloworld +---- + +Perform the deployment executing +[source,shell] +---- + kubectl kustomize usecases/usecase2 | kubectl apply -f - -n usecase2 +---- + +---- +configmap/greeting-props created +configmap/helloworld-props created +sonataflow.sonataflow.org/greeting created +sonataflow.sonataflow.org/helloworld created +sonataflowplatform.sonataflow.org/sonataflow-platform created +---- + +Give some time for the sonataflow operator to build and deploy the workflow. +To check that the workflow is ready you can use this command. + +[source,shell] +---- +kubectl get workflow -n usecase2 +---- + +---- +NAME PROFILE VERSION URL READY REASON +greeting 0.0.1 True +helloworld 0.0.1 True +---- +-- + +. Expose the workflows and get the urls: ++ +-- +[source,shell] +---- +kubectl patch svc greeting helloworld -p '{"spec": {"type": "NodePort"}}' -n usecase2 +---- + +[source,shell] +---- +minikube service greeting --url -n usecase2 +---- + +[source,shell] +---- +minikube service helloworld --url -n usecase2 +---- +-- + +. Create a workflow instance: ++ +-- +You must use the URLs calculated in step 5. + +[source,shell] +---- +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "English"}' http://192.168.49.2:32407/greeting +---- + +[source,shell] +---- +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{}' http://192.168.49.2:32327/helloworld +---- +-- + +. Clean the use case: ++ +-- +[source,shell] +---- +kubectl delete namespace usecase2 +---- +-- + +include::common/_querying_dataindex.adoc[] + +== Additional resources + +* xref:data-index/data-index-core-concepts.adoc[] +* xref:data-index/data-index-usecase-singleton.adoc[] +* xref:cloud/quarkus/deploying-on-minikube.adoc[] +* xref:cloud/operator/install-serverless-operator.adoc[] + +include::../../pages/_common-content/report-issue.adoc[] diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc new file mode 100644 index 000000000..1c54d8b0e --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc @@ -0,0 +1,206 @@ += Deploying Data Index and {product_name} application on Minikube +:compat-mode!: +// Metadata: +:description: Deploying {product_name} application and Data Index on Minikube with operator +:keywords: kogito, workflow, quarkus, serverless, kn, kubectl, minikube, operator, dataindex +:table-caption: Data Set +// envs for common content +:kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. +//Common constants +:data_index_ref: Data Index + + +This document describes how to deploy a workflow application and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. + +For more information about Minikube and related system requirements, see link:{minikube_url}/docs/start/[Getting started with Minikube] documentation. + +This use case is intended to represent an installation with: + +* A singleton Data Index Service with PostgreSQL persistence +* The `greeting` workflow (no persistence), that is configured to register events to the Data Index Service. + +You can directly access the UseCase1 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Use Cases repository]. + +// shared pre req +include::common/_prerequisites.adoc[] + +You can check the Minikube installation by entering the following commands in a command terminal: + +.Verify Minikube version +[source,shell] +---- +minikube version +---- + +.Verify `kubectl` CLI version +[source,shell] +---- +kubectl version +---- + +[NOTE] +==== +If `kubectl` is not installed, then Minikube handles it when you execute the following command: + +.`kubectl` is available using Minikube +[source,shell] +---- +alias kubectl="minikube kubectl --" +---- +==== + +.Procedure +. After cloning the link:{flow_examples_operator_url}[SonataFlow Use Cases repository]. Open a terminal and run the following commands +. Create the namespace: ++ +-- +[source,shell] +---- +kubectl create namespace usecase1 +---- +-- + +. Deploy the {data_index_ref} Service and postgresql database: ++ +-- +link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. + +.Use case kustomization.yaml resources that deploy {data_index_ref} deployment with persistence to a postgresql database +[source,yaml,subs="attributes+"] +---- +resources: +- 01-postgres.yaml <1> +- 02-dataindex.yaml <2> + +secretGenerator: + - name: postgres-secrets + literals: + - POSTGRES_USER=sonataflow + - POSTGRES_PASSWORD=sonataflow + - POSTGRES_DB=sonataflow + - PGDATA=/var/lib/postgresql/data/mydata + +configMapGenerator: + - name: dataindex-properties + files: + - application.properties +---- +<1> Postgres database deployment +<2> {data_index_ref} deployment + +Perform the deployments executing +[source,shell] +---- +kubectl kustomize infra/dataindex | kubectl apply -f - -n usecase1 +---- + +---- +configmap/dataindex-properties-hg9ff8bff5 created +secret/postgres-secrets-22tkgc2dt7 created +service/data-index-service-postgresql created +service/postgres created +persistentvolumeclaim/postgres-pvc created +deployment.apps/data-index-service-postgresql created +deployment.apps/postgres created +---- + +Give some time for the data index to start, you can check that it's running by executing. + +[source,shell] +---- +kubectl get pod -n usecase1 +---- + +---- +NAME READY STATUS RESTARTS AGE +data-index-service-postgresql-5d76dc4468-lb259 1/1 Running 0 2m11s +postgres-7f78499688-lc8n6 1/1 Running 0 2m11s +---- +-- +. Deploy the workflow: ++ +-- + +link:{flow_examples_operator_url}/tree/main/usecases/usecase1[Here] you can find the use case kustomization required to deploy the workflow + +.Use case kustomization.yaml resources that deploys the workflow +[source,yaml,subs="attributes+"] +---- +resources: +- ../../platforms/dataindex_platform +- ../../infra/service_discovery +- ../../workflows/sonataflow-greeting +---- + +Perform the deployment executing + +[source,shell] +---- + kubectl kustomize usecases/usecase1 | kubectl apply -f - -n usecase1 +---- + +---- +configmap/greeting-props created +sonataflow.sonataflow.org/greeting created +sonataflowplatform.sonataflow.org/sonataflow-platform created +---- + +Give some time for the sonataflow operator to build and deploy the workflow. +To check that the workflow is ready you can use this command. + +[source,shell] +---- +kubectl get workflow -n usecase1 +---- + +---- +NAME PROFILE VERSION URL READY REASON +greeting 0.0.1 True +---- +-- + +. Expose the workflow and get the url: ++ +-- +[source,shell] +---- +kubectl patch svc greeting -p '{"spec": {"type": "NodePort"}}' -n usecase1 +---- + +[source,shell] +---- +minikube service greeting --url -n usecase1 +---- +-- + +. Create a workflow instance: ++ +-- +You must use the URLs calculated in step 5. + +[source,shell] +---- +curl -X POST -H 'Content-Type:application/json' -H 'Accept:application/json' -d '{"name": "John", "language": "English"}' http://192.168.49.2:32407/greeting +---- + +-- + +. Clean the use case: ++ +-- +[source,shell] +---- +kubectl delete namespace usecase1 +---- +-- + +include::common/_querying_dataindex.adoc[] + +== Additional resources + +* xref:data-index/data-index-core-concepts.adoc[] +* xref:data-index/data-index-usecase-multi.adoc[] +* xref:cloud/quarkus/deploying-on-minikube.adoc[] +* xref:cloud/operator/install-serverless-operator.adoc[] + +include::../../pages/_common-content/report-issue.adoc[] diff --git a/serverlessworkflow/modules/ROOT/pages/index.adoc b/serverlessworkflow/modules/ROOT/pages/index.adoc index 0b3470c0d..e870f7b92 100644 --- a/serverlessworkflow/modules/ROOT/pages/index.adoc +++ b/serverlessworkflow/modules/ROOT/pages/index.adoc @@ -397,6 +397,14 @@ xref:data-index/data-index-quarkus-extension.adoc[] Explore Data Index as Quarkus extension in {PRODUCT_NAME} -- +[.card] +-- +[.card-title] +xref:data-index/data-index-usecase-singleton.adoc[Operator Data Index Deployment] +[.card-description] +Learn about the options to deploy workflow applications and Data Index using The {PRODUCT_NAME} Operator +-- + [.card-section] == Use Cases From cef268a7789da3fb9abb592e647d2d820610e2c5 Mon Sep 17 00:00:00 2001 From: nmirasch Date: Fri, 1 Dec 2023 11:24:36 +0100 Subject: [PATCH 2/6] KOGITO-9808:Add Data Index persistence addon documentation --- serverlessworkflow/modules/ROOT/nav.adoc | 2 +- .../data-index-quarkus-extension.adoc | 99 +++++++++++++++++-- .../modules/ROOT/pages/index.adoc | 2 +- 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/serverlessworkflow/modules/ROOT/nav.adoc b/serverlessworkflow/modules/ROOT/nav.adoc index 1f8a3db4c..d020166e1 100644 --- a/serverlessworkflow/modules/ROOT/nav.adoc +++ b/serverlessworkflow/modules/ROOT/nav.adoc @@ -110,7 +110,7 @@ * Data Index ** xref:data-index/data-index-core-concepts.adoc[Core concepts] ** xref:data-index/data-index-service.adoc[Standalone service] -** xref:data-index/data-index-quarkus-extension.adoc[Quarkus Extension] +** xref:data-index/data-index-quarkus-extension.adoc[Quarkus Extensions] ** Operator *** xref:data-index/data-index-usecase-singleton.adoc[] *** xref:data-index/data-index-usecase-multi.adoc[] diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc index dd8ebf882..0d4b760dc 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc @@ -1,4 +1,4 @@ -= Data Index Quarkus extension += Data Index Quarkus extensions :compat-mode!: // Metadata: :description: Data Index Service to allow to index and query audit data in {product_name} @@ -10,6 +10,8 @@ // External pages :kogito_sw_timeouts_showcase_embedded_example_url: {kogito_sw_examples_url}/serverless-workflow-timeouts-showcase-embedded :kogito_sw_timeouts_showcase_embedded_example_application_properties_url: {kogito_sw_timeouts_showcase_embedded_example_url}/src/main/resources/application.properties +:kogito_sw_dataindex_persistence_example_url: {kogito_sw_examples_url}/serverless-workflow-data-index-persistence-addon-quarkus + :infinispan_url: https://infinispan.org/ :mongo_url: https://www.mongodb.com/ :postgresql_url: https://www.postgresql.org/ @@ -39,12 +41,19 @@ These extensions are distributed as addons ready to work with different types of * kogito-addons-quarkus-data-index-infinispan * kogito-addons-quarkus-data-index-mongodb +With the same purpose, the Quarkus {data_index_ref} persistence extension can be added to any workflow application and incorporates the {data_index_ref} persistence functionality into the same application without needing an external {data_index_ref} service to do that indexation. +These extensions are distributed as addons ready to work with different types of persistence: + +* kogito-addons-quarkus-data-index-persistence-postgresql +* kogito-addons-quarkus-data-index-persistence-infinispan +* kogito-addons-quarkus-data-index-persistence-mongodb + [NOTE] ==== The {data_index_ref} extensions are provided as addons for each kind of supported persistence relying on the link:{quarkus_guides_base_url}/writing-extensions[Quarkus extensions] mechanism. ==== -Once one of these `kogito-addons-quarkus-data-index` addons is added to a workflow, it incorporates the functionality to index and store the workflow data and also incorporates the GraphQL endpoint to perform queries and management operations. +Once one of these `kogito-addons-quarkus-data-index` or `kogito-addons-quarkus-data-index-persistence` addons is added to a workflow, it incorporates the functionality to index and store the workflow data. In case of the `kogito-addons-quarkus-data-index` also incorporates the GraphQL endpoint to perform queries and management operations. In the same way as the {data_index_ref} service, there is a specific addon for each type of persistence you want to work with. Currently, you can find {data_index_ref} addons for: link:{postgresql_url}[PostgreSQL], link:{infinispan_url}[Infinispan], and link:{mongo_url}[MongoDB] @@ -54,11 +63,14 @@ The {data_index_ref} addon distribution added to the workflow must match the wor The addon will share the data source used by the workflow where it is added, and it will create separate tables for that purpose. ==== -When any of the {data_index_ref} addons is added: +When any of the `kogito-addons-quarkus-data-index` or `kogito-addons-quarkus-data-index-persistence` addons is added: * The communication with the workflow is direct, the workflow data is *not* transmitted or consumed through events, they are stored directly in the configured database. There is no need to configure the events connection for this purpose. -* A new GraphQL endpoint is added to perform queries and management operations + +Only when any of the `kogito-addons-quarkus-data-index` addons is added: + +* A new GraphQL endpoint is added to perform queries and management operations when `kogito-addons-quarkus-data-index` is added [[data-index-ext-use]] == Adding {data_index_ref} extension to a workflow application @@ -67,14 +79,19 @@ You can add the {data_index_ref} quarkus extension as an addon: .Prerequisites * Your workflow is running and has persistence enabled. +* {data_index_ref} is using the same datasource to store indexed data + For more information about creating a workflow, see {getting_started_create_first_workflow_guide}[Creating your first workflow]. You also can find more details about enabling persistence in {persistence_with_postgresql_guide}[Running a workflow using PostgreSQL] .Procedure -. Add the required {data_index_ref} addon dependencies to the `pom.xml` file of your workflow: +. Add the `kogito-addons-quarkus-data-index` extension to your Quarkus Workflow Project using any of the following alternatives: + -- -.Add {data_index_ref} Addon dependencies to `pom.xml` file + +[tabs] +==== +Manually:: ++ [source,xml] ---- @@ -82,6 +99,19 @@ For more information about creating a workflow, see {getting_started_create_firs kogito-addons-quarkus-data-index-postgresql ---- +Apache Maven:: ++ +[source,shell] +---- +mvn quarkus:add-extension -Dextensions="kogito-addons-quarkus-data-index-postgresql" +---- +Quarkus CLI:: ++ +[source,shell] +---- +quarkus extension add kogito-addons-quarkus-data-index-postgresql +---- +==== -- @@ -103,6 +133,63 @@ When adding the addon to the workflow, you need to disable it by setting `quarku For more information, see `application.properties` file of link:{kogito_sw_timeouts_showcase_embedded_example_application_properties_url}[`serverless-timeouts_showcase_embedded`] example application. -- + +[#kogito-addons-quarkus-dataindex-persistence-extension] +== Adding {data_index_ref} persistence extension to a workflow application + +You can add the {data_index_ref} persistence quarkus extension as an addon: + +.Prerequisites +* Your workflow is running and has persistence enabled +* {data_index_ref} is using the same datasource to store indexed data ++ +For more information about creating a workflow, see {getting_started_create_first_workflow_guide}[Creating your first workflow]. You also can find more details about enabling persistence in {persistence_with_postgresql_guide}[Running a workflow using PostgreSQL] + +.Procedure +. Add the `kogito-addons-quarkus-data-index-persistence` extension to your Quarkus Workflow Project using any of the following alternatives: ++ +-- + +[tabs] +==== +Manually:: ++ +[source,xml] +---- + + org.kie.kogito + kogito-addons-quarkus-data-index-persistence-postgresql + +---- +Apache Maven:: ++ +[source,shell] +---- +mvn quarkus:add-extension -Dextensions="kogito-addons-quarkus-data-index-persistence-postgresql" +---- +Quarkus CLI:: ++ +[source,shell] +---- +quarkus extension add kogito-addons-quarkus-data-index-persistence-postgresql +---- +==== + +-- + +. Add the following configurations to the `application.properties` file of your project. + +.Example adding Data Index addon properties in `application.properties` file +[source,properties] +---- +quarkus.kogito.devservices.enabled=false <1> +---- +<1> By default, when a workflow is running in dev mode, automatically a Data Index Dev Service is started and a temporary dev service Database is created. +When adding the addon to the workflow, you need to disable it by setting `quarkus.kogito.devservices.enabled` to `false` in the `application.properties` file. + + +For more information, see link:{kogito_sw_dataindex_persistence_example_url}[`serverless-workflow-data-index-persistence-addon-quarkus`] example application. + == Additional resources * xref:getting-started/create-your-first-workflow-service.adoc[] diff --git a/serverlessworkflow/modules/ROOT/pages/index.adoc b/serverlessworkflow/modules/ROOT/pages/index.adoc index e870f7b92..ac5b922b1 100644 --- a/serverlessworkflow/modules/ROOT/pages/index.adoc +++ b/serverlessworkflow/modules/ROOT/pages/index.adoc @@ -394,7 +394,7 @@ Go deeper in details about Data Index as standalone service deployment. [.card-title] xref:data-index/data-index-quarkus-extension.adoc[] [.card-description] -Explore Data Index as Quarkus extension in {PRODUCT_NAME} +Explore Data Index as Quarkus extensions in {PRODUCT_NAME} -- [.card] From 9735e14ef63813cb3e6251ebe3cfc95bb20d2c2b Mon Sep 17 00:00:00 2001 From: nmirasch Date: Thu, 7 Dec 2023 11:35:15 +0100 Subject: [PATCH 3/6] Adding reference to examples to be able to explore the implied files --- serverlessworkflow/antora.yml | 1 - .../images/data-index/data-index-addon.drawio | 128 +++++++--- .../images/data-index/data-index-addon.png | Bin 32522 -> 56448 bytes .../_dataindex_deployment_operator.adoc | 220 ++++++++++++++++++ .../data-index-quarkus-extension.adoc | 12 +- .../data-index/data-index-usecase-multi.adoc | 35 +-- .../data-index-usecase-singleton.adoc | 32 +-- 7 files changed, 338 insertions(+), 90 deletions(-) create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc diff --git a/serverlessworkflow/antora.yml b/serverlessworkflow/antora.yml index c2f8c8685..eb283e70b 100644 --- a/serverlessworkflow/antora.yml +++ b/serverlessworkflow/antora.yml @@ -109,7 +109,6 @@ asciidoc: kaoto_url: https://marketplace.visualstudio.com/items?itemName=redhat.vscode-kaoto minikube_url: https://minikube.sigs.k8s.io kogito_serverless_operator_url: https://github.com/apache/incubator-kie-kogito-serverless-operator/ - flow_examples_operator_url: https://github.com/flows-examples/techpreview2/ docs_issues_url: https://github.com/apache/incubator-kie-kogito-docs/issues/new ocp_local_url: https://access.redhat.com/documentation/en-us/red_hat_openshift_local/2.17 ocp_knative_serving_url: https://docs.openshift.com/container-platform/4.12/serverless/install/installing-knative-serving.html diff --git a/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.drawio b/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.drawio index 062a02835..79d2b08cd 100644 --- a/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.drawio +++ b/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.drawio @@ -1,100 +1,164 @@ - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.png b/serverlessworkflow/modules/ROOT/assets/images/data-index/data-index-addon.png index 727b2a6da5c61b12de756ace98c9f7dd8bfd5764..02f8fc1441140ec925ef39bbfe31215664a737da 100644 GIT binary patch literal 56448 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 delta 19902 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 diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc new file mode 100644 index 000000000..3dd35bf25 --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc @@ -0,0 +1,220 @@ + +link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. + +Thas folder woud contain the following four files: + +* kustomization.yaml +* 01-postgres.yaml +* 02-dataindex.yaml +* application.properties + +.`kustomization.yaml` resources that deploy {data_index_ref} deployment with persistence to a postgresql database +[source,yaml,subs="attributes+"] +---- +resources: +- 01-postgres.yaml <1> +- 02-dataindex.yaml <2> + +secretGenerator: + - name: postgres-secrets + literals: + - POSTGRES_USER=sonataflow + - POSTGRES_PASSWORD=sonataflow + - POSTGRES_DB=sonataflow + - PGDATA=/var/lib/postgresql/data/mydata + +configMapGenerator: + - name: dataindex-properties + files: + - application.properties +---- +<1> Postgres database deployment +<2> {data_index_ref} deployment + +.`01_postgres.yaml` that deploys Postgresql database +[source,yaml,subs="attributes+"] +---- +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app.kubernetes.io/name: postgres + name: postgres-pvc +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: postgres + name: postgres +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: postgres + template: + metadata: + labels: + app.kubernetes.io/name: postgres + spec: + containers: + - name: postgres + image: postgres:13.2-alpine + imagePullPolicy: 'IfNotPresent' + ports: + - containerPort: 5432 + volumeMounts: + - name: storage + mountPath: /var/lib/postgresql/data + envFrom: + - secretRef: + name: postgres-secrets + readinessProbe: + exec: + command: ["pg_isready"] + initialDelaySeconds: 15 + timeoutSeconds: 2 + livenessProbe: + exec: + command: ["pg_isready"] + initialDelaySeconds: 15 + timeoutSeconds: 2 + resources: + limits: + memory: "256Mi" + cpu: "500m" + volumes: + - name: storage + persistentVolumeClaim: + claimName: postgres-pvc +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: postgres + name: postgres +spec: + selector: + app.kubernetes.io/name: postgres + ports: + - port: 5432 +---- + +.`02-dataindex.yaml` that deploys {data_index_ref} with persistence to the previous defined postgresql database +[source,yaml,subs="attributes+"] +---- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/name: data-index-service-postgresql + name: data-index-service-postgresql +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: data-index-service-postgresql + template: + metadata: + labels: + app.kubernetes.io/name: data-index-service-postgresql + spec: + containers: + - name: data-index-service-postgresql + image: quay.io/kiegroup/kogito-data-index-postgresql:latest + imagePullPolicy: Always + resources: + limits: + memory: "256Mi" + cpu: "500m" + ports: + - containerPort: 8080 + name: http + protocol: TCP + env: + - name: KOGITO_DATA_INDEX_QUARKUS_PROFILE + value: http-events-support + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: QUARKUS_DATASOURCE_USERNAME + valueFrom: + secretKeyRef: + key: POSTGRES_USER + name: postgres-secrets + - name: QUARKUS_DATASOURCE_PASSWORD + valueFrom: + secretKeyRef: + key: POSTGRES_PASSWORD + name: postgres-secrets + volumeMounts: + - name: application-config + mountPath: "/home/kogito/config" + livenessProbe: + failureThreshold: 3 + httpGet: + path: /q/health/live + port: 8080 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + readinessProbe: + failureThreshold: 3 + httpGet: + path: /q/health/ready + port: 8080 + scheme: HTTP + initialDelaySeconds: 0 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 10 + volumes: + - name: application-config + configMap: + name: dataindex-properties + initContainers: + - name: init-postgres + image: registry.access.redhat.com/ubi9/ubi-minimal:latest + imagePullPolicy: IfNotPresent + command: ['sh', '-c', 'until (echo 1 > /dev/tcp/postgres.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local/5432) >/dev/null 2>&1; do echo "Waiting for postgres server"; sleep 3; done;'] +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: data-index-service-postgresql + name: data-index-service-postgresql +spec: + ports: + - name: http + port: 80 + targetPort: 8080 + selector: + app.kubernetes.io/name: data-index-service-postgresql + type: NodePort +---- +.`application.properties` referenced by `kustomization.yaml` +[source,properties] +---- +quarkus.http.port=8080 +quarkus.http.cors=true +quarkus.http.cors.origins=/.*/ + +quarkus.datasource.jdbc.url=jdbc:postgresql://postgres:5432/sonataflow?currentSchema=data-index-service +quarkus.hibernate-orm.database.generation=update +quarkus.flyway.migrate-at-start=true + +# Disable kafka client health check since the quarkus-http connector is being used instead. +quarkus.smallrye-health.check."io.quarkus.kafka.client.health.KafkaHealthCheck".enabled=false +---- diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc index 0d4b760dc..0304013b1 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc @@ -32,8 +32,10 @@ The example described in this document is based on the link:{kogito_sw_timeouts_ The {data_index_ref} service has been designed to store and manage data from different workflow instances. Communication with the service is through events that contain the workflows related data and the service is responsible for storing them and exposing a GraphQL endpoint to allow queries and maintenance operations on the different workflow instances. +image::data-index/data-index-addon.png[Image of data-index as a Quarkus Extension] + In specific use cases, to avoid deploying the service separately, it could be useful to have the indexing functionality and the query capabilities embedded in the same application. -For this purpose, the Quarkus {data_index_ref} extension can be added to any workflow application and incorporates the {data_index_ref} functionality into the same application without needing an external {data_index_ref} service. +For this purpose, the Quarkus {data_index_ref} extension can be added to any workflow application and incorporates the full {data_index_ref} functionality into the same application without needing an external {data_index_ref} service. These extensions are distributed as addons ready to work with different types of persistence: * kogito-addons-quarkus-data-index-inmemory (inmemory PostgreSQL) @@ -41,13 +43,15 @@ These extensions are distributed as addons ready to work with different types of * kogito-addons-quarkus-data-index-infinispan * kogito-addons-quarkus-data-index-mongodb -With the same purpose, the Quarkus {data_index_ref} persistence extension can be added to any workflow application and incorporates the {data_index_ref} persistence functionality into the same application without needing an external {data_index_ref} service to do that indexation. +With the same purpose, the Quarkus {data_index_ref} persistence extension can be added to any workflow application and incorporates only the {data_index_ref} indexation and data persistence functionality into the same application without needing an external {data_index_ref} service to do that. These extensions are distributed as addons ready to work with different types of persistence: * kogito-addons-quarkus-data-index-persistence-postgresql * kogito-addons-quarkus-data-index-persistence-infinispan * kogito-addons-quarkus-data-index-persistence-mongodb +In this case to interact with that data and related runtimes using GraphQL you will need an external {data_index_ref} service that makes that endpoint available. + [NOTE] ==== The {data_index_ref} extensions are provided as addons for each kind of supported persistence relying on the link:{quarkus_guides_base_url}/writing-extensions[Quarkus extensions] mechanism. @@ -90,7 +94,7 @@ For more information about creating a workflow, see {getting_started_create_firs [tabs] ==== -Manually:: +Manually to the POM.xml:: + [source,xml] ---- @@ -152,7 +156,7 @@ For more information about creating a workflow, see {getting_started_create_firs [tabs] ==== -Manually:: +Manually to the POM.xml:: + [source,xml] ---- diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc index 078ffe22e..c4073a92f 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc @@ -8,6 +8,7 @@ :kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. //Common constants :data_index_ref: Data Index +:flow_examples_operator_url: {kogito_sw_examples_url}/serverless-workflow-dataindex-operator-use-cases This document describes how to deploy a multiple {product_name} workflow applications and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. @@ -21,9 +22,8 @@ This use case is intended to represent an installation with: * The `helloworld` workflow (no persistence), that is configured to register events to the Data Index Service. * Both workflows are configured to register the process events on the {data_index_ref} Service. -You can directly access the UseCase2 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Use Cases repository]. +You can directly access the UseCase2 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Data Index Use Cases with operator]. -// shared pre req include::common/_prerequisites.adoc[] You can check the Minikube installation by entering the following commands in a command terminal: @@ -52,7 +52,7 @@ alias kubectl="minikube kubectl --" ==== .Procedure -. After cloning the link:{flow_examples_operator_url}[SonataFlow Use Cases repository]. Open a terminal and run the following commands +. After cloning the link:{flow_examples_operator_url}[SonataFlow Data Index Use Cases]. Open a terminal and run the following commands . Create the namespace: + -- @@ -65,31 +65,7 @@ kubectl create namespace usecase2 . Deploy the {data_index_ref} Service and postgresql database: + -- - -link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. - -.Use case kustomization.yaml resources that deploy {data_index_ref} deployment with persistence to a postgresql database -[source,yaml,subs="attributes+"] ----- -resources: -- 01-postgres.yaml <1> -- 02-dataindex.yaml <2> - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DB=sonataflow - - PGDATA=/var/lib/postgresql/data/mydata - -configMapGenerator: - - name: dataindex-properties - files: - - application.properties ----- -<1> Postgres database deployment -<2> {data_index_ref} deployment +include::common/_dataindex_deployment_operator.adoc[] Perform the deployments executing [source,shell] @@ -136,6 +112,9 @@ resources: - ../../workflows/sonataflow-helloworld ---- +To see in more detail access to xref:cloud/operator/build-and-deploy-workflows.adoc[] + + Perform the deployment executing [source,shell] ---- diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc index 1c54d8b0e..1751aafad 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc @@ -8,6 +8,7 @@ :kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. //Common constants :data_index_ref: Data Index +:flow_examples_operator_url: {kogito_sw_examples_url}/serverless-workflow-dataindex-operator-use-cases This document describes how to deploy a workflow application and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. @@ -50,7 +51,7 @@ alias kubectl="minikube kubectl --" ==== .Procedure -. After cloning the link:{flow_examples_operator_url}[SonataFlow Use Cases repository]. Open a terminal and run the following commands +. After cloning the link:{flow_examples_operator_url}[SonataFlow Data Index Use Cases]. Open a terminal and run the following commands . Create the namespace: + -- @@ -63,30 +64,7 @@ kubectl create namespace usecase1 . Deploy the {data_index_ref} Service and postgresql database: + -- -link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. - -.Use case kustomization.yaml resources that deploy {data_index_ref} deployment with persistence to a postgresql database -[source,yaml,subs="attributes+"] ----- -resources: -- 01-postgres.yaml <1> -- 02-dataindex.yaml <2> - -secretGenerator: - - name: postgres-secrets - literals: - - POSTGRES_USER=sonataflow - - POSTGRES_PASSWORD=sonataflow - - POSTGRES_DB=sonataflow - - PGDATA=/var/lib/postgresql/data/mydata - -configMapGenerator: - - name: dataindex-properties - files: - - application.properties ----- -<1> Postgres database deployment -<2> {data_index_ref} deployment +include::common/_dataindex_deployment_operator.adoc[] Perform the deployments executing [source,shell] @@ -132,6 +110,8 @@ resources: - ../../workflows/sonataflow-greeting ---- +To see in more detail how to deploy the workflow access to xref:cloud/operator/build-and-deploy-workflows.adoc[] + Perform the deployment executing [source,shell] @@ -145,6 +125,8 @@ sonataflow.sonataflow.org/greeting created sonataflowplatform.sonataflow.org/sonataflow-platform created ---- +To see in more detail how to generate this resources access to xref:cloud/operator/build-and-deploy-workflows.adoc[] + Give some time for the sonataflow operator to build and deploy the workflow. To check that the workflow is ready you can use this command. From 07e13e209b556283b594b81e5198d2694672cd1b Mon Sep 17 00:00:00 2001 From: nmirasch Date: Thu, 7 Dec 2023 12:24:38 +0100 Subject: [PATCH 4/6] Typo fix --- .../pages/data-index/common/_dataindex_deployment_operator.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc index 3dd35bf25..7b3724e4c 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc @@ -1,7 +1,7 @@ link:{flow_examples_operator_url}/tree/main/infra/dataindex[Here] you can find the infrastructure kustomization required to deploy {data_index_ref} service and a postgresql database explained in this use case. -Thas folder woud contain the following four files: +Thas folder contains four files: * kustomization.yaml * 01-postgres.yaml From 26054a99941da870a84defd50e8fdae8ea1dfb52 Mon Sep 17 00:00:00 2001 From: nmirasch Date: Thu, 7 Dec 2023 14:22:35 +0100 Subject: [PATCH 5/6] Updated references to examples after moving the files to operator use cases --- serverlessworkflow/antora.yml | 1 + .../data-index/data-index-usecase-multi.adoc | 15 ++++++++++++--- .../data-index/data-index-usecase-singleton.adoc | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/serverlessworkflow/antora.yml b/serverlessworkflow/antora.yml index eb283e70b..4824117e8 100644 --- a/serverlessworkflow/antora.yml +++ b/serverlessworkflow/antora.yml @@ -65,6 +65,7 @@ asciidoc: sonataflow_devmode_imagename: quay.io/kiegroup/kogito-swf-devmode kogito_examples_repository_url: https://github.com/apache/incubator-kie-kogito-examples kogito_sw_examples_url: https://github.com/apache/incubator-kie-kogito-examples/tree/main/serverless-workflow-examples + kogito_sw_operator_examples_url: https://github.com/apache/incubator-kie-kogito-examples/tree/main/serverless-operator-examples kogito_examples_url: https://github.com/apache/incubator-kie-kogito-examples.git kogito_apps_url: https://github.com/apache/incubator-kie-kogito-apps/tree/main quarkus_cli_url: https://quarkus.io/guides/cli-tooling diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc index c4073a92f..f69fb033f 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc @@ -8,7 +8,7 @@ :kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. //Common constants :data_index_ref: Data Index -:flow_examples_operator_url: {kogito_sw_examples_url}/serverless-workflow-dataindex-operator-use-cases +:flow_examples_operator_url: {kogito_sw_operator_examples_url}/serverless-workflow-dataindex-use-cases This document describes how to deploy a multiple {product_name} workflow applications and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. @@ -22,7 +22,7 @@ This use case is intended to represent an installation with: * The `helloworld` workflow (no persistence), that is configured to register events to the Data Index Service. * Both workflows are configured to register the process events on the {data_index_ref} Service. -You can directly access the UseCase2 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Data Index Use Cases with operator]. +You can directly access the UseCase2 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Data Index Use Cases with operator]. include::common/_prerequisites.adoc[] @@ -52,7 +52,16 @@ alias kubectl="minikube kubectl --" ==== .Procedure -. After cloning the link:{flow_examples_operator_url}[SonataFlow Data Index Use Cases]. Open a terminal and run the following commands +. After cloning the link:{kogito_examples_url}[{product_name} examples repository]. Open a terminal and run the following commands + ++ +-- +[source,shell] +---- +cd serverless-operator-examples/serverless-workflow-dataindex-use-cases/ +---- +-- + . Create the namespace: + -- diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc index 1751aafad..ac0a4ee4b 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc @@ -8,7 +8,7 @@ :kubectl_prereq: command-line tool is installed. Otherwise, Minikube handles it. //Common constants :data_index_ref: Data Index -:flow_examples_operator_url: {kogito_sw_examples_url}/serverless-workflow-dataindex-operator-use-cases +:flow_examples_operator_url: {kogito_sw_operator_examples_url}/serverless-workflow-dataindex-use-cases This document describes how to deploy a workflow application and the {data_index_ref} service using a local Kubernetes cluster, such as link:{minikube_url}[Minikube], using the link:{kogito_serverless_operator_url}[{operator_name}]. @@ -20,7 +20,7 @@ This use case is intended to represent an installation with: * A singleton Data Index Service with PostgreSQL persistence * The `greeting` workflow (no persistence), that is configured to register events to the Data Index Service. -You can directly access the UseCase1 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Use Cases repository]. +You can directly access the UseCase1 example application we are going to follow at link:{flow_examples_operator_url}[{product_name} Data Index Use Cases with operator]. // shared pre req include::common/_prerequisites.adoc[] @@ -51,7 +51,17 @@ alias kubectl="minikube kubectl --" ==== .Procedure -. After cloning the link:{flow_examples_operator_url}[SonataFlow Data Index Use Cases]. Open a terminal and run the following commands + +. After cloning the link:{kogito_examples_url}[{product_name} examples repository]. Open a terminal and run the following commands + ++ +-- +[source,shell] +---- +cd serverless-operator-examples/serverless-workflow-dataindex-use-cases/ +---- +-- + . Create the namespace: + -- From 765b87dc0b2f71d9d7453b2c4929ba4049bb0d2c Mon Sep 17 00:00:00 2001 From: nmirasch Date: Thu, 7 Dec 2023 19:25:20 +0100 Subject: [PATCH 6/6] removed dataindex_platform references --- .../modules/ROOT/pages/data-index/data-index-usecase-multi.adoc | 2 -- .../ROOT/pages/data-index/data-index-usecase-singleton.adoc | 2 -- 2 files changed, 4 deletions(-) diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc index f69fb033f..c71d1191a 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc @@ -115,7 +115,6 @@ link:{flow_examples_operator_url}/tree/main/usecases/usecase2[Here] you can find [source,yaml,subs="attributes+"] ---- resources: -- ../../platforms/dataindex_platform - ../../infra/service_discovery - ../../workflows/sonataflow-greeting - ../../workflows/sonataflow-helloworld @@ -135,7 +134,6 @@ configmap/greeting-props created configmap/helloworld-props created sonataflow.sonataflow.org/greeting created sonataflow.sonataflow.org/helloworld created -sonataflowplatform.sonataflow.org/sonataflow-platform created ---- Give some time for the sonataflow operator to build and deploy the workflow. diff --git a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc index ac0a4ee4b..e496a93f2 100644 --- a/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc @@ -115,7 +115,6 @@ link:{flow_examples_operator_url}/tree/main/usecases/usecase1[Here] you can find [source,yaml,subs="attributes+"] ---- resources: -- ../../platforms/dataindex_platform - ../../infra/service_discovery - ../../workflows/sonataflow-greeting ---- @@ -132,7 +131,6 @@ Perform the deployment executing ---- configmap/greeting-props created sonataflow.sonataflow.org/greeting created -sonataflowplatform.sonataflow.org/sonataflow-platform created ---- To see in more detail how to generate this resources access to xref:cloud/operator/build-and-deploy-workflows.adoc[]