mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
The mesh-public profile ran in neither runner: ci-local's static suite list carries only static-mesh and static-chain, and the GitHub matrix has only mesh and chain. It also added no coverage over static-mesh. ping-test.sh and iperf-test.sh branched mesh and mesh-public together and exercised the same 20 directed pairs among node-a through node-e, and no script referenced the external node at all. The convergence waits even used mesh's peer counts rather than mesh-public's, so the extra link to the public node was never counted, let alone asserted. Running it would therefore have added a dependency on a live internet host (test-us01.fips.network) in exchange for zero additional assertions. Remove the topology, its five compose services, the script branches that aliased it to mesh, and the documentation rows. An invocation using the old profile name now fails on ping-test.sh's unknown-profile guard instead of silently behaving as mesh. The config generator's external-node support (external_ip, is_external_node) stays. It has no consumer now, but it is woven into the config path every remaining topology uses, so removing it would put the gating suites at risk for no present gain.
180 lines
6.0 KiB
Bash
Executable File
180 lines
6.0 KiB
Bash
Executable File
#!/bin/bash
|
||
# End-to-end ping test between FIPS nodes via DNS resolution.
|
||
# Usage: ./ping-test.sh [mesh|chain]
|
||
#
|
||
# Requires containers to be running:
|
||
# docker compose --profile mesh up -d
|
||
# ./scripts/ping-test.sh mesh
|
||
set -e
|
||
|
||
# Exit entire script on Ctrl+C
|
||
trap 'echo ""; echo "Test interrupted"; exit 130' INT
|
||
|
||
PROFILE="${1:-mesh}"
|
||
COUNT=1
|
||
TIMEOUT=5
|
||
PASSED=0
|
||
FAILED=0
|
||
|
||
# Node identities (from generated env file)
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
source "$SCRIPT_DIR/../../lib/wait-converge.sh"
|
||
ENV_FILE="$SCRIPT_DIR/../generated-configs${FIPS_CI_NAME_SUFFIX:-}/npubs.env"
|
||
if [ ! -f "$ENV_FILE" ]; then
|
||
echo "Error: $ENV_FILE not found. Run generate-configs.sh first." >&2
|
||
exit 1
|
||
fi
|
||
# shellcheck source=../generated-configs/npubs.env
|
||
source "$ENV_FILE"
|
||
|
||
NPUBS=("$NPUB_A" "$NPUB_B" "$NPUB_C" "$NPUB_D" "$NPUB_E")
|
||
LABELS=(A B C D E)
|
||
|
||
ping_test() {
|
||
local from="$1"
|
||
local to_npub="$2"
|
||
local label="$3"
|
||
|
||
echo -n " $label ... "
|
||
local output
|
||
if output=$(docker exec "fips-${from}${FIPS_CI_NAME_SUFFIX:-}" ping6 -c "$COUNT" -W "$TIMEOUT" "${to_npub}.fips" 2>&1); then
|
||
# Extract round-trip time from ping output
|
||
local rtt
|
||
rtt=$(echo "$output" | grep -oE 'time=[0-9.]+' | cut -d= -f2)
|
||
if [ -n "$rtt" ]; then
|
||
echo "OK (${rtt}ms)"
|
||
else
|
||
echo "OK"
|
||
fi
|
||
PASSED=$((PASSED + 1))
|
||
else
|
||
echo "FAIL"
|
||
FAILED=$((FAILED + 1))
|
||
fi
|
||
}
|
||
|
||
# Quietly ping all pairs to check FSP-level convergence.
|
||
ping_all_quiet() {
|
||
PASSED=0
|
||
FAILED=0
|
||
local n=${#LABELS[@]}
|
||
for ((i=0; i<n; i++)); do
|
||
for ((j=0; j<n; j++)); do
|
||
[ "$i" -eq "$j" ] && continue
|
||
if docker exec "fips-node-${LABELS[$i],,}${FIPS_CI_NAME_SUFFIX:-}" \
|
||
ping6 -c 1 -W 1 "${NPUBS[$j]}.fips" >/dev/null 2>&1; then
|
||
PASSED=$((PASSED + 1))
|
||
else
|
||
FAILED=$((FAILED + 1))
|
||
fi
|
||
done
|
||
done
|
||
}
|
||
|
||
echo "=== FIPS Ping Test ($PROFILE topology) ==="
|
||
echo ""
|
||
|
||
# Wait for nodes to converge — all nodes must reach expected peer counts.
|
||
#
|
||
# Every wait below is `|| true` on purpose, for the same reason the
|
||
# wait_until_connected call further down is: these are settling delays, not
|
||
# assertions. A node that has not reached its configured peer count by the
|
||
# deadline may still be reachable, and the directed-pair pings are what
|
||
# actually decide the run. Letting a wait fail the script here would turn a
|
||
# slow convergence into a failure the pings would have passed.
|
||
#
|
||
# The converse is what makes it safe: because these cannot fail, they also
|
||
# cannot pass, so nothing about the run's verdict rests on them.
|
||
echo "Waiting for mesh convergence..."
|
||
if [ "$PROFILE" = "chain" ]; then
|
||
# Chain: A-B-C-D-E, each interior node has 2 peers, endpoints have 1
|
||
wait_for_peers fips-node-a${FIPS_CI_NAME_SUFFIX:-} 1 20 || true
|
||
wait_for_peers fips-node-b${FIPS_CI_NAME_SUFFIX:-} 2 20 || true
|
||
wait_for_peers fips-node-c${FIPS_CI_NAME_SUFFIX:-} 2 20 || true
|
||
wait_for_peers fips-node-d${FIPS_CI_NAME_SUFFIX:-} 2 20 || true
|
||
wait_for_peers fips-node-e${FIPS_CI_NAME_SUFFIX:-} 1 20 || true
|
||
elif [ "$PROFILE" = "mesh" ]; then
|
||
# Mesh: check all nodes reach their configured peer counts
|
||
wait_for_peers fips-node-a${FIPS_CI_NAME_SUFFIX:-} 2 20 || true
|
||
wait_for_peers fips-node-b${FIPS_CI_NAME_SUFFIX:-} 1 20 || true
|
||
wait_for_peers fips-node-c${FIPS_CI_NAME_SUFFIX:-} 3 20 || true
|
||
wait_for_peers fips-node-d${FIPS_CI_NAME_SUFFIX:-} 3 20 || true
|
||
wait_for_peers fips-node-e${FIPS_CI_NAME_SUFFIX:-} 3 20 || true
|
||
else
|
||
# An unrecognised profile used to fall straight through, and every
|
||
# section below is guarded by these same profile names, so the script
|
||
# ran no assertion at all and exited 0. A typo in the caller's profile
|
||
# argument produced a green run that tested nothing.
|
||
echo "ERROR: unknown profile '$PROFILE' (expected: chain, mesh)" >&2
|
||
exit 2
|
||
fi
|
||
# Wait for full pairwise connectivity, progress-aware: the actual pings
|
||
# are the convergence signal, the deadline extends while more pairs come
|
||
# up, and it only gives up if progress stalls — so it does not
|
||
# false-time-out under load while routing is still converging. The
|
||
# directed-pair ping assertions below remain the actual test.
|
||
wait_until_connected ping_all_quiet 45 15 || true
|
||
|
||
# Reset counters for the actual test
|
||
PASSED=0
|
||
FAILED=0
|
||
|
||
if [ "$PROFILE" = "mesh" ]; then
|
||
# Sparse mesh topology: A-B, B-C, C-D, D-E, E-A, A-D
|
||
# Test all 20 directed pairs (5 nodes × 4 targets each)
|
||
echo ""
|
||
echo "From node-a:"
|
||
ping_test node-a "$NPUB_B" "A → B"
|
||
ping_test node-a "$NPUB_C" "A → C"
|
||
ping_test node-a "$NPUB_D" "A → D"
|
||
ping_test node-a "$NPUB_E" "A → E"
|
||
|
||
echo ""
|
||
echo "From node-b:"
|
||
ping_test node-b "$NPUB_A" "B → A"
|
||
ping_test node-b "$NPUB_C" "B → C"
|
||
ping_test node-b "$NPUB_D" "B → D"
|
||
ping_test node-b "$NPUB_E" "B → E"
|
||
|
||
echo ""
|
||
echo "From node-c:"
|
||
ping_test node-c "$NPUB_A" "C → A"
|
||
ping_test node-c "$NPUB_B" "C → B"
|
||
ping_test node-c "$NPUB_D" "C → D"
|
||
ping_test node-c "$NPUB_E" "C → E"
|
||
|
||
echo ""
|
||
echo "From node-d:"
|
||
ping_test node-d "$NPUB_A" "D → A"
|
||
ping_test node-d "$NPUB_B" "D → B"
|
||
ping_test node-d "$NPUB_C" "D → C"
|
||
ping_test node-d "$NPUB_E" "D → E"
|
||
|
||
echo ""
|
||
echo "From node-e:"
|
||
ping_test node-e "$NPUB_A" "E → A"
|
||
ping_test node-e "$NPUB_B" "E → B"
|
||
ping_test node-e "$NPUB_C" "E → C"
|
||
ping_test node-e "$NPUB_D" "E → D"
|
||
|
||
elif [ "$PROFILE" = "chain" ]; then
|
||
echo ""
|
||
echo "Adjacent peer tests:"
|
||
ping_test node-a "$NPUB_B" "A → B (1 hop)"
|
||
ping_test node-b "$NPUB_C" "B → C (1 hop)"
|
||
|
||
echo ""
|
||
echo "Multi-hop tests:"
|
||
ping_test node-a "$NPUB_C" "A → C (2 hops)"
|
||
ping_test node-a "$NPUB_D" "A → D (3 hops)"
|
||
ping_test node-a "$NPUB_E" "A → E (4 hops)"
|
||
|
||
echo ""
|
||
echo "Reverse multi-hop:"
|
||
ping_test node-e "$NPUB_A" "E → A (4 hops)"
|
||
fi
|
||
|
||
echo ""
|
||
echo "=== Results: $PASSED passed, $FAILED failed ==="
|
||
[ "$FAILED" -eq 0 ] && exit 0 || exit 1
|