Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ prepare-workdir:
# Depends on: prepare-workdir target.
# Usage: make build-image
ifeq ($(IS_WORKFLOW),true)
build-image: BUILD_ARGS=--build-arg-file=workflows/$(WORKFLOW_ID)/argfile.conf --build-arg=BUILDER_IMAGE=$(BUILDER_IMAGE) --build-arg WF_RESOURCES=workflows/$(WORKFLOW_ID)
build-image: BUILD_ARGS=--build-arg-file=workflows/$(WORKFLOW_ID)/argfile.conf --build-arg=WORKFLOW_ID=$(WORKFLOW_ID) --build-arg=BUILDER_IMAGE=$(BUILDER_IMAGE) --build-arg WF_RESOURCES=workflows/$(WORKFLOW_ID)
endif
build-image: EXTRA_ARGS=--ulimit nofile=4096:4096 --platform='linux/amd64'
build-image: prepare-workdir
Expand Down
33 changes: 32 additions & 1 deletion pipeline/workflow-builder.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ FROM ${BUILDER_IMAGE:-quay.io/orchestrator/logic-swf-builder-rhel8:1.36.0-discon
# ARG QUARKUS_EXTENSIONS=org.kie:kogito-addons-quarkus-jobs-knative-eventing:999-SNAPSHOT,org.kie:kie-addons-quarkus-persistence-jdbc:999-SNAPSHOT,io.quarkus:quarkus-jdbc-postgresql:3.8.4,io.quarkus:quarkus-agroal:3.8.4,org.kie:kie-addons-quarkus-monitoring-prometheus:999-SNAPSHOT,org.kie:kie-addons-quarkus-monitoring-sonataflow:999-SNAPSHOT
# When using prod:
ARG QUARKUS_EXTENSIONS=io.quarkiverse.openapi.generator:quarkus-openapi-generator:2.9.1-lts,org.kie:kie-addons-quarkus-monitoring-sonataflow,org.kie:kogito-addons-quarkus-jobs-knative-eventing,org.kie:kie-addons-quarkus-persistence-jdbc,io.quarkus:quarkus-jdbc-postgresql:3.15.4.redhat-00001,io.quarkus:quarkus-agroal:3.15.4.redhat-00001
ARG WORKFLOW_ID
ENV WORKFLOW_ID=${WORKFLOW_ID}

# Args to pass to the Quarkus CLI
# add extension command
Expand All @@ -43,13 +45,42 @@ RUN ls -la ./resources
ENV swf_home_dir=/home/kogito/serverless-workflow-project
RUN if [[ -d "./resources/src" ]]; then cp -r ./resources/src/* ./src/; fi

RUN /home/kogito/launch/build-app.sh ./resources
RUN if [ "$WORKFLOW_ID" = "python" ]; then \
QUARKUS_EXTENSIONS="${QUARKUS_EXTENSIONS},org.apache.kie.sonataflow:sonataflow-addons-quarkus-python:10.1.0"; \
fi && \
echo "Final QUARKUS_EXTENSIONS=$QUARKUS_EXTENSIONS" && \
/home/kogito/launch/build-app.sh ./resources

#=============================
# Runtime Run
#=============================
FROM registry.access.redhat.com/ubi9/openjdk-17:1.21-2

# Conditional JEP installation based on WORKFLOW_ID
ARG WORKFLOW_ID
ENV WORKFLOW_ID=${WORKFLOW_ID}
USER root
RUN if [ "$WORKFLOW_ID" = "python" ]; then \
echo "Installing JEP because WORKFLOW_ID=$WORKFLOW_ID"; \
microdnf install -y \
python3 \
python3-devel \
gcc \
gcc-c++ \
make \
libffi-devel \
&& microdnf clean all \
&& pip3 install --no-cache-dir jep \
&& PY_VER=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') \
&& cp /usr/local/lib64/python${PY_VER}/site-packages/jep/libjep.so /usr/lib64 \
&& echo "JEP installation complete"; \
else \
echo "Skipping JEP installation"; \
fi
USER 185

# Necessary command for python workflow. Copy command can not be conditional
COPY --chown=185:185 workflows/python/my_scripts /usr/local/lib64/python3.9/site-packages/my_scripts

ARG FLOW_NAME
ARG FLOW_SUMMARY
Expand Down
38 changes: 38 additions & 0 deletions workflows/python/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#
# This Dockerfile adds Python support to the SonataFlow devmode image.
#
# To build the image, run the following command:
# docker build -t sonataflow-devmode-python .
#
# To run the image with your workflow, run the following commands:
# IMAGE=sonataflow-devmode-python
# PATH_TO_WORKFLOW=<path-to-workflow-directory>
# docker run --ulimit nofile=262144:262144 -d --name sonataflow-devmode-python --add-host host.docker.internal:host-gateway -e QUARKUS_HTTP_PORT=8080 -p 8080:8080 -e KOGITO_SERVICE_URL=http://localhost:8080 -v $PATH_TO_WORKFLOW:/home/kogito/serverless-workflow-project/src/main/resources:Z -e KOGITO.CODEGEN.PROCESS.FAILONERROR=false -e QUARKUS_EMBEDDED_POSTGRESQL_DATA_DIR=/home/kogito/persistence -e QUARKUS_EXTENSIONS=org.apache.kie.sonataflow:sonataflow-addons-quarkus-python $IMAGE
#
#
#

FROM quay.io/kubesmarts/incubator-kie-sonataflow-devmode:1.36.0

USER root

# Install Python & build dependencies
RUN microdnf install -y \
python3 \
python3-devel \
gcc \
gcc-c++ \
make \
libffi-devel \
&& microdnf clean all

# Install JEP (compiles native lib)
RUN pip3 install --no-cache-dir jep

# Copy jep SO file to known location
RUN PY_VER=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') \
&& cp /usr/local/lib64/python${PY_VER}/site-packages/jep/libjep.so /usr/lib64

COPY --chown=185:185 path-to-your-python-scripts-folder /usr/local/lib64/python3.6/site-packages/my_scripts

USER 185
11 changes: 11 additions & 0 deletions workflows/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Python workflow - Workflow demonstrating usage of Python scripts and functions
This workflow shows how to execute python functions and scripts from within a workflow. The workflow does the following:
- Uses existing python packages to determine current time and date and sets it to the workflow output.
- Calls a custom python function from a custom script. The function creates a greeting message.

## Workflow diagram
![Python workflow diagram](https://github.com/rhdhorchestrator/serverless-workflows/blob/main/python/mtv.svg?raw=true)

## Installation

See [official installation guide](https://github.com/rhdhorchestrator/serverless-workflows/blob/main/deploy/docs/main/python)
9 changes: 9 additions & 0 deletions workflows/python/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
quarkus.tls.trust-all=true
quarkus.kubernetes-client.trust-certs=true

# This property is used to select the log level, which controls the amount
# of information logged on HTTP requests based on the severity of the events.
# Possible values: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL.
# and see https://quarkus.io/guides/logging for documentation
quarkus.log.category."org.apache.http".level=DEBUG
quarkus.log.level=INFO
3 changes: 3 additions & 0 deletions workflows/python/argfile.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FLOW_NAME=python
FLOW_SUMMARY=python
FLOW_DESCRIPTION=YAML based Python workflow
41 changes: 41 additions & 0 deletions workflows/python/my_scripts/my_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Example script with functions to import from SonataFlow workflows
"""

def greet(name):
"""Simple greeting function"""
return f"Hello, {name}!"

def process_data(data_list):
"""Process a list of data"""
if not data_list:
return []

processed = [item.upper() if isinstance(item, str) else str(item) for item in data_list]
return processed

def calculate_sum(numbers):
"""Calculate sum of numbers"""
return sum(numbers)
Comment on lines +17 to +19

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you using this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no. but this is an example for a real script with multiple functions. do u think i should remove the unused function?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the use to it, you just want to show that an external script has multiple functions and some are used and some are not?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly


class DataProcessor:
"""Example class for data processing"""

def __init__(self, name):
self.name = name

def process(self, data):
"""Process data with processor name"""
return f"Processed by {self.name}: {data}"

# Module-level variable
MODULE_VERSION = "1.0.0"

def workflow_helper(input_data):
"""Helper function specifically for workflow usage"""
result = {
"processed": process_data(input_data.get("items", [])),
"greeting": greet(input_data.get("user", "Anonymous")),
"version": MODULE_VERSION
}
return result
1 change: 1 addition & 0 deletions workflows/python/python.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading