mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-06-11 19:07:01 +00:00
99 lines
3.4 KiB
Bash
99 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
# ==========================================================
|
|
# ProxMenux backup restore — manifest reader
|
|
# ==========================================================
|
|
# Reads the JSON manifest from a ProxMenux host backup. Supports:
|
|
# - A loose manifest.json file path
|
|
# - A backup archive (.tar.gz / .tar.zst / .tar)
|
|
# - A pre-extracted backup directory
|
|
#
|
|
# Emits the manifest's `proxmenux_backup_manifest` sub-object as
|
|
# JSON to stdout (i.e. unwraps the top-level key) so downstream
|
|
# scripts can use `jq '.source_host'` directly. Exit 0 on success,
|
|
# non-zero with a message on stderr if the manifest can't be found.
|
|
#
|
|
# Usage:
|
|
# parse_manifest.sh <archive-or-dir-or-manifest> [--with-wrapper]
|
|
#
|
|
# --with-wrapper keeps the outer { proxmenux_backup_manifest: { ... } }
|
|
# wrap (useful when piping to jsonschema validation).
|
|
# ==========================================================
|
|
set -euo pipefail
|
|
|
|
SOURCE="${1:-}"
|
|
KEEP_WRAPPER=0
|
|
shift || true
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--with-wrapper) KEEP_WRAPPER=1 ;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [[ -z "$SOURCE" ]]; then
|
|
printf 'parse_manifest: missing source path\n' >&2
|
|
exit 64
|
|
fi
|
|
|
|
# Locate the manifest. Three input shapes:
|
|
manifest_json=""
|
|
case "$SOURCE" in
|
|
*.tar.gz|*.tgz|*.tar.zst|*.tar)
|
|
# Archive — extract just the manifest entry to stdout. We tolerate
|
|
# the manifest sitting at the root OR under any meta/ subdirectory.
|
|
extractor=()
|
|
case "$SOURCE" in
|
|
*.tar.zst) extractor=(zstd -d --long=27 -c "$SOURCE") ;;
|
|
*.tar.gz|*.tgz) extractor=(gzip -dc "$SOURCE") ;;
|
|
*.tar) extractor=(cat "$SOURCE") ;;
|
|
esac
|
|
# Use --wildcards so the manifest is found at any depth. We extract
|
|
# to stdout and stop at the first match.
|
|
if ! manifest_json="$("${extractor[@]}" | tar -xO --wildcards '*manifest.json' 2>/dev/null | head -c 4194304)"; then
|
|
printf 'parse_manifest: no manifest.json found inside %s\n' "$SOURCE" >&2
|
|
exit 65
|
|
fi
|
|
;;
|
|
*)
|
|
if [[ -f "$SOURCE" ]]; then
|
|
manifest_json="$(cat "$SOURCE")"
|
|
elif [[ -d "$SOURCE" ]]; then
|
|
# Pre-extracted directory — try common paths first, then a search.
|
|
for candidate in "$SOURCE/manifest.json" "$SOURCE/meta/manifest.json"; do
|
|
if [[ -f "$candidate" ]]; then
|
|
manifest_json="$(cat "$candidate")"; break
|
|
fi
|
|
done
|
|
if [[ -z "$manifest_json" ]]; then
|
|
found="$(find "$SOURCE" -maxdepth 3 -name 'manifest.json' -print -quit 2>/dev/null || true)"
|
|
[[ -n "$found" ]] && manifest_json="$(cat "$found")"
|
|
fi
|
|
if [[ -z "$manifest_json" ]]; then
|
|
printf 'parse_manifest: no manifest.json under %s\n' "$SOURCE" >&2
|
|
exit 65
|
|
fi
|
|
else
|
|
printf 'parse_manifest: %s is neither archive, dir, nor file\n' "$SOURCE" >&2
|
|
exit 66
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Verify it's at least valid JSON before unwrapping.
|
|
if ! printf '%s' "$manifest_json" | jq -e 'type == "object"' >/dev/null 2>&1; then
|
|
printf 'parse_manifest: contents are not a JSON object\n' >&2
|
|
exit 67
|
|
fi
|
|
|
|
# Check the wrapper key is present.
|
|
if ! printf '%s' "$manifest_json" | jq -e '.proxmenux_backup_manifest' >/dev/null 2>&1; then
|
|
printf 'parse_manifest: missing proxmenux_backup_manifest key (not a ProxMenux manifest?)\n' >&2
|
|
exit 68
|
|
fi
|
|
|
|
if [[ "$KEEP_WRAPPER" == 1 ]]; then
|
|
printf '%s' "$manifest_json"
|
|
else
|
|
printf '%s' "$manifest_json" | jq '.proxmenux_backup_manifest'
|
|
fi
|