compose setup with postgres

This commit is contained in:
burnettk 2024-03-15 17:08:28 -04:00
commit 6fcc591428
No known key found for this signature in database
13 changed files with 338 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/.idea/
.aider*
default.py

37
Makefile Normal file
View File

@ -0,0 +1,37 @@
include configs/spiffworkflow-backend.env
include configs/spiffworkflow-frontend.env
# if the directory is called something other than the repo name, let's still call
# the docker project by something we can refer to later.
docker_prefix = "bpmn"
# credit: helper code to implement the help target originally from https://stackoverflow.com/a/64996042/6090676
help: ## Show this help message
@grep -Eh '\s##\s' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-30s\033[0m %s\n", $$1, $$2}'
start: ## Start SpiffWorkflow for local development
@docker compose -p $(docker_prefix) up
up: ## Alias for start
up: start
pull: ## Pull latest container images
@docker compose -p $(docker_prefix) pull
build: ## Build or rebuild connector proxy image from source
@docker compose -p $(docker_prefix) build
destroy-db: ## Delete the database docker volume
@if docker volume inspect "$(docker_prefix)_spiffworkflow_backend_db" >/dev/null; then \
mountpoint=$$(docker volume inspect bpmn_spiffworkflow_backend_db --format="{{.Mountpoint}}"); \
sudo rm "$$mountpoint/db.sqlite3"; \
fi
down: ## Shut down containers, but leave images and database data around
@docker compose -p $(docker_prefix) down
destroy-all: ## Delete all docker images, containers, and volumes. Leave no trace.
@docker compose -p $(docker_prefix) down --volumes --rmi all
update-docker-tags: ## Update docker tags for backend, frontend, and connector
@./bin/update_docker_tags

37
README.md Normal file
View File

@ -0,0 +1,37 @@
## arena-compose-postgres
This application consists of a frontend and a backend service, a PostgreSQL database, and a connector proxy, all orchestrated with Docker Compose.
### Services and Default Ports:
- `spiffworkflow-frontend`: The frontend user interface for the workflow application.
- `spiffworkflow-backend`: The backend service providing API endpoints for the frontend.
- `spiffdb`: A PostgreSQL database service used by the backend to store workflow data.
- `spiffworkflow-connector`: A connector proxy service for external integrations.
### Getting Started:
1. Ensure Docker and Docker Compose are installed on your system.
2. Clone the repository and navigate to the directory containing the `docker-compose.yml` file. The default ports are set in this file, but you can change them if needed.
3. Run `make up` to start all services. The services will be available on the following default ports:
4. Access the frontend at `http://localhost:8001`, where `8001` is the default port for the frontend service.
5. Access the backend API at `http://localhost:8000/v1.0`, where `8000` is the default port for the backend service.
6. Run `make down` to stop all services.
### Database Access:
To access the PostgreSQL database from within the `spiffdb` container, use the following command:
```sh
psql -U spiffuser -d spiffworkflow
```
The default username is `spiffuser` and the password is `spiffpass`, as configured in the `docker-compose.yml` file.
### Health Checks:
Health checks are configured for the `spiffworkflow-backend` and `spiffdb` services to ensure they are ready before dependent services start.
### Troubleshooting:
If you encounter any issues with the services, check the logs using `docker-compose logs`.

6
backend/Dockerfile Normal file
View File

@ -0,0 +1,6 @@
ARG SPIFFWORKFLOW_BACKEND_TAG=${SPIFFWORKFLOW_BACKEND_TAG}
FROM ghcr.io/sartography/spiffworkflow-backend:${SPIFFWORKFLOW_BACKEND_TAG}
RUN apt-get update \
&& apt-get install -y -q libpq-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

44
bin/update_docker_tags Executable file
View File

@ -0,0 +1,44 @@
#!/usr/bin/env bash
function error_handler() {
>&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}."
exit "$2"
}
trap 'error_handler ${LINENO} $?' ERR
set -o errtrace -o errexit -o nounset -o pipefail
if ! command -v jq > /dev/null; then
>&2 echo "ERROR: this command requires jq to be installed."
exit 1
fi
branch=main
docker_image_repos=(
"spiffworkflow-backend"
"spiffworkflow-frontend"
)
spiff_arena_directory="${HOME}/spiff-arena"
if [[ ! -d "$spiff_arena_directory" ]]; then
git clone https://github.com/sartography/spiff-arena.git "$spiff_arena_directory"
else
git -C "$spiff_arena_directory" pull
fi
current_year="$(date +%Y)"
current_month="$(date +%m)"
for docker_image_repo in "${docker_image_repos[@]}" ; do
normalized_repo_name=$(tr '-' '_' <<<"$docker_image_repo")
config_file="configs/${docker_image_repo}.env"
if [[ ! -f "$config_file" ]]; then
>&2 echo "ERROR: Could not find config file: ${config_file}"
exit 1
fi
tags=$("${spiff_arena_directory}/bin/list_ghcr_tags" "$docker_image_repo" "${branch}-${current_year}-${current_month}")
latest_tag="$(echo "${tags}" | jq -r '. | last')"
config_to_update="$(tr "[:lower:]" "[:upper:]" <<<"$normalized_repo_name")_TAG"
perl -pi -e "s/(${config_to_update}=).*/\1${latest_tag}/" "$config_file"
done

