mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
82 lines
4.3 KiB
Bash
82 lines
4.3 KiB
Bash
#!/usr/bin/env bash
|
|||
|
|
# Multi-node smoke tests against a running stack (start-multinode-test.sh): load-balancer spread, cross-node JWT validation (signing keys persist in the shared DB), and processor state visible from every node.
|
||
|
|
# Auth: extracts the Bearer JWT from the login body via sed (no jq needed host-side) and hits nodes directly with docker exec.
|
||
|
|
# Non-destructive - safe to re-run against the stack at http://localhost:8080.
|
||
|
|
set -uo pipefail
|
||
|
|
cd "$(dirname "$0")"
|
||
|
|
|
||
|
|
LB="http://localhost:8080"
|
||
|
|
ADMIN_USER="admin"; ADMIN_PASS="stirling"
|
||
|
|
NODES="multinode-stirling-1 multinode-stirling-2"
|
||
|
|
# An authed, admin-visible endpoint that returns 200 with a valid token, 401 without.
|
||
|
|
PROBE="/api/v1/sources"
|
||
|
|
pass=0; fail=0
|
||
|
|
ok() { echo " PASS - $*"; pass=$((pass+1)); }
|
||
|
|
bad() { echo " FAIL - $*"; fail=$((fail+1)); }
|
||
|
|
|
||
|
|
login() { # -> prints the bearer token
|
||
|
|
curl -s -X POST "$LB/api/v1/auth/login" -H 'Content-Type: application/json' \
|
||
|
|
-d "{\"username\":\"$ADMIN_USER\",\"password\":\"$ADMIN_PASS\"}" \
|
||
|
|
| sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p'
|
||
|
|
}
|
||
|
|
|
||
|
|
echo "== 1. Load balancer spreads requests across nodes =="
|
||
|
|
served=$(for i in $(seq 1 12); do
|
||
|
|
curl -s -D - -o /dev/null "$LB/api/v1/info/status" | tr -d '\r' | awk -F': ' '/^X-Served-By/{print $2}'
|
||
|
|
done | sort -u)
|
||
|
|
distinct=$(printf '%s\n' "$served" | grep -c .)
|
||
|
|
echo " upstreams seen: $(printf '%s' "$served" | paste -sd, -)"
|
||
|
|
[ "$distinct" -ge 2 ] && ok "LB round-robined across $distinct nodes" \
|
||
|
|
|| bad "only $distinct node(s) served (expected >=2; is X-Served-By enabled?)"
|
||
|
|
|
||
|
|
echo "== 2. A JWT from the LB is accepted by BOTH nodes directly (shared signing key) =="
|
||
|
|
jwt=$(login)
|
||
|
|
if [ -z "$jwt" ]; then
|
||
|
|
bad "admin login via LB failed - cannot test cross-node JWT"
|
||
|
|
else
|
||
|
|
ok "logged in via LB, got a JWT (${#jwt} chars)"
|
||
|
|
for n in $NODES; do
|
||
|
|
hc=$(docker exec "$n" curl -s -o /dev/null -w '%{http_code}' \
|
||
|
|
-H "Authorization: Bearer $jwt" "http://localhost:8080$PROBE" 2>/dev/null)
|
||
|
|
[ "$hc" = "200" ] && ok "$n accepted the foreign-minted JWT (HTTP 200)" \
|
||
|
|
|| bad "$n rejected the JWT (HTTP $hc) - keys not shared across nodes"
|
||
|
|
done
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "== 3. Processor state is shared: each node sees the same sources =="
|
||
|
|
count_of() { # $1=node -> number of sources that node reports
|
||
|
|
docker exec "$1" curl -s -H "Authorization: Bearer $jwt" "http://localhost:8080$PROBE" 2>/dev/null \
|
||
|
|
| grep -o '"id"' | grep -c .
|
||
|
|
}
|
||
|
|
a=$(count_of multinode-stirling-1); b=$(count_of multinode-stirling-2)
|
||
|
|
echo " stirling-1 sources: $a stirling-2 sources: $b"
|
||
|
|
if [ "$a" -gt 0 ] && [ "$a" = "$b" ]; then
|
||
|
|
ok "both nodes report the same $a sources (shared DB)"
|
||
|
|
else
|
||
|
|
bad "source counts differ or zero across nodes ($a vs $b)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "== 4. Seeded org is in the shared DB =="
|
||
|
|
users=$(docker exec multinode-postgres psql -U stirling -d stirling -tAc "select count(*) from users" 2>/dev/null | tr -d '[:space:]')
|
||
|
|
teams=$(docker exec multinode-postgres psql -U stirling -d stirling -tAc "select count(*) from teams" 2>/dev/null | tr -d '[:space:]')
|
||
|
|
conns=$(docker exec multinode-postgres psql -U stirling -d stirling -tAc "select count(*) from integration_configs" 2>/dev/null | tr -d '[:space:]')
|
||
|
|
echo " users=$users teams=$teams integration_configs=$conns"
|
||
|
|
[ "${users:-0}" -ge 40 ] && ok "$users users present" || bad "only ${users:-0} users (did the seed run?)"
|
||
|
|
[ "${conns:-0}" -ge 1 ] && ok "$conns S3/integration connection(s) present" || bad "no integration connections"
|
||
|
|
|
||
|
|
echo "== 5. Cross-node encrypted-secret read (shared credential key) =="
|
||
|
|
# The seed's S3 secret was encrypted by whichever node handled it; fetching it via the LB (either node) and getting a masked, non-error view proves the credential key is shared, not per-node.
|
||
|
|
lc=$(curl -s -o /tmp/mn_conns.json -w '%{http_code}' -H "Authorization: Bearer $jwt" "$LB/api/v1/integrations")
|
||
|
|
if [ "$lc" = "200" ] && grep -q '"integrationType"' /tmp/mn_conns.json; then
|
||
|
|
ok "integration list decrypts through the LB (HTTP 200) - credential key is shared"
|
||
|
|
else
|
||
|
|
bad "integration list failed (HTTP $lc) - credential key may not be shared across nodes"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo
|
||
|
|
echo "============================================================"
|
||
|
|
echo " Multi-node validation: $pass passed, $fail failed."
|
||
|
|
echo " Stack left running: $LB (admin / stirling)"
|
||
|
|
echo "============================================================"
|
||
|
|
[ "$fail" -eq 0 ]
|