Files
cli/sunbeam-net/tests/run.sh
Sienna Meridian Satterwhite f1668682b7 test(net): TUN-mode docker stack and ignored e2e test
- docker-compose.yml: run peer-a and peer-b with TS_USERSPACE=false +
  /dev/net/tun device + cap_add. Pin peer-a's WG listen port to 41641
  via TS_TAILSCALED_EXTRA_ARGS and publish it to the host so direct
  UDP from outside docker has somewhere to land.
- run.sh: use an ephemeral pre-auth key for the test client so
  Headscale auto-deletes the test node when its map stream drops
  (instead of accumulating hundreds of stale entries that eventually
  slow netmap propagation to a crawl). Disable shields-up on both
  peers so the kernel firewall doesn't drop inbound tailnet TCP. Tweak
  the JSON key extraction to handle pretty-printed output.
- integration.rs: add `test_e2e_tcp_through_tunnel` that brings up
  the daemon, dials peer-a's echo server through the proxy, and
  asserts the echo body comes back. Currently `#[ignore]`d — the
  docker stack runs Headscale over plain HTTP, but Tailscale's client
  unconditionally tries TLS to DERP relays ("tls: first record does
  not look like a TLS handshake"), so peer-a can never receive
  packets we forward via the relay. Unblocking needs either TLS
  termination on the docker DERP or running the test inside the same
  docker network as peer-a. Test stays in the tree because everything
  it tests up to the read timeout is real verified behavior.
2026-04-07 14:33:59 +01:00

67 lines
2.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# Integration test runner for sunbeam-net.
#
# Spins up Headscale + two Tailscale peers, creates pre-auth keys,
# runs the Rust integration tests, then tears everything down.
set -euo pipefail
cd "$(dirname "$0")"
COMPOSE="docker compose -f docker-compose.yml"
cleanup() { $COMPOSE down -v 2>/dev/null; }
trap cleanup EXIT
echo "==> Starting Headscale..."
$COMPOSE up -d headscale
$COMPOSE exec -T headscale sh -c 'until headscale health 2>/dev/null; do sleep 1; done'
echo "==> Creating pre-auth keys..."
# Helper that handles both compact and pretty-printed JSON shapes from
# headscale preauthkeys create.
extract_key() {
grep -o '"key":[[:space:]]*"[^"]*"' | sed 's/.*"\([^"]*\)"$/\1/'
}
# Test client uses an ephemeral key so headscale auto-deletes the node when
# the streaming map connection drops, keeping the test database clean.
PEER_A_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | extract_key)
PEER_B_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --expiration 1h -o json | extract_key)
CLIENT_KEY=$($COMPOSE exec -T headscale headscale preauthkeys create --user test --reusable --ephemeral --expiration 1h -o json | extract_key)
echo "==> Starting peers..."
PEER_A_AUTH_KEY="$PEER_A_KEY" PEER_B_AUTH_KEY="$PEER_B_KEY" $COMPOSE up -d peer-a peer-b echo
echo "==> Waiting for peers to register..."
for i in $(seq 1 30); do
NODES=$($COMPOSE exec -T headscale headscale nodes list -o json 2>/dev/null | grep -c '"id"' || true)
if [ "$NODES" -ge 2 ]; then
echo " $NODES peers registered."
break
fi
sleep 2
done
# In TUN mode tailscale installs a stateful firewall that DROPs incoming
# tailnet traffic by default. Disable it on both peers so the integration
# tests can actually exchange TCP through the tunnel.
echo "==> Disabling tailscale firewall on peers..."
$COMPOSE exec -T peer-a tailscale set --shields-up=false 2>/dev/null || true
$COMPOSE exec -T peer-b tailscale set --shields-up=false 2>/dev/null || true
# Get the server's Noise public key
SERVER_KEY=$($COMPOSE exec -T headscale cat /var/lib/headscale/noise_private.key 2>/dev/null | head -1 || echo "")
echo "==> Peer A tailnet IP:"
$COMPOSE exec -T peer-a tailscale ip -4 || true
echo "==> Peer B tailnet IP:"
$COMPOSE exec -T peer-b tailscale ip -4 || true
echo "==> Running integration tests..."
cd ../..
SUNBEAM_NET_TEST_AUTH_KEY="$CLIENT_KEY" \
SUNBEAM_NET_TEST_COORD_URL="http://localhost:8080" \
SUNBEAM_NET_TEST_PEER_A_IP=$($COMPOSE -f sunbeam-net/tests/docker-compose.yml exec -T peer-a tailscale ip -4 2>/dev/null | tr -d '[:space:]') \
cargo test -p sunbeam-net --features integration --test integration -- --nocapture
echo "==> Done."