View File

@ -0,0 +1,50 @@
users:
admin:
service: local_open_id
email: admin@spiffworkflow.org
password: admin
preferred_username: Admin
patrick:
service: local_open_id
email: patrick@example.com
password: patrick
preferred_username: Patrick
test_user:
service: local_open_id
email: testing@example.com
password: testing
preferred_username: Test User
groups:
admin:
users: [admin@spiffworkflow.org, patrick@example.com]
testing:
users: [testing@example.com]
permissions:
# Admins have access to everything.
admin:
groups: [admin]
allowed_permissions: [all]
uri: /*
# Everybody can participate in tasks assigned to them.
# BASIC, PG, PM, are documented at https://spiff-arena.readthedocs.io/en/latest/DevOps_installation_integration/permission_url.html
basic:
groups: [everybody, testing]
allowed_permissions: [all]
uri: BASIC
# Everyone can see everything (all groups, and processes are visible)
read-all-process-groups:
groups: [everybody, testing]
allowed_permissions: [read]
uri: PG:ALL
read-all-process-models:
groups: [everybody, testing]
allowed_permissions: [read]
uri: PM:ALL
run-all-process-models:
groups: [everybody, testing]
allowed_permissions: [start]
uri: PM:ALL

View File

@ -0,0 +1,2 @@
export SPIFFWORKFLOW_BACKEND_TAG=main-2024-03-14_19-55-58-9acd295
export SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH=/app/permissions/local_development.yml

View File

@ -0,0 +1 @@
export SPIFFWORKFLOW_FRONTEND_TAG=main-2024-03-14_19-55-55-9acd295

93
docker-compose.yml Normal file
View File

@ -0,0 +1,93 @@
version: "3.8"
services:
spiffworkflow-frontend:
container_name: spiffworkflow-frontend
image: ghcr.io/sartography/spiffworkflow-frontend:${SPIFFWORKFLOW_FRONTEND_TAG:-latest}
depends_on:
spiffworkflow-backend:
condition: service_healthy
environment:
APPLICATION_ROOT: "/"
PORT0: "${SPIFFWORKFLOW_FRONTEND_PORT:-8001}"
ports:
- "${SPIFFWORKFLOW_FRONTEND_PORT:-8001}:${SPIFFWORKFLOW_FRONTEND_PORT:-8001}/tcp"
spiffworkflow-backend:
depends_on:
spiffdb:
condition: service_healthy
container_name: spiffworkflow-backend
# image: ghcr.io/sartography/spiffworkflow-backend:${SPIFFWORKFLOW_BACKEND_TAG:-latest}
build:
context: backend
args:
SPIFFWORKFLOW_BACKEND_TAG: "${SPIFFWORKFLOW_BACKEND_TAG}" # Replace "value" with the value you want to pass
environment:
SPIFFWORKFLOW_BACKEND_APPLICATION_ROOT: "/"
SPIFFWORKFLOW_BACKEND_ENV: "local_docker"
FLASK_DEBUG: "0"
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
# WARNING: Frontend is a static site which assumes backend is frontend port - 1 on localhost.
SPIFFWORKFLOW_BACKEND_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}"
SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR: "/app/process_models"
SPIFFWORKFLOW_BACKEND_CONNECTOR_PROXY_URL: "http://spiffworkflow-connector:8004"
SPIFFWORKFLOW_BACKEND_DATABASE_TYPE: "postgres"
SPIFFWORKFLOW_BACKEND_DATABASE_URI: "postgresql://spiffuser:spiffpass@spiffdb:5432/spiffworkflow"
SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: "false"
SPIFFWORKFLOW_BACKEND_LOG_LEVEL: "DEBUG"
SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID: "spiffworkflow-backend"
SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY: "my_open_id_secret_key"
SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}/openid"
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH: "${SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH}"
SPIFFWORKFLOW_BACKEND_PORT: "${SPIFF_BACKEND_PORT:-8000}"
SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER_IN_CREATE_APP: "true"
SPIFFWORKFLOW_BACKEND_UPGRADE_DB: "true"
SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND: "http://localhost:${SPIFFWORKFLOW_FRONTEND_PORT:-8001}"
ports:
- "${SPIFF_BACKEND_PORT:-8000}:${SPIFF_BACKEND_PORT:-8000}/tcp"
volumes:
- ./process_models:/app/process_models
- ./configs/permissions:/app/permissions
healthcheck:
test: "curl localhost:${SPIFF_BACKEND_PORT:-8000}/v1.0/status --fail"
interval: 10s
timeout: 5s
retries: 20
spiffdb:
image: postgres:latest
environment:
POSTGRES_USER: spiffuser
POSTGRES_PASSWORD: spiffpass
POSTGRES_DB: spiffworkflow
ports:
- "8005:5432"
volumes:
- spiffworkflow_backend_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U spiffuser -d spiffworkflow"]
interval: 10s
timeout: 5s
retries: 5
spiffworkflow-connector:
container_name: spiffworkflow-connector
image: ghcr.io/sartography/connector-proxy-demo:latest
environment:
FLASK_ENV: "${FLASK_ENV:-development}"
FLASK_DEBUG: "0"
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
CONNECTOR_PROXY_PORT: "${SPIFF_CONNECTOR_PORT:-8004}"
ports:
- "${SPIFF_CONNECTOR_PORT:-8004}:${SPIFF_CONNECTOR_PORT:-8004}/tcp"
healthcheck:
test: "curl localhost:${SPIFF_CONNECTOR_PORT:-8004}/liveness --fail"
interval: 10s
timeout: 5s
retries: 20
volumes:
spiffworkflow_backend_db:
driver: local

0
process_models/.keep Normal file
View File

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:spiffworkflow="http://spiffworkflow.org/bpmn/schema/1.0/core" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_96f6665" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.0.0-dev">
<bpmn:process id="Process_check_part_qcpfm3t" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_17db3yp</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_17db3yp" sourceRef="StartEvent_1" targetRef="Activity_0qpzdpu" />
<bpmn:endEvent id="EndEvent_1">
<bpmn:extensionElements>
<spiffworkflow:instructionsForEndUser>The process instance completed successfully.</spiffworkflow:instructionsForEndUser>
</bpmn:extensionElements>
<bpmn:incoming>Flow_12pkbxb</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_12pkbxb" sourceRef="Activity_0qpzdpu" targetRef="EndEvent_1" />
<bpmn:manualTask id="Activity_0qpzdpu" name="Example manual task">
<bpmn:extensionElements>
<spiffworkflow:instructionsForEndUser>This is an example **Manual Task**. A **Manual Task** is designed to allow someone to complete a task outside of the system and then report back that it is complete. You can click the *Continue* button to proceed. When you are done running this process, you can edit the **Process Model** to include a:
* **Script Task** - write a short snippet of python code to update some data
* **User Task** - generate a form that collects information from a user
* **Service Task** - communicate with an external API to fetch or update some data.
You can also change the text you are reading here by updating the *Instructions* on this example manual task.</spiffworkflow:instructionsForEndUser>
</bpmn:extensionElements>
<bpmn:incoming>Flow_17db3yp</bpmn:incoming>
<bpmn:outgoing>Flow_12pkbxb</bpmn:outgoing>
</bpmn:manualTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_check_part_qcpfm3t">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="179" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_14za570_di" bpmnElement="EndEvent_1">
<dc:Bounds x="432" y="159" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0zqotmb_di" bpmnElement="Activity_0qpzdpu">
<dc:Bounds x="270" y="137" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_17db3yp_di" bpmnElement="Flow_17db3yp">
<di:waypoint x="215" y="177" />
<di:waypoint x="270" y="177" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_12pkbxb_di" bpmnElement="Flow_12pkbxb">
<di:waypoint x="370" y="177" />
<di:waypoint x="432" y="177" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -0,0 +1,9 @@
{
"description": "Process to check on aviation part",
"display_name": "Check part",
"exception_notification_addresses": [],
"fault_or_suspend_on_exception": "fault",
"metadata_extraction_paths": null,
"primary_file_name": "check-part.bpmn",
"primary_process_id": "Process_check_part_qcpfm3t"
}

View File

@ -0,0 +1,5 @@
{
"data_store_specifications": {},
"description": "Group for aviation-related process models",
"display_name": "Aviation"
}