monitoring/merge: origin ladder+metrics + stage domains/profiles

This commit is contained in:
Hernâni Marques 2026-07-17 15:46:50 +02:00
commit d6f4f649c1
No known key found for this signature in database
GPG key ID: CB5738652768F7E9
86 changed files with 8199 additions and 256 deletions

View file

@ -0,0 +1,179 @@
#!/usr/bin/env bash
# Host (hernani@koopa): start Taler *apps inside* merchant/bank containers.
#
# Containers use CMD sleep infinity — podman start alone is not enough.
# Called by user systemd units after container-taler-*.service.
#
# Usage:
# ensure-taler-apps.sh # merchant + bank + helpers
# ensure-taler-apps.sh merchant
# ensure-taler-apps.sh bank
# ensure-taler-apps.sh status
set -euo pipefail
MER_CTR="${MER_CTR:-taler-hacktivism}"
BANK_CTR="${BANK_CTR:-taler-hacktivism-bank}"
AUTO_LOOP_SECS="${AUTO_CONFIRM_LOOP_SECS:-2}"
WAIT_SECS="${WAIT_SECS:-90}"
log() { printf '%s %s\n' "$(date -Iseconds)" "$*"; }
# Oneshot container-*.service stays "active" after podman stop — always start here.
ensure_container() {
local name="$1"
if podman inspect -f '{{.State.Running}}' "$name" 2>/dev/null | grep -qx true; then
return 0
fi
log "container $name: not running — podman start"
podman start "$name" >/dev/null
}
wait_running() {
local name="$1" i
ensure_container "$name"
for i in $(seq 1 "$WAIT_SECS"); do
if podman inspect -f '{{.State.Running}}' "$name" 2>/dev/null | grep -qx true; then
return 0
fi
sleep 1
done
log "ERROR: container $name not running after ${WAIT_SECS}s"
return 1
}
ctr_has_proc() {
local ctr="$1" pattern="$2"
podman exec "$ctr" bash -lc "ps -eo args= | grep -F -- '$pattern' | grep -v grep" >/dev/null 2>&1
}
ensure_merchant_loopback_helper() {
# Optional loopback helper on :19097 if present in the container image
if podman exec "$MER_CTR" bash -lc "ss -tln 2>/dev/null | grep -q ':19097'" 2>/dev/null; then
log "merchant: loopback :19097 already listening"
return 0
fi
if ! podman exec "$MER_CTR" test -f /usr/local/bin/ui-unlock-api.py 2>/dev/null; then
return 0
fi
log "merchant: start loopback helper :19097…"
podman exec -u root -d "$MER_CTR" python3 /usr/local/bin/ui-unlock-api.py \
|| log "WARN: loopback helper start failed"
}
ensure_merchant() {
wait_running "$MER_CTR"
if ctr_has_proc "$MER_CTR" 'taler-merchant-httpd'; then
log "merchant: httpd already up"
ensure_merchant_loopback_helper
return 0
fi
log "merchant: start base (postgres/nginx)…"
podman exec -u root "$MER_CTR" \
/root/start_base_services_for_taler.sh --no-shell
log "merchant: start_merchant.sh…"
podman exec -u root "$MER_CTR" \
runuser -u taler-merchant-httpd -- /usr/local/bin/start_merchant.sh
ensure_merchant_loopback_helper
log "merchant: done"
}
ensure_bank() {
wait_running "$BANK_CTR"
if ! ctr_has_proc "$BANK_CTR" 'libeufin-bank'; then
log "bank: start base + libeufin-bank…"
podman exec -u root "$BANK_CTR" \
/root/start_base_services_for_taler_bank.sh --no-shell --start-bank
else
log "bank: libeufin-bank already up"
fi
# Landing nginx on :9013 (separate from bank API :9012)
if ! podman exec "$BANK_CTR" bash -lc "ss -tln 2>/dev/null | grep -q ':9013 '" 2>/dev/null; then
log "bank: start landing nginx :9013…"
podman exec -u root "$BANK_CTR" bash -lc '
if [ -x /etc/init.d/nginx ]; then /etc/init.d/nginx start || true
else nginx || true
fi
'
else
log "bank: nginx :9013 already listening"
fi
ensure_bank_helpers
log "bank: done"
}
# Single auto-confirm loop + demo-withdraw API (idempotent)
ensure_bank_helpers() {
local n
# Collapse duplicate loops (common after manual restarts)
n=$(podman exec "$BANK_CTR" bash -lc \
"ps -eo pid=,args= | awk '/auto-confirm-withdrawals\\.sh --loop/ {print \$1}'" 2>/dev/null || true)
set -- $n
if [ "$#" -gt 1 ]; then
log "bank: stop $(($# - 1)) extra auto-confirm pid(s)…"
shift # keep first
for pid in "$@"; do
podman exec -u root "$BANK_CTR" kill "$pid" 2>/dev/null || true
done
sleep 0.3
fi
if [ "$#" -eq 0 ]; then
log "bank: start auto-confirm --loop ${AUTO_LOOP_SECS}"
podman exec -u root -d "$BANK_CTR" \
/usr/local/bin/auto-confirm-withdrawals.sh --loop "$AUTO_LOOP_SECS" \
|| log "WARN: auto-confirm start failed (script missing?)"
else
log "bank: auto-confirm already running"
fi
if podman exec "$BANK_CTR" test -f /usr/local/bin/demo-withdraw-api.py 2>/dev/null; then
if ! ctr_has_proc "$BANK_CTR" 'demo-withdraw-api.py'; then
log "bank: start demo-withdraw-api…"
podman exec -u root -d "$BANK_CTR" \
python3 /usr/local/bin/demo-withdraw-api.py \
|| log "WARN: demo-withdraw-api start failed"
else
log "bank: demo-withdraw-api already running"
fi
fi
}
status() {
echo "=== containers ==="
podman ps -a --filter name='taler-hacktivism' --format '{{.Names}} {{.Status}}'
echo "=== merchant procs (sample) ==="
podman exec "$MER_CTR" bash -lc "ps -eo args= | grep -E 'taler-merchant-httpd|postgres -D|nginx: master' | grep -v grep || true" 2>/dev/null || echo "(container down)"
echo "=== bank procs (sample) ==="
podman exec "$BANK_CTR" bash -lc "ps -eo args= | grep -E 'libeufin-bank|auto-confirm|demo-withdraw|nginx: master' | grep -v grep || true" 2>/dev/null || echo "(container down)"
echo "=== public ==="
for u in \
https://taler.hacktivism.ch/config \
https://taler.hacktivism.ch/intro/ \
https://bank.hacktivism.ch/config \
https://bank.hacktivism.ch/intro/
do
code=$(curl -sk -o /dev/null -w '%{http_code}' --connect-timeout 4 --max-redirs 0 "$u" || echo err)
printf ' %s %s\n' "$code" "$u"
done
}
cmd="${1:-all}"
case "$cmd" in
all|"")
ensure_merchant
ensure_bank
;;
merchant) ensure_merchant ;;
bank) ensure_bank ;;
helpers) ensure_bank_helpers ;;
status) status ;;
-h|--help)
sed -n '2,16p' "$0"
exit 0
;;
*)
echo "unknown: $cmd (all|merchant|bank|helpers|status)" >&2
exit 2
;;
esac

