Make the setup-state push report whether it worked
It was documented 'Always returns 0', so the offboard's new 'Phase flags pushed' check was testing a constant and ticking regardless.
This commit is contained in:
@@ -264,7 +264,12 @@ write_onboard_phase() {
|
|||||||
local state_file="$(platform_setup_db_path)"
|
local state_file="$(platform_setup_db_path)"
|
||||||
[[ "$DRY_RUN" == true ]] && { warn "DRY RUN — would write ${key}=true"; return 0; }
|
[[ "$DRY_RUN" == true ]] && { warn "DRY RUN — would write ${key}=true"; return 0; }
|
||||||
set_state_var "$state_file" "$key" "true"
|
set_state_var "$state_file" "$key" "true"
|
||||||
platform_push_setup_state
|
# The push now reports failure, so it is warned about rather than returned. This function's
|
||||||
|
# contract is "the phase is recorded here" — the flag is on local disk either way, and an
|
||||||
|
# unreachable partner must not make a completed phase look like it did not happen.
|
||||||
|
platform_push_setup_state \
|
||||||
|
|| warn "Phase flag ${key} written locally but not delivered to the partner"
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -429,10 +429,14 @@ exit(\$failed > 0 ? 1 : 0);
|
|||||||
# ──────────────────────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
# platform_push_setup_state
|
# platform_push_setup_state
|
||||||
# Pushes the Varaverk wizard setup state to all partners via the WebGUI PHP API.
|
# Pushes the Varaverk wizard setup state to all partners via the WebGUI PHP API.
|
||||||
# No-op if php is unavailable. Always returns 0.
|
# Returns 1 if any partner did not take it, 0 otherwise. No-op returning 0 if php is absent.
|
||||||
|
#
|
||||||
|
# This used to end with a bare `return 0` under the comment "Always returns 0", which meant
|
||||||
|
# every caller that wrote `platform_push_setup_state || X=false` was testing a constant.
|
||||||
|
# Wiring a failure branch onto a helper that cannot fail is worse than hardcoding the tick,
|
||||||
|
# because the code reads as though it checked.
|
||||||
# ──────────────────────────────────────────────────────────────────────────────────────────────
|
# ──────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
platform_push_setup_state() {
|
platform_push_setup_state() {
|
||||||
command -v php &>/dev/null || return 0
|
command -v php &>/dev/null || return 0
|
||||||
php -r "require_once '/usr/local/emhttp/plugins/varaverk/include/config.php'; vv_push_setup_state();" 2>/dev/null
|
php -r "require_once '/usr/local/emhttp/plugins/varaverk/include/config.php'; exit(vv_push_setup_state() > 0 ? 1 : 0);" 2>/dev/null
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,12 +238,23 @@ function vv_setup_state_write(array $data): bool {
|
|||||||
|
|
||||||
// Push the setup state file to all remote hosts via scp.
|
// Push the setup state file to all remote hosts via scp.
|
||||||
// Reads the remote's varaverk.cfg to find their actual SCRIPTS_DIR (handles appdata mode).
|
// Reads the remote's varaverk.cfg to find their actual SCRIPTS_DIR (handles appdata mode).
|
||||||
function vv_push_setup_state(): void {
|
//
|
||||||
if (!file_exists(VV_SETUP_STATE_FILE)) return;
|
// Returns the number of hosts the push FAILED to reach — 0 when every partner took it, and 0
|
||||||
|
// when there was nothing to do. This was `: void`, and it threw away the exec() status too, so
|
||||||
|
// the adapter that wraps it was documented "Always returns 0" and every caller testing it was
|
||||||
|
// testing a constant. partnership_offboard.sh reported "Phase flags pushed ✅" on runs whose own
|
||||||
|
// body had just warned the push failed, which is the difference between a mirror that knows the
|
||||||
|
// partnership ended and one whose wizard still shows a finished onboard.
|
||||||
|
//
|
||||||
|
// A host with no resolvable Tailscale IP counts as a failure, not a skip: it is precisely the
|
||||||
|
// case where the partner keeps stale state and nobody is told.
|
||||||
|
function vv_push_setup_state(): int {
|
||||||
|
if (!file_exists(VV_SETUP_STATE_FILE)) return 0;
|
||||||
$myHostId = vv_detect_host();
|
$myHostId = vv_detect_host();
|
||||||
$vars = vv_conf_vars();
|
$vars = vv_conf_vars();
|
||||||
$sshKey = $vars[strtoupper($myHostId) . '_SSH_KEY'] ?? '';
|
$sshKey = $vars[strtoupper($myHostId) . '_SSH_KEY'] ?? '';
|
||||||
if (!$sshKey || !file_exists($sshKey)) return;
|
if (!$sshKey || !file_exists($sshKey)) return 0;
|
||||||
|
$failed = 0;
|
||||||
|
|
||||||
$master = vv_read_conf_raw('master.conf');
|
$master = vv_read_conf_raw('master.conf');
|
||||||
preg_match_all('/^\s*(HOST\d+)(?:_NAME)?\s*=\s*["\']?(\S+?)["\']?\s*$/m', $master, $m);
|
preg_match_all('/^\s*(HOST\d+)(?:_NAME)?\s*=\s*["\']?(\S+?)["\']?\s*$/m', $master, $m);
|
||||||
@@ -255,9 +266,9 @@ function vv_push_setup_state(): void {
|
|||||||
$hostname = trim($m[2][$i]);
|
$hostname = trim($m[2][$i]);
|
||||||
if (!$hostname) continue;
|
if (!$hostname) continue;
|
||||||
$ip = vv_resolve_tailscale_ip($hostname);
|
$ip = vv_resolve_tailscale_ip($hostname);
|
||||||
if (!$ip) continue;
|
if (!$ip) { $failed++; continue; }
|
||||||
$sshBase = 'ssh -i ' . escapeshellarg($sshKey)
|
$sshBase = 'ssh -i ' . escapeshellarg($sshKey)
|
||||||
. ' -o ConnectTimeout=10 -o StrictHostKeyChecking=no root@' . $ip;
|
. ' -o ConnectTimeout=10 -o StrictHostKeyChecking=no -o BatchMode=yes root@' . $ip;
|
||||||
|
|
||||||
// Get remote SCRIPTS_DIR from varaverk.cfg — handles appdata mode on remote.
|
// Get remote SCRIPTS_DIR from varaverk.cfg — handles appdata mode on remote.
|
||||||
// Falls back to the default install path if varaverk.cfg is absent (pre-install).
|
// Falls back to the default install path if varaverk.cfg is absent (pre-install).
|
||||||
@@ -282,9 +293,15 @@ function vv_push_setup_state(): void {
|
|||||||
. '[ -d "$sf" ] || { [ -d "' . $remoteSD . '/State_Files" ] '
|
. '[ -d "$sf" ] || { [ -d "' . $remoteSD . '/State_Files" ] '
|
||||||
. '&& sf="' . $remoteSD . '/State_Files"; }; '
|
. '&& sf="' . $remoteSD . '/State_Files"; }; '
|
||||||
. 'mkdir -p "$sf" && cat > "$sf/varaverk_setup.db"';
|
. 'mkdir -p "$sf" && cat > "$sf/varaverk_setup.db"';
|
||||||
|
// 2>&1 without capturing the status was the whole problem: the command could fail on an
|
||||||
|
// unreachable host, a full disk or a refused key and this function returned identically.
|
||||||
|
$out = [];
|
||||||
|
$rc = 0;
|
||||||
exec('cat ' . escapeshellarg(VV_SETUP_STATE_FILE) . ' | '
|
exec('cat ' . escapeshellarg(VV_SETUP_STATE_FILE) . ' | '
|
||||||
. $sshBase . ' ' . escapeshellarg($remoteResolve) . ' 2>&1');
|
. $sshBase . ' ' . escapeshellarg($remoteResolve) . ' 2>&1', $out, $rc);
|
||||||
|
if ($rc !== 0) $failed++;
|
||||||
}
|
}
|
||||||
|
return $failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push master.conf to all remote hosts via scp after a local save.
|
// Push master.conf to all remote hosts via scp after a local save.
|
||||||
|
|||||||
Reference in New Issue
Block a user