LibrePortal/scripts/cli/commands/backup/cli_backup_commands.sh
librelad 3f582120ba feat(cli): route all long-running app + update commands through tasks
Extends the install-routing spike (e5273a4) to every long-running CLI
command, so CLI and WebUI now share one execution path everywhere:

  app install      ← already done
  app uninstall
  app start / stop / restart / up / down / reload
  app backup
  app restore
  update apply
  backup app create   (matches `app backup` — same end target)

Each handler now has the same shape:
  if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
      <inline call>            # processor's recursive invocation
  else
      cliTaskRun "<cmd>" <type> <app>   # user invocation: enqueue + follow
  fi

Processor change — crontab_task_processor.sh:
  Adds `export LIBREPORTAL_TASK_EXEC=1` next to LIBREPORTAL_NONINTERACTIVE.
  Universal bypass: every task command the processor runs (CLI-queued OR
  pre-existing WebUI-queued like `libreportal app install adguard`)
  inherits the env var, so the inline branch fires and we never
  re-enqueue. This also lets us drop the env-var prefix the install spike
  was baking into the command string (e5273a4) — cleaner task files +
  one place to think about the bypass.

`backup app schedule` (the cron-driven path that already enqueues via
createTaskFile in backup_app_schedule.sh) is left alone — different
entry point, different runtime context, already correctly task-routed.

Why route the fast ones too (start/stop/restart/up/down):
  Consistency beats the ~1s task-roundtrip latency for a CLI button.
  Locking now serialises a CLI `app stop foo` against a WebUI restart of
  the same app; the audit trail covers every state change. Cheap to
  revert any individually if the latency turns out to bother someone.

Validated live earlier with `libreportal app install dashy` — task file
written, processor dispatched, follower streamed install live, exit 0
propagated. Same machinery now powers the other 9 handlers.

Signed-off-by: librelad <librelad@digitalangels.vip>
2026-05-27 14:38:14 +01:00

123 lines
4.9 KiB
Bash
Executable File

#!/bin/bash
cliHandleBackupCommands()
{
local backup_type="$initial_command2"
local action="$initial_command3"
local name="$initial_command4"
local extra="$initial_command5"
local extra2="$initial_command6"
if [[ -z "$backup_type" ]]; then
cliShowBackupHelp
return
fi
case "$backup_type" in
app)
case "$action" in
""|help) cliShowBackupHelp ;;
create)
[[ -z "$name" ]] && { isNotice "No app name provided."; cliShowBackupHelp; return; }
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
backupAppStart "$name"
else
cliTaskRun "libreportal backup app create $name" "backup" "$name"
fi
;;
schedule)
[[ -z "$name" ]] && { isNotice "No app name provided."; cliShowBackupHelp; return; }
backupAppSchedule "$name"
;;
delete)
[[ -z "$name" ]] && { isNotice "No app name provided."; cliShowBackupHelp; return; }
[[ -z "$extra" ]] && { isNotice "No <location_idx>:<snapshot_id> provided (e.g. 1:abc123)."; cliShowBackupHelp; return; }
local idx="${extra%%:*}"
local snap="${extra##*:}"
backupAppDeleteSnapshot "$idx" "$snap"
;;
delete_all)
[[ -z "$name" ]] && { isNotice "No app name provided."; cliShowBackupHelp; return; }
backupAppDeleteAll "$name"
;;
list)
[[ -z "$name" ]] && { isNotice "No app name provided."; cliShowBackupHelp; return; }
local idx
while IFS= read -r idx; do
[[ -z "$idx" ]] && continue
echo "--- $(resticLocationName "$idx") (loc $idx) ---"
engineSnapshotsJson "$idx" "$name"
done < <(resticEnabledLocations)
;;
*)
isNotice "Invalid app backup action: $action"
cliShowBackupHelp
;;
esac
;;
all)
backupAllApps
;;
system)
backupSystemConfig
;;
scheduled)
backupScheduleEnabledApps
;;
location)
case "$action" in
add)
[[ -z "$name" ]] && { isNotice "Usage: backup location add <name> [type]"; cliShowBackupHelp; return; }
locationAdd "$name" "$extra"
;;
remove)
[[ -z "$name" ]] && { isNotice "Usage: backup location remove <idx>"; cliShowBackupHelp; return; }
locationRemove "$name" "$extra"
;;
list)
local idx
while IFS= read -r idx; do
[[ -z "$idx" ]] && continue
local enabled="no"; resticLocationEnabled "$idx" && enabled="yes"
echo "[$idx] $(resticLocationName "$idx") — type=$(resticLocationType "$idx"), enabled=$enabled"
done < <(resticAllLocationIndices)
;;
init)
engineInitAllLocations
;;
check)
engineCheckAllLocations "${name:-5}"
;;
stats)
[[ -z "$name" ]] && name="1"
engineLocationStats "$name"
;;
ssh-key-set)
[[ -z "$name" || -z "$extra" ]] && { isNotice "Usage: backup location ssh-key-set <idx> <base64-key>"; return; }
backupSshKeySet "$name" "$extra"
;;
ssh-key-generate)
[[ -z "$name" ]] && { isNotice "Usage: backup location ssh-key-generate <idx>"; return; }
backupSshKeyGenerate "$name"
;;
ssh-key-public)
[[ -z "$name" ]] && { isNotice "Usage: backup location ssh-key-public <idx>"; return; }
backupSshKeyPublic "$name"
;;
ssh-key-delete)
[[ -z "$name" ]] && { isNotice "Usage: backup location ssh-key-delete <idx>"; return; }
backupSshKeyDelete "$name"
;;
*) isNotice "Invalid location action: $action"; cliShowBackupHelp ;;
esac
;;
verify)
engineCheckAllLocations "${action:-5}"
;;
*)
isNotice "Invalid backup type: $backup_type"
cliShowBackupHelp
;;
esac
}