feat(demo): bring up coordinator + userservice, seed root admin
make demo-ui now starts the userservice (own Postgres + migrations) beside the coordinator on a shared JWT secret, and seeds a root admin. The coordinator runs in UI session mode, so /ui opens a login page instead of a basic-auth prompt. - docker-compose.users.yml overlay: userservice stack + coordinator JWT wiring - demo-ui.sh: waits for the userservice, logs in as the seeded admin to poll the now session-gated dashboard, and prints the admin credentials - validated with docker compose config (6 services, merged env)
This commit is contained in:
@@ -35,7 +35,7 @@ help:
|
||||
' make demo-down Stop the demo services and workers.' \
|
||||
' make test / make vet Run Go verification.' \
|
||||
'' \
|
||||
'Demo UI: http://localhost:18080/ui (operator / demo-ui-secret).'
|
||||
'Demo UI: http://localhost:18080/ui (login page; admin root@scimesh.local / rootpassword).'
|
||||
|
||||
demo-ui:
|
||||
@DEMO_PROJECT="$(DEMO_PROJECT)" \
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Demo overlay: adds the userservice (its own Postgres + migrations) alongside
|
||||
# the coordinator and wires the two together with a shared JWT secret, so the
|
||||
# operator UI authenticates through userservice login/registration.
|
||||
#
|
||||
# Used only by scripts/demo-ui.sh, merged onto docker-compose.yml with a second
|
||||
# -f. Not part of the plain `make up` stack.
|
||||
|
||||
services:
|
||||
postgres-users:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-scimesh}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-scimesh}
|
||||
POSTGRES_DB: scimesh_users
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-scimesh} -d scimesh_users"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
start_period: 5s
|
||||
|
||||
migrate-users:
|
||||
image: migrate/migrate:v4.17.1
|
||||
depends_on:
|
||||
postgres-users:
|
||||
condition: service_healthy
|
||||
volumes:
|
||||
- ../users/migrations:/migrations:ro
|
||||
command:
|
||||
- -path=/migrations
|
||||
- -database=postgres://${POSTGRES_USER:-scimesh}:${POSTGRES_PASSWORD:-scimesh}@postgres-users:5432/scimesh_users?sslmode=disable
|
||||
- up
|
||||
restart: on-failure
|
||||
|
||||
userservice:
|
||||
build:
|
||||
context: ../users
|
||||
depends_on:
|
||||
postgres-users:
|
||||
condition: service_healthy
|
||||
migrate-users:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
USERSERVICE_ADDR: ":8081"
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-scimesh}:${POSTGRES_PASSWORD:-scimesh}@postgres-users:5432/scimesh_users?sslmode=disable
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
# Seeds the first admin the very first time it boots (idempotent after).
|
||||
BOOTSTRAP_ADMIN_EMAIL: ${BOOTSTRAP_ADMIN_EMAIL:-root@scimesh.local}
|
||||
BOOTSTRAP_ADMIN_PASSWORD: ${BOOTSTRAP_ADMIN_PASSWORD}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
ports:
|
||||
- "${USERSERVICE_PORT:-18081}:8081"
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8081/health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
start_period: 5s
|
||||
restart: unless-stopped
|
||||
|
||||
# Turn the coordinator UI into session mode: the same shared secret verifies
|
||||
# userservice tokens locally, and USERSERVICE_URL is where login/register proxy.
|
||||
coordinator:
|
||||
environment:
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
USERSERVICE_URL: http://userservice:8081
|
||||
@@ -11,8 +11,15 @@ repo_dir=$(CDPATH= cd -- "$coordinator_dir/.." && pwd)
|
||||
project=${DEMO_PROJECT:-scimesh-demo}
|
||||
postgres_port=${DEMO_POSTGRES_PORT:-55432}
|
||||
coordinator_port=${DEMO_COORDINATOR_PORT:-18080}
|
||||
userservice_port=${DEMO_USERSERVICE_PORT:-18081}
|
||||
ui_token=${DEMO_UI_TOKEN:-demo-ui-secret}
|
||||
worker_token=${DEMO_WORKER_TOKEN:-demo-worker-token}
|
||||
# Shared HS256 secret; the coordinator verifies userservice tokens with it. Must
|
||||
# be at least 32 bytes (both services refuse a shorter one).
|
||||
jwt_secret=${DEMO_JWT_SECRET:-demo-jwt-secret-please-change-me-0123456789}
|
||||
# The first admin, seeded into the userservice on first boot.
|
||||
admin_email=${DEMO_ADMIN_EMAIL:-root@scimesh.local}
|
||||
admin_password=${DEMO_ADMIN_PASSWORD:-rootpassword}
|
||||
workers=${DEMO_WORKERS:-2}
|
||||
demo_dir=${DEMO_DIR:-.demo}
|
||||
case "$demo_dir" in
|
||||
@@ -26,9 +33,15 @@ logs_dir="$demo_dir/logs"
|
||||
compose() {
|
||||
POSTGRES_PORT="$postgres_port" \
|
||||
COORDINATOR_PORT="$coordinator_port" \
|
||||
USERSERVICE_PORT="$userservice_port" \
|
||||
UI_AUTH_TOKEN="$ui_token" \
|
||||
WORKER_AUTH_TOKEN="$worker_token" \
|
||||
docker compose -p "$project" -f "$coordinator_dir/docker-compose.yml" "$@"
|
||||
JWT_SECRET="$jwt_secret" \
|
||||
BOOTSTRAP_ADMIN_EMAIL="$admin_email" \
|
||||
BOOTSTRAP_ADMIN_PASSWORD="$admin_password" \
|
||||
docker compose -p "$project" \
|
||||
-f "$coordinator_dir/docker-compose.yml" \
|
||||
-f "$coordinator_dir/docker-compose.users.yml" "$@"
|
||||
}
|
||||
|
||||
stop_workers() {
|
||||
@@ -57,10 +70,29 @@ wait_for_coordinator() {
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_userservice() {
|
||||
local attempt=0
|
||||
until curl --fail --silent --show-error "http://localhost:$userservice_port/health" >/dev/null; do
|
||||
attempt=$((attempt + 1))
|
||||
if (( attempt >= 45 )); then
|
||||
echo "Userservice did not become ready. Recent logs:" >&2
|
||||
compose logs --tail=80 userservice >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_workers() {
|
||||
local attempt=0 registered overview
|
||||
local attempt=0 registered overview cookie="$demo_dir/session.cookies"
|
||||
# The dashboard API is behind a userservice session now, not basic auth. Log in
|
||||
# as the seeded admin (who sees every worker) to obtain a session cookie.
|
||||
curl --fail --silent -c "$cookie" \
|
||||
--data-urlencode "email=$admin_email" \
|
||||
--data-urlencode "password=$admin_password" \
|
||||
"http://localhost:$coordinator_port/ui/login" >/dev/null 2>&1 || true
|
||||
until false; do
|
||||
overview=$(curl --fail --silent --show-error --user "operator:$ui_token" \
|
||||
overview=$(curl --fail --silent --show-error -b "$cookie" \
|
||||
"http://localhost:$coordinator_port/ui/api/overview" 2>/dev/null || true)
|
||||
# The overview contains no jobs at demo startup, so every `id` belongs to
|
||||
# a registered worker. Avoid adding jq just for this local helper.
|
||||
@@ -96,6 +128,8 @@ start() {
|
||||
compose up -d --build
|
||||
echo "Waiting for the coordinator on http://localhost:$coordinator_port ..."
|
||||
wait_for_coordinator
|
||||
echo "Waiting for the userservice on http://localhost:$userservice_port ..."
|
||||
wait_for_userservice
|
||||
|
||||
: > "$pid_file"
|
||||
for index in $(seq 1 "$workers"); do
|
||||
@@ -115,13 +149,15 @@ start() {
|
||||
|
||||
SciMesh manual demo is ready.
|
||||
|
||||
UI: http://localhost:$coordinator_port/ui
|
||||
Username: operator
|
||||
Password: $ui_token
|
||||
Workers: $workers local reference workers
|
||||
UI: http://localhost:$coordinator_port/ui (shows a login page)
|
||||
Admin login: $admin_email / $admin_password
|
||||
Userservice: http://localhost:$userservice_port
|
||||
Workers: $workers local reference workers
|
||||
|
||||
Upload a small ChEMBL TSV through “New similarity search”, then watch the job
|
||||
page update. Worker logs are in $logs_dir. Stop everything with:
|
||||
Sign in with the admin above, or register a new account from the login page.
|
||||
The admin sees every job; a plain user sees only their own. Upload a small
|
||||
ChEMBL TSV through “New similarity search”, then watch the job page update.
|
||||
Worker logs are in $logs_dir. Stop everything with:
|
||||
|
||||
make demo-down
|
||||
EOF
|
||||
|
||||
Reference in New Issue
Block a user