#!/usr/bin/env bash # Sanity checks for bank · exchange · merchant (public + server-side). # Sections are independent; continues after failures. set -euo pipefail ROOT=$(cd "$(dirname "$0")" && pwd) # shellcheck source=lib.sh source "$ROOT/lib.sh" tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT expect_code() { local label="$1" want="$2" url="$3" local code code=$(http_code "$url") case ",$want," in *",$code,"*) ok "$label" ;; *) fail "$label" "HTTP $code (want $want) $url" ;; esac } json_currency() { python3 -c 'import json,sys; d=json.load(open(sys.argv[1])); print(d.get("currency") or "")' "$1" 2>/dev/null || true } # Area sanity-### — public + optional server-side per component set_area sanity # --------------------------------------------------------------------------- section "sanity · bank" # --------------------------------------------------------------------------- expect_code "bank public /config" 200 "$BANK_PUBLIC/config" expect_code "bank public /taler-integration/config" 200 "$BANK_PUBLIC/taler-integration/config" expect_code "bank public /webui/" 200 "$BANK_PUBLIC/webui/" code=$(http_body "$BANK_PUBLIC/config" "$tmp/bank-config.json") if [ "$code" = "200" ]; then cur=$(json_currency "$tmp/bank-config.json") [ "$cur" = "GOA" ] && ok "bank currency GOA" || fail "bank currency" "got ${cur:-?}" # wire type / name if present python3 - "$tmp/bank-config.json" <<'PY' 2>/dev/null && ok "bank config JSON object" || fail "bank config JSON" import json,sys d=json.load(open(sys.argv[1])) sys.exit(0 if isinstance(d, dict) and d.get("currency") else 1) PY if json_has_alt_unit_names "$tmp/bank-config.json" >/tmp/alt-bank-s.$$ 2>&1; then ok "bank /config alt_unit_names" "$(tr '\n' '; ' /dev/null || echo 000) echo "LOCAL_CONFIG=$code" code2=$(curl -sS -m 5 -o /dev/null -w '%{http_code}' http://127.0.0.1:9012/taler-integration/config 2>/dev/null || echo 000) echo "LOCAL_INT=$code2" if podman exec "$BANK" bash -c 'pgrep -f "MainKt serve|libeufin-bank serve" >/dev/null' 2>/dev/null; then echo "LIBEUFIN=1" else echo "LIBEUFIN=0" fi if podman exec "$BANK" bash -c 'pg_isready -q' 2>/dev/null; then echo "PG=1" else echo "PG=0" fi # in-container health if present if podman exec "$BANK" test -x /usr/local/bin/check_bank-health.sh 2>/dev/null; then podman exec "$BANK" /usr/local/bin/check_bank-health.sh 2>&1 | sed 's/^/HEALTH /' | tail -20 echo "HEALTH_EC=${PIPESTATUS[0]}" fi REMOTE ) echo "$BOUT" | grep -q '^CTR=.\+' && ok "bank container $(echo "$BOUT" | sed -n 's/^CTR=//p' | head -1)" || fail "bank container" "not found" echo "$BOUT" | grep -q 'LOCAL_CONFIG=200' && ok "bank local :9012/config" || fail "bank local :9012/config" echo "$BOUT" | grep -q 'LOCAL_INT=200' && ok "bank local :9012/taler-integration/config" || fail "bank local integration" echo "$BOUT" | grep -q 'LIBEUFIN=1' && ok "bank libeufin-bank process" || fail "bank libeufin-bank process" echo "$BOUT" | grep -q 'PG=1' && ok "bank postgres ready" || warn "bank postgres" "pg_isready failed" if echo "$BOUT" | grep -q 'HEALTH '; then if echo "$BOUT" | grep -qE 'HEALTH_EC=0|ALL CRITICAL CHECKS PASSED'; then ok "bank check_bank-health.sh" else # health script may false-fail process grep; warn not fail if local config ok warn "bank check_bank-health.sh" "non-zero or incomplete" fi fi else warn "bank server-side" "ssh ${KOOPA_SSH} unavailable" fi # --------------------------------------------------------------------------- section "sanity · exchange" # --------------------------------------------------------------------------- expect_code "exchange public /config" 200 "$EXCHANGE_PUBLIC/config" expect_code "exchange public /keys" 200 "$EXCHANGE_PUBLIC/keys" expect_code "exchange public /terms" 200 "$EXCHANGE_PUBLIC/terms" code=$(http_body "$EXCHANGE_PUBLIC/config" "$tmp/ex-config.json") if [ "$code" = "200" ]; then cur=$(json_currency "$tmp/ex-config.json") [ "$cur" = "GOA" ] && ok "exchange currency GOA" || fail "exchange currency" "got ${cur:-?}" if json_has_alt_unit_names "$tmp/ex-config.json" "GOA" >/tmp/alt-ex-s.$$ 2>&1; then ok "exchange /config alt_unit_names" "$(tr '\n' '; ' /dev/null || echo 000) echo "LOCAL_CONFIG=$code" codek=$(curl -sS -m 8 -o /dev/null -w '%{http_code}' http://127.0.0.1:9011/keys 2>/dev/null || echo 000) echo "LOCAL_KEYS=$codek" if [ -n "$EX" ]; then if podman exec "$EX" bash -c 'pgrep -f taler-exchange-httpd >/dev/null' 2>/dev/null; then echo "HTTPD=1" else echo "HTTPD=0" fi for p in taler-exchange-secmod-rsa taler-exchange-secmod-eddsa taler-exchange-wirewatch taler-exchange-aggregator; do if podman exec "$EX" bash -c "pgrep -f $p >/dev/null" 2>/dev/null; then echo "PROC_$p=1" else echo "PROC_$p=0" fi done if podman exec "$EX" test -x /usr/local/bin/check_exchange-health.sh 2>/dev/null; then SKIP_ENSURE=1 podman exec -e SKIP_ENSURE=1 "$EX" /usr/local/bin/check_exchange-health.sh 2>&1 | sed 's/^/HEALTH /' | tail -25 fi fi REMOTE ) echo "$EOUT" | grep -q '^CTR=.\+' && ok "exchange container $(echo "$EOUT" | sed -n 's/^CTR=//p' | head -1)" || fail "exchange container" echo "$EOUT" | grep -q 'LOCAL_CONFIG=200' && ok "exchange local :9011/config" || fail "exchange local :9011/config" echo "$EOUT" | grep -q 'LOCAL_KEYS=200' && ok "exchange local :9011/keys" || fail "exchange local :9011/keys" echo "$EOUT" | grep -q 'HTTPD=1' && ok "exchange-httpd process" || warn "exchange-httpd process" "not detected" echo "$EOUT" | grep -q 'PROC_taler-exchange-wirewatch=1' && ok "exchange wirewatch" || warn "exchange wirewatch" "not running" echo "$EOUT" | grep -q 'PROC_taler-exchange-aggregator=1' && ok "exchange aggregator" || warn "exchange aggregator" "not running" else warn "exchange server-side" "ssh unavailable" fi # --------------------------------------------------------------------------- section "sanity · merchant" # --------------------------------------------------------------------------- expect_code "merchant public /config" 200 "$MERCHANT_PUBLIC/config" expect_code "merchant public /webui/" 200 "$MERCHANT_PUBLIC/webui/" code=$(http_body "$MERCHANT_PUBLIC/config" "$tmp/mer-config.json") if [ "$code" = "200" ]; then if python3 - "$tmp/mer-config.json" "$EXCHANGE_PUBLIC" <<'PY' import json,sys d=json.load(open(sys.argv[1])) want=sys.argv[2].rstrip("/") curs=list((d.get("currencies") or {}).keys()) ex=d.get("exchanges") or [] urls=[] for e in ex: if isinstance(e, dict): u=e.get("base_url") or e.get("url") or e.get("exchange_base_url") or "" if u: urls.append(u.rstrip("/")) elif isinstance(e, str): urls.append(e.rstrip("/")) ok_goa = "GOA" in curs or any((e.get("currency") if isinstance(e, dict) else None)=="GOA" for e in ex) ok_ex = any(want in u or "exchange.hacktivism.ch" in u for u in urls) print("currencies", curs) print("exchanges", urls[:5]) sys.exit(0 if ok_goa and ok_ex else 1) PY then ok "merchant config GOA + exchange.hacktivism.ch" else fail "merchant config GOA + exchange" "see currencies/exchanges" fi if json_has_alt_unit_names "$tmp/mer-config.json" >/tmp/alt-mer-s.$$ 2>&1; then ok "merchant currencies alt_unit_names" "$(tr '\n' '; ' /dev/null || echo 000) echo "LOCAL_CONFIG=$code" if [ -n "$MER" ]; then if podman exec "$MER" bash -c 'pgrep -f taler-merchant-httpd >/dev/null' 2>/dev/null; then echo "HTTPD=1" else echo "HTTPD=0" fi if podman exec "$MER" test -x /usr/local/bin/check_merchant-health.sh 2>/dev/null; then SKIP_ENSURE=1 podman exec -e SKIP_ENSURE=1 "$MER" /usr/local/bin/check_merchant-health.sh 2>&1 | sed 's/^/HEALTH /' | tail -30 fi fi REMOTE ) echo "$MOUT" | grep -q '^CTR=.\+' && ok "merchant container $(echo "$MOUT" | sed -n 's/^CTR=//p' | head -1)" || fail "merchant container" echo "$MOUT" | grep -q 'LOCAL_CONFIG=200' && ok "merchant local :9010/config" || fail "merchant local :9010/config" echo "$MOUT" | grep -q 'HTTPD=1' && ok "merchant-httpd process" || warn "merchant-httpd process" "not detected" if echo "$MOUT" | grep -q 'HEALTH '; then if echo "$MOUT" | grep -qiE 'ALL CRITICAL|HEALTH_EC=0|\[OK\]'; then ok "merchant check_merchant-health.sh (sample OK)" else warn "merchant check_merchant-health.sh" "see remote output" fi fi else warn "merchant server-side" "ssh unavailable" fi summary