stack-orchestrator/scripts/test-ashburn-relay.sh

110 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# End-to-end test for Ashburn validator relay
#
# Sends real packets from the kind node through the full relay path
# and waits for responses. A response proves both directions work.
#
# Outbound: kind node (172.20.0.2:8001) → biscayne mangle (fwmark 0x64)
# → policy route table ashburn → gre-ashburn → mia-sw01 Tunnel100
# (VRF relay) → egress-vrf default → backbone Et4/1 → was-sw01 Et1/1
# → internet (src 137.239.194.65)
#
# Inbound: internet → was-sw01 Et1/1 (dst 137.239.194.65) → static route
# → backbone → mia-sw01 → egress-vrf relay → Tunnel100 → biscayne
# gre-ashburn → conntrack reverse-SNAT → kind node (172.20.0.2:8001)
#
# Runs from the ansible controller host.
#
# Usage:
# ./scripts/test-ashburn-relay.sh
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SCRIPT_DIR/.."
KIND_NODE=laconic-70ce4c4b47e23b85-control-plane
BISCAYNE_INV=inventory/biscayne.yml
GOSSIP_PORT=8001
PASS=0
FAIL=0
pass() { echo " PASS: $1"; PASS=$((PASS + 1)); }
fail() { echo " FAIL: $1"; FAIL=$((FAIL + 1)); }
# Copy test scripts to biscayne (once)
setup() {
for f in "$SCRIPT_DIR"/relay-test-*.py; do
ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.copy \
-a "src=$f dest=/tmp/$(basename "$f") mode=0755" \
--become >/dev/null 2>&1
done
# Get kind node PID for nsenter (run in its network namespace,
# use biscayne's python3 since the kind node only has perl)
KIND_PID=$(ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.shell \
-a "docker inspect --format '{{ '{{' }}.State.Pid{{ '}}' }}' $KIND_NODE" \
--become 2>&1 | grep -oP '^\d+$' || true)
if [[ -z "$KIND_PID" ]]; then
echo "FATAL: could not get kind node PID"
exit 1
fi
echo "Kind node PID: $KIND_PID"
}
# Run a test script in the kind node's network namespace
run_test() {
local name=$1
shift
ansible biscayne -i "$BISCAYNE_INV" -m ansible.builtin.shell \
-a "nsenter --net --target $KIND_PID python3 /tmp/$name $*" \
--become 2>&1 | grep -E '^OK|^TIMEOUT|^ERROR|^REFUSED|^NOTE' || echo "NO OUTPUT"
}
echo "=== Ashburn Relay End-to-End Test ==="
echo ""
setup
echo ""
# Test 1: UDP sport 8001 → DNS query to 8.8.8.8
# Triggers: mangle -p udp --sport 8001 → mark → SNAT → tunnel
echo "--- Test 1: UDP sport $GOSSIP_PORT (DNS query) ---"
result=$(run_test relay-test-udp.py "$GOSSIP_PORT")
if echo "$result" | grep -q "^OK"; then
pass "UDP sport $GOSSIP_PORT: $result"
else
fail "UDP sport $GOSSIP_PORT: $result"
fi
echo ""
# Test 2: TCP sport 8001 → HTTP HEAD to 1.1.1.1
# Triggers: mangle -p tcp --sport 8001 → mark → SNAT → tunnel
echo "--- Test 2: TCP sport $GOSSIP_PORT (HTTP request) ---"
result=$(run_test relay-test-tcp-sport.py "$GOSSIP_PORT")
if echo "$result" | grep -q "^OK"; then
pass "TCP sport $GOSSIP_PORT: $result"
else
fail "TCP sport $GOSSIP_PORT: $result"
fi
echo ""
# Test 3: TCP dport 8001 → connect to Solana entrypoint (ip_echo)
# Triggers: mangle -p tcp --dport 8001 → mark → SNAT → tunnel
# REFUSED counts as pass — proves the round trip completed.
echo "--- Test 3: TCP dport $GOSSIP_PORT (ip_echo path) ---"
result=$(run_test relay-test-tcp-dport.py "$GOSSIP_PORT")
if echo "$result" | grep -q "^OK"; then
pass "TCP dport $GOSSIP_PORT: $result"
else
fail "TCP dport $GOSSIP_PORT: $result"
fi
echo ""
# Summary
echo "=== Results: $PASS passed, $FAIL failed ==="
if [[ $FAIL -gt 0 ]]; then
exit 1
fi