Wire the live-test gate and pin the toolchain to 3.14
README advertised `uv run pytest -m live --live`, but there was no --live option and no `live` marker registered — the command errored out, so the one workflow that catches an upstream renaming a series did not exist. - conftest adds --live and skips `live`-marked tests without it, so the default run stays hermetic (258 passed, 6 skipped, no network). - tests/test_live_fleet.py drives the real code paths (collectors.*, NutMonitor.collect) against the fleet, both engines, and upsd. Each skips when its source is unset, and none of them may write — a battery test on live hardware is not a unit test. The host test polls twice because a rate has no second point on the first scrape. - The agent's real-/proc test stays in the default run and is explicitly not `live`: it touches only the box running pytest. - dev-tunnels.sh grows DEV_FORWARDS for services already listening remotely, which is how upsd gets reachable without opening 3493; pidfiles are now host+port so one host can carry two tunnels. - requires-python, ruff and pyright were still on 3.13 while the venv and Containerfile are 3.14, so the lock resolved for a stack nobody deploys. LLM-Generated: true
This commit is contained in:
+77
-10
@@ -1,13 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
# Dev-only: run agent/host_agent.py on each monitored host and forward it to localhost,
|
||||
# so `make dev` on the laptop sees live fleet data without opening a single port.
|
||||
# Dev-only: reach live services on each host from the laptop without opening a single port.
|
||||
#
|
||||
# ./scripts/dev-tunnels.sh start|stop|status|restart
|
||||
#
|
||||
# Each tunnel is ssh -L <local>:127.0.0.1:<remote-port> <host> 'python3 agent/host_agent.py'
|
||||
# and restarts itself if the link drops. Production is the opposite: deploy/install-agent.sh
|
||||
# installs a systemd unit that binds the LAN address with a bearer token, and the dashboard
|
||||
# dials it directly.
|
||||
# DEV_TUNNELS starts agent/host_agent.py remotely and forwards it:
|
||||
# ssh -L <local>:127.0.0.1:<rport> <host> 'python3 host_agent.py --port <rport>'
|
||||
# DEV_FORWARDS forwards a service that is already listening remotely (e.g. upsd on 3493):
|
||||
# nothing is started over there, the port just appears on localhost.
|
||||
#
|
||||
# Both supervise themselves: a dropped link retries every 5s. Production is the opposite —
|
||||
# deploy/install-agent.sh installs a systemd unit that binds the LAN address with a bearer
|
||||
# token, and the dashboard dials it directly.
|
||||
set -uo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
@@ -22,21 +25,33 @@ AGENT_COMMAND="${AGENT_COMMAND:-python3 host_agent.py}"
|
||||
# stays portable and holds no hostnames of ours.
|
||||
[ -f "$ROOT/.env.dev" ] && . "$ROOT/.env.dev"
|
||||
DEV_TUNNELS="${DEV_TUNNELS:-}"
|
||||
if [ -z "$DEV_TUNNELS" ]; then
|
||||
echo "no DEV_TUNNELS set — copy .env.dev.example to .env.dev first"; exit 2
|
||||
DEV_FORWARDS="${DEV_FORWARDS:-}"
|
||||
if [ -z "$DEV_TUNNELS" ] && [ -z "$DEV_FORWARDS" ]; then
|
||||
echo "no DEV_TUNNELS or DEV_FORWARDS set — copy .env.dev.example to .env.dev first"; exit 2
|
||||
fi
|
||||
TUNNELS=()
|
||||
for entry in $DEV_TUNNELS; do
|
||||
# 9121:driveripper-ops:9120 -> "9121 driveripper-ops 9120"
|
||||
TUNNELS+=("$(echo "$entry" | tr ':' ' ')")
|
||||
done
|
||||
FORWARDS=()
|
||||
for entry in $DEV_FORWARDS; do
|
||||
FORWARDS+=("$(echo "$entry" | tr ':' ' ')")
|
||||
done
|
||||
|
||||
mkdir -p "$RUN" "$LOGS"
|
||||
|
||||
start() {
|
||||
for spec in "${TUNNELS[@]}"; do
|
||||
read -r local host remote <<<"$(echo "$spec" | tr -s ' ')"
|
||||
pidfile="$RUN/$host.pid"
|
||||
# pidfiles are named by host AND port: one host can carry an agent tunnel plus an upsd
|
||||
# forward. The older host-only name is cleared so a restart does not double-bind.
|
||||
pidfile="$RUN/$host-$local.pid"
|
||||
if [ -f "$RUN/$host.pid" ] && kill -0 "$(cat "$RUN/$host.pid")" 2>/dev/null; then
|
||||
pkill -P "$(cat "$RUN/$host.pid")" 2>/dev/null
|
||||
kill "$(cat "$RUN/$host.pid")" 2>/dev/null
|
||||
fi
|
||||
rm -f "$RUN/$host.pid"
|
||||
if [ -f "$pidfile" ] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
|
||||
echo " $host already tunnelling on :$local (pid $(cat "$pidfile"))"
|
||||
continue
|
||||
@@ -64,12 +79,42 @@ EOF
|
||||
echo $! >"$pidfile"
|
||||
echo " $host -> http://127.0.0.1:$local (pid $!)"
|
||||
done
|
||||
|
||||
# Plain forwards: `-N` because there is no remote command to run, and nothing to clean up
|
||||
# over there when the link goes.
|
||||
for spec in "${FORWARDS[@]}"; do
|
||||
read -r local host remote <<<"$(echo "$spec" | tr -s ' ')"
|
||||
pidfile="$RUN/$host-$local.pid"
|
||||
if [ -f "$pidfile" ] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
|
||||
echo " $host:$remote already forwarded on :$local (pid $(cat "$pidfile"))"
|
||||
continue
|
||||
fi
|
||||
cat > "$RUN/$host-$local.sh" <<EOF
|
||||
#!/usr/bin/env bash
|
||||
# generated by scripts/dev-tunnels.sh — do not edit, it is rewritten on every start
|
||||
while true; do
|
||||
ssh -n -N -o ServerAliveInterval=30 -o ServerAliveCountMax=4 -o ExitOnForwardFailure=yes \
|
||||
-L $local:127.0.0.1:$remote "$host"
|
||||
echo "[forward] $host:$remote dropped at \$(date -Is) (exit \$?); retrying in 5s"
|
||||
sleep 5
|
||||
done
|
||||
EOF
|
||||
chmod +x "$RUN/$host-$local.sh"
|
||||
nohup "$RUN/$host-$local.sh" >>"$LOGS/tunnel-$host-$local.log" 2>&1 &
|
||||
echo $! >"$pidfile"
|
||||
echo " $host:$remote -> 127.0.0.1:$local (pid $!)"
|
||||
done
|
||||
}
|
||||
|
||||
stop() {
|
||||
for spec in "${TUNNELS[@]}"; do
|
||||
read -r local host remote <<<"$(echo "$spec" | tr -s ' ')"
|
||||
pidfile="$RUN/$host.pid"
|
||||
pidfile="$RUN/$host-$local.pid"
|
||||
if [ -f "$RUN/$host.pid" ]; then
|
||||
pkill -P "$(cat "$RUN/$host.pid")" 2>/dev/null
|
||||
kill "$(cat "$RUN/$host.pid")" 2>/dev/null
|
||||
rm -f "$RUN/$host.pid"
|
||||
fi
|
||||
[ -f "$pidfile" ] || continue
|
||||
pid=$(cat "$pidfile")
|
||||
pkill -P "$pid" 2>/dev/null
|
||||
@@ -84,6 +129,17 @@ stop() {
|
||||
rm -f "$pidfile"
|
||||
echo " stopped $host"
|
||||
done
|
||||
|
||||
for spec in "${FORWARDS[@]}"; do
|
||||
read -r local host remote <<<"$(echo "$spec" | tr -s ' ')"
|
||||
pidfile="$RUN/$host-$local.pid"
|
||||
[ -f "$pidfile" ] || continue
|
||||
pkill -P "$(cat "$pidfile")" 2>/dev/null
|
||||
kill "$(cat "$pidfile")" 2>/dev/null
|
||||
pkill -f "ssh -n -N.*-L $local:127.0.0.1:$remote $host" 2>/dev/null
|
||||
rm -f "$pidfile" "$RUN/$host-$local.sh"
|
||||
echo " stopped forward $host:$remote (:$local)"
|
||||
done
|
||||
}
|
||||
|
||||
status() {
|
||||
@@ -96,6 +152,17 @@ status() {
|
||||
echo " DOWN $host http://127.0.0.1:$local"
|
||||
fi
|
||||
done
|
||||
|
||||
for spec in "${FORWARDS[@]}"; do
|
||||
read -r local host remote <<<"$(echo "$spec" | tr -s ' ')"
|
||||
# no HTTP behind these (upsd speaks its own line protocol), so the check is a bare TCP
|
||||
# handshake — enough to tell "the tunnel is up" from "nothing listens over there".
|
||||
if timeout 3 bash -c "exec 3<>/dev/tcp/127.0.0.1/$local" 2>/dev/null; then
|
||||
echo " OK $host:$remote 127.0.0.1:$local"
|
||||
else
|
||||
echo " DOWN $host:$remote 127.0.0.1:$local"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case "${1:-start}" in
|
||||
|
||||
Reference in New Issue
Block a user