deploy: --apply-network changes nothing itself; helper does install/apply, two-stage gate, checked rollback, status file
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KqhjP7nud5gdBg25zCiRk9
This commit is contained in:
@@ -257,16 +257,109 @@ rm -rf "$nmd" "$nme"
|
||||
# 17c. NM must not auto-create "Wired connection" profiles
|
||||
[ "$(grep -v '^[[:space:]]*#' ap/nm-no-auto-default.conf 2>/dev/null | grep -v '^[[:space:]]*$')" = "$(printf '[main]\nno-auto-default=*')" ] && ok "nm-no-auto-default.conf is [main] + no-auto-default=*" || bad "ap/nm-no-auto-default.conf missing or wrong"
|
||||
|
||||
# 18. the detached apply helper: syntax, ordering, rollback branch
|
||||
# 18. the detached apply helper: syntax, then behaviour against stubbed system commands in a sandbox
|
||||
h=$(VANLINK_CONF=hosts/van.conf ./deploy.sh --print-apply-helper 2>&1) || { bad "--print-apply-helper failed"; echo "$h" | sed 's/^/ /'; h=; }
|
||||
if [ -n "$h" ]; then
|
||||
echo "$h" | bash -n && ok "apply helper: bash -n" || bad "apply helper: bash -n"
|
||||
echo "$h" | grep -q 'netplan generate' && echo "$h" | grep -q 'netplan apply' && ok "apply helper applies netplan" || bad "apply helper lacks netplan generate/apply"
|
||||
echo "$h" | grep -q 'restoring' && ok "apply helper has a rollback branch" || bad "apply helper lacks rollback"
|
||||
echo "$h" | grep -q 'enP2p33s0' && ok "apply helper waits on the Starlink port" || bad "apply helper does not reference STARLINK_IFACE"
|
||||
# rollback must come after the wait loop, and the backup is restored wholesale
|
||||
a=$(echo "$h" | grep -n 'netplan apply' | head -1 | cut -d: -f1); r=$(echo "$h" | grep -n 'restoring' | head -1 | cut -d: -f1)
|
||||
[ "$a" -lt "$r" ] && ok "apply helper: apply precedes rollback" || bad "apply helper: rollback ordering"
|
||||
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
|
||||
printf '#!/bin/bash\necho "%s $*" >> "$STUB_CALLS"\n' "$c" > "$stubs/$c"
|
||||
done
|
||||
cat >> "$stubs/netplan" <<'STUB'
|
||||
if [ "$1" = apply ]; then
|
||||
n=$(cat "$STUB_SB/napply" 2>/dev/null || echo 0); echo $((n + 1)) > "$STUB_SB/napply"
|
||||
[ "${STUB_FAIL_APPLY:-}" = first ] && [ "$n" = 0 ] && exit 1
|
||||
fi
|
||||
exit 0
|
||||
STUB
|
||||
cat >> "$stubs/nmcli" <<'STUB'
|
||||
case "$2" in
|
||||
GENERAL.STATE) echo "${NM_STATE-100 (connected)}" ;;
|
||||
GENERAL.CONNECTION) echo "${NM_CONN-netplan-enP2p33s0}" ;;
|
||||
IP4.ADDRESS) echo "${NM_ADDR-192.168.100.10/24}" ;;
|
||||
IP4.GATEWAY) echo "${NM_GW-192.168.100.1}" ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
cat >> "$stubs/ip" <<'STUB'
|
||||
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" ;;
|
||||
esac
|
||||
exit 0
|
||||
STUB
|
||||
cat >> "$stubs/ping" <<'STUB'
|
||||
case " $* " in *" -I "*) exit "${STUB_GW_PING:-0}" ;; esac
|
||||
exit "${STUB_NET_PING:-0}"
|
||||
STUB
|
||||
printf '#!/bin/bash\nexec /bin/sleep 0.05\n' > "$stubs/sleep"
|
||||
printf '#!/bin/bash\nshift\nexec "$@"\n' > "$stubs/timeout"
|
||||
printf '#!/bin/bash\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
|
||||
[ "$stubs_ok" = 1 ] && ok "apply helper sandbox: all system commands stubbed" || bad "apply helper sandbox: stub missing"
|
||||
|
||||
an_run() { # an_run [VAR=val ...] — fresh sandbox, run the helper; sets sb rc
|
||||
sb=$(mktemp -d); mkdir -p "$sb/netplan" "$sb/sysnet"
|
||||
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"
|
||||
[ -n "${AN_NOPORT:-}" ] || mkdir "$sb/sysnet/enP2p33s0"
|
||||
[ -z "${AN_NOBAK:-}" ] || rm -rf "$sb/bak"
|
||||
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"
|
||||
env PATH="$stubs:/usr/bin:/bin" STUB_CALLS="$sb/calls" STUB_SB="$sb" STUB_ND="$sb/netplan" "$@" bash "$sb/helper.sh" && rc=0 || rc=$?
|
||||
}
|
||||
a_is() { [ "$2" = "$3" ] && ok "apply helper $1" || bad "apply helper $1 (got '$2', want '$3')"; }
|
||||
st_word() { cut -d' ' -f1 "$sb/status" 2>/dev/null; }
|
||||
# (1) success
|
||||
an_run
|
||||
a_is "success: exit 0" "$rc" 0; a_is "success: status" "$(st_word)" ok
|
||||
grep -q 'apply-network OK' "$sb/log" && ok "apply helper success: log OK" || bad "apply helper success: log"
|
||||
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"
|
||||
rm -rf "$sb"
|
||||
# (2) stage 1 fails: connected (externally)
|
||||
an_run NM_STATE="100 (connected (externally))"
|
||||
a_is "stage1: exit 1" "$rc" 1; a_is "stage1: status" "$(st_word)" rolled-back
|
||||
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"
|
||||
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"
|
||||
an_run STUB_GW_PING=1; a_is "stage1 gateway ping: status" "$(st_word)" rolled-back; rm -rf "$sb"
|
||||
an_run NM_GW=; a_is "stage1 no gateway: status" "$(st_word)" rolled-back; rm -rf "$sb"
|
||||
# (3) netplan apply fails, port absent
|
||||
AN_NOPORT=1 an_run STUB_FAIL_APPLY=first
|
||||
a_is "apply failure: exit 1" "$rc" 1; a_is "apply failure: not ok" "$(st_word)" rolled-back
|
||||
[ -e "$sb/netplan/10-dhcp-all-interfaces.yaml" ] && [ ! -e "$sb/netplan/50-van-wan.yaml" ] && ok "apply helper apply failure: restored" || bad "apply helper apply failure: not restored"
|
||||
rm -rf "$sb"
|
||||
# (3b) port absent and apply ok: stage 1 needs only the apply
|
||||
AN_NOPORT=1 an_run; a_is "port absent, apply ok: status" "$(st_word)" ok; rm -rf "$sb"
|
||||
# (4) rollback cp fails (backup dir missing)
|
||||
AN_NOBAK=1 an_run NM_STATE=bad
|
||||
a_is "rollback cp failure: exit 1" "$rc" 1; a_is "rollback cp failure: status" "$(st_word)" rollback-failed
|
||||
grep -q 'ROLLBACK FAILED' "$sb/log" && ok "apply helper rollback failure: loud log" || bad "apply helper rollback failure: log"
|
||||
grep -q '^reboot\|systemctl reboot' "$sb/calls" && bad "apply helper rollback failure with connectivity: must not reboot" || ok "apply helper rollback failure with connectivity: no reboot"
|
||||
rm -rf "$sb"
|
||||
# (5) stage 2 fails: no default route until rolled back
|
||||
an_run STUB_ROUTE=after-rollback
|
||||
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"
|
||||
# (6) no connectivity even after rollback: last-resort reboot
|
||||
an_run STUB_ROUTE=none
|
||||
a_is "no connectivity: status" "$(st_word)" rollback-failed
|
||||
grep -q '^systemctl reboot' "$sb/calls" && ok "apply helper: reboots when connectivity is not back after rollback" || bad "apply helper: no reboot"
|
||||
rm -rf "$sb"
|
||||
rm -rf "$stubs"
|
||||
fi
|
||||
|
||||
exit "$fail"
|
||||
|
||||
Reference in New Issue
Block a user