Partnership echo/log audit pass + exit trap
Exit trap (_pm_trap_restart_stopped) in partnership_manager.sh: restarts locally stopped containers if script crashes mid-cleanup; partnership_offboard.sh registers same trap. echo/log audit: step result lines (stack deployed counts, state writes, onboard/offboard complete) → echo; check mode ACTIVE/INACTIVE status → echo; ssh_setup.sh key-exists and install/verify results → echo. Manual-Partnership.md: added Output Tiers section.
This commit is contained in:
@@ -371,6 +371,29 @@ Counter resets after `SSH_STRIKE_RESET_HRS` of clean connectivity.
|
||||
|
||||
---
|
||||
|
||||
## ━━━ OUTPUT TIERS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
All scripts use a two-tier output model: `echo` lines are always visible; `log`
|
||||
lines only appear when `--log` is passed.
|
||||
|
||||
**partnership_onboard.sh** — one-shot setup. Without `--log`, step headers, per-step
|
||||
result lines (deployed/failed counts), and the final summary are visible. Per-container
|
||||
deploy detail suppressed.
|
||||
|
||||
**partnership_offboard.sh** — one-shot teardown. Without `--log`, step headers, key
|
||||
state transitions, and the final checklist summary are visible. Per-container cleanup
|
||||
detail suppressed.
|
||||
|
||||
**partnership_manager.sh** — check/status/transfer/onboard modes. Without `--log`,
|
||||
mode-specific result lines (`--check` prints ACTIVE/INACTIVE status always), state
|
||||
transitions, warnings, and summary blocks are visible. Per-operation detail suppressed.
|
||||
|
||||
**ssh_setup.sh** — one-shot key setup. Without `--log`, section headers and per-step
|
||||
results (key created, key installed, auth verified) are visible. Strike-counter
|
||||
management (`--validate`) uses `log` for healthy cycles; `warn` for failures.
|
||||
|
||||
---
|
||||
|
||||
## ━━━ FLAG REFERENCE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
### partnership_onboard.sh
|
||||
|
||||
@@ -270,6 +270,21 @@ OWNER_STATE_FILE="/boot/config/partnership_${OWNER}.db"
|
||||
MIRROR_STATE_FILE="/boot/config/partnership_${MIRROR}.db"
|
||||
OFFLINE_COUNTER="/boot/config/partnership_offline_days.db"
|
||||
|
||||
# ── Exit Trap — restart locally stopped containers if script crashes mid-cleanup ──────────────
|
||||
# Used by folderview3_remove_partner_folder() and cleanup_partner_containers() — also shared
|
||||
# with partnership_offboard.sh which sources this file and registers the same trap.
|
||||
declare -a _PM_TRAP_STOPPED=()
|
||||
_pm_trap_restart_stopped() {
|
||||
[[ ${#_PM_TRAP_STOPPED[@]} -eq 0 ]] && return
|
||||
for c in "${_PM_TRAP_STOPPED[@]}"; do
|
||||
[[ -z "$c" ]] && continue
|
||||
if docker inspect "$c" >/dev/null 2>&1; then
|
||||
warn "Exit trap: restarting $c (stopped but not removed)"
|
||||
docker start "$c" >/dev/null 2>&1 || warn " Failed to restart $c"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [[ "${PARTNERSHIP_LIB_MODE:-}" != "1" ]]; then
|
||||
if [[ -z "$MODE" ]]; then
|
||||
error "No mode specified"
|
||||
@@ -297,6 +312,8 @@ if [[ "${PARTNERSHIP_LIB_MODE:-}" != "1" ]]; then
|
||||
# Lock for all modes except --check (frequent) and --offboard (offboard script holds its own)
|
||||
[[ "$MODE" != "check" && "$MODE" != "offboard" ]] && acquire_lock "strict"
|
||||
|
||||
trap _pm_trap_restart_stopped EXIT
|
||||
|
||||
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes will be made"
|
||||
fi
|
||||
|
||||
@@ -679,6 +696,7 @@ folderview3_remove_partner_folder() {
|
||||
if timeout "${DOCKER_TIMEOUT:-30}" docker inspect "$container" >/dev/null 2>&1; then
|
||||
if timeout "${DOCKER_TIMEOUT:-30}" docker stop "$container" >/dev/null 2>&1; then
|
||||
log "$container stopped ✅"
|
||||
_PM_TRAP_STOPPED+=("$container")
|
||||
(( stopped++ ))
|
||||
else
|
||||
warn "$container stop failed"
|
||||
@@ -822,6 +840,7 @@ cleanup_partner_containers() {
|
||||
fi
|
||||
if timeout "${DOCKER_TIMEOUT:-30}" docker inspect "$container" >/dev/null 2>&1; then
|
||||
timeout "${DOCKER_TIMEOUT:-30}" docker stop "$container" >/dev/null 2>&1 || true
|
||||
_PM_TRAP_STOPPED+=("$container")
|
||||
timeout "${DOCKER_TIMEOUT:-30}" docker rm "$container" >/dev/null 2>&1 && \
|
||||
log "$container removed ✅" || warn "$container rm failed"
|
||||
else
|
||||
@@ -1337,7 +1356,7 @@ if [[ "$MODE" == "check" ]]; then
|
||||
|
||||
# Both agree and active — healthy, silent
|
||||
if [[ "$LOCAL_STATE" == "$REMOTE_STATE" ]] && [[ "$LOCAL_STATE" == "ACTIVE" ]]; then
|
||||
log "Partnership check — ACTIVE, both servers agree ✅"
|
||||
echo "Partnership check — ACTIVE, both servers agree ✅"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -1397,7 +1416,7 @@ if [[ "$MODE" == "check" ]]; then
|
||||
|
||||
# Both inactive — nothing to do
|
||||
if [[ "$LOCAL_STATE" == "INACTIVE" ]] && [[ "$REMOTE_STATE" == "INACTIVE" ]]; then
|
||||
log "Partnership check — INACTIVE on both servers"
|
||||
echo "Partnership check — INACTIVE on both servers"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -1489,7 +1508,7 @@ if [[ "$MODE" == "onboard" ]]; then
|
||||
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
write_state_file "$LOCAL_STATE_FILE" "ACTIVE" "$NOW" "" "$LOCAL_SERVER_NAME" "onboard"
|
||||
log "Local state: ACTIVE ✅"
|
||||
echo "Local state: ACTIVE ✅"
|
||||
remove_from_blocklist "$MIRROR"
|
||||
push_state_to_remote "$LOCAL_STATE_FILE" "$MIRROR_IP" "$MIRROR_SSH_KEY"
|
||||
echo "0" > "$OFFLINE_COUNTER"
|
||||
|
||||
@@ -124,6 +124,8 @@ OFFLINE_COUNTER="/boot/config/partnership_offline_days.db"
|
||||
|
||||
acquire_lock "strict"
|
||||
|
||||
trap _pm_trap_restart_stopped EXIT
|
||||
|
||||
# Check already offboarded
|
||||
if [[ -f "$LOCAL_STATE_FILE" ]]; then
|
||||
CURRENT_STATE=$(read_state_file "$LOCAL_STATE_FILE" "state")
|
||||
@@ -265,6 +267,7 @@ cleanup_deployed_stack_locally() {
|
||||
--format '{{range .HostConfig.Binds}}{{println .}}{{end}}' \
|
||||
"$cname" 2>/dev/null | awk -F: '{print $1}' | grep '^/mnt/.*/appdata')
|
||||
timeout "${DOCKER_TIMEOUT:-30}" docker stop "$cname" >/dev/null 2>&1 || true
|
||||
_PM_TRAP_STOPPED+=("$cname")
|
||||
timeout "${DOCKER_TIMEOUT:-30}" docker rm "$cname" >/dev/null 2>&1 && \
|
||||
log " $cname removed ✅" || warn " $cname rm failed"
|
||||
else
|
||||
@@ -428,7 +431,7 @@ if [[ "$AM_MIRROR" == true ]]; then
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
write_state_file "$LOCAL_STATE_FILE" \
|
||||
"INACTIVE" "" "$NOW" "$LOCAL_SERVER_NAME" "$REASON"
|
||||
log "Local state: INACTIVE ✅"
|
||||
echo "Local state: INACTIVE ✅"
|
||||
add_to_blocklist "$OWNER" "$REASON"
|
||||
else
|
||||
warn "DRY RUN — would write INACTIVE state and blocklist $OWNER"
|
||||
@@ -626,7 +629,7 @@ fi
|
||||
if [[ ${#PARTNERSHIP_MIRROR_BACKUPS[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo "━━━ $ICON_DISK Backup Handover ━━━"
|
||||
log "Backups available for $MIRROR:"
|
||||
echo "Backups available for $MIRROR:"
|
||||
for path in "${PARTNERSHIP_MIRROR_BACKUPS[@]}"; do
|
||||
[[ -z "$path" ]] && continue
|
||||
echo " $path"
|
||||
|
||||
@@ -553,7 +553,7 @@ else
|
||||
deploy_xml_stack PARTNERSHIP_AUTH_STACK
|
||||
AUTH_DEPLOYED=$_STACK_DEPLOYED
|
||||
AUTH_FAILED=$_STACK_FAILED
|
||||
log "Auth stack: $AUTH_DEPLOYED deployed, $AUTH_FAILED failed"
|
||||
echo "Auth stack: $AUTH_DEPLOYED deployed, $AUTH_FAILED failed"
|
||||
[[ "$AUTH_FAILED" -gt 0 ]] && STEP_AUTH_OK=false
|
||||
fi
|
||||
|
||||
@@ -580,7 +580,7 @@ else
|
||||
deploy_xml_stack PARTNERSHIP_ARR_STACK
|
||||
ARR_DEPLOYED=$_STACK_DEPLOYED
|
||||
ARR_FAILED=$_STACK_FAILED
|
||||
log "Arr stack: $ARR_DEPLOYED deployed, $ARR_FAILED failed"
|
||||
echo "Arr stack: $ARR_DEPLOYED deployed, $ARR_FAILED failed"
|
||||
[[ "$ARR_FAILED" -gt 0 ]] && STEP_ARR_OK=false
|
||||
fi
|
||||
|
||||
@@ -589,7 +589,7 @@ echo ""
|
||||
echo "━━━ Step 7/8 — Partnership Onboard ━━━"
|
||||
|
||||
if bash "$SCRIPTS_ROOT/Partnership/partnership_manager.sh" --onboard "${EXTRA_FLAGS[@]}"; then
|
||||
log "Partnership onboard complete ✅"
|
||||
echo "Partnership onboard complete ✅"
|
||||
ONBOARD_OK=true
|
||||
else
|
||||
error "Partnership onboard failed"
|
||||
@@ -607,7 +607,7 @@ elif [[ "$SKIP_ARR_SYNC" == true ]]; then
|
||||
elif [[ ! -f "$SCRIPTS_ROOT/Media/arr_sync.sh" ]]; then
|
||||
warn "arr_sync.sh not found — run Media/arr_sync.sh manually once arrs are live"
|
||||
elif bash "$SCRIPTS_ROOT/Media/arr_sync.sh" "${EXTRA_FLAGS[@]}"; then
|
||||
log "Arr bootstrap complete ✅"
|
||||
echo "Arr bootstrap complete ✅"
|
||||
ARR_SYNC_OK=true
|
||||
else
|
||||
warn "Arr sync had errors — partnership still valid"
|
||||
@@ -637,8 +637,8 @@ echo ""
|
||||
|
||||
if [[ "$ONBOARD_OK" == true ]]; then
|
||||
[[ "$DRY_RUN" == true ]] && warn "DRY RUN — no changes made" || \
|
||||
log "$ICON_DONE DONE — partnership established ✅"
|
||||
log "Verify with: Partnership/partnership_manager.sh --status"
|
||||
echo "$ICON_DONE DONE — partnership established ✅"
|
||||
echo "Verify with: Partnership/partnership_manager.sh --status"
|
||||
else
|
||||
error "Setup incomplete — resolve errors above and re-run"
|
||||
fi
|
||||
|
||||
@@ -290,8 +290,8 @@ echo "━━━ $ICON_GEAR Key Generation ━━━"
|
||||
|
||||
if [[ -f "$SSH_KEY_PATH" ]] && [[ "$FORCE" == false ]]; then
|
||||
local_fp=$(ssh-keygen -lf "$SSH_KEY_PATH" 2>/dev/null || echo "unreadable")
|
||||
log "Key already exists — skipping generation (--force to regenerate)"
|
||||
log " $local_fp"
|
||||
echo "Key already exists — skipping generation (--force to regenerate)"
|
||||
echo " $local_fp"
|
||||
else
|
||||
if [[ "$FORCE" == true ]] && [[ -f "$SSH_KEY_PATH" ]]; then
|
||||
warn "Regenerating key (--force) — existing key will be replaced"
|
||||
@@ -339,7 +339,7 @@ else
|
||||
|
||||
if ssh-copy-id -i "$SSH_PUB_PATH" -o ConnectTimeout="${SSH_TIMEOUT:-15}" \
|
||||
root@"$REMOTE_SERVER" 2>/dev/null; then
|
||||
log "Public key installed on $REMOTE_SERVER_NAME ✅"
|
||||
echo "Public key installed on $REMOTE_SERVER_NAME ✅"
|
||||
else
|
||||
error "ssh-copy-id failed — check that:"
|
||||
error " 1. Remote server is reachable: tailscale status"
|
||||
@@ -355,7 +355,7 @@ echo "━━━ $ICON_VERIFY Verify SSH Auth ━━━"
|
||||
|
||||
if [[ "$DRY_RUN" == false ]]; then
|
||||
if test_ssh_auth "$REMOTE_SERVER"; then
|
||||
log "SSH auth to $REMOTE_SERVER_NAME working ✅"
|
||||
echo "SSH auth to $REMOTE_SERVER_NAME working ✅"
|
||||
# Reset any existing strikes
|
||||
if [[ -f "$SSH_STRIKE_FILE" ]]; then
|
||||
write_strike_file 0 "" "$(date '+%Y-%m-%d %H:%M:%S')"
|
||||
|
||||
Reference in New Issue
Block a user