diff --git a/tests/multinode/.env.example b/tests/multinode/.env.example new file mode 100644 index 00000000..5baca825 --- /dev/null +++ b/tests/multinode/.env.example @@ -0,0 +1,15 @@ +# Local credentials for the multinode test suites — copy to tests/multinode/.env +# (git-ignored) and fill in. Sourced automatically by lib/multinode.bash. +# NEVER commit real node passwords. + +# smoke.sh / repro-federation-sync.sh +A_PW=changeme # node A (default URL http://192.168.1.116) +B_PW=changeme # node B (default URL https://192.168.1.228) +#C_URL=https://x.x.x.x # optional third node +#C_PW=changeme + +# meshtastic.sh +MA_PW=changeme +MB_PW=changeme +#MC_URL=https://x.x.x.x +#MC_PW=changeme diff --git a/tests/multinode/lib/multinode.bash b/tests/multinode/lib/multinode.bash index 00734ed4..84023802 100755 --- a/tests/multinode/lib/multinode.bash +++ b/tests/multinode/lib/multinode.bash @@ -11,18 +11,27 @@ # # Usage: # source tests/multinode/lib/multinode.bash -# node_register A https://192.168.1.228 password123 -# node_register B http://192.168.1.116 'ThisIsWeb54321@' +# node_register A https://192.168.1.228 "$A_PW" +# node_register B http://192.168.1.116 "$B_PW" # node_login A; node_login B # node_rpc A node.tor-address # node_result B federation.list-nodes # # Requires: curl, jq. # +# Credentials: node passwords are NEVER committed. Export *_PW env vars, or +# put them in tests/multinode/.env (git-ignored; see .env.example) — sourced +# automatically below so every suite picks them up. +# # Note: this is a library — it does NOT set shell options (set -u/-e), since # that would leak into the sourcing script. Each function guards its own vars # with ${var:-} defaults. Callers set their own options. +# Auto-load git-ignored local credentials (tests/multinode/.env), if present. +_MN_ENV_FILE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)/.env" +# shellcheck disable=SC1090 +[[ -f "$_MN_ENV_FILE" ]] && source "$_MN_ENV_FILE" + # Where per-node session state lives (one file per handle). MULTINODE_STATE_DIR="${MULTINODE_STATE_DIR:-/tmp/archy-multinode}" mkdir -p "$MULTINODE_STATE_DIR" @@ -52,7 +61,8 @@ node_login() { fi local headers; headers=$(mktemp) local body - body=$(curl -sk -D "$headers" -X POST "${url}/rpc/v1" \ + body=$(curl -sk --connect-timeout 10 --max-time "${MULTINODE_RPC_TIMEOUT:-120}" \ + -D "$headers" -X POST "${url}/rpc/v1" \ -H 'Content-Type: application/json' \ --data-raw "{\"jsonrpc\":\"2.0\",\"method\":\"auth.login\",\"params\":{\"password\":\"${pw}\"},\"id\":1}") local err; err=$(echo "$body" | jq -r '.error.message // empty' 2>/dev/null) @@ -90,7 +100,10 @@ node_rpc() { else payload=$(jq -nc --arg m "$method" --argjson p "$params" '{jsonrpc:"2.0",method:$m,params:$p,id:1}') fi - curl -sk -X POST "${url}/rpc/v1" \ + # Bounded so one slow/hung server-side RPC can't hang the whole suite; + # override per-run with MULTINODE_RPC_TIMEOUT (seconds). + curl -sk --connect-timeout 10 --max-time "${MULTINODE_RPC_TIMEOUT:-120}" \ + -X POST "${url}/rpc/v1" \ -H 'Content-Type: application/json' \ -H "Cookie: session=${session}; csrf_token=${csrf}" \ -H "X-CSRF-Token: ${csrf}" \ diff --git a/tests/multinode/meshtastic.sh b/tests/multinode/meshtastic.sh index 5bb0a9f2..c5cec31e 100755 --- a/tests/multinode/meshtastic.sh +++ b/tests/multinode/meshtastic.sh @@ -44,9 +44,9 @@ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$HERE/lib/multinode.bash" # ── node registration ────────────────────────────────────────────────────── -MA_URL="${MA_URL:-http://192.168.1.116}"; MA_PW="${MA_PW:-ThisIsWeb54321@}" -MB_URL="${MB_URL:-https://192.168.1.228}"; MB_PW="${MB_PW:-password123}" -MC_URL="${MC_URL:-}"; MC_PW="${MC_PW:-password123}" +MA_URL="${MA_URL:-http://192.168.1.116}"; MA_PW="${MA_PW:?MA_PW required — export it or set tests/multinode/.env (see .env.example)}" +MB_URL="${MB_URL:-https://192.168.1.228}"; MB_PW="${MB_PW:?MB_PW required — export it or set tests/multinode/.env (see .env.example)}" +MC_URL="${MC_URL:-}"; MC_PW="${MC_PW:-}" PROP_WAIT="${PROP_WAIT:-45}" MB_NAME="${MB_NAME:-}" ASSIST="${ASSIST:-0}" diff --git a/tests/multinode/repro-federation-sync.sh b/tests/multinode/repro-federation-sync.sh index 9492204f..7de94bff 100755 --- a/tests/multinode/repro-federation-sync.sh +++ b/tests/multinode/repro-federation-sync.sh @@ -18,8 +18,8 @@ set -uo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$HERE/lib/multinode.bash" -A_URL="${A_URL:-http://192.168.1.116}"; A_PW="${A_PW:-ThisIsWeb54321@}" -B_URL="${B_URL:-https://192.168.1.228}"; B_PW="${B_PW:-password123}" +A_URL="${A_URL:-http://192.168.1.116}"; A_PW="${A_PW:?A_PW required — export it or set tests/multinode/.env (see .env.example)}" +B_URL="${B_URL:-https://192.168.1.228}"; B_PW="${B_PW:?B_PW required — export it or set tests/multinode/.env (see .env.example)}" bar() { printf '\n=== %s ===\n' "$*"; } diff --git a/tests/multinode/smoke.sh b/tests/multinode/smoke.sh index 16aaca0e..1cbbe71b 100644 --- a/tests/multinode/smoke.sh +++ b/tests/multinode/smoke.sh @@ -26,8 +26,8 @@ set -uo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$HERE/lib/multinode.bash" -A_URL="${A_URL:-http://192.168.1.116}"; A_PW="${A_PW:-ThisIsWeb54321@}" -B_URL="${B_URL:-https://192.168.1.228}"; B_PW="${B_PW:-password123}" +A_URL="${A_URL:-http://192.168.1.116}"; A_PW="${A_PW:?A_PW required — export it or set tests/multinode/.env (see .env.example)}" +B_URL="${B_URL:-https://192.168.1.228}"; B_PW="${B_PW:?B_PW required — export it or set tests/multinode/.env (see .env.example)}" C_URL="${C_URL:-}"; C_PW="${C_PW:-}" # ── tiny assertion framework ──────────────────────────────────────────────