rework backup interface to no longer need to list backups to restore them

This commit is contained in:
Jörg Thalheim 2024-03-20 07:13:01 +01:00
parent f5d32d0b22
commit 92ac151292
3 changed files with 16 additions and 38 deletions

View File

@ -15,7 +15,7 @@ in
{
options = {
name = lib.mkOption {
type = lib.types.str;
type = lib.types.strMatching "^[a-zA-Z0-9._-]+$";
default = name;
description = "the name of the backup job";
};
@ -96,11 +96,11 @@ in
# TODO list needs to run locally or on the remote machine
list = ''
set -efu
# we need yes here to skip the changed url verification
(${
lib.concatMapStringsSep "\n" (
dest:
''yes y | borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.repo}::" + .name), "job_name": "${dest.name}"}]' ''
# we need yes here to skip the changed url verification
''yes y | borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.name}::${dest.repo}::" + .name)}]' ''
) (lib.attrValues cfg.destinations)
}) | jq -s 'add'
'';
@ -114,7 +114,8 @@ in
set -efu
cd /
IFS=';' read -ra FOLDER <<< "$FOLDERS"
yes y | borg-job-"$JOB_NAME" extract --list "$NAME" "''${FOLDER[@]}"
job_name=$(echo "$NAME" | cut -d'::' -f1)
yes y | borg-job-"$job_name" extract --list "$NAME" "''${FOLDER[@]}"
'';
};
};

View File

@ -18,25 +18,21 @@
list = lib.mkOption {
type = lib.types.str;
description = ''
script to list backups
Command to list backups.
'';
};
restore = lib.mkOption {
type = lib.types.str;
description = ''
script to restore a backup
should take an optional service name as argument
gets ARCHIVE_ID, LOCATION, JOB and FOLDERS as environment variables
ARCHIVE_ID is the id of the backup
LOCATION is the remote identifier of the backup
JOB is the job name of the backup
FOLDERS is a colon separated list of folders to restore
Command to restore a backup.
The name of the backup and the folders to restore will be
set as environment variables NAME and FOLDERS respectively.
'';
};
create = lib.mkOption {
type = lib.types.str;
description = ''
script to start a backup
Command to start a backup
'';
};
};

View File

@ -4,22 +4,16 @@ import subprocess
from ..errors import ClanError
from ..machines.machines import Machine
from .list import Backup, list_backups
def restore_service(
machine: Machine, backup: Backup, provider: str, service: str
) -> None:
def restore_service(machine: Machine, name: str, provider: str, service: str) -> None:
backup_metadata = json.loads(machine.eval_nix("config.clanCore.backups"))
backup_folders = json.loads(machine.eval_nix("config.clanCore.state"))
folders = backup_folders[service]["folders"]
env = {}
env["NAME"] = backup.name
env["NAME"] = name
env["FOLDERS"] = ":".join(folders)
if backup.job_name is not None:
env["JOB_NAME"] = backup.job_name
proc = machine.target_host.run(
[
"bash",
@ -65,35 +59,22 @@ def restore_service(
def restore_backup(
machine: Machine,
backups: list[Backup],
provider: str,
name: str,
service: str | None = None,
) -> None:
if service is None:
for backup in backups:
if backup.name == name:
backup_folders = json.loads(machine.eval_nix("config.clanCore.state"))
for _service in backup_folders:
restore_service(machine, backup, provider, _service)
break
else:
raise ClanError(f"backup {name} not found")
backup_folders = json.loads(machine.eval_nix("config.clanCore.state"))
for _service in backup_folders:
restore_service(machine, name, provider, _service)
else:
for backup in backups:
if backup.name == name:
restore_service(machine, backup, provider, service)
break
else:
raise ClanError(f"backup {name} not found")
restore_service(machine, name, provider, service)
def restore_command(args: argparse.Namespace) -> None:
machine = Machine(name=args.machine, flake=args.flake)
backups = list_backups(machine=machine, provider=args.provider)
restore_backup(
machine=machine,
backups=backups,
provider=args.provider,
name=args.name,
service=args.service,