From ea6e22dfa66061424b0f4add84ca5290325f3565 Mon Sep 17 00:00:00 2001 From: nmirasch Date: Tue, 12 Dec 2023 11:35:02 +0100 Subject: [PATCH] KOGITO-9971: [Guides] Dataindex deployment use cases with operator (#519) * KOGITO-9971: [Guides] Dataindex deployment use cases with operator * KOGITO-9808:Add Data Index persistence addon documentation * Adding reference to examples to be able to explore the implied files * Typo fix * Updated references to examples after moving the files to operator use cases * removed dataindex_platform references --- serverlessworkflow/antora.yml | 1 + .../images/data-index/data-index-addon.drawio | 128 +++++++--- .../images/data-index/data-index-addon.png | Bin 32522 -> 56448 bytes serverlessworkflow/modules/ROOT/nav.adoc | 5 +- .../_dataindex_deployment_operator.adoc | 220 ++++++++++++++++++ .../data-index/common/_prerequisites.adoc | 28 +++ .../common/_querying_dataindex.adoc | 105 +++++++++ .../data-index-quarkus-extension.adoc | 105 ++++++++- .../data-index/data-index-usecase-multi.adoc | 207 ++++++++++++++++ .../data-index-usecase-singleton.adoc | 196 ++++++++++++++++ .../modules/ROOT/pages/index.adoc | 10 +- 11 files changed, 964 insertions(+), 41 deletions(-) create mode 100644 serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc 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..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/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/nav.adoc b/serverlessworkflow/modules/ROOT/nav.adoc index 7429f9d6f..d020166e1 100644 --- a/serverlessworkflow/modules/ROOT/nav.adoc +++ b/serverlessworkflow/modules/ROOT/nav.adoc @@ -110,7 +110,10 @@ * 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[] //** 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/_dataindex_deployment_operator.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/common/_dataindex_deployment_operator.adoc new file mode 100644 index 000000000..7b3724e4c --- /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 contains 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/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-quarkus-extension.adoc b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-quarkus-extension.adoc index dd8ebf882..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 @@ -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/ @@ -30,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) @@ -39,12 +43,21 @@ 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 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. ==== -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 +67,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 +83,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 to the POM.xml:: ++ [source,xml] ---- @@ -82,6 +103,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 +137,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 to the POM.xml:: ++ +[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/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..c71d1191a --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-multi.adoc @@ -0,0 +1,207 @@ += 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 +: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}]. + +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} Data Index Use Cases with operator]. + +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:{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: ++ +-- +[source,shell] +---- +kubectl create namespace usecase2 +---- +-- + +. Deploy the {data_index_ref} Service and postgresql database: ++ +-- +include::common/_dataindex_deployment_operator.adoc[] + +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: +- ../../infra/service_discovery +- ../../workflows/sonataflow-greeting +- ../../workflows/sonataflow-helloworld +---- + +To see in more detail access to xref:cloud/operator/build-and-deploy-workflows.adoc[] + + +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 +---- + +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..e496a93f2 --- /dev/null +++ b/serverlessworkflow/modules/ROOT/pages/data-index/data-index-usecase-singleton.adoc @@ -0,0 +1,196 @@ += 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 +: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}]. + +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} 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: + +.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:{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: ++ +-- +[source,shell] +---- +kubectl create namespace usecase1 +---- +-- + +. Deploy the {data_index_ref} Service and postgresql database: ++ +-- +include::common/_dataindex_deployment_operator.adoc[] + +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: +- ../../infra/service_discovery +- ../../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] +---- + kubectl kustomize usecases/usecase1 | kubectl apply -f - -n usecase1 +---- + +---- +configmap/greeting-props created +sonataflow.sonataflow.org/greeting 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. + +[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..ac5b922b1 100644 --- a/serverlessworkflow/modules/ROOT/pages/index.adoc +++ b/serverlessworkflow/modules/ROOT/pages/index.adoc @@ -394,7 +394,15 @@ 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] +-- +[.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]