From 92ac151292ac03d22321a8e1fb8cdf8620e9ad33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Wed, 20 Mar 2024 07:13:01 +0100 Subject: [PATCH] rework backup interface to no longer need to list backups to restore them --- clanModules/borgbackup.nix | 9 ++++--- nixosModules/clanCore/backups.nix | 14 ++++------ pkgs/clan-cli/clan_cli/backups/restore.py | 31 +++++------------------ 3 files changed, 16 insertions(+), 38 deletions(-) diff --git a/clanModules/borgbackup.nix b/clanModules/borgbackup.nix index 02a05740..7b5ffb16 100644 --- a/clanModules/borgbackup.nix +++ b/clanModules/borgbackup.nix @@ -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[@]}" ''; }; }; diff --git a/nixosModules/clanCore/backups.nix b/nixosModules/clanCore/backups.nix index 06a43744..3f483cba 100644 --- a/nixosModules/clanCore/backups.nix +++ b/nixosModules/clanCore/backups.nix @@ -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 ''; }; }; diff --git a/pkgs/clan-cli/clan_cli/backups/restore.py b/pkgs/clan-cli/clan_cli/backups/restore.py index fcbbd399..4907acd7 100644 --- a/pkgs/clan-cli/clan_cli/backups/restore.py +++ b/pkgs/clan-cli/clan_cli/backups/restore.py @@ -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,