Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package borgmatic for openSUSE:Factory checked in at 2021-02-10 21:30:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/borgmatic (Old) and /work/SRC/openSUSE:Factory/.borgmatic.new.28504 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "borgmatic" Wed Feb 10 21:30:58 2021 rev:25 rq:870769 version:1.5.12 Changes: -------- --- /work/SRC/openSUSE:Factory/borgmatic/borgmatic.changes 2020-08-31 16:53:14.188441291 +0200 +++ /work/SRC/openSUSE:Factory/.borgmatic.new.28504/borgmatic.changes 2021-02-10 21:30:58.686335768 +0100 @@ -1,0 +2,29 @@ +Tue Feb 9 15:20:37 UTC 2021 - Antonio Larrosa <alarr...@suse.com> + +- Update to 1.5.12 + * Fix for previous release with incorrect version suffix in + setup.py. No other changes. + +- Update to 1.5.11 + * #341: Add "temporary_directory" option for changing Borg's + temporary directory. + * #352: Lock down systemd security settings in sample systemd + service file. + * #355: Fix traceback when a database hook value is null in + a configuration file. + * #361: Merge override values when specifying the "--override" + flag multiple times. The previous behavior was to take the + value of the last "--override" flag only. + * #367: Fix traceback when upgrading old INI-style configuration + with upgrade-borgmatic-config. + * #368: Fix signal forwarding from borgmatic to Borg resulting + in recursion traceback. + * #369: Document support for Borg placeholders in repository + names. + +- Replace patch: + * remove-invalid-test.patch + with patch from upstream that fixes tests: + * 0001-Update-versions-of-test-dependencies.patch + +------------------------------------------------------------------- Old: ---- borgmatic-1.5.10.tar.gz remove-invalid-test.patch New: ---- 0001-Update-versions-of-test-dependencies.patch borgmatic-1.5.12.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ borgmatic.spec ++++++ --- /var/tmp/diff_new_pack.MYXF6o/_old 2021-02-10 21:30:59.522336977 +0100 +++ /var/tmp/diff_new_pack.MYXF6o/_new 2021-02-10 21:30:59.526336983 +0100 @@ -1,7 +1,7 @@ # # spec file for package borgmatic # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2021 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,15 +17,16 @@ Name: borgmatic -Version: 1.5.10 +Version: 1.5.12 Release: 0 Summary: Automation tool for borgbackup License: GPL-3.0-only Group: Productivity/Archiving/Backup URL: https://torsion.org/borgmatic/ Source: https://github.com/witten/borgmatic/archive/%{version}.tar.gz#/borgmatic-%{version}.tar.gz -Patch0: remove-invalid-test.patch Patch1: skip-tests.patch +# PATCH-FIX-UPSTREAM 0001-Update-versions-of-test-dependencies.patch -- alarr...@suse.com +Patch2: 0001-Update-versions-of-test-dependencies.patch # testing requirements BuildRequires: borgbackup # To create the manpage @@ -75,8 +76,8 @@ %prep %setup -q -%patch0 -p1 %patch1 -p1 +%patch2 -p1 sed -i -e "s/colorama>=0.4.1,<0.5/colorama>=0.3.9/" setup.py %if 0%{?suse_version} <= 1500 ++++++ 0001-Update-versions-of-test-dependencies.patch ++++++ >From ea6cd53067435365a96786b006aec391714501c4 Mon Sep 17 00:00:00 2001 From: Dan Helfman <wit...@torsion.org> Date: Sun, 22 Nov 2020 14:48:07 -0800 Subject: [PATCH] Update versions of test dependencies (test_requirements.txt and test containers). --- NEWS | 3 ++ docs/Dockerfile | 6 ++-- scripts/run-full-tests | 6 ++-- setup.py | 2 +- test_requirements.txt | 43 ++++++++++++++------------- tests/end-to-end/docker-compose.yaml | 4 +-- tests/unit/commands/test_borgmatic.py | 4 ++- tests/unit/hooks/test_healthchecks.py | 14 +++++---- tox.ini | 4 +-- 9 files changed, 49 insertions(+), 37 deletions(-) #diff --git a/NEWS b/NEWS #index 38d4d82..6f2227b 100644 #--- a/NEWS #+++ b/NEWS #@@ -1,3 +1,6 @@ #+1.5.13.dev0 #+ * Update versions of test dependencies (test_requirements.txt and test containers). #+ # 1.5.12 # * Fix for previous release with incorrect version suffix in setup.py. No other changes. # #diff --git a/docs/Dockerfile b/docs/Dockerfile #index 56857ed..d407fcc 100644 #--- a/docs/Dockerfile #+++ b/docs/Dockerfile #@@ -1,4 +1,4 @@ #-FROM python:3.8.1-alpine3.11 as borgmatic #+FROM python:3.8-alpine3.12 as borgmatic # # COPY . /app # RUN pip install --no-cache /app && generate-borgmatic-config && chmod +r /etc/borgmatic/config.yaml #@@ -7,7 +7,7 @@ RUN borgmatic --help > /command-line.txt \ # echo -e "\n--------------------------------------------------------------------------------\n" >> /command-line.txt \ # && borgmatic "$action" --help >> /command-line.txt; done # #-FROM node:13.7.0-alpine as html #+FROM node:15.2.1-alpine as html # # ARG ENVIRONMENT=production # #@@ -26,7 +26,7 @@ COPY . /source # RUN NODE_ENV=${ENVIRONMENT} npx eleventy --input=/source/docs --output=/output/docs \ # && mv /output/docs/index.html /output/index.html # #-FROM nginx:1.16.1-alpine #+FROM nginx:1.19.4-alpine # # COPY --from=html /output /usr/share/nginx/html # COPY --from=borgmatic /etc/borgmatic/config.yaml /usr/share/nginx/html/docs/reference/config.yaml #diff --git a/scripts/run-full-tests b/scripts/run-full-tests #index bfde13e..0f374cf 100755 #--- a/scripts/run-full-tests #+++ b/scripts/run-full-tests #@@ -10,9 +10,9 @@ # # set -e # #-python -m pip install --upgrade pip==20.0.2 #-pip install tox==3.14.3 #+python -m pip install --upgrade pip==20.2.4 #+pip install tox==3.20.1 # export COVERAGE_FILE=/tmp/.coverage #+apk add --no-cache borgbackup postgresql-client mariadb-client py3-typed-ast # tox --workdir /tmp/.tox #-apk add --no-cache borgbackup postgresql-client mariadb-client # tox --workdir /tmp/.tox -e end-to-end #diff --git a/setup.py b/setup.py #index c2ba568..56fa523 100644 #--- a/setup.py #+++ b/setup.py #@@ -1,6 +1,6 @@ # from setuptools import find_packages, setup # #-VERSION = '1.5.12' #+VERSION = '1.5.13.dev0' # # # setup( #diff --git a/test_requirements.txt b/test_requirements.txt #index 4b18270..0a69060 100644 #--- a/test_requirements.txt #+++ b/test_requirements.txt #@@ -1,25 +1,28 @@ #-appdirs==1.4.3 #-atomicwrites==1.3.0 #-attrs==19.3.0 #-black==19.3b0; python_version >= '3.6' #-click==7.0 #-colorama==0.4.1 #-coverage==4.5.4 #+appdirs==1.4.4 #+atomicwrites==1.4.0 #+attrs==20.3.0 #+black==19.10b0; python_version >= '3.6' #+click==7.1.2 #+colorama==0.4.4 #+coverage==5.3 # docopt==0.6.2 #-flake8==3.7.9 #+flake8==3.8.4 # flexmock==0.10.4 #-isort==4.3.21 #+isort==5.6.4 # mccabe==0.6.1 #-more-itertools==7.2.0 #-pluggy==0.13.0 #-py==1.8.0 #-pycodestyle==2.5.0 #-pyflakes==2.1.1 #+more-itertools==8.6.0 #+pluggy==0.13.1 #+pathspec==0.8.1 #+py==1.9.0 #+pycodestyle==2.6.0 #+pyflakes==2.2.0 # pykwalify==1.7.0 #-pytest==5.2.2 #-pytest-cov==2.8.1 #-python-dateutil==2.8.0 #-PyYAML==5.1.2 #-requests==2.22.0 #+pytest==6.1.2 #+pytest-cov==2.10.1 #+python-dateutil==2.8.1 #+PyYAML==5.3.1 #+regex==2020.11.13 #+requests==2.25.0 # ruamel.yaml>0.15.0,<0.17.0 #-toml==0.10.0 #+toml==0.10.2 #+typed-ast==1.4.1 #diff --git a/tests/end-to-end/docker-compose.yaml b/tests/end-to-end/docker-compose.yaml #index 3830f55..65d4a22 100644 #--- a/tests/end-to-end/docker-compose.yaml #+++ b/tests/end-to-end/docker-compose.yaml #@@ -1,7 +1,7 @@ # version: '3' # services: # postgresql: #- image: postgres:12.2-alpine #+ image: postgres:13.1-alpine # environment: # POSTGRES_PASSWORD: test # POSTGRES_DB: test #@@ -11,7 +11,7 @@ services: # MYSQL_ROOT_PASSWORD: test # MYSQL_DATABASE: test # tests: #- image: python:3.8-alpine3.11 #+ image: python:3.8-alpine3.12 # volumes: # - "../..:/app:ro" # tmpfs: diff --git a/tests/unit/commands/test_borgmatic.py b/tests/unit/commands/test_borgmatic.py index e9453d2..95947f6 100644 --- a/tests/unit/commands/test_borgmatic.py +++ b/tests/unit/commands/test_borgmatic.py @@ -447,7 +447,9 @@ def test_collect_configuration_run_summary_logs_outputs_merged_json_results(): flexmock(module).should_receive('run_configuration').and_return(['foo', 'bar']).and_return( ['baz'] ) - flexmock(module.sys.stdout).should_receive('write').with_args('["foo", "bar", "baz"]').once() + stdout = flexmock() + stdout.should_receive('write').with_args('["foo", "bar", "baz"]').once() + flexmock(module.sys).stdout = stdout arguments = {} tuple( diff --git a/tests/unit/hooks/test_healthchecks.py b/tests/unit/hooks/test_healthchecks.py index 7f90438..59e86d5 100644 --- a/tests/unit/hooks/test_healthchecks.py +++ b/tests/unit/hooks/test_healthchecks.py @@ -28,7 +28,9 @@ def test_forgetful_buffering_handler_emit_forgets_log_records_when_capacity_reac def test_format_buffered_logs_for_payload_flattens_log_buffer(): handler = module.Forgetful_buffering_handler(byte_capacity=100, log_level=1) handler.buffer = ['foo\n', 'bar\n'] - flexmock(module.logging).should_receive('getLogger').and_return(flexmock(handlers=[handler])) + logger = flexmock(handlers=[handler]) + logger.should_receive('removeHandler') + flexmock(module.logging).should_receive('getLogger').and_return(logger) payload = module.format_buffered_logs_for_payload() @@ -39,7 +41,9 @@ def test_format_buffered_logs_for_payload_inserts_truncation_indicator_when_logs handler = module.Forgetful_buffering_handler(byte_capacity=100, log_level=1) handler.buffer = ['foo\n', 'bar\n'] handler.forgot = True - flexmock(module.logging).should_receive('getLogger').and_return(flexmock(handlers=[handler])) + logger = flexmock(handlers=[handler]) + logger.should_receive('removeHandler') + flexmock(module.logging).should_receive('getLogger').and_return(logger) payload = module.format_buffered_logs_for_payload() @@ -47,9 +51,9 @@ def test_format_buffered_logs_for_payload_inserts_truncation_indicator_when_logs def test_format_buffered_logs_for_payload_without_handler_produces_empty_payload(): - flexmock(module.logging).should_receive('getLogger').and_return( - flexmock(handlers=[module.logging.Handler()]) - ) + logger = flexmock(handlers=[module.logging.Handler()]) + logger.should_receive('removeHandler') + flexmock(module.logging).should_receive('getLogger').and_return(logger) payload = module.format_buffered_logs_for_payload() diff --git a/tox.ini b/tox.ini index b6b0537..1d177b8 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ passenv = COVERAGE_FILE commands = pytest {posargs} py36,py37,py38: black --check . - isort --recursive --check-only --settings-path setup.cfg . + isort --check-only --settings-path setup.cfg . flake8 borgmatic tests [testenv:black] @@ -34,4 +34,4 @@ commands = [testenv:isort] deps = {[testenv]deps} commands = - isort {posargs:--recursive} --settings-path setup.cfg . + isort --settings-path setup.cfg . ++++++ borgmatic-1.5.10.tar.gz -> borgmatic-1.5.12.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/NEWS new/borgmatic-1.5.12/NEWS --- old/borgmatic-1.5.10/NEWS 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/NEWS 2020-11-21 22:56:19.000000000 +0100 @@ -1,3 +1,16 @@ +1.5.12 + * Fix for previous release with incorrect version suffix in setup.py. No other changes. + +1.5.11 + * #341: Add "temporary_directory" option for changing Borg's temporary directory. + * #352: Lock down systemd security settings in sample systemd service file. + * #355: Fix traceback when a database hook value is null in a configuration file. + * #361: Merge override values when specifying the "--override" flag multiple times. The previous + behavior was to take the value of the last "--override" flag only. + * #367: Fix traceback when upgrading old INI-style configuration with upgrade-borgmatic-config. + * #368: Fix signal forwarding from borgmatic to Borg resulting in recursion traceback. + * #369: Document support for Borg placeholders in repository names. + 1.5.10 * #347: Add hooks that run for the "extract" action: "before_extract" and "after_extract". * #350: Fix traceback when a configuration directory is non-readable due to directory permissions. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/README.md new/borgmatic-1.5.12/README.md --- old/borgmatic-1.5.10/README.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/README.md 2020-11-21 22:56:19.000000000 +0100 @@ -22,8 +22,9 @@ # Paths of local or remote repositories to backup to. repositories: - - k8pdx...@k8pdxu32.repo.borgbase.com:repo - 1...@usw-s001.rsync.net:backups.borg + - k8pdx...@k8pdxu32.repo.borgbase.com:repo + - us...@scp2.cdn.lima-labs.com:repo - /var/lib/backups/local.borg retention: @@ -66,9 +67,9 @@ <a href="https://healthchecks.io/"><img src="docs/static/healthchecks.png" alt="Healthchecks" height="60px" style="margin-bottom:20px;"></a> <a href="https://cronitor.io/"><img src="docs/static/cronitor.png" alt="Cronitor" height="60px" style="margin-bottom:20px;"></a> <a href="https://cronhub.io/"><img src="docs/static/cronhub.png" alt="Cronhub" height="60px" style="margin-bottom:20px;"></a> -<a href="https://www.pagerduty.com/"><img src="docs/static/pagerduty.png" alt="PagerDuty" height="60px" style="margin-bottom:20px;"></a> +<a href="https://www.pagerduty.com/"><img src="docs/static/pagerduty.png" alt="PagerDuty" height="60px" style="margin-bottom:20px;"></a> +<a href="https://www.rsync.net/cgi-bin/borg.cgi?campaign=borg&adgroup=borgmatic"><img src="docs/static/rsyncnet.png" alt="rsync.net" height="60px" style="margin-bottom:20px;"></a> <a href="https://www.borgbase.com/?utm_source=borgmatic"><img src="docs/static/borgbase.png" alt="BorgBase" height="60px" style="margin-bottom:20px;"></a> -<img src="docs/static/rsyncnet.png" alt="rsync.net" height="60px" style="margin-bottom:20px;"> ## Getting started @@ -89,8 +90,9 @@ links, but without any tracking scripts or cookies.) <ul> + <li class="referral"><a href="https://www.rsync.net/cgi-bin/borg.cgi?campaign=borg&adgroup=borgmatic">rsync.net</a>: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li> <li class="referral"><a href="https://www.borgbase.com/?utm_source=borgmatic">BorgBase</a>: Borg hosting service with support for monitoring, 2FA, and append-only repos</li> - <li>rsync.net: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li> + <li class="referral"><a href="https://storage.lima-labs.com/special-pricing-offer-for-borgmatic-users/">Lima-Labs</a>: Affordable, reliable cloud data storage accessable via SSH/SCP/FTP for Borg backups or any other bulk storage needs</li> </ul> ## Support and contributing diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/borg/environment.py new/borgmatic-1.5.12/borgmatic/borg/environment.py --- old/borgmatic-1.5.10/borgmatic/borg/environment.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/borg/environment.py 2020-11-21 22:56:19.000000000 +0100 @@ -9,6 +9,7 @@ 'encryption_passcommand': 'BORG_PASSCOMMAND', 'encryption_passphrase': 'BORG_PASSPHRASE', 'ssh_command': 'BORG_RSH', + 'temporary_directory': 'TMPDIR', } DEFAULT_BOOL_OPTION_TO_ENVIRONMENT_VARIABLE = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/commands/arguments.py new/borgmatic-1.5.12/borgmatic/commands/arguments.py --- old/borgmatic-1.5.10/borgmatic/commands/arguments.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/commands/arguments.py 2020-11-21 22:56:19.000000000 +0100 @@ -1,5 +1,5 @@ import collections -from argparse import ArgumentParser +from argparse import Action, ArgumentParser from borgmatic.config import collect @@ -102,6 +102,20 @@ return top_level_parser.parse_args(remaining_arguments) +class Extend_action(Action): + ''' + An argparse action to support Python 3.8's "extend" action in older versions of Python. + ''' + + def __call__(self, parser, namespace, values, option_string=None): + items = getattr(namespace, self.dest, None) + + if items: + items.extend(values) + else: + setattr(namespace, self.dest, list(values)) + + def parse_arguments(*unparsed_arguments): ''' Given command-line arguments with which this script was invoked, parse the arguments and return @@ -111,6 +125,7 @@ unexpanded_config_paths = collect.get_default_config_paths(expand_home=False) global_parser = ArgumentParser(add_help=False) + global_parser.register('action', 'extend', Extend_action) global_group = global_parser.add_argument_group('global arguments') global_group.add_argument( @@ -178,6 +193,7 @@ metavar='SECTION.OPTION=VALUE', nargs='+', dest='overrides', + action='extend', help='One or more configuration file options to override with specified values', ) global_group.add_argument( @@ -581,7 +597,7 @@ help='Show info for first N archives after other filters are applied', ) info_group.add_argument( - '--last', metavar='N', help='Show info for first N archives after other filters are applied' + '--last', metavar='N', help='Show info for last N archives after other filters are applied' ) info_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/commands/borgmatic.py new/borgmatic-1.5.12/borgmatic/commands/borgmatic.py --- old/borgmatic-1.5.10/borgmatic/commands/borgmatic.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/commands/borgmatic.py 2020-11-21 22:56:19.000000000 +0100 @@ -658,7 +658,9 @@ if not configs: yield from make_error_log_records( - '{}: No configuration files found'.format(' '.join(arguments['global'].config_paths)) + '{}: No valid configuration files found'.format( + ' '.join(arguments['global'].config_paths) + ) ) return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/commands/convert_config.py new/borgmatic-1.5.12/borgmatic/commands/convert_config.py --- old/borgmatic-1.5.10/borgmatic/commands/convert_config.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/commands/convert_config.py 2020-11-21 22:56:19.000000000 +0100 @@ -99,7 +99,9 @@ ) generate.write_configuration( - args.destination_config_filename, destination_config, mode=source_config_file_mode + args.destination_config_filename, + generate.render_configuration(destination_config), + mode=source_config_file_mode, ) display_result(args) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/config/generate.py new/borgmatic-1.5.12/borgmatic/config/generate.py --- old/borgmatic-1.5.10/borgmatic/config/generate.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/config/generate.py 2020-11-21 22:56:19.000000000 +0100 @@ -99,7 +99,7 @@ return '\n'.join(lines) -def _render_configuration(config): +def render_configuration(config): ''' Given a config data structure of nested OrderedDicts, render the config as YAML and return it. ''' @@ -284,5 +284,5 @@ write_configuration( destination_filename, - _comment_out_optional_configuration(_render_configuration(destination_config)), + _comment_out_optional_configuration(render_configuration(destination_config)), ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/config/schema.yaml new/borgmatic-1.5.12/borgmatic/config/schema.yaml --- old/borgmatic-1.5.10/borgmatic/config/schema.yaml 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/config/schema.yaml 2020-11-21 22:56:19.000000000 +0100 @@ -27,10 +27,14 @@ desc: | Paths to local or remote repositories (required). Tildes are expanded. Multiple repositories are backed up to in - sequence. See ssh_command for SSH options like identity file - or port. + sequence. Borg placeholders can be used. See the output of + "borg help placeholders" for details. See ssh_command for + SSH options like identity file or port. If systemd service + is used, then add local repository paths in the systemd + service file to the ReadWritePaths list. example: - user@backupserver:sourcehostname.borg + - "user@backupserver:{fqdn}" one_file_system: type: bool desc: | @@ -226,6 +230,12 @@ Remote network upload rate limit in kiBytes/second. Defaults to unlimited. example: 100 + temporary_directory: + type: str + desc: | + Directory where temporary files are stored. Defaults to + $TMPDIR + example: /path/to/tmpdir ssh_command: type: str desc: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/hooks/dispatch.py new/borgmatic-1.5.12/borgmatic/hooks/dispatch.py --- old/borgmatic-1.5.10/borgmatic/hooks/dispatch.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/hooks/dispatch.py 2020-11-21 22:56:19.000000000 +0100 @@ -58,5 +58,5 @@ return { hook_name: call_hook(function_name, hooks, log_prefix, hook_name, *args, **kwargs) for hook_name in hook_names - if hook_name in hooks + if hooks.get(hook_name) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/borgmatic/signals.py new/borgmatic-1.5.12/borgmatic/signals.py --- old/borgmatic-1.5.10/borgmatic/signals.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/borgmatic/signals.py 2020-11-21 22:56:19.000000000 +0100 @@ -4,8 +4,13 @@ def _handle_signal(signal_number, frame): # pragma: no cover ''' - Send the signal to all processes in borgmatic's process group, which includes child process. + Send the signal to all processes in borgmatic's process group, which includes child processes. ''' + # Prevent infinite signal handler recursion. If the parent frame is this very same handler + # function, we know we're recursing. + if frame.f_back.f_code.co_name == _handle_signal.__name__: + return + os.killpg(os.getpgrp(), signal_number) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/docs/how-to/backup-your-databases.md new/borgmatic-1.5.12/docs/how-to/backup-your-databases.md --- old/borgmatic-1.5.10/docs/how-to/backup-your-databases.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/docs/how-to/backup-your-databases.md 2020-11-21 22:56:19.000000000 +0100 @@ -74,6 +74,17 @@ Note that you may need to use a `username` of the `postgres` superuser for this to work with PostgreSQL. +If you would like to backup databases only and not source directories, you can +specify an empty `source_directories` value because it is a mandatory field: + +```yaml +location: + source_directories: [] +hooks: + mysql_databases: + - name: all +``` + ### Configuration backups diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/docs/how-to/deal-with-very-large-backups.md new/borgmatic-1.5.12/docs/how-to/deal-with-very-large-backups.md --- old/borgmatic-1.5.10/docs/how-to/deal-with-very-large-backups.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/docs/how-to/deal-with-very-large-backups.md 2020-11-21 22:56:19.000000000 +0100 @@ -18,7 +18,7 @@ If you find yourself in this situation, you have some options. First, you can run borgmatic's pruning, creating, or checking actions separately. For -instance, the the following optional actions are available: +instance, the following optional actions are available: ```bash borgmatic prune diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/docs/how-to/make-backups-redundant.md new/borgmatic-1.5.12/docs/how-to/make-backups-redundant.md --- old/borgmatic-1.5.10/docs/how-to/make-backups-redundant.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/docs/how-to/make-backups-redundant.md 2020-11-21 22:56:19.000000000 +0100 @@ -20,8 +20,9 @@ # Paths of local or remote repositories to backup to. repositories: - - k8pdx...@k8pdxu32.repo.borgbase.com:repo - 1...@usw-s001.rsync.net:backups.borg + - k8pdx...@k8pdxu32.repo.borgbase.com:repo + - us...@scp2.cdn.lima-labs.com:repo - /var/lib/backups/local.borg ``` @@ -32,9 +33,10 @@ Here's a way of visualizing what borgmatic does with the above configuration: -2. Backup `/home` and `/etc` to `k8pdx...@k8pdxu32.repo.borgbase.com:repo` 1. Backup `/home` and `/etc` to `1...@usw-s001.rsync.net:backups.borg` -3. Backup `/home` and `/etc` to `/var/lib/backups/local.borg` +2. Backup `/home` and `/etc` to `k8pdx...@k8pdxu32.repo.borgbase.com:repo` +3. Backup `/home` and `/etc` to `us...@scp2.cdn.lima-labs.com:repo` +4. Backup `/home` and `/etc` to `/var/lib/backups/local.borg` This gives you redundancy of your data across repositories and even potentially across providers. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/docs/how-to/make-per-application-backups.md new/borgmatic-1.5.12/docs/how-to/make-per-application-backups.md --- old/borgmatic-1.5.10/docs/how-to/make-per-application-backups.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/docs/how-to/make-per-application-backups.md 2020-11-21 22:56:19.000000000 +0100 @@ -140,7 +140,19 @@ the configured value for the `remote_path` option in the `location` section, and use the value of `/usr/local/bin/borg1` instead. -Note that the value is parsed as an actual YAML string, so you can even set +You can even override multiple values at once. For instance: + +```bash +borgmatic create --override section.option1=value1 section.option2=value2 +``` + +This will accomplish the same thing: + +```bash +borgmatic create --override section.option1=value1 --override section.option2=value2 +``` + +Note that each value is parsed as an actual YAML string, so you can even set list values by using brackets. For instance: ```bash diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/docs/how-to/set-up-backups.md new/borgmatic-1.5.12/docs/how-to/set-up-backups.md --- old/borgmatic-1.5.10/docs/how-to/set-up-backups.md 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/docs/how-to/set-up-backups.md 2020-11-21 22:56:19.000000000 +0100 @@ -99,8 +99,9 @@ links, but without any tracking scripts or cookies.) <ul> + <li class="referral"><a href="https://www.rsync.net/cgi-bin/borg.cgi?campaign=borg&adgroup=borgmatic">rsync.net</a>: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li> <li class="referral"><a href="https://www.borgbase.com/?utm_source=borgmatic">BorgBase</a>: Borg hosting service with support for monitoring, 2FA, and append-only repos</li> - <li>rsync.net: Cloud Storage provider with full support for borg and any other SSH/SFTP tool</li> + <li class="referral"><a href="https://storage.lima-labs.com/special-pricing-offer-for-borgmatic-users/">Lima-Labs</a>: Affordable, reliable cloud data storage accessable via SSH/SCP/FTP for Borg backups or any other bulk storage needs</li> </ul> ## Configuration @@ -268,6 +269,10 @@ sudo systemctl enable --now borgmatic.timer ``` +Review the security settings in the service file and update them as needed. +If `ProtectSystem=strict` is enabled and local repositories are used, then +the repository path must be added to the `ReadWritePaths` list. + Feel free to modify the timer file based on how frequently you'd like borgmatic to run. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/sample/systemd/borgmatic.service new/borgmatic-1.5.12/sample/systemd/borgmatic.service --- old/borgmatic-1.5.10/sample/systemd/borgmatic.service 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/sample/systemd/borgmatic.service 2020-11-21 22:56:19.000000000 +0100 @@ -7,6 +7,38 @@ [Service] Type=oneshot +# Security settings for systemd running as root +# For more details about this settings check the systemd manuals +# https://www.freedesktop.org/software/systemd/man/systemd.exec.html +LockPersonality=true +# Certain borgmatic features like Healthchecks integration need MemoryDenyWriteExecute to be off. +# But you can try setting it to "yes" for improved security if you don't use those features. +MemoryDenyWriteExecute=no +NoNewPrivileges=yes +PrivateDevices=yes +PrivateTmp=yes +ProtectClock=yes +ProtectControlGroups=yes +ProtectHostname=yes +ProtectKernelLogs=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK +RestrictNamespaces=yes +RestrictRealtime=yes +RestrictSUIDSGID=yes +SystemCallArchitectures=native +SystemCallFilter=@system-service +# Restrict write access +# Change to 'ProtectSystem=strict' and uncomment 'ProtectHome' to make the whole file +# system read-only be default and uncomment 'ReadWritePaths' for the required write access. +# Add local repositroy paths to the list of 'ReadWritePaths' like '-/mnt/my_backup_drive'. +ProtectSystem=full +# ProtectHome=read-only +# ReadWritePaths=-/root/.config/borg -/root/.cache/borg -/root/.borgmatic + +CapabilityBoundingSet=CAP_DAC_READ_SEARCH CAP_NET_RAW + # Lower CPU and I/O priority. Nice=19 CPUSchedulingPolicy=batch diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/setup.py new/borgmatic-1.5.12/setup.py --- old/borgmatic-1.5.10/setup.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/setup.py 2020-11-21 22:56:19.000000000 +0100 @@ -1,6 +1,6 @@ from setuptools import find_packages, setup -VERSION = '1.5.10' +VERSION = '1.5.12' setup( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/tests/end-to-end/test_borgmatic.py new/borgmatic-1.5.12/tests/end-to-end/test_borgmatic.py --- old/borgmatic-1.5.10/tests/end-to-end/test_borgmatic.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/tests/end-to-end/test_borgmatic.py 2020-11-21 22:56:19.000000000 +0100 @@ -19,6 +19,7 @@ open(config_path) .read() .replace('user@backupserver:sourcehostname.borg', repository_path) + .replace('- user@backupserver:{fqdn}', '') .replace('- /home', '- {}'.format(config_path)) .replace('- /etc', '') .replace('- /var/log/syslog*', '') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/tests/integration/commands/test_arguments.py new/borgmatic-1.5.12/tests/integration/commands/test_arguments.py --- old/borgmatic-1.5.10/tests/integration/commands/test_arguments.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/tests/integration/commands/test_arguments.py 2020-11-21 22:56:19.000000000 +0100 @@ -71,6 +71,35 @@ assert global_arguments.log_file_verbosity == -1 +def test_parse_arguments_with_single_override_parses(): + flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) + + arguments = module.parse_arguments('--override', 'foo.bar=baz') + + global_arguments = arguments['global'] + assert global_arguments.overrides == ['foo.bar=baz'] + + +def test_parse_arguments_with_multiple_overrides_parses(): + flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) + + arguments = module.parse_arguments('--override', 'foo.bar=baz', 'foo.quux=7') + + global_arguments = arguments['global'] + assert global_arguments.overrides == ['foo.bar=baz', 'foo.quux=7'] + + +def test_parse_arguments_with_multiple_overrides_and_flags_parses(): + flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default']) + + arguments = module.parse_arguments( + '--override', 'foo.bar=baz', '--override', 'foo.quux=7', 'this.that=8' + ) + + global_arguments = arguments['global'] + assert global_arguments.overrides == ['foo.bar=baz', 'foo.quux=7', 'this.that=8'] + + def test_parse_arguments_with_list_json_overrides_default(): arguments = module.parse_arguments('list', '--json') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/tests/integration/config/test_generate.py new/borgmatic-1.5.12/tests/integration/config/test_generate.py --- old/borgmatic-1.5.10/tests/integration/config/test_generate.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/tests/integration/config/test_generate.py 2020-11-21 22:56:19.000000000 +0100 @@ -87,8 +87,8 @@ assert module._comment_out_optional_configuration(config.strip()) == expected_config.strip() -def test_render_configuration_converts_configuration_to_yaml_string(): - yaml_string = module._render_configuration({'foo': 'bar'}) +def testrender_configuration_converts_configuration_to_yaml_string(): + yaml_string = module.render_configuration({'foo': 'bar'}) assert yaml_string == 'foo: bar\n' @@ -194,7 +194,7 @@ flexmock(module.yaml).should_receive('round_trip_load') flexmock(module).should_receive('_schema_to_sample_configuration') flexmock(module).should_receive('merge_source_configuration_into_destination') - flexmock(module).should_receive('_render_configuration') + flexmock(module).should_receive('render_configuration') flexmock(module).should_receive('_comment_out_optional_configuration') flexmock(module).should_receive('write_configuration') @@ -208,7 +208,7 @@ flexmock(module.load).should_receive('load_configuration') flexmock(module).should_receive('_schema_to_sample_configuration') flexmock(module).should_receive('merge_source_configuration_into_destination') - flexmock(module).should_receive('_render_configuration') + flexmock(module).should_receive('render_configuration') flexmock(module).should_receive('_comment_out_optional_configuration') flexmock(module).should_receive('write_configuration') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/tests/unit/borg/test_create.py new/borgmatic-1.5.12/tests/unit/borg/test_create.py --- old/borgmatic-1.5.10/tests/unit/borg/test_create.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/tests/unit/borg/test_create.py 2020-11-21 22:56:19.000000000 +0100 @@ -1326,6 +1326,34 @@ ) +def test_create_archive_with_repository_accepts_borg_placeholders(): + flexmock(module).should_receive('borgmatic_source_directories').and_return([]) + flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) + flexmock(module).should_receive('map_directories_to_devices').and_return({}) + flexmock(module).should_receive('_expand_directories').and_return(()) + flexmock(module).should_receive('_expand_home_directories').and_return(()) + flexmock(module).should_receive('_write_pattern_file').and_return(None) + flexmock(module).should_receive('_make_pattern_flags').and_return(()) + flexmock(module).should_receive('_make_exclude_flags').and_return(()) + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'create', '{fqdn}::Documents_{hostname}-{now}', 'foo', 'bar'), + output_log_level=logging.INFO, + output_file=None, + borg_local_path='borg', + ) + + module.create_archive( + dry_run=False, + repository='{fqdn}', + location_config={ + 'source_directories': ['foo', 'bar'], + 'repositories': ['{fqdn}'], + 'exclude_patterns': None, + }, + storage_config={'archive_name_format': 'Documents_{hostname}-{now}'}, + ) + + def test_create_archive_with_extra_borg_options_calls_borg_with_extra_options(): flexmock(module).should_receive('borgmatic_source_directories').and_return([]) flexmock(module).should_receive('deduplicate_directories').and_return(('foo', 'bar')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/borgmatic-1.5.10/tests/unit/hooks/test_dispatch.py new/borgmatic-1.5.12/tests/unit/hooks/test_dispatch.py --- old/borgmatic-1.5.10/tests/unit/hooks/test_dispatch.py 2020-08-21 23:27:47.000000000 +0200 +++ new/borgmatic-1.5.12/tests/unit/hooks/test_dispatch.py 2020-11-21 22:56:19.000000000 +0100 @@ -58,11 +58,21 @@ assert return_values == expected_return_values -def test_call_hooks_calls_skips_return_values_for_unconfigured_hooks(): +def test_call_hooks_calls_skips_return_values_for_missing_hooks(): hooks = {'super_hook': flexmock()} expected_return_values = {'super_hook': flexmock()} flexmock(module).should_receive('call_hook').and_return(expected_return_values['super_hook']) + return_values = module.call_hooks('do_stuff', hooks, 'prefix', ('super_hook', 'other_hook'), 55) + + assert return_values == expected_return_values + + +def test_call_hooks_calls_skips_return_values_for_null_hooks(): + hooks = {'super_hook': flexmock(), 'other_hook': None} + expected_return_values = {'super_hook': flexmock()} + flexmock(module).should_receive('call_hook').and_return(expected_return_values['super_hook']) + return_values = module.call_hooks('do_stuff', hooks, 'prefix', ('super_hook', 'other_hook'), 55) assert return_values == expected_return_values