The Services tab restart button POSTed to a backend endpoint that (a) checked the app's compose path from INSIDE the webui container, where the host's containers root isn't mounted — so every restart failed with 'Compose file not found' — and (b) queued a raw 'docker compose restart' that the host task processor would run as the manager user, which can't talk to the rootless daemon anyway. Errors surfaced via a bare alert(). Per-service restart now follows the exact shape of the whole-app verbs: - CLI: 'libreportal app restart <app> [service]' — the optional service arg makes dockerRestartApp restart just that compose service, via dockerCommandRun (right user in rootless mode) from the app dir on the host, where the compose file actually lives. Service names validated against compose-legal characters before touching a shell line. - WebUI: the button dispatches a 'service_restart' task action through the task router (mutations-via-tasks), runs in the background with the standard task toast + link — no page switch — and failures use the notification system instead of alert(). Because the task runs host- side, restarting the WebUI's own libreportal-service now works too. - Backend: the mutating restart endpoint and its now-unused helpers are removed; service-routes.js is read-only surface (status + log tails). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: librelad <librelad@digitalangels.vip>
192 lines
7.2 KiB
Bash
Executable File
192 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# App Commands Handler
|
|
# Handles all app subcommands by calling core functions
|
|
|
|
cliHandleAppCommands()
|
|
{
|
|
local action="$initial_command2"
|
|
local app_name="$initial_command3"
|
|
local config="$initial_command4"
|
|
local restore_arg2="$initial_command4"
|
|
local restore_arg3="$initial_command5"
|
|
local restore_arg4="$initial_command6"
|
|
local tool_name="$initial_command4"
|
|
local tool_args="$initial_command5"
|
|
|
|
local reset_network="false"
|
|
if [[ "$config" == "--reset-network" ]]; then
|
|
reset_network="true"
|
|
config=""
|
|
elif [[ "$initial_command5" == "--reset-network" ]]; then
|
|
reset_network="true"
|
|
fi
|
|
|
|
case "$action" in
|
|
"list")
|
|
if [[ -z "$app_name" ]]; then
|
|
cliShowAppHelp
|
|
elif [ "$app_name" = "available" ]; then
|
|
appScanAvailable
|
|
elif [ "$app_name" = "installed" ]; then
|
|
databaseListInstalledApps
|
|
else
|
|
isNotice "Invalid list type: $app_name"
|
|
cliShowAppHelp
|
|
fi
|
|
;;
|
|
|
|
"install")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerInstallApp "$app_name" "$config" "$reset_network"
|
|
else
|
|
local _mode=""
|
|
for _arg in "$config" "$initial_command5" "$initial_command6"; do
|
|
[[ "$_arg" == "--detach" ]] && _mode="--detach"
|
|
done
|
|
# config / --reset-network passthrough — strip CLI-only
|
|
# flags, keep what dockerInstallApp expects.
|
|
local _passthrough_config="$config"
|
|
[[ "$_passthrough_config" == "--detach" || "$_passthrough_config" == "--reset-network" ]] && _passthrough_config=""
|
|
local _cmd="libreportal app install $app_name"
|
|
[[ -n "$_passthrough_config" ]] && _cmd+=" '$_passthrough_config'"
|
|
[[ "$reset_network" == "true" ]] && _cmd+=" --reset-network"
|
|
cliTaskRun "$_cmd" "install" "$app_name" "$_mode"
|
|
fi
|
|
;;
|
|
|
|
"uninstall")
|
|
# Optional `--delete-images` flag (in any of the trailing
|
|
# positions) tells the uninstall to also remove the app's
|
|
# docker images. Default behaviour: keep them so a reinstall
|
|
# is fast and offline-friendly.
|
|
local _del_images="false"
|
|
local _del_tasks="false"
|
|
local _u_mode=""
|
|
for _arg in "$config" "$initial_command5" "$initial_command6" "$initial_command7"; do
|
|
[[ "$_arg" == "--delete-images" ]] && _del_images="true"
|
|
[[ "$_arg" == "--delete-tasks" ]] && _del_tasks="true"
|
|
[[ "$_arg" == "--detach" ]] && _u_mode="--detach"
|
|
done
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerUninstallApp "$app_name" "$_del_images" "$_del_tasks"
|
|
else
|
|
local _cmd="libreportal app uninstall $app_name"
|
|
[[ "$_del_images" == "true" ]] && _cmd+=" --delete-images"
|
|
[[ "$_del_tasks" == "true" ]] && _cmd+=" --delete-tasks"
|
|
cliTaskRun "$_cmd" "uninstall" "$app_name" "$_u_mode"
|
|
fi
|
|
;;
|
|
|
|
"start")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerStartApp "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app start $app_name" "start" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"stop")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerStopApp "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app stop $app_name" "stop" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"restart")
|
|
# Optional 4th arg = one compose service to restart instead of the
|
|
# whole app (the WebUI Services tab routes per-service restarts
|
|
# here): libreportal app restart <app> [service]
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerRestartApp "$app_name" "$config"
|
|
else
|
|
cliTaskRun "libreportal app restart $app_name${config:+ $config}" "restart" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"up")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerComposeUp "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app up $app_name" "up" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"down")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerComposeDown "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app down $app_name" "down" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"reload")
|
|
if [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
dockerRestartAppViaInstall "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app reload $app_name" "reload" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"backup")
|
|
if [[ -z "$app_name" ]]; then
|
|
isNotice "No app provided."
|
|
cliShowAppHelp
|
|
elif [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
backupAppStart "$app_name"
|
|
else
|
|
cliTaskRun "libreportal app backup $app_name" "backup" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"restore")
|
|
if [[ -z "$app_name" ]]; then
|
|
isNotice "No app provided."
|
|
cliShowAppHelp
|
|
elif [[ "$LIBREPORTAL_TASK_EXEC" == "1" ]]; then
|
|
cliAppRestore "$app_name" "$restore_arg2" "$restore_arg3" "$restore_arg4"
|
|
else
|
|
# Pass the positional args through verbatim. They may
|
|
# include local|remote1|… selector, filename, password —
|
|
# quote each to survive shell re-parse in the processor.
|
|
local _cmd="libreportal app restore $app_name"
|
|
for _a in "$restore_arg2" "$restore_arg3" "$restore_arg4"; do
|
|
[[ -n "$_a" ]] && _cmd+=" '$_a'"
|
|
done
|
|
cliTaskRun "$_cmd" "restore" "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"status")
|
|
if [[ -z "$app_name" ]]; then
|
|
isNotice "No app provided."
|
|
cliShowAppHelp
|
|
else
|
|
appStatus "$app_name"
|
|
fi
|
|
;;
|
|
|
|
"tool")
|
|
# `libreportal app tool list [<app>]` — discover available tools.
|
|
# When the second arg is the literal `list`, the third is treated
|
|
# as an optional app filter. Otherwise the standard run shape
|
|
# applies: `libreportal app tool <app> <tool_id> [args]`.
|
|
if [[ "$app_name" == "list" ]]; then
|
|
cliAppToolList "$tool_name"
|
|
elif [[ -z "$app_name" || -z "$tool_name" ]]; then
|
|
isNotice "Usage: libreportal app tool <app_name> <tool_name> [args]"
|
|
isNotice " libreportal app tool list [<app_name>]"
|
|
cliShowAppHelp
|
|
else
|
|
dockerAppRunTool "$app_name" "$tool_name" "$tool_args"
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
isNotice "Invalid app command: $action"
|
|
cliShowAppHelp
|
|
;;
|
|
esac
|
|
}
|