View file

@ -0,0 +1,43 @@
#!/usr/bin/env bash
# Install ensure-taler-apps + user systemd units on this host (hernani@koopa).
# Run from admin-log checkout or with ADMIN_LOG set.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
ADMIN_LOG="${ADMIN_LOG:-$ROOT}"
UNIT_SRC="$ADMIN_LOG/configs/systemd/user"
BIN_DST="${HOME}/.local/bin"
UNIT_DST="${HOME}/.config/systemd/user"
mkdir -p "$BIN_DST" "$UNIT_DST"
install -m 0755 "$ADMIN_LOG/scripts/taler-shared/ensure-taler-apps.sh" \
"$BIN_DST/ensure-taler-apps.sh"
install -m 0644 "$UNIT_SRC/taler-merchant-apps.service" "$UNIT_DST/"
install -m 0644 "$UNIT_SRC/taler-bank-apps.service" "$UNIT_DST/"
mkdir -p \
"$UNIT_DST/container-taler-hacktivism.service.d" \
"$UNIT_DST/container-taler-hacktivism-bank.service.d" \
"$UNIT_DST/container-koopa-paivana.service.d"
install -m 0644 "$UNIT_SRC/container-taler-hacktivism.service.d/apps.conf" \
"$UNIT_DST/container-taler-hacktivism.service.d/apps.conf"
install -m 0644 "$UNIT_SRC/container-taler-hacktivism-bank.service.d/apps.conf" \
"$UNIT_DST/container-taler-hacktivism-bank.service.d/apps.conf"
install -m 0644 "$UNIT_SRC/container-koopa-paivana.service.d/order.conf" \
"$UNIT_DST/container-koopa-paivana.service.d/order.conf"
systemctl --user daemon-reload
systemctl --user enable taler-merchant-apps.service taler-bank-apps.service
echo "Installed:"
echo " $BIN_DST/ensure-taler-apps.sh"
echo " $UNIT_DST/taler-{merchant,bank}-apps.service (enabled)"
echo " drop-ins: container-taler-hacktivism{,-bank}.service.d/apps.conf"
echo " drop-in: container-koopa-paivana.service.d/order.conf"
echo
echo "Start now (if containers already up):"
echo " systemctl --user start taler-merchant-apps.service taler-bank-apps.service"
echo " $BIN_DST/ensure-taler-apps.sh status"

