diff --git a/scripts/taler-monitoring/domains.conf b/scripts/taler-monitoring/domains.conf new file mode 100644 index 0000000..fccc411 --- /dev/null +++ b/scripts/taler-monitoring/domains.conf @@ -0,0 +1,32 @@ +# taler-monitoring domain profiles +# +# When you add a stack, declare the three public endpoints here: +# name bank exchange merchant-backend currency local landing [canonical] +# +# - name: what -d / TALER_DOMAIN matches (aliases allowed as extra lines) +# - bank / exchange / merchant: hostname or full https:// URL +# - currency: GOA | KUDOS | CHF | … (empty = report only) +# - local: 1 = koopa SSH/inside/e2e stack; 0 = public-only +# - landing: 1 = check /intro landings + assets; 0 = skip (no GOA-style landings) +# - canonical: optional TALER_DOMAIN label after alias match +# +# CLI overrides after load: --bank --exchange --merchant --currency +# Alternate file: TALER_DOMAINS_CONF=/path/to/domains.conf + +# Local GOA (koopa) — landings matter +koopa bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch GOA 1 1 hacktivism.ch +hacktivism bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch GOA 1 1 hacktivism.ch +hacktivism.ch bank.hacktivism.ch exchange.hacktivism.ch taler.hacktivism.ch GOA 1 1 + +# Public demo (KUDOS) — has intro-style pages; keep soft landing checks +taler.net bank.demo.taler.net exchange.demo.taler.net backend.demo.taler.net KUDOS 0 1 demo.taler.net +demo.taler.net bank.demo.taler.net exchange.demo.taler.net backend.demo.taler.net KUDOS 0 1 + +# Public test stack (TESTKUDOS) — no GOA-style landings +test.taler.net bank.test.taler.net exchange.test.taler.net backend.test.taler.net TESTKUDOS 0 0 + +# TOPS CHF — multi-tenant merchant my.taler-ops.ch; no public GOA landings +taler-ops.ch bank.taler-ops.ch exchange.taler-ops.ch my.taler-ops.ch CHF 0 0 +my.taler-ops.ch bank.taler-ops.ch exchange.taler-ops.ch my.taler-ops.ch CHF 0 0 taler-ops.ch +stage.taler-ops.ch bank.stage.taler-ops.ch exchange.stage.taler-ops.ch my.stage.taler-ops.ch CHF 0 0 +my.stage.taler-ops.ch bank.stage.taler-ops.ch exchange.stage.taler-ops.ch my.stage.taler-ops.ch CHF 0 0 stage.taler-ops.ch diff --git a/scripts/taler-monitoring/lib.sh b/scripts/taler-monitoring/lib.sh index d405a2d..451d56d 100755 --- a/scripts/taler-monitoring/lib.sh +++ b/scripts/taler-monitoring/lib.sh @@ -14,10 +14,13 @@ : "${MERCHANT_INSTANCE:=goa-demo-cp4zqk}" : "${WITHDRAW_AMT:=GOA:20}" # single-shot fallback; e2e ladder uses ATM notes : "${PAY_AMT:=GOA:0.01}" -: "${CREDIT_AMT:=GOA:400}" # covers ATM ladder 20+50+100+200 +: "${CREDIT_AMT:=GOA:4700}" # covers ATM ladder 20+50+100+200+4200 (paivana) : "${TIMEOUT:=12}" -: "${E2E_TIMEOUT:=55}" # whole e2e budget; skip rest when exceeded +: "${E2E_TIMEOUT:=55}" # whole e2e budget; skip rest when exceeded (e2e raises as needed) : "${E2E_PAY_SECS:=22}" # dedicated seconds for pay handle-uri (avoid Alarm clock) +# Local GOA: public paivana paywall (https://paivana.hacktivism.ch · template GOA:4200) +: "${PAIVANA_PUBLIC:=https://paivana.hacktivism.ch}" +: "${E2E_PAIVANA:=1}" # 0 = skip paivana section in e2e # Devtest: inject reserve credit via wire-gateway admin/add-incoming (optional). # Default off once wirewatch DNS works; set E2E_FAKE_INCOMING=1 to force. : "${E2E_FAKE_INCOMING:=0}" @@ -37,17 +40,103 @@ EXCHANGE_PUBLIC=${EXCHANGE_PUBLIC%/} MERCHANT_PUBLIC=${MERCHANT_PUBLIC%/} # --------------------------------------------------------------------------- -# Domain presets → public bank / exchange / merchant base URLs +# Domain profiles → bank / exchange / merchant base URLs # -# TALER_DOMAIN=hacktivism.ch (default, GOA, local stack) -# TALER_DOMAIN=taler.net → demo.taler.net (KUDOS) -# TALER_DOMAIN=demo.taler.net -# TALER_DOMAIN=taler-ops.ch → exchange.taler-ops.ch (CHF; bank/merchant if up) -# TALER_DOMAIN=example.org → bank/exchange/backend|taler|merchant.example.org +# Single place to declare a stack: scripts/taler-monitoring/domains.conf +# (or TALER_DOMAINS_CONF). Each profile names the three public endpoints. # -# Explicit BANK_PUBLIC / EXCHANGE_PUBLIC / MERCHANT_PUBLIC still win if set -# *after* apply_taler_domain, or pass full URLs via --bank/--exchange/--merchant. +# CLI still wins after profile load: +# --bank URL --exchange URL --merchant URL --currency CODE +# Env: BANK_PUBLIC EXCHANGE_PUBLIC MERCHANT_PUBLIC EXPECT_CURRENCY +# +# Unknown domains fall back to heuristics (see apply_taler_domain). # --------------------------------------------------------------------------- + +_MONITOR_LIB_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +: "${TALER_DOMAINS_CONF:=${_MONITOR_LIB_DIR}/domains.conf}" + +# host_or_url → https://… (no trailing slash) +_to_https_base() { + local x="${1%/}" + case "$x" in + https://*|http://*) printf '%s' "$x" ;; + "") printf '' ;; + *) printf 'https://%s' "$x" ;; + esac +} + +# 1 = check GOA-style /intro landing pages (assets, link crawl, demo-withdraw). +# 0 = skip (e.g. taler-ops.ch / mytops — no public landings). +: "${CHECK_LANDING:=1}" + +# Declare bank + exchange + merchant (+ currency, local stack, landing, domain id). +# Usage: +# set_taler_stack BANK EXCHANGE MERCHANT [CURRENCY] [LOCAL 0|1] [LANDING 0|1] [TALER_DOMAIN] +# BANK/EXCHANGE/MERCHANT: hostname or full URL +set_taler_stack() { + local bank="${1:-}" exchange="${2:-}" merchant="${3:-}" + local currency="${4:-}" local_stack="${5:-0}" landing="${6:-}" domain_id="${7:-}" + + BANK_PUBLIC=$(_to_https_base "$bank") + EXCHANGE_PUBLIC=$(_to_https_base "$exchange") + MERCHANT_PUBLIC=$(_to_https_base "$merchant") + [ -n "$currency" ] && EXPECT_CURRENCY="$currency" + LOCAL_STACK="$local_stack" + if [ "$LOCAL_STACK" = "1" ]; then + SKIP_SSH=0 + else + SKIP_SSH=1 + fi + # default: landings only matter on local GOA stack + if [ -n "$landing" ]; then + CHECK_LANDING="$landing" + elif [ "$LOCAL_STACK" = "1" ]; then + CHECK_LANDING=1 + else + CHECK_LANDING=0 + fi + [ -n "$domain_id" ] && TALER_DOMAIN="$domain_id" + + BANK_PUBLIC=${BANK_PUBLIC%/} + EXCHANGE_PUBLIC=${EXCHANGE_PUBLIC%/} + MERCHANT_PUBLIC=${MERCHANT_PUBLIC%/} +} + +# Load first matching profile from domains.conf. +# Fields (whitespace-separated; # comments; blank lines ignored): +# name bank exchange merchant currency local[0|1] landing[0|1] [canonical_domain] +# Returns 0 if found, 1 if not. +load_domain_profile() { + local want="$1" conf="${TALER_DOMAINS_CONF:-}" + local line name bank exchange merchant currency local_stack landing canon + [ -n "$want" ] || return 1 + [ -n "$conf" ] && [ -f "$conf" ] || return 1 + + while IFS= read -r line || [ -n "$line" ]; do + line="${line%%#*}" + # shellcheck disable=SC2086 + set -- $line + [ $# -ge 5 ] || continue + name="$1" + [ "$name" = "$want" ] || continue + bank="$2" + exchange="$3" + merchant="$4" + currency="$5" + local_stack="${6:-0}" + landing="${7:-}" + canon="${8:-$name}" + # Backward compat: old 7th field was canonical domain (contains a dot) + if [ -n "$landing" ] && [[ "$landing" == *.* && "$landing" != "0" && "$landing" != "1" ]]; then + canon="$landing" + landing="" + fi + set_taler_stack "$bank" "$exchange" "$merchant" "$currency" "$local_stack" "$landing" "$canon" + return 0 + done <"$conf" + return 1 +} + _normalize_domain() { local d="$1" d="${d#https://}" @@ -58,7 +147,7 @@ _normalize_domain() { # e.g. bank.demo.taler.net → demo.taler.net, taler.hacktivism.ch → hacktivism.ch # but NOT taler.net → net case "$d" in - bank.*|exchange.*|taler.*|backend.*|merchant.*|shop.*|libeufin.*) + bank.*|exchange.*|taler.*|backend.*|merchant.*|shop.*|libeufin.*|my.*|map.*) rest="${d#*.}" if [[ "$rest" == *.* ]]; then d="$rest" @@ -82,75 +171,50 @@ apply_taler_domain() { d=$(_normalize_domain "$raw") TALER_DOMAIN="$d" - case "$d" in - # Local koopa stack only — SSH / inside / e2e allowed - koopa|hacktivism.ch|hacktivism) - BANK_PUBLIC="https://bank.hacktivism.ch" - EXCHANGE_PUBLIC="https://exchange.hacktivism.ch" - MERCHANT_PUBLIC="https://taler.hacktivism.ch" - EXPECT_CURRENCY="GOA" - LOCAL_STACK=1 - SKIP_SSH=0 - TALER_DOMAIN="hacktivism.ch" - : "${WITHDRAW_AMT:=GOA:20}" - : "${PAY_AMT:=GOA:0.01}" - : "${CREDIT_AMT:=GOA:400}" - ;; - taler.net|demo.taler.net) - # Official public demo (KUDOS) — public only, never SSH; tiny e2e amounts - BANK_PUBLIC="https://bank.demo.taler.net" - EXCHANGE_PUBLIC="https://exchange.demo.taler.net" - MERCHANT_PUBLIC="https://backend.demo.taler.net" - EXPECT_CURRENCY="KUDOS" - LOCAL_STACK=0 - SKIP_SSH=1 - MERCHANT_INSTANCE="${MERCHANT_INSTANCE:-sandbox}" - WITHDRAW_AMT="${WITHDRAW_AMT:-KUDOS:20}" - PAY_AMT="${PAY_AMT:-KUDOS:0.01}" - CREDIT_AMT="${CREDIT_AMT:-KUDOS:100}" - TALER_DOMAIN="demo.taler.net" - ;; - taler-ops.ch) - # Public CHF exchange; bank/merchant hosts vary — probe common names - EXCHANGE_PUBLIC="https://exchange.taler-ops.ch" - BANK_PUBLIC="https://bank.taler-ops.ch" - MERCHANT_PUBLIC="https://backend.taler-ops.ch" - EXPECT_CURRENCY="CHF" - LOCAL_STACK=0 - SKIP_SSH=1 - WITHDRAW_AMT="${WITHDRAW_AMT:-CHF:20}" - PAY_AMT="${PAY_AMT:-CHF:0.01}" - CREDIT_AMT="${CREDIT_AMT:-CHF:100}" - if [ "${TALER_DOMAIN_PROBE}" = "1" ]; then - local h - for h in bank.taler-ops.ch bank.demo.taler-ops.ch; do - _probe_https_config "$h" && { BANK_PUBLIC="https://$h"; break; } - done - for h in backend.taler-ops.ch merchant.taler-ops.ch taler.taler-ops.ch shop.taler-ops.ch; do - _probe_https_config "$h" && { MERCHANT_PUBLIC="https://$h"; break; } - done - fi - ;; - *) - # Any other domain — public HTTPS only, never SSH to koopa - BANK_PUBLIC="https://bank.${d}" - EXCHANGE_PUBLIC="https://exchange.${d}" - MERCHANT_PUBLIC="https://backend.${d}" - EXPECT_CURRENCY="${EXPECT_CURRENCY:-}" # unknown — don't hard-fail currency - LOCAL_STACK=0 - SKIP_SSH=1 - if [ "${TALER_DOMAIN_PROBE}" = "1" ]; then - local h - for h in "backend.${d}" "taler.${d}" "merchant.${d}" "shop.${d}"; do - _probe_https_config "$h" && { MERCHANT_PUBLIC="https://$h"; break; } - done - for h in "bank.${d}" "libeufin.${d}"; do - _probe_https_config "$h" && { BANK_PUBLIC="https://$h"; break; } - done - _probe_https_config "exchange.${d}" || true - fi - ;; - esac + # 1) Explicit profile (domains.conf) — preferred way to add stacks + if load_domain_profile "$d" || load_domain_profile "$raw"; then + # Optional tiny defaults for e2e ladders by currency + case "${EXPECT_CURRENCY:-}" in + GOA) + : "${WITHDRAW_AMT:=GOA:20}" + : "${PAY_AMT:=GOA:0.01}" + : "${CREDIT_AMT:=GOA:400}" + ;; + KUDOS|TESTKUDOS) + MERCHANT_INSTANCE="${MERCHANT_INSTANCE:-sandbox}" + WITHDRAW_AMT="${WITHDRAW_AMT:-${EXPECT_CURRENCY}:20}" + PAY_AMT="${PAY_AMT:-${EXPECT_CURRENCY}:0.01}" + CREDIT_AMT="${CREDIT_AMT:-${EXPECT_CURRENCY}:100}" + ;; + CHF) + WITHDRAW_AMT="${WITHDRAW_AMT:-CHF:20}" + PAY_AMT="${PAY_AMT:-CHF:0.01}" + CREDIT_AMT="${CREDIT_AMT:-CHF:100}" + ;; + esac + else + # 2) Unknown domain — heuristics only (prefer profile in domains.conf) + # Override: --bank / --exchange / --merchant / --currency + # Do not keep default GOA: empty currency = report only, no hard fail. + BANK_PUBLIC="https://bank.${d}" + EXCHANGE_PUBLIC="https://exchange.${d}" + # TOPS-style multi-tenant merchant first, then legacy names + MERCHANT_PUBLIC="https://my.${d}" + EXPECT_CURRENCY="" + LOCAL_STACK=0 + SKIP_SSH=1 + CHECK_LANDING=0 + if [ "${TALER_DOMAIN_PROBE}" = "1" ]; then + local h + for h in "backend.${d}" "my.${d}" "taler.${d}" "merchant.${d}" "shop.${d}"; do + _probe_https_config "$h" && { MERCHANT_PUBLIC="https://$h"; break; } + done + for h in "bank.${d}" "libeufin.${d}"; do + _probe_https_config "$h" && { BANK_PUBLIC="https://$h"; break; } + done + _probe_https_config "exchange.${d}" || true + fi + fi BANK_PUBLIC=${BANK_PUBLIC%/} EXCHANGE_PUBLIC=${EXCHANGE_PUBLIC%/} @@ -241,10 +305,18 @@ koopa_ssh_bash() { with_timeout "$t" ssh "${SSH_BASE_OPTS[@]}" "${KOOPA_SSH}" 'bash -s' } -if [ "${NO_COLOR:-0}" = "1" ] || [ ! -t 1 ]; then +# ANSI colours for tags (green OK / yellow WARN / red ERROR·BLOCKER / cyan INFO). +# Default: always on so pasted ```bash``` logs keep visible tags when the terminal +# supports colour. Disable: NO_COLOR=1. Force off for dumb pipes: CLICOLOR=0. +if [ "${NO_COLOR:-0}" = "1" ] || [ "${CLICOLOR:-1}" = "0" ]; then G= R= Y= C= N= B= else - G=$'\e[32m'; R=$'\e[31m'; Y=$'\e[33m'; C=$'\e[36m'; B=$'\e[1m'; N=$'\e[0m' + G=$'\e[1;32m' # bold green [OK] + R=$'\e[1;31m' # bold red [ERROR] [BLOCKER] + Y=$'\e[1;33m' # bold yellow [WARN] + C=$'\e[1;36m' # bold cyan [INFO] + B=$'\e[1m' + N=$'\e[0m' fi PASS_N=0 @@ -282,9 +354,13 @@ _fmt_tid() { } ok() { - local label="$1" + local label="$1" detail="${2:-}" _take_tid - printf '%s[OK]%s %s%s\n' "$G" "$N" "$(_fmt_tid)" "$label" + if [ -n "$detail" ]; then + printf '%s[OK]%s %s%s — %s\n' "$G" "$N" "$(_fmt_tid)" "$label" "$detail" + else + printf '%s[OK]%s %s%s\n' "$G" "$N" "$(_fmt_tid)" "$label" + fi PASS_N=$((PASS_N + 1)) } # component-scoped error: err bank "libeufin down" "detail" diff --git a/scripts/taler-monitoring/taler-monitoring.sh b/scripts/taler-monitoring/taler-monitoring.sh index 321525b..6ee72b4 100755 --- a/scripts/taler-monitoring/taler-monitoring.sh +++ b/scripts/taler-monitoring/taler-monitoring.sh @@ -29,27 +29,33 @@ Phases: all urls + inside + versions + sanity + e2e (SSH phases only on koopa) Options: - -d, --domain DOMAIN target domain - koopa / hacktivism.ch → local stack, SSH ok - everything else → no SSH; e2e optional (tiny amounts) + -d, --domain DOMAIN load profile from domains.conf (bank/exchange/merchant) presets: koopa | hacktivism.ch | taler.net | taler-ops.ch - generic: bank/exchange/backend. - --bank URL override bank base (https://…) - --exchange URL override exchange base - --merchant URL override merchant base + | my.taler-ops.ch | stage.taler-ops.ch + unknown domain → heuristic hosts (see README) + local (koopa) allows SSH; others public-only + --bank URL bank base (hostname or https://…) — overrides profile + --exchange URL exchange base — overrides profile + --merchant URL merchant-backend base — overrides profile --currency CODE expected currency (GOA, KUDOS, CHF, …); empty = report only - --no-probe do not probe alternate merchant/bank hostnames + --no-probe do not probe alternate hosts (unknown domains only) -h, --help +Add a stack: edit domains.conf (name + bank + exchange + merchant + currency). + Examples: ./taler-monitoring.sh -d taler.net ./taler-monitoring.sh -d taler-ops.ch urls + ./taler-monitoring.sh -d my.taler-ops.ch urls + ./taler-monitoring.sh -d taler-ops.ch --merchant https://my.taler-ops.ch urls ./taler-monitoring.sh -d demo.taler.net --currency KUDOS - ./taler-monitoring.sh --exchange https://exchange.taler-ops.ch urls + ./taler-monitoring.sh --exchange https://exchange.taler-ops.ch \ + --merchant https://my.taler-ops.ch --bank https://bank.taler-ops.ch urls Env (same meaning): TALER_DOMAIN BANK_PUBLIC EXCHANGE_PUBLIC MERCHANT_PUBLIC EXPECT_CURRENCY - SKIP_SSH=1 NO_COLOR=1 + TALER_DOMAINS_CONF SKIP_SSH=1 + NO_COLOR=1 / CLICOLOR=0 disable green/yellow/red tags (default: coloured) EOF } @@ -129,10 +135,11 @@ fi # Export so check_*.sh (re-source lib) see the same targets via env export TALER_DOMAIN BANK_PUBLIC EXCHANGE_PUBLIC MERCHANT_PUBLIC -export EXPECT_CURRENCY SKIP_SSH LOCAL_STACK TALER_DOMAIN_PROBE +export EXPECT_CURRENCY SKIP_SSH LOCAL_STACK TALER_DOMAIN_PROBE CHECK_LANDING export WITHDRAW_AMT PAY_AMT CREDIT_AMT MERCHANT_INSTANCE export E2E_FAKE_INCOMING E2E_REMOTE E2E_VARIABLE E2E_ATM_MAX export E2E_WITHDRAW_VALUES E2E_PAY_VALUES +export PAIVANA_PUBLIC E2E_PAIVANA E2E_PAIVANA_TEMPLATE E2E_PAIVANA_AMOUNT E2E_PAIVANA_INSTANCE export TALER_DOMAIN_APPLIED=1 # Default phases