#!/usr/bin/env bash set -euo pipefail API_URL="${API_URL:-http://127.0.0.1:8080}" INTEGRATION_VMID="${INTEGRATION_VMID:-}" INTEGRATION_GUEST_NAME="${INTEGRATION_GUEST_NAME:-}" INTEGRATION_STORAGE="${INTEGRATION_STORAGE:-}" INTEGRATION_LOCAL_BACKUP_DIR="${INTEGRATION_LOCAL_BACKUP_DIR:-}" INTEGRATION_CRON="${INTEGRATION_CRON:-0 3 * * *}" INTEGRATION_RETENTION_TYPE="${INTEGRATION_RETENTION_TYPE:-latest}" INTEGRATION_RETENTION_VALUE="${INTEGRATION_RETENTION_VALUE:-1}" INTEGRATION_RUN_NOW="${INTEGRATION_RUN_NOW:-1}" if [[ -z "$INTEGRATION_VMID" ]]; then echo "Set INTEGRATION_VMID to the Proxmox VMID/LXC ID to test." >&2 echo "Example:" >&2 echo " INTEGRATION_VMID=110 INTEGRATION_STORAGE=local API_URL=http://127.0.0.1:8080 $0" >&2 exit 1 fi python3 - "$API_URL" \ "$INTEGRATION_VMID" \ "$INTEGRATION_GUEST_NAME" \ "$INTEGRATION_STORAGE" \ "$INTEGRATION_LOCAL_BACKUP_DIR" \ "$INTEGRATION_CRON" \ "$INTEGRATION_RETENTION_TYPE" \ "$INTEGRATION_RETENTION_VALUE" \ "$INTEGRATION_RUN_NOW" <<'PY' import json import sys import urllib.error import urllib.request api = sys.argv[1].rstrip("/") vmid = int(sys.argv[2]) expected_name = sys.argv[3] or None storage_override = sys.argv[4] or None expected_local_dir = sys.argv[5] or None cron = sys.argv[6] retention_type = sys.argv[7] retention_value = int(sys.argv[8]) run_now = sys.argv[9] == "1" def request(method, path, body=None): data = None if body is None else json.dumps(body).encode() req = urllib.request.Request( api + path, data=data, method=method, headers={"Content-Type": "application/json"}, ) try: with urllib.request.urlopen(req, timeout=30) as res: return json.loads(res.read().decode()) except urllib.error.HTTPError as exc: raise SystemExit(f"{method} {path} failed: {exc.code} {exc.read().decode()}") from exc settings = request("GET", "/api/settings") if not settings.get("setup_complete"): raise SystemExit("Setup is not complete. Configure the app before running integration tests.") if expected_local_dir and settings.get("local_backup_dir") != expected_local_dir: raise SystemExit( f"Expected configured local backup directory to be {expected_local_dir!r}, " f"found {settings.get('local_backup_dir')!r}" ) guests = request("GET", "/api/guests") guest = next((g for g in guests if int(g["vmid"]) == vmid), None) if not guest: raise SystemExit(f"Expected Proxmox guest with VMID {vmid}") if expected_name and guest.get("name") != expected_name: raise SystemExit(f"Expected guest {vmid} to be named {expected_name!r}, found {guest.get('name')!r}") storage = storage_override or settings["proxmox_storage"] job = request("POST", "/api/jobs", { "guest_vmid": vmid, "guest_name": guest["name"], "guest_type": guest["type"], "node": guest["node"], "enabled": False, "cron_schedule": cron, "proxmox_storage": storage, "backup_mode": settings["default_backup_mode"], "compression": settings["default_compression"], "retention_type": retention_type, "retention_value": retention_value, }) result = {"job": job} if run_now: result["queued_backup"] = request("POST", f"/api/jobs/{job['id']}/run") print(json.dumps(result, indent=2)) print(f"Created integration job for VMID {vmid} using storage {storage!r}.") if run_now: print("Queued the job immediately. Watch Backup history or worker logs for completion.") else: print("Did not queue the job because INTEGRATION_RUN_NOW is not 1.") PY