diff --git a/helpers/helpers.v2.1.d/backup b/helpers/helpers.v2.1.d/backup index 2a024fa8f..642c66e65 100644 --- a/helpers/helpers.v2.1.d/backup +++ b/helpers/helpers.v2.1.d/backup @@ -4,85 +4,48 @@ CAN_BIND=${CAN_BIND:-1} # Add a file or a directory to the list of paths to backup # -# usage: ynh_backup --target=/path/to/stuff [--is_big] [--not_mandatory] -# | arg: -s, --target= - file or directory to bind or symlink or copy. it shouldn't be in the backup dir. -# | arg: -b, --is_big - Indicate data are big (mail, video, image ...) -# | arg: -m, --not_mandatory - Indicate that if the file is missing, the backup can ignore it. +# usage: ynh_backup /path/to/stuff # -# This helper can be used both in a system backup hook, and in an app backup script +# NB : note that this helper does *NOT* perform any copy in itself, it only +# declares stuff to be backuped via a CSV which is later picked up by the core # -# `ynh_backup` writes `target` and the corresponding path inside the archive (dest_path) into a CSV file, and it -# creates the parent destination directory +# NB 2 : there is a specific behavior for $data_dir (or childs of $data_dir) and +# /var/log/$app which are *NOT* backedup during safety-backup-before-upgrade, +# OR if the setting "do_not_backup_data" is equals 1 for that app # -# Example in the context of a wordpress app : -# ``` -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" -# # => This line will be added into CSV file -# # "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/etc/nginx/conf.d/$domain.d/$app.conf" +# The rationale is that these directories are usually too heavy to be integrated in every backup +# (think for example about Nextcloud with quite a lot of data, or an app with a lot of media files...) # -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf/nginx.conf" -# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/nginx.conf" +# This is coupled to the fact that $data_dir and the log dir won't be (and +# should NOT) be deleted during remove, unless --purge is used. Hence, if the +# upgrade fails and the script is removed prior to restoring the backup, the +# data/logs are not destroyed. # -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf/" -# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf" -# -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "conf" -# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf" -# -# #Deprecated usages (maintained for retro-compatibility) -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "${backup_dir}/conf/nginx.conf" -# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/nginx.conf" -# -# ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" "/conf/" -# # => "/etc/nginx/conf.d/$domain.d/$app.conf","apps/wordpress/conf/$app.conf" -# -# ``` -# -# How to use `--is_big`: -# -# `--is_big` is used to specify that this part of the backup can be quite huge. -# So, you don't want that your package does backup that part during ynh_backup_before_upgrade. -# In the same way, an user may doesn't want to backup this big part of the app for -# each of his backup. And so handle that part differently. -# -# As this part of your backup may not be done, your restore script has to handle it. -# In your restore script, use `--not_mandatory` with `ynh_restore` -# As well in your remove script, you should not remove those data ! Or an user may end up with -# a failed upgrade restoring an app without data anymore ! -# -# To have the benefit of `--is_big` while doing a backup, you can whether set the environement -# variable `BACKUP_CORE_ONLY` to 1 (`BACKUP_CORE_ONLY=1`) before the backup command. It will affect -# only that backup command. -# Or set the config `do_not_backup_data` to 1 into the `settings.yml` of the app. This will affect -# all backups for this app until the setting is removed. -# -# Requires YunoHost version 2.4.0 or higher. -# Requires YunoHost version 3.5.0 or higher for the argument `--not_mandatory` ynh_backup() { - # TODO find a way to avoid injection by file strange naming ! - # ============ Argument parsing ============= - local -A args_array=([t]=target= [b]=is_big [m]=not_mandatory) - local target - local is_big - local not_mandatory - ynh_handle_getopts_args "$@" - is_big="${is_big:-0}" - not_mandatory="${not_mandatory:-0}" - # =========================================== + local target="$1" + local is_data=false - BACKUP_CORE_ONLY=${BACKUP_CORE_ONLY:-0} - test -n "${app:-}" && do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data) + # If the path starts with /var/log/$app or $data_dir + if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]) + then + is_data=true + fi + + if [[ -n "${app:-}" ]] + then + local do_not_backup_data=$(ynh_app_setting_get --key=do_not_backup_data) + fi # If backing up core only (used by ynh_backup_before_upgrade), # don't backup big data items - if [ $is_big -eq 1 ] && ([ ${do_not_backup_data:-0} -eq 1 ] || [ $BACKUP_CORE_ONLY -eq 1 ]); then + if [[ "$is_data" == true ]] && ([[ ${do_not_backup_data:-0} -eq 1 ]] || [[ ${BACKUP_CORE_ONLY:-0} -eq 1 ]]); then if [ $BACKUP_CORE_ONLY -eq 1 ]; then ynh_print_info --message="$target will not be saved, because 'BACKUP_CORE_ONLY' is set." else ynh_print_info --message="$target will not be saved, because 'do_not_backup_data' is set." fi - return 0 + return 1 fi # ============================================================================== @@ -90,12 +53,8 @@ ynh_backup() { # ============================================================================== # Be sure the source path is not empty if [ ! -e "$target" ]; then - ynh_print_warn --message="Source path '${src_path}' does not exist" - if [ "$not_mandatory" == "0" ]; then - return 1 - else - return 0 - fi + ynh_print_warn --message="File or folder '${target}' to be backed up does not exist" + return 1 fi # Transform the source path as an absolute path @@ -154,46 +113,45 @@ with open(sys.argv[1], 'r') as backup_file: return $? } -# Restore a file or a directory +# Restore a file or a directory from the backup archive # -# usage: ynh_restore --target=/path/to/stuff [--not_mandatory] -# | arg: -t, --target= - Path where was located the file or the directory before to be backuped or relative path to $YNH_CWD where it is located in the backup archive -# | arg: -m, --not_mandatory - Indicate that if the file is missing, the restore process can ignore it. -# -# Use the registered path in backup_list by ynh_backup to restore the file at the right place. +# usage: ynh_restore /path/to/stuff # # examples: -# ynh_restore -t "/etc/nginx/conf.d/$domain.d/$app.conf" -# # You can also use relative paths: -# ynh_restore -t "conf/nginx.conf" +# ynh_restore "/etc/nginx/conf.d/$domain.d/$app.conf" # -# If `DEST_PATH` already exists and is lighter than 500 Mo, a backup will be made in -# `/var/cache/yunohost/appconfbackup/`. Otherwise, the existing file is removed. +# If the file or dir to be restored already exists on the system and is lighter +# than 500 Mo, it is backed up in `/var/cache/yunohost/appconfbackup/`. +# Otherwise, the existing file or dir is removed. # # if `apps/$app/etc/nginx/conf.d/$domain.d/$app.conf` exists, restore it into # `/etc/nginx/conf.d/$domain.d/$app.conf` -# if no, search for a match in the csv (eg: conf/nginx.conf) and restore it into +# otheriwse, search for a match in the csv (eg: conf/nginx.conf) and restore it into # `/etc/nginx/conf.d/$domain.d/$app.conf` # # Requires YunoHost version 2.6.4 or higher. -# Requires YunoHost version 3.5.0 or higher for the argument --not_mandatory ynh_restore() { - # ============ Argument parsing ============= - local -A args_array=([t]=target= [m]=not_mandatory) - local target - local not_mandatory - ynh_handle_getopts_args "$@" - target="/${target#/}" - not_mandatory="${not_mandatory:-0}" - # =========================================== + target="$1" local archive_path="$YNH_CWD${target}" + + # If the path starts with /var/log/$app or $data_dir + local is_data=false + if ([[ -n "${app:-}" ]] && [[ "$target" == "/var/log/$app*" ]]) || ([[ -n "${data_dir:-}" ]] && [[ "$target" == "$data_dir*" ]]) + then + is_data=true + fi + # If archive_path doesn't exist, search for a corresponding path in CSV if [ ! -d "$archive_path" ] && [ ! -f "$archive_path" ] && [ ! -L "$archive_path" ]; then - if [ "$not_mandatory" == "0" ]; then - archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$target\")" - else + if [[ "$is_data" == true ]] + then + ynh_print_info --message="Skipping $target which doesn't exists in the archive, probably because restoring from a safety-backup-before-upgrade" + # Assume it's not a big deal, we may be restoring a safety-backup-before-upgrade which doesnt contain those return 0 + else + # (get_archive_path will raise an exception if no match found) + archive_path="$YNH_BACKUP_DIR/$(_get_archive_path \"$target\")" fi fi @@ -239,7 +197,7 @@ ynh_restore_everything() { cat ${YNH_BACKUP_CSV} | tr --delete $'\r' | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR.*\"$" \ | while read line; do local ARCHIVE_PATH=$(echo "$line" | grep --only-matching --no-filename --perl-regexp "^\".*\",\"$REL_DIR\K.*(?=\"$)") - ynh_restore --target="$ARCHIVE_PATH" + ynh_restore "$ARCHIVE_PATH" done }