apply-network: final-review fixes (diagnostics, NM off the uplink until handover, preflight, stricter stage 2)
I-1 helper logs diagnostics (nmcli, DHCP routers, networkctl -n 0, ip addr, ip route; each
under timeout 5) before a stage 1/2 restore, and the port's networkctl list line on success
(information only, never gating).
I-2 ap/nm-uplink-pending.conf -> /etc/NetworkManager/conf.d/zz-van-wan-pending.conf keeps NM
off STARLINK_IFACE while the WAN netplan is missing; installed before network-manager,
removed once the netplan matches, left as is when it differs (port already handed to NM).
apply_network backs it up as nm-pending.conf; the helper removes it + reloads NM conf right
before netplan generate/apply, restore() puts it back and reloads after the re-apply.
--wan-plan prints "uplink NM pending conf: ...".
I-3 nm_wan_state_netplan: "unreadable" (0600 file, non-root); --wan-plan and post-check say so
without warning.
I-4 apply_preflight_problems (+ hidden --apply-preflight, VANLINK_HOSTNAME test knob ignored as
root): port absent / conf of another host -> refused without --force. Stage 2 also needs
van-failover's own "proto static" default route on the port.
M-1 helper restarts van-br0-setup (if the unit exists) after the forward netplan apply.
M-3 nm_pkg_installed (dpkg-query Status) in deploy, --wan-plan and --apply-network.
M-5 header documents VANLINK_CONF; stale test comment fixed.
M-6 cellular_profile_exists ignores VANLINK_NM_DIR as root.
M-7 tests: NM-off files installed before network-manager; read-only sub-commands never apt-get.
M-8 an existing, differing WAN netplan is shown (redact_secrets now masks YAML password:) and
refused without --force.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
+155
-11
@@ -35,8 +35,8 @@ fi
|
||||
|
||||
# 2. every file carrying an @TOKEN@ is installed through install_rendered
|
||||
# (plain `install` would ship the placeholder unrendered — the 2026-09-23 failure)
|
||||
# vanrouter.js: installed by the loop in the cockpit block; 50-van-wan.yaml: reference copy,
|
||||
# rendered by hand via `deploy.sh render` (deploy.sh only warns when it differs)
|
||||
# vanrouter.js: installed by the loop in the cockpit block; 50-van-wan.yaml: installed only by
|
||||
# the detached helper of `./deploy.sh --apply-network` (a routine deploy only warns when it differs)
|
||||
# 50-van-wan-wifi.yaml, cellular.nmconnection: installed by dedicated code, not `install_rendered <src> /abs/dst` literal lines
|
||||
exempt=" cockpit/vanrouter/vanrouter.js ap/50-van-wan.yaml ap/50-van-wan-wifi.yaml ap/cellular.nmconnection "
|
||||
for f in $(./deploy.sh --templates); do
|
||||
@@ -266,9 +266,16 @@ elif [ -n "$h" ]; then
|
||||
echo "$h" | grep -q 'enP2p33s0' && ok "apply helper waits on the Starlink port" || bad "apply helper does not reference STARLINK_IFACE"
|
||||
echo "$h" | grep -q 'systemctl restart van-failover' && ok "apply helper restarts van-failover" || bad "apply helper lacks van-failover restart"
|
||||
stubs=$(mktemp -d)
|
||||
for c in netplan nmcli ip ping systemctl reboot; do
|
||||
for c in netplan nmcli ip ping systemctl reboot networkctl; do
|
||||
printf '#!/bin/bash\necho "%s $*" >> "$STUB_CALLS"\n' "$c" > "$stubs/$c"
|
||||
done
|
||||
cat >> "$stubs/networkctl" <<'STUB'
|
||||
case " $* " in
|
||||
*" list "*) echo " 3 enP2p33s0 ether routable configured" ;;
|
||||
*" status "*) echo "STUB-NETWORKCTL-STATUS" ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
cat >> "$stubs/netplan" <<'STUB'
|
||||
if [ "$1" = apply ]; then
|
||||
if [ -e "${STUB_HOLD:-/nonexistent}" ]; then
|
||||
@@ -288,14 +295,25 @@ case "$2" in
|
||||
IP4.GATEWAY) echo "${NM_GW-}" ;;
|
||||
# never-default: IP4.GATEWAY is empty, the router is only in the DHCP lease options (nmcli -g joins them with " | ")
|
||||
DHCP4.OPTION) echo "${NM_DHCP-requested_routers = 1 | routers = 192.168.100.1 | subnet_mask = 255.255.255.0}" ;;
|
||||
GENERAL.STATE,GENERAL.CONNECTION,IP4.ADDRESS,IP4.GATEWAY) echo "STUB-DIAG-NM" ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
# STUB_ROUTE: yes | after-rollback | none; STUB_ROUTE_PROTO: static (van-failover's own route, default) | dhcp (a leftover networkd route)
|
||||
cat >> "$stubs/ip" <<'STUB'
|
||||
if [ "$2" = get ]; then echo "1.1.1.1 via 192.168.100.1 dev x"; exit 0; fi
|
||||
case "$*" in
|
||||
"route get "*) echo "1.1.1.1 via 192.168.100.1 dev x"; exit 0 ;;
|
||||
"-4 addr show "*) echo "STUB-ADDR inet 192.168.100.10/24"; exit 0 ;;
|
||||
esac
|
||||
r=
|
||||
case "${STUB_ROUTE:-yes}" in
|
||||
yes) echo "default via 192.168.100.1 dev x" ;;
|
||||
after-rollback) [ -e "$STUB_ND/50-van-wan.yaml" ] || echo "default via 192.168.100.1 dev x" ;;
|
||||
yes) r=1 ;;
|
||||
after-rollback) [ -e "$STUB_ND/50-van-wan.yaml" ] || r=1 ;;
|
||||
esac
|
||||
[ -n "$r" ] || exit 0
|
||||
case "$*" in
|
||||
*"proto static"*) [ "${STUB_ROUTE_PROTO:-static}" = static ] && echo "default via 192.168.100.1 dev enP2p33s0 proto static metric 200" ;;
|
||||
*) echo "default via 192.168.100.1 dev enP2p33s0 proto ${STUB_ROUTE_PROTO:-static} metric 200" ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
@@ -305,26 +323,32 @@ exit "${STUB_NET_PING:-0}"
|
||||
STUB
|
||||
printf '#!/bin/bash\nexec /bin/sleep 0.05\n' > "$stubs/sleep"
|
||||
printf '#!/bin/bash\n[ "$1" = -k ] && shift 2\nshift\nexec "$@"\n' > "$stubs/timeout"
|
||||
printf '#!/bin/bash\nexit 0\n' >> "$stubs/systemctl"
|
||||
printf '#!/bin/bash\n[ "$1" = cat ] && [ -n "${STUB_NO_BR0:-}" ] && exit 1\nexit 0\n' >> "$stubs/systemctl"
|
||||
chmod +x "$stubs"/*
|
||||
stubs_ok=1
|
||||
for c in netplan nmcli ip ping systemctl reboot sleep timeout; do [ -x "$stubs/$c" ] || stubs_ok=0; done
|
||||
for c in netplan nmcli ip ping systemctl reboot networkctl sleep timeout; do [ -x "$stubs/$c" ] || stubs_ok=0; done
|
||||
[ "$stubs_ok" = 1 ] && ok "apply helper sandbox: all system commands stubbed" || bad "apply helper sandbox: stub missing"
|
||||
|
||||
an_prep() { # fresh sandbox + generated helper; sets sb
|
||||
sb=$(mktemp -d); mkdir -p "$sb/netplan" "$sb/sysnet"
|
||||
sb=$(mktemp -d); mkdir -p "$sb/netplan" "$sb/sysnet" "$sb/nmconf"
|
||||
printf 'armbian\n' > "$sb/netplan/10-dhcp-all-interfaces.yaml"; chmod 0600 "$sb/netplan/10-dhcp-all-interfaces.yaml"
|
||||
printf 'old\n' > "$sb/netplan/60-other.yaml"
|
||||
cp -a "$sb/netplan" "$sb/bak"
|
||||
# the uplink-pending NM conf, and its copy in the backup (as apply_network makes it)
|
||||
if [ -z "${AN_NOPEND:-}" ]; then
|
||||
printf '[keyfile]\nunmanaged-devices+=interface-name:enP2p33s0\n' > "$sb/nmconf/zz-van-wan-pending.conf"
|
||||
cp -a "$sb/nmconf/zz-van-wan-pending.conf" "$sb/bak/nm-pending.conf"
|
||||
fi
|
||||
[ -n "${AN_NOPORT:-}" ] || mkdir "$sb/sysnet/enP2p33s0"
|
||||
[ -z "${AN_NOBAK:-}" ] || rm -rf "$sb/bak"
|
||||
[ -z "${AN_BAKBAD:-}" ] || chmod 000 "$sb/bak/60-other.yaml"
|
||||
printf 'network:\n version: 2\n' > "$sb/rendered.yaml"
|
||||
VANLINK_CONF=hosts/van.conf ./deploy.sh --print-apply-helper --backup "$sb/bak" --netplan-dir "$sb/netplan" \
|
||||
--log "$sb/log" --status "$sb/status" --sysnet "$sb/sysnet" --rendered "$sb/rendered.yaml" \
|
||||
--deadlines "1 1 1" --stamp T > "$sb/helper.sh"
|
||||
--nm-conf-dir "$sb/nmconf" --deadlines "1 1 1" --stamp T > "$sb/helper.sh"
|
||||
# never run a helper that does not point at the sandbox
|
||||
grep -qF "nd='$sb/netplan'" "$sb/helper.sh" && [ "$(id -u)" != 0 ] || { bad "helper does not bake the sandbox netplan dir (or root) - refusing to run"; return 1; }
|
||||
grep -qF "nd='$sb/netplan'" "$sb/helper.sh" && grep -qF "ncd='$sb/nmconf'" "$sb/helper.sh" && [ "$(id -u)" != 0 ] \
|
||||
|| { bad "helper does not bake the sandbox netplan/NM conf dirs (or root) - refusing to run"; return 1; }
|
||||
}
|
||||
an_run() { # an_run [VAR=val ...] — fresh sandbox, run the helper; sets sb rc
|
||||
an_prep || { rc=99; return 0; }
|
||||
@@ -342,6 +366,23 @@ STUB
|
||||
a_is "success: 50-van-wan.yaml mode" "$(stat -c %a "$sb/netplan/50-van-wan.yaml" 2>/dev/null)" 600
|
||||
[ -e "$sb/netplan/10-dhcp-all-interfaces.yaml.vanlink-disabled" ] && [ ! -e "$sb/netplan/10-dhcp-all-interfaces.yaml" ] && ok "apply helper success: Armbian file moved aside" || bad "apply helper success: Armbian file not moved aside"
|
||||
grep -q '^systemctl restart van-failover' "$sb/calls" && ok "apply helper success: van-failover restarted" || bad "apply helper success: no van-failover restart"
|
||||
[ ! -e "$sb/nmconf/zz-van-wan-pending.conf" ] && ok "apply helper success: uplink-pending NM conf removed" || bad "apply helper success: uplink-pending NM conf left in place"
|
||||
[ ! -e "$sb/netplan/nm-pending.conf" ] && ok "apply helper success: no nm-pending.conf in the netplan dir" || bad "apply helper success: nm-pending.conf leaked into the netplan dir"
|
||||
# order in the call log: NM conf reload -> netplan generate -> netplan apply -> van-br0-setup restart -> van-failover restart
|
||||
ln_of() { grep -n -m1 -- "$1" "$sb/calls" 2>/dev/null | cut -d: -f1 || true; }
|
||||
l_rl=$(ln_of '^nmcli general reload conf$'); l_gen=$(ln_of '^netplan generate'); l_ap=$(ln_of '^netplan apply')
|
||||
l_br=$(ln_of '^systemctl restart van-br0-setup$'); l_fo=$(ln_of '^systemctl restart van-failover')
|
||||
[ -n "$l_rl" ] && [ -n "$l_gen" ] && [ "$l_rl" -lt "$l_gen" ] && ok "apply helper success: NM conf reloaded before netplan generate" || bad "apply helper success: NM conf reload missing or after netplan generate (reload '$l_rl', generate '$l_gen')"
|
||||
[ -n "$l_br" ] && [ -n "$l_ap" ] && [ -n "$l_fo" ] && [ "$l_ap" -lt "$l_br" ] && [ "$l_br" -lt "$l_fo" ] && ok "apply helper success: van-br0-setup restarted after netplan apply, before stage 2" || bad "apply helper success: van-br0-setup restart missing or misplaced (apply '$l_ap', br0 '$l_br', failover '$l_fo')"
|
||||
[ "$(grep -c '^systemctl restart van-br0-setup$' "$sb/calls")" = 1 ] && ok "apply helper success: van-br0-setup restarted once" || bad "apply helper success: van-br0-setup restart count"
|
||||
grep -q '^networkd (info, not gating): *3 enP2p33s0 ether routable configured' "$sb/log" && ok "apply helper success: networkd state of the port logged" || bad "apply helper success: networkd info line missing"
|
||||
grep -q -- '--- diagnostics' "$sb/log" && bad "apply helper success: diagnostics must only be logged on a failed gate" || ok "apply helper success: no failure diagnostics"
|
||||
rm -rf "$sb"
|
||||
# (1b) van-br0-setup unit absent: not restarted, still ok; no pending conf: nothing to reload
|
||||
AN_NOPEND=1 an_run STUB_NO_BR0=1
|
||||
a_is "no van-br0-setup unit: status" "$(st_word)" ok
|
||||
grep -q '^systemctl restart van-br0-setup' "$sb/calls" && bad "apply helper: restarted a van-br0-setup that does not exist" || ok "apply helper: van-br0-setup restart skipped when the unit is absent"
|
||||
grep -q '^nmcli general reload conf$' "$sb/calls" && bad "apply helper: reloaded NM conf with no pending conf" || ok "apply helper: no NM conf reload without a pending conf"
|
||||
rm -rf "$sb"
|
||||
# (2) stage 1 fails: connected (externally)
|
||||
an_run NM_STATE="100 (connected (externally))"
|
||||
@@ -349,6 +390,22 @@ STUB
|
||||
grep -q 'ROLLED BACK (restored, connectivity ok)' "$sb/log" && ok "apply helper stage1: log ROLLED BACK" || bad "apply helper stage1: log"
|
||||
a_is "stage1: Armbian file restored mode" "$(stat -c %a "$sb/netplan/10-dhcp-all-interfaces.yaml" 2>/dev/null)" 600
|
||||
[ ! -e "$sb/netplan/50-van-wan.yaml" ] && [ ! -e "$sb/netplan/10-dhcp-all-interfaces.yaml.vanlink-disabled" ] && [ -e "$sb/netplan/60-other.yaml" ] && ok "apply helper stage1: netplan dir restored wholesale" || bad "apply helper stage1: netplan dir not restored"
|
||||
cmp -s "$sb/nmconf/zz-van-wan-pending.conf" "$sb/bak/nm-pending.conf" && ok "apply helper stage1: uplink-pending NM conf restored" || bad "apply helper stage1: uplink-pending NM conf not restored"
|
||||
[ ! -e "$sb/netplan/nm-pending.conf" ] && ok "apply helper stage1: nm-pending.conf not copied into the netplan dir" || bad "apply helper stage1: nm-pending.conf leaked into the netplan dir"
|
||||
l_ap2=$(grep -n '^netplan apply' "$sb/calls" | sed -n 2p | cut -d: -f1 || true); l_rl2=$(grep -n '^nmcli general reload conf$' "$sb/calls" | sed -n 2p | cut -d: -f1 || true)
|
||||
[ -n "$l_ap2" ] && [ -n "$l_rl2" ] && [ "$l_ap2" -lt "$l_rl2" ] && ok "apply helper stage1: NM conf reloaded after the rollback apply" || bad "apply helper stage1: no NM conf reload after the rollback apply (apply '$l_ap2', reload '$l_rl2')"
|
||||
for m in '--- diagnostics: stage 1' 'STUB-DIAG-NM' 'routers = 192.168.100.1' 'STUB-NETWORKCTL-STATUS' 'STUB-ADDR inet' 'default via 192.168.100.1 dev enP2p33s0'; do
|
||||
sed -n '/--- diagnostics/,/--- end diagnostics/p' "$sb/log" | grep -qF -- "$m" && ok "apply helper stage1: diagnostics contain '$m'" || bad "apply helper stage1: diagnostics lack '$m'"
|
||||
done
|
||||
d_ln=$(grep -n -m1 -- '--- diagnostics' "$sb/log" | cut -d: -f1 || true); r_ln=$(grep -n -m1 'restoring' "$sb/log" | cut -d: -f1 || true)
|
||||
[ -n "$d_ln" ] && [ -n "$r_ln" ] && [ "$d_ln" -lt "$r_ln" ] && ok "apply helper stage1: diagnostics logged before the restore" || bad "apply helper stage1: diagnostics not before the restore"
|
||||
grep -q '^networkctl .*status enP2p33s0' "$sb/calls" && ok "apply helper: networkctl status called" || bad "apply helper: networkctl status not called"
|
||||
grep '^networkctl .*status' "$sb/calls" | grep -qv -- ' -n 0 ' && bad "apply helper: networkctl status must pass -n 0 (no journal)" || ok "apply helper: networkctl status without journal lines"
|
||||
rm -rf "$sb"
|
||||
# (2c) stage 1 fails on a host without a pending conf: nothing to restore there
|
||||
AN_NOPEND=1 an_run NM_STATE=bad
|
||||
a_is "stage1 without pending conf: status" "$(st_word)" rolled-back
|
||||
[ ! -e "$sb/nmconf/zz-van-wan-pending.conf" ] && ok "apply helper stage1 without pending conf: none created" || bad "apply helper stage1 without pending conf: one appeared"
|
||||
rm -rf "$sb"
|
||||
# (2b) stage 1 fails: wrong connection name; gateway unpingable
|
||||
an_run NM_CONN="Wired connection 1"; a_is "stage1 conn name: status" "$(st_word)" rolled-back; rm -rf "$sb"
|
||||
@@ -383,6 +440,15 @@ STUB
|
||||
a_is "stage2: exit 1" "$rc" 1; a_is "stage2: status" "$(st_word)" rolled-back
|
||||
[ ! -e "$sb/netplan/50-van-wan.yaml" ] && [ -e "$sb/netplan/10-dhcp-all-interfaces.yaml" ] && ok "apply helper stage2: restored" || bad "apply helper stage2: not restored"
|
||||
rm -rf "$sb"
|
||||
# (5b) stage 2: a default route that is only a leftover networkd/DHCP one (not van-failover's proto static) must not pass
|
||||
an_run STUB_ROUTE_PROTO=dhcp
|
||||
a_is "stage2 dhcp-only default route: exit 1" "$rc" 1; a_is "stage2 dhcp-only default route: status" "$(st_word)" rolled-back
|
||||
grep -q '^ip route show default dev enP2p33s0 proto static$' "$sb/calls" && ok "apply helper stage2: checks van-failover's proto static route on the port" || bad "apply helper stage2: no proto static route check"
|
||||
grep -qF -- '--- diagnostics: stage 2' "$sb/log" && ok "apply helper stage2: diagnostics logged" || bad "apply helper stage2: diagnostics missing"
|
||||
[ -e "$sb/netplan/10-dhcp-all-interfaces.yaml" ] && cmp -s "$sb/nmconf/zz-van-wan-pending.conf" "$sb/bak/nm-pending.conf" && ok "apply helper stage2: Armbian file and pending conf restored" || bad "apply helper stage2: Armbian file / pending conf not restored"
|
||||
rm -rf "$sb"
|
||||
# (5c) port absent: stage 2 needs no proto static route on it
|
||||
AN_NOPORT=1 an_run STUB_ROUTE_PROTO=dhcp; a_is "port absent, dhcp route: status" "$(st_word)" ok; rm -rf "$sb"
|
||||
# (6) clean rollback but no connectivity (uplink unplugged): must NOT reboot
|
||||
an_run STUB_ROUTE=none
|
||||
a_is "no connectivity after clean rollback: exit" "$rc" 1
|
||||
@@ -421,6 +487,10 @@ STUB
|
||||
[ -n "$so" ] && [ -n "$tr" ] && [ "$so" -lt "$tr" ] && ok "apply helper: status ok is written before the trap is removed" || bad "apply helper: status ok must precede trap removal"
|
||||
echo "$h" | grep -q "^trap 'rm -f \"\$0\"' EXIT$" && ok "apply helper removes itself on exit" || bad "apply helper lacks the self-remove EXIT trap"
|
||||
echo "$h" | grep -q 'timeout -k 10 30 netplan generate' && echo "$h" | grep -q 'timeout -k 10 90 netplan apply' && ok "apply helper: netplan under timeout -k" || bad "apply helper: netplan lacks timeout -k"
|
||||
dg=$(echo "$h" | sed -n '/^diag() {/,/^}/p')
|
||||
[ -n "$dg" ] && ! echo "$dg" | grep -E '(^ *|[;|&(] *)(nmcli|networkctl|ip) ' | grep -q . && [ "$(echo "$dg" | grep -c 'timeout 5 ')" -ge 5 ] \
|
||||
&& ok "apply helper: every diagnostic command runs under timeout 5" || bad "apply helper: diag() missing or a diagnostic command without timeout 5"
|
||||
echo "$h" | grep -q journalctl && bad "apply helper must not call journalctl" || ok "apply helper: no journal calls"
|
||||
fi
|
||||
# 18b. status file gate and STARLINK_IFACE validation
|
||||
gs=$(mktemp -d)
|
||||
@@ -501,6 +571,18 @@ echo "$o" | grep -q -- "-> post-deploy: NetworkManager connection $conn not foun
|
||||
echo "$o" | grep -q -- '-> post-deploy: WAN netplan differs' && ok "19e: netplan differs -> warn" || bad "19e: netplan warn missing"
|
||||
printf 'id=%s\n' "$conn" > "$tc/nm/x.nmconnection"
|
||||
nm | grep -q " ok NetworkManager connection $conn exists" && ok "19e: cellular keyfile scan -> ok" || bad "19e: keyfile scan ok missing"
|
||||
# 19g. an installed WAN netplan this user cannot read (the helper installs it 0600) is "unreadable", not "differs"
|
||||
if [ "$(id -u)" = 0 ]; then
|
||||
ok "19g: unreadable-netplan checks skipped (running as root)"
|
||||
else
|
||||
chmod 000 "$tc/np.yaml"
|
||||
o=$(nm)
|
||||
echo "$o" | grep -qxF ' ok WAN netplan: cannot read as non-root (run with sudo to verify)' && ok "19g: post-check unreadable netplan -> ok line" || bad "19g: post-check unreadable netplan ok line missing"
|
||||
echo "$o" | grep -q -- '-> post-deploy: WAN netplan' && bad "19g: post-check must not warn about an unreadable netplan" || ok "19g: post-check does not warn about an unreadable netplan"
|
||||
p=$(VANLINK_WAN_NETPLAN="$tc/np.yaml" ./deploy.sh --wan-plan hosts/van.conf 2>&1)
|
||||
echo "$p" | grep -qxF ' netplan: /etc/netplan/50-van-wan.yaml unreadable (run with sudo)' && ok "19g: wan-plan unreadable netplan" || bad "19g: wan-plan unreadable netplan line"
|
||||
chmod 600 "$tc/np.yaml"
|
||||
fi
|
||||
# 19f. VANLINK_WAN_NETPLAN is a read-only-path test knob: apply_network must neutralise it, and no apply code reads other VANLINK_* vars
|
||||
an=$(sed -n '/^apply_network() {/,/^}/p' deploy.sh)
|
||||
echo "$an" | grep -q "VANLINK_WAN_NETPLAN='' nm_wan_state_netplan" && ! echo "$an" | grep -E 'nm_wan_state_netplan' | grep -qv "VANLINK_WAN_NETPLAN=''" \
|
||||
@@ -508,4 +590,66 @@ echo "$an" | grep -q "VANLINK_WAN_NETPLAN='' nm_wan_state_netplan" && ! echo "$a
|
||||
if { echo "$an"; sed -n '/^apply_helper_script() {/,/^}/p' deploy.sh; } | grep 'VANLINK_' | grep -vE 'VANLINK_CONF|VANLINK_WAN_NETPLAN=' | grep -q .; then bad "19f: apply path reads a VANLINK_* variable"; else ok "19f: apply path reads no VANLINK_* variable besides VANLINK_CONF"; fi
|
||||
rm -rf "$tc"
|
||||
|
||||
# 20. final-review fixes
|
||||
t20=$(mktemp -d)
|
||||
# 20a. (M-7) the files keeping NM off the AP/LAN ports and the uplink are installed before the package that starts NM
|
||||
l_pkg=$(grep -n 'apt-get install -y network-manager' deploy.sh | head -1 | cut -d: -f1 || true)
|
||||
for pat in 'ap/van-ap-unmanaged.conf' 'ap/nm-no-auto-default.conf' 'ap/nm-uplink-pending.conf'; do
|
||||
l=$(grep -n "^[[:space:]]*install[_ -].*$pat" deploy.sh | head -1 | cut -d: -f1 || true)
|
||||
[ -n "$l" ] && [ -n "$l_pkg" ] && [ "$l" -lt "$l_pkg" ] && ok "20a: $pat installed (line $l) before network-manager (line $l_pkg)" || bad "20a: $pat install line '$l' must precede the network-manager install line '$l_pkg'"
|
||||
done
|
||||
# 20b. (M-7) read-only sub-commands never call apt-get
|
||||
mkdir -p "$t20/apt"
|
||||
printf '#!/bin/sh\necho "apt-get $*" >> "$APT_LOG"\nexit 1\n' > "$t20/apt/apt-get"; chmod +x "$t20/apt/apt-get"
|
||||
for sub in --check --diff --post-check --wan-plan --print-apply-helper; do
|
||||
PATH="$t20/apt:$PATH" APT_LOG="$t20/apt.log" POSTCHECK_WAIT=0 ./deploy.sh "$sub" hosts/van.conf >/dev/null 2>&1 || true
|
||||
done
|
||||
[ ! -s "$t20/apt.log" ] && ok "20b: --check/--diff/--post-check/--wan-plan/--print-apply-helper never call apt-get" || { bad "20b: a read-only sub-command called apt-get"; sed 's/^/ /' "$t20/apt.log"; }
|
||||
# 20c. (M-3) network-manager is detected with dpkg-query's Status, in one helper
|
||||
grep -qE 'dpkg -s network-manager' deploy.sh && bad "20c: deploy.sh still uses dpkg -s network-manager" || ok "20c: no dpkg -s network-manager"
|
||||
[ "$(grep -c 'nm_pkg_installed' deploy.sh)" -ge 4 ] && grep -q "dpkg-query -W -f='\${Status}' network-manager" deploy.sh && ok "20c: nm_pkg_installed (dpkg-query) used by deploy, --wan-plan and --apply-network" || bad "20c: nm_pkg_installed missing or not used in all three places"
|
||||
# 20d. (I-2) uplink-pending NM conf template and its --wan-plan line
|
||||
[ "$(grep -v '^[[:space:]]*#' ap/nm-uplink-pending.conf 2>/dev/null | grep -v '^[[:space:]]*$')" = "$(printf '[keyfile]\nunmanaged-devices+=interface-name:@STARLINK_IFACE@')" ] && ok "20d: nm-uplink-pending.conf is [keyfile] + unmanaged-devices+=" || bad "20d: ap/nm-uplink-pending.conf missing or wrong"
|
||||
expect_line van ap/nm-uplink-pending.conf 'unmanaged-devices+=interface-name:enP2p33s0'
|
||||
if [ -e /etc/NetworkManager/conf.d/zz-van-wan-pending.conf ]; then
|
||||
ok "20d: wan-plan pending-conf assertions skipped (this machine has the pending conf)"
|
||||
else
|
||||
VANLINK_CONF=hosts/van.conf ./deploy.sh --render-wan-netplan > "$t20/np.yaml"
|
||||
p=$(VANLINK_WAN_NETPLAN="$t20/none.yaml" ./deploy.sh --wan-plan hosts/van.conf 2>&1)
|
||||
echo "$p" | grep -qxF ' uplink NM pending conf: would install' && ok "20d: netplan missing -> pending conf would install" || bad "20d: netplan missing -> 'would install' expected"
|
||||
p=$(VANLINK_WAN_NETPLAN="$t20/np.yaml" ./deploy.sh --wan-plan hosts/van.conf 2>&1)
|
||||
echo "$p" | grep -qxF ' uplink NM pending conf: absent' && ok "20d: netplan matches -> pending conf absent" || bad "20d: netplan matches -> 'absent' expected"
|
||||
echo '# differs' >> "$t20/np.yaml"
|
||||
p=$(VANLINK_WAN_NETPLAN="$t20/np.yaml" ./deploy.sh --wan-plan hosts/van.conf 2>&1)
|
||||
echo "$p" | grep -qxF ' uplink NM pending conf: absent' && ok "20d: netplan differs (already handed to NM) -> pending conf not installed" || bad "20d: netplan differs -> 'absent' expected"
|
||||
fi
|
||||
# 20e. (I-4) apply preflight: port present and conf named after this host
|
||||
mkdir -p "$t20/sys/enP2p33s0" "$t20/nosys"
|
||||
pf() { VANLINK_SYSNET="$1" VANLINK_HOSTNAME="$2" ./deploy.sh --apply-preflight "$3" 2>&1; }
|
||||
o=$(pf "$t20/sys" van hosts/van.conf) && rc=0 || rc=$?
|
||||
[ -z "$o" ] && [ "$rc" = 0 ] && ok "20e: preflight fine -> no output, exit 0" || bad "20e: preflight fine gave '$o' (exit $rc)"
|
||||
o=$(pf "$t20/sys" wan hosts/van.conf) && rc=0 || rc=$?
|
||||
[ "$rc" = 1 ] && [ "$(echo "$o" | grep -c .)" = 1 ] && echo "$o" | grep -q 'van.conf.*hostname wan' && ok "20e: preflight wrong host -> one problem" || bad "20e: preflight wrong host gave '$o' (exit $rc)"
|
||||
o=$(pf "$t20/nosys" van hosts/van.conf) && rc=0 || rc=$?
|
||||
[ "$rc" = 1 ] && [ "$(echo "$o" | grep -c .)" = 1 ] && echo "$o" | grep -q 'enP2p33s0' && ok "20e: preflight absent port -> one problem" || bad "20e: preflight absent port gave '$o' (exit $rc)"
|
||||
cp hosts/van.conf "$t20/other.conf"
|
||||
o=$(pf "$t20/sys" wan "$t20/other.conf") && rc=0 || rc=$?
|
||||
[ -z "$o" ] && [ "$rc" = 0 ] && ok "20e: preflight skips the host-name check for a conf outside hosts/" || bad "20e: preflight conf outside hosts/ gave '$o' (exit $rc)"
|
||||
an=$(sed -n '/^apply_network() {/,/^}/p' deploy.sh)
|
||||
echo "$an" | grep -q 'apply_preflight_problems "$VANLINK_CONF" /sys/class/net "$(hostname -s)"' && ok "20e: apply_network runs the preflight on the real sysfs/hostname" || bad "20e: apply_network does not call apply_preflight_problems with real paths"
|
||||
# 20f. (M-8) a differing installed netplan is shown redacted and refused without --force
|
||||
psk=$(sed -n 's/^ *password: *"\(.*\)"$/\1/p' ap/50-van-wan-wifi.yaml || true)
|
||||
d=$(diff -u /dev/null <(VANLINK_CONF=hosts/wan.conf ./deploy.sh --render-wan-netplan) | ./deploy.sh --redact) || true
|
||||
[ -n "$psk" ] && ! echo "$d" | grep -qF -- "$psk" && echo "$d" | grep -qE '^\+ +password: <redacted>$' && ok "20f: --redact masks the netplan Wi-Fi password in a diff" || bad "20f: netplan Wi-Fi password not redacted"
|
||||
echo "$an" | grep -q 'diff -u /etc/netplan/50-van-wan.yaml <(render_wan_netplan) | redact_secrets' && echo "$an" | grep -q 'without --force' && ok "20f: apply_network prints a redacted diff and refuses a differing netplan without --force" || bad "20f: apply_network differs handling"
|
||||
# 20g. (M-6) root ignores VANLINK_NM_DIR
|
||||
cpe=$(sed -n '/^cellular_profile_exists() {/,/^}/p' deploy.sh)
|
||||
grep -q '"$(id -u)" = 0 ] || d=${VANLINK_NM_DIR' <<<"$cpe" && ok "20g: cellular_profile_exists ignores VANLINK_NM_DIR as root" || bad "20g: cellular_profile_exists must ignore VANLINK_NM_DIR as root"
|
||||
# 20h. (M-5) documented overrides
|
||||
hdr=$(sed -n '1,/^set -euo pipefail/{/^#/p}' deploy.sh)
|
||||
for k in 'VANLINK_CONF=' 'VANLINK_HOSTNAME=' '--apply-preflight'; do
|
||||
grep -qF -- "$k" <<<"$hdr" && ok "20h: header documents $k" || bad "20h: header lacks $k"
|
||||
done
|
||||
rm -rf "$t20"
|
||||
|
||||
exit "$fail"
|
||||
|
||||
Reference in New Issue
Block a user