An end-to-end run restored 4 of 13 apps and reported
"First-run restore complete — 4 apps restored" as a success.
Two truncations, and fixing the first had hidden the second:
* the CLI dispatcher calls handlers with no arguments, so "$@"/shift inside
one operate on an empty list. Fixed earlier with LP_CLI_ARGS.
* LP_CLI_ARGS was built from start.sh's "$@" — but the root wrapper invokes
start.sh with exactly nine hardcoded positional slots. So the array could
never hold more than nine entries, and `${LP_CLI_ARGS[@]:5}` yielded at
most four app names.
The wrapper now forwards the real argv after those nine slots (they stay
untouched: every dispatcher reads them, and unset ones must keep arriving as
the literal "empty"), and start.sh reads it back as "${@:10}". Verified: a
preflight given six apps checks six, where five was the previous ceiling.
footprint_version 7 -> 8, since the wrapper is root-owned and baked at install.
Two further fixes so a truncation cannot pass as success again:
* restoreFirstRunBulk with no app list is now a whole-host restore — it
discovers the host's apps and re-applies the preflight. The installer's
report runs in its own process, so without this an app the user was told
would be skipped got restored anyway. init.sh now passes no list, so a
whole-host restore builds nothing that can be truncated.
* it counts what actually landed and returns non-zero naming the failures,
instead of reporting the length of the list it was handed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
81 lines
2.8 KiB
Bash
81 lines
2.8 KiB
Bash
#!/bin/bash
|
|
|
|
restoreFirstRunDiscover()
|
|
{
|
|
local idx="$1"
|
|
|
|
if ! resticLocationEnabled "$idx"; then
|
|
isError "Location $idx is not enabled"
|
|
return 1
|
|
fi
|
|
|
|
resticEnvExport "$idx" || return 1
|
|
# Via runBackupOp rather than its own sudo: this was the one backup-engine
|
|
# call bypassing that funnel, so it silently missed the -E fix for sudo-rs
|
|
# (and the -H that puts restic's cache under the backup user's HOME).
|
|
runBackupOp restic snapshots --tag engine=libreportal --json --no-lock 2>/dev/null
|
|
local rc=$?
|
|
resticEnvUnset
|
|
return $rc
|
|
}
|
|
|
|
# Restore a host's apps onto this machine.
|
|
#
|
|
# With no app list this is a WHOLE-HOST restore: the apps are discovered from
|
|
# the repository and filtered through the preflight. Both halves matter.
|
|
#
|
|
# Discovery, because an explicit list has to survive the CLI wrapper's fixed
|
|
# positional slots to get here — a 13-app restore arrived as four, restored
|
|
# those, and reported success. The wrapper now forwards the real argv, but a
|
|
# whole-host restore that never builds a list cannot be truncated at all.
|
|
#
|
|
# The preflight, because the installer prints its report in a separate process,
|
|
# so the decision it made there is gone by the time this runs. Without
|
|
# re-applying it, an app the user was told would be skipped — one this version
|
|
# no longer ships, or one too big for the disk — gets restored anyway.
|
|
restoreFirstRunBulk()
|
|
{
|
|
local idx="$1"
|
|
local source_host="$2"
|
|
shift 2
|
|
local apps_to_restore=("$@")
|
|
local -i preflighted=0
|
|
|
|
if [[ ${#apps_to_restore[@]} -eq 0 ]]; then
|
|
restorePreflightReport "$idx" "$source_host" >/dev/null 2>&1
|
|
apps_to_restore=("${RESTORE_PREFLIGHT_OK[@]}")
|
|
preflighted=1
|
|
fi
|
|
|
|
if [[ ${#apps_to_restore[@]} -eq 0 ]]; then
|
|
isError "No apps to restore for '$source_host' in this repository"
|
|
return 1
|
|
fi
|
|
|
|
isHeader "First-run bulk restore from $(resticLocationName "$idx") (host=$source_host)"
|
|
(( preflighted )) && isNotice "Restoring ${#apps_to_restore[@]} apps the preflight approved."
|
|
|
|
# Count what actually landed. A per-app failure must not be reported as a
|
|
# complete restore — that is how "4 apps restored" read as success when
|
|
# nine had gone missing.
|
|
local app
|
|
local -i ok=0 bad=0
|
|
local -a failed=()
|
|
for app in "${apps_to_restore[@]}"; do
|
|
if restoreAppStart "$app" "latest" "$idx" "$source_host"; then
|
|
ok=$(( ok + 1 ))
|
|
else
|
|
bad=$(( bad + 1 )); failed+=("$app")
|
|
fi
|
|
done
|
|
|
|
if (( bad > 0 )); then
|
|
isError "First-run restore finished with failures — $ok of ${#apps_to_restore[@]} restored"
|
|
isNotice "Failed: ${failed[*]}"
|
|
return 1
|
|
fi
|
|
|
|
isSuccessful "First-run restore complete — $ok apps restored"
|
|
return 0
|
|
}
|