mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-04 05:46:14 +00:00
Giving the mixed-profile services a run-scoped container_name broke this script's two ping sites, which assemble the name as "fips-$from" rather than writing it out. A grep for the literal name finds neither, which is the same trap the earlier naming sweep hit on the other static scripts. The failure was loud — link convergence passed 3/2/2/1 and then every ping failed, because docker exec could not find the container — but it is worth noting that these names were unsuffixed until now, so this suite was never safe to run twice on one host.
170 lines
5.3 KiB
Bash
Executable File
170 lines
5.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Mixed-profile integration test: Full, NonRouting, and Leaf nodes.
|
|
#
|
|
# Topology:
|
|
# A (Full) ─── B (Full)
|
|
# │ \ │
|
|
# │ \ │
|
|
# D (Leaf) C (NonRouting)
|
|
#
|
|
# Usage:
|
|
# ./mixed-profile-test.sh inject-config Inject profile config overrides
|
|
# ./mixed-profile-test.sh Run the full test
|
|
#
|
|
# inject-config is run separately by CI after generate-configs.sh and
|
|
# before building Docker images.
|
|
|
|
set -e
|
|
trap 'echo ""; echo "Test interrupted"; exit 130' INT
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
TOPOLOGY="mixed-profile"
|
|
NODES="a b c d"
|
|
|
|
# ── inject-config subcommand ──────────────────────────────────────────
|
|
# Inject profile overrides into generated node configs.
|
|
if [ "${1:-}" = "inject-config" ]; then
|
|
echo "Injecting mixed-profile config overrides..."
|
|
|
|
# Node C: non-routing
|
|
cfg="$SCRIPT_DIR/../generated-configs${FIPS_CI_NAME_SUFFIX:-}/$TOPOLOGY/node-c.yaml"
|
|
if [ ! -f "$cfg" ]; then
|
|
echo " Error: $cfg not found" >&2
|
|
exit 1
|
|
fi
|
|
python3 -c "
|
|
import yaml
|
|
with open('$cfg') as f:
|
|
cfg = yaml.safe_load(f)
|
|
cfg.setdefault('node', {})['disable_routing'] = True
|
|
with open('$cfg', 'w') as f:
|
|
yaml.dump(cfg, f, default_flow_style=False, sort_keys=False)
|
|
"
|
|
echo " ✓ node-c (disable_routing: true)"
|
|
|
|
# Node D: leaf
|
|
cfg="$SCRIPT_DIR/../generated-configs${FIPS_CI_NAME_SUFFIX:-}/$TOPOLOGY/node-d.yaml"
|
|
if [ ! -f "$cfg" ]; then
|
|
echo " Error: $cfg not found" >&2
|
|
exit 1
|
|
fi
|
|
python3 -c "
|
|
import yaml
|
|
with open('$cfg') as f:
|
|
cfg = yaml.safe_load(f)
|
|
cfg.setdefault('node', {})['leaf_only'] = True
|
|
with open('$cfg', 'w') as f:
|
|
yaml.dump(cfg, f, default_flow_style=False, sort_keys=False)
|
|
"
|
|
echo " ✓ node-d (leaf_only: true)"
|
|
|
|
echo "✓ Config injection complete"
|
|
exit 0
|
|
fi
|
|
|
|
# ── Full test ─────────────────────────────────────────────────────────
|
|
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
|
|
source "$ENV_FILE"
|
|
|
|
PASSED=0
|
|
FAILED=0
|
|
|
|
check() {
|
|
local desc="$1"
|
|
shift
|
|
echo -n " $desc ... "
|
|
if "$@" >/dev/null 2>&1; then
|
|
echo "PASS"
|
|
PASSED=$((PASSED + 1))
|
|
else
|
|
echo "FAIL"
|
|
FAILED=$((FAILED + 1))
|
|
fi
|
|
}
|
|
|
|
ping_fips() {
|
|
local from="$1"
|
|
local to_npub="$2"
|
|
docker exec "fips-${from}${FIPS_CI_NAME_SUFFIX:-}" ping6 -c 1 -W 5 "${to_npub}.fips"
|
|
}
|
|
|
|
echo "=== Mixed-Profile Integration Test ==="
|
|
echo ""
|
|
|
|
# Phase 1: Wait for link convergence
|
|
echo "Phase 1: Link convergence"
|
|
# A: peers with B, C, D → 3 links
|
|
# B: peers with A, C → 2 links
|
|
# C (NonRouting): peers with A, B → 2 links
|
|
# D (Leaf): peers with A → 1 link
|
|
wait_for_peers fips-node-a${FIPS_CI_NAME_SUFFIX:-} 3 30 || true
|
|
wait_for_peers fips-node-b${FIPS_CI_NAME_SUFFIX:-} 2 30 || true
|
|
wait_for_peers fips-node-c${FIPS_CI_NAME_SUFFIX:-} 2 30 || true
|
|
wait_for_peers fips-node-d${FIPS_CI_NAME_SUFFIX:-} 1 30 || true
|
|
|
|
# Phase 2: Verify link counts (already validated by wait_for_peers above)
|
|
echo ""
|
|
echo "Phase 2: Link counts verified via convergence wait"
|
|
|
|
# Phase 3: Wait for discovery/session convergence
|
|
echo ""
|
|
echo "Phase 3: Waiting for session convergence (up to 45s)..."
|
|
# Try all pairs repeatedly until they all work
|
|
CONV_START=$SECONDS
|
|
CONV_TIMEOUT=45
|
|
ALL_OK=false
|
|
while (( SECONDS - CONV_START < CONV_TIMEOUT )); do
|
|
ALL_GOOD=true
|
|
for pair in "node-a:$NPUB_B" "node-a:$NPUB_C" "node-a:$NPUB_D" \
|
|
"node-b:$NPUB_A" "node-b:$NPUB_C" \
|
|
"node-c:$NPUB_A" "node-c:$NPUB_B" \
|
|
"node-d:$NPUB_A" "node-d:$NPUB_B"; do
|
|
from="${pair%%:*}"
|
|
to="${pair##*:}"
|
|
if ! docker exec "fips-${from}${FIPS_CI_NAME_SUFFIX:-}" ping6 -c 1 -W 1 "${to}.fips" >/dev/null 2>&1; then
|
|
ALL_GOOD=false
|
|
break
|
|
fi
|
|
done
|
|
if $ALL_GOOD; then
|
|
echo " All pairs reachable after $((SECONDS - CONV_START))s"
|
|
ALL_OK=true
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
if ! $ALL_OK; then
|
|
echo " WARNING: Not all pairs converged within ${CONV_TIMEOUT}s (continuing with tests)"
|
|
fi
|
|
|
|
# Phase 4: Connectivity tests
|
|
echo ""
|
|
echo "Phase 4: F↔F connectivity"
|
|
check "A → B (Full → Full, direct)" ping_fips node-a "$NPUB_B"
|
|
check "B → A (Full → Full, direct)" ping_fips node-b "$NPUB_A"
|
|
|
|
echo ""
|
|
echo "Phase 5: F↔N connectivity"
|
|
check "A → C (Full → NonRouting, direct)" ping_fips node-a "$NPUB_C"
|
|
check "C → A (NonRouting → Full, direct)" ping_fips node-c "$NPUB_A"
|
|
check "B → C (Full → NonRouting, direct)" ping_fips node-b "$NPUB_C"
|
|
check "C → B (NonRouting → Full, direct)" ping_fips node-c "$NPUB_B"
|
|
|
|
echo ""
|
|
echo "Phase 6: F↔L connectivity"
|
|
check "A → D (Full → Leaf, direct)" ping_fips node-a "$NPUB_D"
|
|
check "D → A (Leaf → Full, direct)" ping_fips node-d "$NPUB_A"
|
|
|
|
echo ""
|
|
echo "Phase 7: Multi-hop through Full nodes"
|
|
check "D → B (Leaf → Full, via A)" ping_fips node-d "$NPUB_B"
|
|
|
|
echo ""
|
|
echo "=== Results: $PASSED passed, $FAILED failed ==="
|
|
[ "$FAILED" -eq 0 ] && exit 0 || exit 1
|