1
0
forked from clan/clan-core

backups: no longer interpret backup interface as bash commands

This commit is contained in:
Jörg Thalheim 2024-03-20 07:28:02 +01:00
parent 92ac151292
commit aa659bcc17
5 changed files with 32 additions and 37 deletions

View File

@ -119,13 +119,13 @@
# list # list
backup_id = json.loads(machine.succeed("borg-job-test-backup list --json"))["archives"][0]["archive"] backup_id = json.loads(machine.succeed("borg-job-test-backup list --json"))["archives"][0]["archive"]
out = machine.succeed("clan --debug --flake ${self} backups list test-backup") out = machine.succeed("clan --debug --flake ${self} backups list test-backup").strip()
print(out) print(out)
assert backup_id in out, f"backup {backup_id} not found in {out}" assert backup_id in out, f"backup {backup_id} not found in {out}"
# restore # restore
machine.succeed("rm -f /var/test-backups/somefile") machine.succeed("rm -f /var/test-backups/somefile")
machine.succeed(f"clan --debug --flake ${self} backups restore test-backup borgbackup borg@machine:.::{backup_id} >&2") machine.succeed(f"clan --debug --flake ${self} backups restore test-backup borgbackup {out} >&2")
assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed" assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
''; '';
} { inherit pkgs self; }; } { inherit pkgs self; };

View File

@ -90,11 +90,14 @@ in
''; '';
}; };
environment.systemPackages = [ pkgs.jq ]; environment.systemPackages = [
(pkgs.writeShellScriptBin "borgbackup-create" ''
clanCore.backups.providers.borgbackup = { set -efu -o pipefail
# TODO list needs to run locally or on the remote machine ${lib.concatMapStringsSep "\n" (dest: ''
list = '' systemctl start borgbackup-job-${dest.name}
'') (lib.attrValues cfg.destinations)}
'')
(pkgs.writeShellScriptBin "borgbackup-list" ''
set -efu set -efu
(${ (${
lib.concatMapStringsSep "\n" ( lib.concatMapStringsSep "\n" (
@ -102,21 +105,25 @@ in
# we need yes here to skip the changed url verification # 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)}]' '' ''yes y | borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.name}::${dest.repo}::" + .name)}]' ''
) (lib.attrValues cfg.destinations) ) (lib.attrValues cfg.destinations)
}) | jq -s 'add' }) | ${pkgs.jq}/bin/jq -s 'add'
''; '')
create = '' (pkgs.writeShellScriptBin "borgbackup-restore" ''
${lib.concatMapStringsSep "\n" (dest: '' set -efux
systemctl start borgbackup-job-${dest.name}
'') (lib.attrValues cfg.destinations)}
'';
restore = ''
set -efu
cd / cd /
IFS=';' read -ra FOLDER <<< "$FOLDERS" IFS=';' read -ra FOLDER <<< "$FOLDERS"
job_name=$(echo "$NAME" | cut -d'::' -f1) job_name=$(echo "$NAME" | ${pkgs.gawk}/bin/awk -F'::' '{print $1}')
if ! command -v borg-job-"$job_name" &> /dev/null; then
echo "borg-job-$job_name not found: Backup name is invalid" >&2
exit 1
fi
yes y | borg-job-"$job_name" extract --list "$NAME" "''${FOLDER[@]}" yes y | borg-job-"$job_name" extract --list "$NAME" "''${FOLDER[@]}"
''; '')
];
clanCore.backups.providers.borgbackup = {
list = "borgbackup-list";
create = "borgbackup-create";
restore = "borgbackup-restore";
}; };
}; };
} }

View File

@ -14,7 +14,7 @@ def create_backup(machine: Machine, provider: str | None = None) -> None:
if provider is None: if provider is None:
for provider in backup_scripts["providers"]: for provider in backup_scripts["providers"]:
proc = machine.target_host.run( proc = machine.target_host.run(
["bash", "-c", backup_scripts["providers"][provider]["create"]], [backup_scripts["providers"][provider]["create"]],
) )
if proc.returncode != 0: if proc.returncode != 0:
raise ClanError("failed to start backup") raise ClanError("failed to start backup")
@ -24,7 +24,7 @@ def create_backup(machine: Machine, provider: str | None = None) -> None:
if provider not in backup_scripts["providers"]: if provider not in backup_scripts["providers"]:
raise ClanError(f"provider {provider} not found") raise ClanError(f"provider {provider} not found")
proc = machine.target_host.run( proc = machine.target_host.run(
["bash", "-c", backup_scripts["providers"][provider]["create"]], [backup_scripts["providers"][provider]["create"]],
) )
if proc.returncode != 0: if proc.returncode != 0:
raise ClanError("failed to start backup") raise ClanError("failed to start backup")

View File

@ -17,7 +17,7 @@ def list_provider(machine: Machine, provider: str) -> list[Backup]:
results = [] results = []
backup_metadata = json.loads(machine.eval_nix("config.clanCore.backups")) backup_metadata = json.loads(machine.eval_nix("config.clanCore.backups"))
proc = machine.target_host.run( proc = machine.target_host.run(
["bash", "-c", backup_metadata["providers"][provider]["list"]], [backup_metadata["providers"][provider]["list"]],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
check=False, check=False,
) )

View File

@ -15,11 +15,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
env["FOLDERS"] = ":".join(folders) env["FOLDERS"] = ":".join(folders)
proc = machine.target_host.run( proc = machine.target_host.run(
[ [backup_folders[service]["preRestoreScript"]],
"bash",
"-c",
backup_folders[service]["preRestoreScript"],
],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
extra_env=env, extra_env=env,
) )
@ -29,11 +25,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
) )
proc = machine.target_host.run( proc = machine.target_host.run(
[ [backup_metadata["providers"][provider]["restore"]],
"bash",
"-c",
backup_metadata["providers"][provider]["restore"],
],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
extra_env=env, extra_env=env,
) )
@ -43,11 +35,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
) )
proc = machine.target_host.run( proc = machine.target_host.run(
[ [backup_folders[service]["postRestoreScript"]],
"bash",
"-c",
backup_folders[service]["postRestoreScript"],
],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
extra_env=env, extra_env=env,
) )