Merge claude/2
This commit is contained in:
commit
f4ba7ffe51
@ -2,54 +2,74 @@
|
|||||||
|
|
||||||
webuiGenerateBackupAppStatus()
|
webuiGenerateBackupAppStatus()
|
||||||
{
|
{
|
||||||
local app_name="$1"
|
local app_name="${1:-}"
|
||||||
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated/apps"
|
local output_dir="$containers_dir/libreportal/frontend/data/backup/generated/apps"
|
||||||
runFileOp mkdir -p "$output_dir"
|
runFileOp mkdir -p "$output_dir"
|
||||||
|
|
||||||
if [[ -z "$app_name" ]]; then
|
# Resolve the app list: a single app (direct call — e.g. right after that
|
||||||
if [[ -f "$docker_dir/$db_file" ]]; then
|
# app's backup) or every installed app (routine WebUI refresh).
|
||||||
while IFS= read -r a; do
|
local apps=()
|
||||||
[[ -n "$a" ]] && webuiGenerateBackupAppStatus "$a"
|
if [[ -n "$app_name" ]]; then
|
||||||
done < <(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE status = 1;" 2>/dev/null)
|
apps=("$app_name")
|
||||||
fi
|
elif [[ -f "$docker_dir/$db_file" ]]; then
|
||||||
return 0
|
while IFS= read -r a; do
|
||||||
|
[[ -n "$a" ]] && apps+=("$a")
|
||||||
|
done < <(runInstallOp sqlite3 "$docker_dir/$db_file" "SELECT name FROM apps WHERE status = 1;" 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
|
[[ ${#apps[@]} -eq 0 ]] && return 0
|
||||||
|
|
||||||
local output_file="$output_dir/${app_name}.json"
|
# Fetch each enabled location's snapshot list ONCE, then filter per app
|
||||||
local temp_file="${output_file}.tmp.$$"
|
# in-process. A single `restic snapshots --json` returns the whole repo,
|
||||||
|
# so this replaces the old O(apps x locations) restic spawns with one
|
||||||
local content="{"
|
# restic call per location. jq reproduces restic's --tag/--host filtering.
|
||||||
content+="\"app\":\"$app_name\","
|
local host="${CFG_INSTALL_NAME}"
|
||||||
content+="\"generated_at\":\"$(date -Iseconds)\","
|
local loc_idxs=()
|
||||||
content+="\"host\":\"${CFG_INSTALL_NAME:-libreportal}\","
|
declare -A loc_name loc_snaps
|
||||||
content+="\"snapshots\":["
|
|
||||||
|
|
||||||
local first=true
|
|
||||||
local idx
|
local idx
|
||||||
while IFS= read -r idx; do
|
while IFS= read -r idx; do
|
||||||
[[ -z "$idx" ]] && continue
|
[[ -z "$idx" ]] && continue
|
||||||
local snaps
|
loc_idxs+=("$idx")
|
||||||
snaps=$(engineSnapshotsJson "$idx" "$app_name" "$CFG_INSTALL_NAME" 2>/dev/null)
|
loc_name["$idx"]=$(resticLocationName "$idx")
|
||||||
[[ -z "$snaps" || "$snaps" == "[]" ]] && continue
|
local raw
|
||||||
local count latest_id latest_time
|
raw=$(engineSnapshotsJson "$idx" 2>/dev/null)
|
||||||
count=$(echo "$snaps" | grep -o '"short_id"' | wc -l | tr -d ' ')
|
[[ -z "$raw" ]] && raw="[]"
|
||||||
latest_id=$(echo "$snaps" | grep -o '"short_id":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
loc_snaps["$idx"]="$raw"
|
||||||
latest_time=$(echo "$snaps" | grep -o '"time":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
|
||||||
|
|
||||||
local name_esc
|
|
||||||
name_esc=$(printf '%s' "$(resticLocationName "$idx")" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
|
||||||
|
|
||||||
$first || content+=","
|
|
||||||
first=false
|
|
||||||
content+="{"
|
|
||||||
content+="\"location_idx\":$idx,"
|
|
||||||
content+="\"location_name\":\"$name_esc\","
|
|
||||||
content+="\"count\":$count,"
|
|
||||||
content+="\"latest_id\":\"$latest_id\","
|
|
||||||
content+="\"latest_time\":\"$latest_time\""
|
|
||||||
content+="}"
|
|
||||||
done < <(resticEnabledLocations)
|
done < <(resticEnabledLocations)
|
||||||
content+="]}"
|
|
||||||
|
|
||||||
echo "$content" | runFileWrite "$output_file"
|
local app
|
||||||
|
for app in "${apps[@]}"; do
|
||||||
|
local content="{"
|
||||||
|
content+="\"app\":\"$app\","
|
||||||
|
content+="\"generated_at\":\"$(date -Iseconds)\","
|
||||||
|
content+="\"host\":\"${host:-libreportal}\","
|
||||||
|
content+="\"snapshots\":["
|
||||||
|
|
||||||
|
local first=true
|
||||||
|
for idx in "${loc_idxs[@]}"; do
|
||||||
|
local count latest_id latest_time
|
||||||
|
IFS=$'\t' read -r count latest_id latest_time <<<"$(printf '%s' "${loc_snaps[$idx]}" | jq -r \
|
||||||
|
--arg tag "app=$app" --arg host "$host" '
|
||||||
|
[ .[] | select($host=="" or .hostname==$host)
|
||||||
|
| select((.tags // []) | index($tag)) ] as $f
|
||||||
|
| ($f[-1] // {}) as $l
|
||||||
|
| "\($f|length)\t\($l.short_id // "")\t\($l.time // "")"' 2>/dev/null)"
|
||||||
|
[[ -z "$count" || "$count" == "0" ]] && continue
|
||||||
|
|
||||||
|
local name_esc
|
||||||
|
name_esc=$(printf '%s' "${loc_name[$idx]}" | sed 's/\\/\\\\/g; s/"/\\"/g')
|
||||||
|
|
||||||
|
$first || content+=","
|
||||||
|
first=false
|
||||||
|
content+="{"
|
||||||
|
content+="\"location_idx\":$idx,"
|
||||||
|
content+="\"location_name\":\"$name_esc\","
|
||||||
|
content+="\"count\":$count,"
|
||||||
|
content+="\"latest_id\":\"$latest_id\","
|
||||||
|
content+="\"latest_time\":\"$latest_time\""
|
||||||
|
content+="}"
|
||||||
|
done
|
||||||
|
content+="]}"
|
||||||
|
|
||||||
|
echo "$content" | runFileWrite "$output_dir/${app}.json"
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,11 +48,20 @@ webuiGenerateBackupDashboard()
|
|||||||
done < <(resticEnabledLocations)
|
done < <(resticEnabledLocations)
|
||||||
locations_json+="]"
|
locations_json+="]"
|
||||||
|
|
||||||
|
# Fetch the primary location's snapshots ONCE, then derive every app tile
|
||||||
|
# and the system-config status below by filtering it in jq — instead of a
|
||||||
|
# restic spawn per app plus one for system. jq reproduces restic's
|
||||||
|
# --tag/--host filtering (empty host = no host filter, as restic does).
|
||||||
|
local primary_idx primary_snaps="[]"
|
||||||
|
primary_idx=$(resticEnabledLocations | head -1)
|
||||||
|
if [[ -n "$primary_idx" ]]; then
|
||||||
|
primary_snaps=$(engineSnapshotsJson "$primary_idx" 2>/dev/null)
|
||||||
|
[[ -z "$primary_snaps" ]] && primary_snaps="[]"
|
||||||
|
fi
|
||||||
|
|
||||||
local apps_json="["
|
local apps_json="["
|
||||||
first=true
|
first=true
|
||||||
if [[ -f "$docker_dir/$db_file" ]]; then
|
if [[ -f "$docker_dir/$db_file" ]]; then
|
||||||
local primary_idx
|
|
||||||
primary_idx=$(resticEnabledLocations | head -1)
|
|
||||||
while IFS= read -r app; do
|
while IFS= read -r app; do
|
||||||
[[ -z "$app" ]] && continue
|
[[ -z "$app" ]] && continue
|
||||||
# The WebUI app is reproducible and skipped by backupAllApps — its
|
# The WebUI app is reproducible and skipped by backupAllApps — its
|
||||||
@ -60,12 +69,11 @@ webuiGenerateBackupDashboard()
|
|||||||
# perpetually-"No backup yet" tile for it.
|
# perpetually-"No backup yet" tile for it.
|
||||||
[[ "$app" == "libreportal" ]] && continue
|
[[ "$app" == "libreportal" ]] && continue
|
||||||
local latest_id="" latest_time=""
|
local latest_id="" latest_time=""
|
||||||
if [[ -n "$primary_idx" ]]; then
|
IFS=$'\t' read -r latest_id latest_time <<<"$(printf '%s' "$primary_snaps" | jq -r \
|
||||||
local snap_json
|
--arg tag "app=$app" --arg host "$CFG_INSTALL_NAME" '
|
||||||
snap_json=$(engineSnapshotsJson "$primary_idx" "$app" "$CFG_INSTALL_NAME" 2>/dev/null)
|
[ .[] | select($host=="" or .hostname==$host)
|
||||||
latest_id=$(echo "$snap_json" | grep -o '"short_id":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
| select((.tags // []) | index($tag)) ] | (.[-1] // {})
|
||||||
latest_time=$(echo "$snap_json" | grep -o '"time":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
| "\(.short_id // "")\t\(.time // "")"' 2>/dev/null)"
|
||||||
fi
|
|
||||||
$first || apps_json+=","
|
$first || apps_json+=","
|
||||||
first=false
|
first=false
|
||||||
apps_json+="{\"app\":\"$app\",\"latest_snapshot\":\"$latest_id\",\"latest_time\":\"$latest_time\"}"
|
apps_json+="{\"app\":\"$app\",\"latest_snapshot\":\"$latest_id\",\"latest_time\":\"$latest_time\"}"
|
||||||
@ -75,14 +83,11 @@ webuiGenerateBackupDashboard()
|
|||||||
|
|
||||||
# System-config backup status (tag system=config) — its own tracked item.
|
# System-config backup status (tag system=config) — its own tracked item.
|
||||||
local system_id="" system_time=""
|
local system_id="" system_time=""
|
||||||
local sys_idx
|
IFS=$'\t' read -r system_id system_time <<<"$(printf '%s' "$primary_snaps" | jq -r \
|
||||||
sys_idx=$(resticEnabledLocations | head -1)
|
--arg tag "system=config" --arg host "$CFG_INSTALL_NAME" '
|
||||||
if [[ -n "$sys_idx" ]]; then
|
[ .[] | select($host=="" or .hostname==$host)
|
||||||
local sys_json
|
| select((.tags // []) | index($tag)) ] | (.[-1] // {})
|
||||||
sys_json=$(engineSystemSnapshotsJson "$sys_idx" "$CFG_INSTALL_NAME" 2>/dev/null)
|
| "\(.short_id // "")\t\(.time // "")"' 2>/dev/null)"
|
||||||
system_id=$(echo "$sys_json" | grep -o '"short_id":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
|
||||||
system_time=$(echo "$sys_json" | grep -o '"time":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
|
||||||
fi
|
|
||||||
|
|
||||||
local content="{"
|
local content="{"
|
||||||
content+="\"generated_at\":\"$generated_at\","
|
content+="\"generated_at\":\"$generated_at\","
|
||||||
|
|||||||
@ -89,15 +89,18 @@ webuiGenerateBackupMigrate()
|
|||||||
local app
|
local app
|
||||||
while IFS= read -r app; do
|
while IFS= read -r app; do
|
||||||
[[ -z "$app" ]] && continue
|
[[ -z "$app" ]] && continue
|
||||||
local app_snaps_json
|
# Filter the location's already-fetched snapshot list in-process
|
||||||
app_snaps_json=$(engineSnapshotsJson "$idx" "$app" "$host" 2>/dev/null)
|
# (jq == restic --tag/--host) rather than a restic spawn per
|
||||||
local count
|
# (host, app). Also gives an accurate count — the old grep -oc
|
||||||
count=$(printf '%s' "$app_snaps_json" | grep -oc '"short_id":"' || echo 0)
|
# over single-line JSON always reported 1.
|
||||||
(( count == 0 )) && continue
|
local count latest_id latest_date
|
||||||
|
IFS=$'\t' read -r count latest_id latest_date <<<"$(printf '%s' "$all_json" | jq -r \
|
||||||
local latest_id latest_date
|
--arg tag "app=$app" --arg host "$host" '
|
||||||
latest_id=$(printf '%s' "$app_snaps_json" | grep -o '"short_id":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
[ .[] | select($host=="" or .hostname==$host)
|
||||||
latest_date=$(printf '%s' "$app_snaps_json" | grep -o '"time":"[^"]*"' | tail -1 | cut -d'"' -f4)
|
| select((.tags // []) | index($tag)) ] as $f
|
||||||
|
| ($f[-1] // {}) as $l
|
||||||
|
| "\($f|length)\t\($l.short_id // "")\t\($l.time // "")"' 2>/dev/null)"
|
||||||
|
[[ -z "$count" || "$count" == "0" ]] && continue
|
||||||
|
|
||||||
local opt_out
|
local opt_out
|
||||||
opt_out=$(migrateUrlRewriteEnabled "$app" 2>/dev/null)
|
opt_out=$(migrateUrlRewriteEnabled "$app" 2>/dev/null)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user