View file

@ -1,7 +1,17 @@
#!/bin/bash
# Memory snapshot for landing-stats (source after json_str is defined).
# Memory snapshot for landing-stats.
# Sets MEM_JSON (fields to embed inside performance.memory).
# Also: mem_snapshot_emit → full JSON object on stdout (host collector).
# IMPORTANT: no pipelines around the /proc loop (bash subshell loses counters).
#
# json_str may already be defined by the caller (landing-stats.sh); provide a
# safe default so this file is usable stand-alone via podman exec.
if ! declare -F json_str >/dev/null 2>&1; then
json_str() {
printf '"%s"' "$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr '\n\r\t' ' ')"
}
fi
mem_fmt_bytes() {
awk -v b="${1:-0}" 'BEGIN{
@ -92,21 +102,39 @@ mem_snapshot_json() {
rm -f "$topf"
lim_json="null"
lim_human_json="null"
if [[ "$limit_b" =~ ^[0-9]+$ ]] && [ "$limit_b" -gt 0 ]; then
lim_json=$limit_b
lim_human_json=$(json_str "$(mem_fmt_bytes "$limit_b")")
fi
cg_json="null"
if [[ "$cgroup_b" =~ ^[0-9]+$ ]]; then
cg_json=$cgroup_b
fi
# Compact container label: "693.4 MiB" or "693.4 MiB / 2.00 GiB" when capped
local ctr_human
ctr_human=$(mem_fmt_bytes "$total_b")
if [ "$lim_human_json" != "null" ]; then
# lim_human_json is a quoted string already
:
fi
MEM_JSON="
\"container_rss_bytes\": ${total_b},
\"container_rss_human\": $(json_str "$(mem_fmt_bytes "$total_b")"),
\"container_rss_human\": $(json_str "$ctr_human"),
\"container_rss_label\": $(json_str "$(
if [ "$lim_json" != "null" ]; then
printf '%s / %s' "$ctr_human" "$(mem_fmt_bytes "$limit_b")"
else
printf '%s' "$ctr_human"
fi
)"),
\"proc_sum_rss_bytes\": ${sum_b},
\"proc_sum_rss_human\": $(json_str "$(mem_fmt_bytes "$sum_b")"),
\"cgroup_bytes\": ${cg_json},
\"cgroup_limit_bytes\": ${lim_json},
\"cgroup_limit_human\": ${lim_human_json},
\"postgres_rss_bytes\": ${postgres_b},
\"postgres_rss_human\": $(json_str "$(mem_fmt_bytes "$postgres_b")"),
\"postgres_n\": ${n_pg},
@ -128,3 +156,15 @@ mem_snapshot_json() {
\"top\": ${top_json}
"
}
# Full JSON for host collector: { ok, loadavg, memory: {…} }
mem_snapshot_emit() {
mem_snapshot_json || return 1
local loadavg=""
if [ -r /proc/loadavg ]; then
loadavg=$(awk '{print $1","$2","$3}' /proc/loadavg)
fi
printf '{\n "ok": true,\n "source": "mem-snapshot",\n "loadavg": %s,\n "memory": {\n%s\n }\n}\n' \
"$(json_str "$loadavg")" \
"$MEM_JSON"
}