diff --git a/clanModules/borgbackup.nix b/clanModules/borgbackup.nix index 8350b3cc..feba43c4 100644 --- a/clanModules/borgbackup.nix +++ b/clanModules/borgbackup.nix @@ -67,11 +67,11 @@ in clanCore.backups.providers.borgbackup = { list = '' - ssh ${config.clan.networking.deploymentAddress} -- ' + ssh ${config.clan.networking.deploymentAddress} < list[dict[str def list_command(args: argparse.Namespace) -> None: machine = Machine(name=args.machine, flake_dir=args.flake) backups_data = list_backups(machine=machine, provider=args.provider) - print(list(backups_data)) + print(json.dumps(list(backups_data))) def register_list_parser(parser: argparse.ArgumentParser) -> None: diff --git a/pkgs/clan-cli/clan_cli/backups/restore.py b/pkgs/clan-cli/clan_cli/backups/restore.py index 6769a01f..f50827ab 100644 --- a/pkgs/clan-cli/clan_cli/backups/restore.py +++ b/pkgs/clan-cli/clan_cli/backups/restore.py @@ -1,32 +1,67 @@ import argparse -from pathlib import Path +import json +import os +import subprocess +from typing import Any from ..errors import ClanError +from ..machines.machines import Machine +from .list import list_backups def restore_backup( - flake_dir: Path, - machine: str, + backup_data: list[dict[str, Any]], + machine: Machine, provider: str, - backup_id: str, + archive_id: str, service: str | None = None, ) -> None: + backup_scripts = json.loads( + machine.eval_nix(f"nixosConfigurations.{machine.name}.config.clanCore.backups") + ) + backup_folders = json.loads( + machine.eval_nix(f"nixosConfigurations.{machine.name}.config.clanCore.state") + ) if service is None: - print("would restore backup", machine, provider, backup_id) + for backup in backup_data: + for archive in backup["archives"]: + if archive["archive"] == archive_id: + env = os.environ.copy() + env["ARCHIVE_ID"] = archive_id + env["LOCATION"] = backup["repository"]["location"] + env["JOB"] = backup["job-name"] + proc = subprocess.run( + [ + "bash", + "-c", + backup_scripts["providers"][provider]["restore"], + ], + stdout=subprocess.PIPE, + env=env, + ) + if proc.returncode != 0: + # TODO this should be a warning, only raise exception if no providers succeed + raise ClanError("failed to restore backup") else: print( - "would restore backup", machine, provider, backup_id, "of service:", service + "would restore backup", + machine, + provider, + archive_id, + "of service:", + service, ) + print(backup_folders) def restore_command(args: argparse.Namespace) -> None: - if args.flake is None: - raise ClanError("Could not find clan flake toplevel directory") + machine = Machine(name=args.machine, flake_dir=args.flake) + backup_data = list_backups(machine=machine, provider=args.provider) restore_backup( - Path(args.flake), - machine=args.machine, + backup_data=backup_data, + machine=machine, provider=args.provider, - backup_id=args.backup_id, + archive_id=args.archive_id, service=args.service, ) @@ -36,6 +71,6 @@ def register_restore_parser(parser: argparse.ArgumentParser) -> None: "machine", type=str, help="machine in the flake to create backups of" ) parser.add_argument("provider", type=str, help="backup provider to use") - parser.add_argument("backup_id", type=str, help="id of the backup to restore") + parser.add_argument("archive_id", type=str, help="id of the backup to restore") parser.add_argument("--service", type=str, help="name of the service to restore") parser.set_defaults(func=restore_command)