From 45853ecb3ec446e0f19478d33527ef3e4cfb515c Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Sat, 2 Nov 2024 18:26:21 +0100 Subject: [PATCH] Add support for backing up and restoring software --- scripts/Arch/OS/backup.fish | 15 +++++++ scripts/Common/OS/backup.fish | 60 ++++++++++++++++++++++++++ scripts/lib/restoration.fish | 81 +++++++++++++++++++++++++++++++++++ scripts/lib/software.fish | 72 ++++++++++++++++++++++++++++++- 4 files changed, 226 insertions(+), 2 deletions(-) create mode 100755 scripts/Arch/OS/backup.fish create mode 100644 scripts/Common/OS/backup.fish create mode 100644 scripts/lib/restoration.fish diff --git a/scripts/Arch/OS/backup.fish b/scripts/Arch/OS/backup.fish new file mode 100755 index 00000000..90772648 --- /dev/null +++ b/scripts/Arch/OS/backup.fish @@ -0,0 +1,15 @@ +#!/bin/env fish +begin + set -l dir (status dirname) + + function installValhallaDeps -V dir + source "$dir/../lib/software.fish" + and pacinst fish git jq nix sudo tmux + end + + function getDeploymentScript -V dir + echo "$dir/../lib/deploy.fish" + end + + source "$dir/../../Common/OS/backup.fish" +end diff --git a/scripts/Common/OS/backup.fish b/scripts/Common/OS/backup.fish new file mode 100644 index 00000000..b9d563e8 --- /dev/null +++ b/scripts/Common/OS/backup.fish @@ -0,0 +1,60 @@ +#!/bin/env fish +set -l dir (status dirname) +source "$dir/../../lib/action.fish" + +function backupAction -V dir + source "$dir/../../lib/hooks.fish" + + if not type -q getDeploymentScript + function getDeploymentScript + echo "No deployment script specified! No software will be installed." 1>&2 + false + end + end + + set -l deployScript (getDeploymentScript) + + if fish "$dir/../../../lib/modules/partition/confirm.fish" "Do you wish to store the backup on an SSH server?" n + read -xP "Please specify the host name of the SSH server: " VALHALLA_BACKUP_SERVER + read -xP "Please specify the port of the SSH server (default 22): " VALHALLA_BACKUP_SERVER_PORT + read -xP "Please specify the name of the user to log in to the SSH server: " VALHALLA_BACKUP_SERVER_USER + + if [ -z "$VALHALLA_BACKUP_SERVER_PORT" ] + set -x VALHALLA_BACKUP_SERVER_PORT 22 + end + + if [ -n "$VALHALLA_BACKUP_USER" ] + set -x VALHALLA_BACKUP_SERVER "$VALHALLA_BACKUP_SERVER_USER@$VALHALLA_BACKUP_SERVER" + end + + echo + echo "$(tput setaf 3)==== WARNING ====$(tput sgr0)" + echo "For a seamless experience, please make sure that you are able to establish an unattended ssh connection using key authentication." + echo + echo "$(tput bold)This command should succeed without user interaction:$(tput sgr0)" + echo "ssh -o PasswordAuthentication=no -p $VALHALLA_BACKUP_SERVER_PORT $VALHALLA_BACKUP_SERVER true" + read -P "Press enter once you're done: " + echo + end + + read -xP "Please specify the path to the directory to save the backup to: " VALHALLA_BACKUP_DIR + + runHook backupSoftware || begin + echo "Backing up software..." + + and if [ -n "$deployScript" ] + source $deployScript backup + end + end + + runHook backupUsers || begin + if [ -n "$deployScript" ] + for name in (getUsers | jq '.[]' --raw-output0 | string split0) + echo "Backing up user `$name`..." + and source $deployScript userBackup $name + end + end + end +end + +runSetupUserAction backupAction diff --git a/scripts/lib/restoration.fish b/scripts/lib/restoration.fish new file mode 100644 index 00000000..efb82393 --- /dev/null +++ b/scripts/lib/restoration.fish @@ -0,0 +1,81 @@ +function backupFiles + if [ -n "$VALHALLA_BACKUP_DIR" ] + argparse -i "base-directory=" -- $argv + set -l tarArgs + set -l path (getArchivePath $argv) + set -l dir (dirname "$path") + argparse -i "u/user=" "n/name=" -- $argv + + if runRestorationCommand test ! -d "$dir" + runRestorationCommand mkdir -p "$dir" + end + + if [ -n "$_flag_base_directory" ] + set -a argv --base-directory "$_flag_base_directory" + set -a tarArgs -C "$_flag_base_directory" + else + set -a tarArgs -P + end + + sudo tar $tarArgs -cvz (fd $argv) | createArchive "$path" + end +end + +function restoreFiles + if [ -n "$VALHALLA_BACKUP_DIR" ] + argparse -i "user=" "base-directory=" -- $argv + set -l tarArgs + set -l sudoArgs + + if [ -n "$_flag_base_directory" ] + set -a tarArgs -C "$_flag_base_directory" + else + set -a tarArgs -P + end + + if [ -n "$_flag_user" ] + set -a sudoArgs -u "$_flag_user" + end + + fetchArchive $argv | begin + sudo $sudoArgs tar $tarArgs -xvz + end + end +end + +function createArchive -a path + runRestorationCommand sh -c "tee $(string escape -- "$path") >/dev/null" +end + +function fetchArchive + set -l path (getArchivePath $argv) + runRestorationCommand cat "$path" +end + +function runRestorationCommand + if [ -z "$VALHALLA_BACKUP_SERVER" ] + $argv + else + set -l args + + if [ -n "$VALHALLA_BACKUP_SERVER_PORT" ] + set -a args -p $VALHALLA_BACKUP_SERVER_PORT + end + + ssh $args "$VALHALLA_BACKUP_SERVER" (string escape -- $argv) + end +end + +function getArchivePath + argparse -i "u/user=" "n/name=" -- $argv + set -l path "$VALHALLA_BACKUP_DIR" + + if [ -b "$_flag_user" ] + set -a path Users "$_flag_user" + else + set -a path System + end + + set -a path "$_flag_name.tar.gz" + realpath -m (string join / $path) +end diff --git a/scripts/lib/software.fish b/scripts/lib/software.fish index 3165e5c9..4f75eb7b 100755 --- a/scripts/lib/software.fish +++ b/scripts/lib/software.fish @@ -2,15 +2,62 @@ begin set -l dir (status dirname) + set -l backupActions \ + backup backupSW backupArgs getBackupArgs restore restoreSW \ + userBackup userBackup userBackupArgs getUserBackupArgs userRestore userRestore + set -l actions \ install installSW \ configure configureSW \ userConfig userConfig + set -a actions $backupActions + for i in (seq 2 2 (count $actions)) functions -e "$actions[$i]" end + for i in (seq 1 6 (count $backupActions)) + set -l function $backupActions[(math $i + 1)] + set -l getArgs $backupActions[(math $i + 3)] + set -l restore $backupActions[(math $i + 5)] + + for functionName in $function $restore + function $functionName -V dir -V getArgs -V functionName -V restore + set -l args + + if functions -q $getArgs + set args ($getArgs $argv) + end + + if [ "$functionName" = "$restore" ] || [ -n "$args" ] + for arg in name user + set -l varName "_flag_$arg" + + begin + set -l backup $argv + argparse -i "$arg=" -- $args + set -l argv $backup + end + + if [ -z "$$varName" ] + argparse -i "$arg=" -- $argv + set -a args "--$arg" "$$varName" + end + end + + source "$dir/restoration.fish" + + if [ "$functionName" != "$restore" ] + backupFiles $args + else + restoreFiles $args + end + end + end + end + end + function runPSUserAction argparse -i "script=" "action=" "user=" -- $argv @@ -86,7 +133,9 @@ begin if [ "$action" = "$actions[$i]" ] set -l message set -l function $actions[(math $i + 1)] + set -l preRun "__preRun" set -l postRun "__postRun" + functions -e $preRun functions -e $postRun switch "$action" @@ -102,7 +151,11 @@ begin end case configure set message "Configuring `$name`..." - case userConfig + + function $preRun -V args + runInstallerAction $args --action restore + end + case userConfig userBackup userRestore argparse -i "user=" -- $argv set -l user "$_flag_user" @@ -117,7 +170,22 @@ begin set install false end - set message "Configuring `$name` for `$user`..." + switch "$action" + case userConfig + set message "Configuring `$name` for `$user`..." + + function $preRun -V args + runInstallerAction $args --action userRestore + end + case userBackup + set message "Backing up `$name` for `$user`..." + case userRestore + set message "Restoring `$name` for `$user`..." + end + end + + if functions -q $preRun + $preRun end if functions -q "$function" && $install