Compare commits

...
5 Commits
25 changed files with 378 additions and 127 deletions
+15
View File
@@ -1,3 +1,18 @@
1.4.17
* #235: Pass extra options directly to particular Borg commands, handy for Borg options that
borgmatic does not yet support natively. Use "extra_borg_options" in the storage configuration
section.
* #266: Attempt to repair any inconsistencies found during a consistency check via
"borgmatic check --repair" flag.
1.4.16
* #256: Fix for "before_backup" hook not triggering an error when the command contains "borg" and
has an exit code of 1.
* #257: Fix for garbled Borg file listing when using "borgmatic create --progress" with
verbosity level 1 or 2.
* #260: Fix for missing Healthchecks monitoring payload or HTTP 500 due to incorrect unicode
encoding.
1.4.15
* Fix for database dump removal incorrectly skipping some database dumps.
* #123: Support for mounting an archive as a FUSE filesystem via "borgmatic mount" action, and
+15 -7
View File
@@ -1,7 +1,7 @@
import logging
from borgmatic.borg import extract
from borgmatic.execute import execute_command
from borgmatic.execute import execute_command, execute_command_without_capture
DEFAULT_CHECKS = ('repository', 'archives')
DEFAULT_PREFIX = '{hostname}-'
@@ -91,23 +91,23 @@ def check_archives(
consistency_config,
local_path='borg',
remote_path=None,
repair=None,
only_checks=None,
):
'''
Given a local or remote repository path, a storage config dict, a consistency config dict,
local/remote commands to run, and an optional list of checks to use instead of configured
checks, check the contained Borg archives for consistency.
local/remote commands to run, whether to attempt a repair, and an optional list of checks
to use instead of configured checks, check the contained Borg archives for consistency.
If there are no consistency checks to run, skip running them.
'''
checks = _parse_checks(consistency_config, only_checks)
check_last = consistency_config.get('check_last', None)
lock_wait = None
extra_borg_options = storage_config.get('extra_borg_options', {}).get('check', '')
if set(checks).intersection(set(DEFAULT_CHECKS + ('data',))):
remote_path_flags = ('--remote-path', remote_path) if remote_path else ()
lock_wait = storage_config.get('lock_wait', None)
lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else ()
verbosity_flags = ()
if logger.isEnabledFor(logging.INFO):
@@ -119,13 +119,21 @@ def check_archives(
full_command = (
(local_path, 'check')
+ (('--repair',) if repair else ())
+ _make_check_flags(checks, check_last, prefix)
+ remote_path_flags
+ lock_wait_flags
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ verbosity_flags
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ (repository,)
)
# The Borg repair option trigger an interactive prompt, which won't work when output is
# captured.
if repair:
execute_command_without_capture(full_command, error_on_warnings=True)
return
execute_command(full_command, error_on_warnings=True)
if 'extract' in checks:
+9 -3
View File
@@ -150,6 +150,7 @@ def create_archive(
files_cache = location_config.get('files_cache')
default_archive_name_format = '{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}'
archive_name_format = storage_config.get('archive_name_format', default_archive_name_format)
extra_borg_options = storage_config.get('extra_borg_options', {}).get('create', '')
full_command = (
(local_path, 'create')
@@ -170,7 +171,11 @@ def create_archive(
+ (('--remote-path', remote_path) if remote_path else ())
+ (('--umask', str(umask)) if umask else ())
+ (('--lock-wait', str(lock_wait)) if lock_wait else ())
+ (('--list', '--filter', 'AME-') if logger.isEnabledFor(logging.INFO) and not json else ())
+ (
('--list', '--filter', 'AME-')
if logger.isEnabledFor(logging.INFO) and not json and not progress
else ()
)
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO and not json else ())
+ (
('--stats',)
@@ -181,6 +186,7 @@ def create_archive(
+ (('--dry-run',) if dry_run else ())
+ (('--progress',) if progress else ())
+ (('--json',) if json else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ (
'{repository}::{archive_name_format}'.format(
repository=repository, archive_name_format=archive_name_format
@@ -192,7 +198,7 @@ def create_archive(
# The progress output isn't compatible with captured and logged output, as progress messes with
# the terminal directly.
if progress:
execute_command_without_capture(full_command)
execute_command_without_capture(full_command, error_on_warnings=False)
return
if json:
@@ -202,4 +208,4 @@ def create_archive(
else:
output_log_level = logging.INFO
return execute_command(full_command, output_log_level)
return execute_command(full_command, output_log_level, error_on_warnings=False)
+1 -1
View File
@@ -27,7 +27,7 @@ def extract_last_archive_dry_run(repository, lock_wait=None, local_path='borg',
+ (repository,)
)
list_output = execute_command(full_list_command, output_log_level=None)
list_output = execute_command(full_list_command, output_log_level=None, error_on_warnings=False)
try:
last_archive_name = list_output.strip().splitlines()[-1]
+3 -1
View File
@@ -39,5 +39,7 @@ def display_archives_info(
)
return execute_command(
full_command, output_log_level=None if info_arguments.json else logging.WARNING
full_command,
output_log_level=None if info_arguments.json else logging.WARNING,
error_on_warnings=False,
)
+8 -4
View File
@@ -11,6 +11,7 @@ INFO_REPOSITORY_NOT_FOUND_EXIT_CODE = 2
def initialize_repository(
repository,
storage_config,
encryption_mode,
append_only=None,
storage_quota=None,
@@ -18,9 +19,9 @@ def initialize_repository(
remote_path=None,
):
'''
Given a local or remote repository path, a Borg encryption mode, whether the repository should
be append-only, and the storage quota to use, initialize the repository. If the repository
already exists, then log and skip initialization.
Given a local or remote repository path, a storage configuration dict, a Borg encryption mode,
whether the repository should be append-only, and the storage quota to use, initialize the
repository. If the repository already exists, then log and skip initialization.
'''
info_command = (local_path, 'info', repository)
logger.debug(' '.join(info_command))
@@ -33,6 +34,8 @@ def initialize_repository(
if error.returncode != INFO_REPOSITORY_NOT_FOUND_EXIT_CODE:
raise
extra_borg_options = storage_config.get('extra_borg_options', {}).get('init', '')
init_command = (
(local_path, 'init')
+ (('--encryption', encryption_mode) if encryption_mode else ())
@@ -41,8 +44,9 @@ def initialize_repository(
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
+ (('--debug',) if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--remote-path', remote_path) if remote_path else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ (repository,)
)
# Don't use execute_command() here because it doesn't support interactive prompts.
execute_command_without_capture(init_command)
execute_command_without_capture(init_command, error_on_warnings=False)
+3 -1
View File
@@ -46,5 +46,7 @@ def list_archives(repository, storage_config, list_arguments, local_path='borg',
)
return execute_command(
full_command, output_log_level=None if list_arguments.json else logging.WARNING
full_command,
output_log_level=None if list_arguments.json else logging.WARNING,
error_on_warnings=False,
)
+2 -2
View File
@@ -40,7 +40,7 @@ def mount_archive(
# Don't capture the output when foreground mode is used so that ctrl-C can work properly.
if foreground:
execute_command_without_capture(full_command)
execute_command_without_capture(full_command, error_on_warnings=False)
return
execute_command(full_command)
execute_command(full_command, error_on_warnings=False)
+7 -1
View File
@@ -49,6 +49,7 @@ def prune_archives(
'''
umask = storage_config.get('umask', None)
lock_wait = storage_config.get('lock_wait', None)
extra_borg_options = storage_config.get('extra_borg_options', {}).get('prune', '')
full_command = (
(local_path, 'prune')
@@ -61,7 +62,12 @@ def prune_archives(
+ (('--debug', '--list', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
+ (('--dry-run',) if dry_run else ())
+ (('--stats',) if stats else ())
+ (tuple(extra_borg_options.split(' ')) if extra_borg_options else ())
+ (repository,)
)
execute_command(full_command, output_log_level=logging.WARNING if stats else logging.INFO)
execute_command(
full_command,
output_log_level=logging.WARNING if stats else logging.INFO,
error_on_warnings=False,
)
+7
View File
@@ -266,6 +266,13 @@ def parse_arguments(*unparsed_arguments):
add_help=False,
)
check_group = check_parser.add_argument_group('check arguments')
check_group.add_argument(
'--repair',
dest='repair',
default=False,
action='store_true',
help='Attempt to repair any inconsistencies found (experimental and only for interactive use)',
)
check_group.add_argument(
'--only',
metavar='CHECK',
+2
View File
@@ -189,6 +189,7 @@ def run_actions(
logger.info('{}: Initializing repository'.format(repository))
borg_init.initialize_repository(
repository,
storage,
arguments['init'].encryption_mode,
arguments['init'].append_only,
arguments['init'].storage_quota,
@@ -229,6 +230,7 @@ def run_actions(
consistency,
local_path=local_path,
remote_path=remote_path,
repair=arguments['check'].repair,
only_checks=arguments['check'].only,
)
if 'extract' in arguments:
+23
View File
@@ -245,6 +245,29 @@ map:
Bypass Borg error about a previously unknown unencrypted repository. Defaults to
false.
example: true
extra_borg_options:
map:
init:
type: str
desc: Extra command-line options to pass to "borg init".
example: "--make-parent-dirs"
prune:
type: str
desc: Extra command-line options to pass to "borg prune".
example: "--save-space"
create:
type: str
desc: Extra command-line options to pass to "borg create".
example: "--no-files-cache"
check:
type: str
desc: Extra command-line options to pass to "borg check".
example: "--save-space"
desc: |
Additional options to pass directly to particular Borg commands, handy for Borg
options that borgmatic does not yet support natively. Note that borgmatic does
not perform any validation on these options. Running borgmatic with
"--verbosity 2" shows the exact Borg command-line invocation.
retention:
desc: |
Retention policy for how many backups to keep in each category. See
+9 -9
View File
@@ -9,15 +9,15 @@ ERROR_OUTPUT_MAX_LINE_COUNT = 25
BORG_ERROR_EXIT_CODE = 2
def exit_code_indicates_error(command, exit_code, error_on_warnings=False):
def exit_code_indicates_error(command, exit_code, error_on_warnings=True):
'''
Return True if the given exit code from running the command corresponds to an error.
If error on warnings is False, then treat exit code 1 as a warning instead of an error.
'''
# If we're running something other than Borg, treat all non-zero exit codes as errors.
if 'borg' in command[0] and not error_on_warnings:
return bool(exit_code >= BORG_ERROR_EXIT_CODE)
if error_on_warnings:
return bool(exit_code != 0)
return bool(exit_code != 0)
return bool(exit_code >= BORG_ERROR_EXIT_CODE)
def log_output(command, process, output_buffer, output_log_level, error_on_warnings):
@@ -65,7 +65,7 @@ def execute_command(
shell=False,
extra_environment=None,
working_directory=None,
error_on_warnings=False,
error_on_warnings=True,
):
'''
Execute the given command (a sequence of command/argument strings) and log its output at the
@@ -75,7 +75,7 @@ def execute_command(
file. If shell is True, execute the command within a shell. If an extra environment dict is
given, then use it to augment the current environment, and pass the result into the command. If
a working directory is given, use that as the present working directory when running the
command.
command. If error on warnings is False, then treat exit code 1 as a warning instead of an error.
Raise subprocesses.CalledProcessError if an error occurs while running the command.
'''
@@ -110,14 +110,14 @@ def execute_command(
)
def execute_command_without_capture(full_command, working_directory=None, error_on_warnings=False):
def execute_command_without_capture(full_command, working_directory=None, error_on_warnings=True):
'''
Execute the given command (a sequence of command/argument strings), but don't capture or log its
output in any way. This is necessary for commands that monkey with the terminal (e.g. progress
display) or provide interactive prompts.
If a working directory is given, use that as the present working directory when running the
command.
command. If error on warnings is False, then treat exit code 1 as a warning instead of an error.
'''
logger.debug(' '.join(full_command))
+1 -1
View File
@@ -97,4 +97,4 @@ def ping_monitor(ping_url_or_uuid, config_filename, state, dry_run):
if not dry_run:
logging.getLogger('urllib3').setLevel(logging.ERROR)
requests.post(ping_url, data=payload)
requests.post(ping_url, data=payload.encode('utf-8'))
+1 -1
View File
@@ -1,6 +1,6 @@
from setuptools import find_packages, setup
VERSION = '1.4.15'
VERSION = '1.4.17'
setup(
+29
View File
@@ -158,6 +158,21 @@ def test_make_check_flags_with_default_checks_and_prefix_includes_prefix_flag():
assert flags == ('--prefix', 'foo-')
def test_check_archives_with_repair_calls_borg_with_repair_parameter():
checks = ('repository',)
consistency_config = {'check_last': None}
flexmock(module).should_receive('_parse_checks').and_return(checks)
flexmock(module).should_receive('_make_check_flags').and_return(())
flexmock(module).should_receive('execute_command').never()
flexmock(module).should_receive('execute_command_without_capture').with_args(
('borg', 'check', '--repair', 'repo'), error_on_warnings=True
).once()
module.check_archives(
repository='repo', storage_config={}, consistency_config=consistency_config, repair=True
)
@pytest.mark.parametrize(
'checks',
(
@@ -296,3 +311,17 @@ def test_check_archives_with_retention_prefix():
module.check_archives(
repository='repo', storage_config={}, consistency_config=consistency_config
)
def test_check_archives_with_extra_borg_options_calls_borg_with_extra_options():
checks = ('repository',)
consistency_config = {'check_last': None}
flexmock(module).should_receive('_parse_checks').and_return(checks)
flexmock(module).should_receive('_make_check_flags').and_return(())
insert_execute_command_mock(('borg', 'check', '--extra', '--options', 'repo'))
module.check_archives(
repository='repo',
storage_config={'extra_borg_options': {'check': '--extra --options'}},
consistency_config=consistency_config,
)
+118 -18
View File
@@ -206,7 +206,9 @@ def test_create_archive_calls_borg_with_parameters():
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') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -232,7 +234,9 @@ def test_create_archive_with_patterns_calls_borg_with_patterns():
flexmock(module).should_receive('_make_pattern_flags').and_return(pattern_flags)
flexmock(module).should_receive('_make_exclude_flags').and_return(())
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create') + pattern_flags + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -258,7 +262,9 @@ def test_create_archive_with_exclude_patterns_calls_borg_with_excludes():
flexmock(module).should_receive('_make_pattern_flags').and_return(())
flexmock(module).should_receive('_make_exclude_flags').and_return(exclude_flags)
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create') + exclude_flags + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -284,6 +290,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--list', '--filter', 'AME-', '--info', '--stats') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
@@ -308,7 +315,9 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output():
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', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None
('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
output_log_level=None,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
@@ -336,6 +345,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter():
('borg', 'create', '--list', '--filter', 'AME-', '--stats', '--debug', '--show-rc')
+ ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
insert_logging_mock(logging.DEBUG)
@@ -359,7 +369,9 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output():
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', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None
('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
output_log_level=None,
error_on_warnings=False,
)
insert_logging_mock(logging.DEBUG)
@@ -385,7 +397,9 @@ def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter():
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', '--dry-run') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--dry-run') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -414,6 +428,7 @@ def test_create_archive_with_dry_run_and_log_info_calls_borg_without_stats_param
('borg', 'create', '--list', '--filter', 'AME-', '--info', '--dry-run')
+ ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
@@ -443,6 +458,7 @@ def test_create_archive_with_dry_run_and_log_debug_calls_borg_without_stats_para
('borg', 'create', '--list', '--filter', 'AME-', '--debug', '--show-rc', '--dry-run')
+ ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
insert_logging_mock(logging.DEBUG)
@@ -468,6 +484,7 @@ def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_inte
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--checkpoint-interval', '600') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -492,6 +509,7 @@ def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_param
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--chunker-params', '1,2,3,4') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -516,6 +534,7 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters(
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--compression', 'rle') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -540,6 +559,7 @@ def test_create_archive_with_remote_rate_limit_calls_borg_with_remote_ratelimit_
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--remote-ratelimit', '100') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -562,7 +582,9 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par
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', '--one-file-system') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--one-file-system') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -586,7 +608,9 @@ def test_create_archive_with_numeric_owner_calls_borg_with_numeric_owner_paramet
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', '--numeric-owner') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--numeric-owner') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -610,7 +634,9 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter
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', '--read-special') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--read-special') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -635,7 +661,9 @@ def test_create_archive_with_option_true_calls_borg_without_corresponding_parame
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') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -662,6 +690,7 @@ def test_create_archive_with_option_false_calls_borg_with_corresponding_paramete
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--no' + option_name.replace('_', '')) + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -687,6 +716,7 @@ def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters(
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--files-cache', 'ctime,size') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -710,7 +740,9 @@ def test_create_archive_with_local_path_calls_borg_via_local_path():
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(
('borg1', 'create') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg1', 'create') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -736,6 +768,7 @@ def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters(
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', '--remote-path', 'borg1') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -759,7 +792,9 @@ def test_create_archive_with_umask_calls_borg_with_umask_parameters():
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', '--umask', '740') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--umask', '740') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -782,7 +817,9 @@ def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters():
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', '--lock-wait', '5') + ARCHIVE_WITH_PATHS, output_log_level=logging.INFO
('borg', 'create', '--lock-wait', '5') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -805,7 +842,9 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter():
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', '--stats') + ARCHIVE_WITH_PATHS, output_log_level=logging.WARNING
('borg', 'create', '--stats') + ARCHIVE_WITH_PATHS,
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.create_archive(
@@ -821,6 +860,32 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter():
)
def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_parameter_and_no_list():
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
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_without_capture').with_args(
('borg', 'create', '--info', '--stats', '--progress') + ARCHIVE_WITH_PATHS,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
module.create_archive(
dry_run=False,
repository='repo',
location_config={
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
},
storage_config={},
progress=True,
)
def test_create_archive_with_progress_calls_borg_with_progress_parameter():
flexmock(module).should_receive('borgmatic_source_directories').and_return([])
flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
@@ -829,7 +894,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter():
flexmock(module).should_receive('_make_pattern_flags').and_return(())
flexmock(module).should_receive('_make_exclude_flags').and_return(())
flexmock(module).should_receive('execute_command_without_capture').with_args(
('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS
('borg', 'create', '--progress') + ARCHIVE_WITH_PATHS, error_on_warnings=False
)
module.create_archive(
@@ -853,7 +918,9 @@ def test_create_archive_with_json_calls_borg_with_json_parameter():
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', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None
('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
output_log_level=None,
error_on_warnings=False,
).and_return('[]')
json_output = module.create_archive(
@@ -879,7 +946,9 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_parameter()
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', '--json') + ARCHIVE_WITH_PATHS, output_log_level=None
('borg', 'create', '--json') + ARCHIVE_WITH_PATHS,
output_log_level=None,
error_on_warnings=False,
).and_return('[]')
json_output = module.create_archive(
@@ -908,6 +977,7 @@ def test_create_archive_with_source_directories_glob_expands():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
output_log_level=logging.INFO,
error_on_warnings=False,
)
flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
@@ -933,6 +1003,7 @@ def test_create_archive_with_non_matching_source_directories_glob_passes_through
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo*'),
output_log_level=logging.INFO,
error_on_warnings=False,
)
flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([])
@@ -958,6 +1029,7 @@ def test_create_archive_with_glob_calls_borg_with_expanded_directories():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food'),
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -980,7 +1052,9 @@ def test_create_archive_with_archive_name_format_calls_borg_with_archive_name():
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', 'repo::ARCHIVE_NAME', 'foo', 'bar'), output_log_level=logging.INFO
('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'),
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -1005,6 +1079,7 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'create', 'repo::Documents_{hostname}-{now}', 'foo', 'bar'),
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
@@ -1017,3 +1092,28 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders():
},
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('_expand_directories').and_return(('foo', 'bar'))
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', '--extra', '--options') + ARCHIVE_WITH_PATHS,
output_log_level=logging.INFO,
error_on_warnings=False,
)
module.create_archive(
dry_run=False,
repository='repo',
location_config={
'source_directories': ['foo', 'bar'],
'repositories': ['repo'],
'exclude_patterns': None,
},
storage_config={'extra_borg_options': {'create': '--extra --options'}},
)
+1 -1
View File
@@ -15,7 +15,7 @@ def insert_execute_command_mock(command, working_directory=None, error_on_warnin
def insert_execute_command_output_mock(command, result):
flexmock(module).should_receive('execute_command').with_args(
command, output_log_level=None
command, output_log_level=None, error_on_warnings=False
).and_return(result).once()
+19 -10
View File
@@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock
def test_display_archives_info_calls_borg_with_parameters():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', 'repo'), output_log_level=logging.WARNING
('borg', 'info', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.display_archives_info(
@@ -20,7 +20,9 @@ def test_display_archives_info_calls_borg_with_parameters():
def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--info', 'repo'), output_log_level=logging.WARNING
('borg', 'info', '--info', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
module.display_archives_info(
@@ -30,7 +32,7 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter():
def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_output():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--json', 'repo'), output_log_level=None
('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False
).and_return('[]')
insert_logging_mock(logging.INFO)
@@ -43,7 +45,9 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu
def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--debug', '--show-rc', 'repo'), output_log_level=logging.WARNING
('borg', 'info', '--debug', '--show-rc', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
insert_logging_mock(logging.DEBUG)
@@ -54,7 +58,7 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter():
def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_output():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--json', 'repo'), output_log_level=None
('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False
).and_return('[]')
insert_logging_mock(logging.DEBUG)
@@ -67,7 +71,7 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp
def test_display_archives_info_with_json_calls_borg_with_json_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--json', 'repo'), output_log_level=None
('borg', 'info', '--json', 'repo'), output_log_level=None, error_on_warnings=False
).and_return('[]')
json_output = module.display_archives_info(
@@ -79,7 +83,7 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter():
def test_display_archives_info_with_archive_calls_borg_with_archive_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', 'repo::archive'), output_log_level=logging.WARNING
('borg', 'info', 'repo::archive'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.display_archives_info(
@@ -89,7 +93,7 @@ def test_display_archives_info_with_archive_calls_borg_with_archive_parameter():
def test_display_archives_info_with_local_path_calls_borg_via_local_path():
flexmock(module).should_receive('execute_command').with_args(
('borg1', 'info', 'repo'), output_log_level=logging.WARNING
('borg1', 'info', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.display_archives_info(
@@ -102,7 +106,9 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path():
def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_parameters():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--remote-path', 'borg1', 'repo'), output_log_level=logging.WARNING
('borg', 'info', '--remote-path', 'borg1', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.display_archives_info(
@@ -116,7 +122,9 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para
def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_parameters():
storage_config = {'lock_wait': 5}
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--lock-wait', '5', 'repo'), output_log_level=logging.WARNING
('borg', 'info', '--lock-wait', '5', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.display_archives_info(
@@ -131,6 +139,7 @@ def test_display_archives_info_passes_through_arguments_to_borg(argument_name):
flexmock(module).should_receive('execute_command').with_args(
('borg', 'info', '--' + argument_name.replace('_', '-'), 'value', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.display_archives_info(
+34 -11
View File
@@ -24,7 +24,7 @@ def insert_info_command_not_found_mock():
def insert_init_command_mock(init_command, **kwargs):
flexmock(module).should_receive('execute_command_without_capture').with_args(
init_command
init_command, error_on_warnings=False
).once()
@@ -32,7 +32,7 @@ def test_initialize_repository_calls_borg_with_parameters():
insert_info_command_not_found_mock()
insert_init_command_mock(INIT_COMMAND + ('repo',))
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(repository='repo', storage_config={}, encryption_mode='repokey')
def test_initialize_repository_raises_for_borg_init_error():
@@ -42,14 +42,16 @@ def test_initialize_repository_raises_for_borg_init_error():
)
with pytest.raises(subprocess.CalledProcessError):
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey'
)
def test_initialize_repository_skips_initialization_when_repository_already_exists():
insert_info_command_found_mock()
flexmock(module).should_receive('execute_command_without_capture').never()
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(repository='repo', storage_config={}, encryption_mode='repokey')
def test_initialize_repository_raises_for_unknown_info_command_error():
@@ -58,21 +60,27 @@ def test_initialize_repository_raises_for_unknown_info_command_error():
)
with pytest.raises(subprocess.CalledProcessError):
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey'
)
def test_initialize_repository_with_append_only_calls_borg_with_append_only_parameter():
insert_info_command_not_found_mock()
insert_init_command_mock(INIT_COMMAND + ('--append-only', 'repo'))
module.initialize_repository(repository='repo', encryption_mode='repokey', append_only=True)
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey', append_only=True
)
def test_initialize_repository_with_storage_quota_calls_borg_with_storage_quota_parameter():
insert_info_command_not_found_mock()
insert_init_command_mock(INIT_COMMAND + ('--storage-quota', '5G', 'repo'))
module.initialize_repository(repository='repo', encryption_mode='repokey', storage_quota='5G')
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey', storage_quota='5G'
)
def test_initialize_repository_with_log_info_calls_borg_with_info_parameter():
@@ -80,7 +88,7 @@ def test_initialize_repository_with_log_info_calls_borg_with_info_parameter():
insert_init_command_mock(INIT_COMMAND + ('--info', 'repo'))
insert_logging_mock(logging.INFO)
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(repository='repo', storage_config={}, encryption_mode='repokey')
def test_initialize_repository_with_log_debug_calls_borg_with_debug_parameter():
@@ -88,18 +96,33 @@ def test_initialize_repository_with_log_debug_calls_borg_with_debug_parameter():
insert_init_command_mock(INIT_COMMAND + ('--debug', 'repo'))
insert_logging_mock(logging.DEBUG)
module.initialize_repository(repository='repo', encryption_mode='repokey')
module.initialize_repository(repository='repo', storage_config={}, encryption_mode='repokey')
def test_initialize_repository_with_local_path_calls_borg_via_local_path():
insert_info_command_not_found_mock()
insert_init_command_mock(('borg1',) + INIT_COMMAND[1:] + ('repo',))
module.initialize_repository(repository='repo', encryption_mode='repokey', local_path='borg1')
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey', local_path='borg1'
)
def test_initialize_repository_with_remote_path_calls_borg_with_remote_path_parameter():
insert_info_command_not_found_mock()
insert_init_command_mock(INIT_COMMAND + ('--remote-path', 'borg1', 'repo'))
module.initialize_repository(repository='repo', encryption_mode='repokey', remote_path='borg1')
module.initialize_repository(
repository='repo', storage_config={}, encryption_mode='repokey', remote_path='borg1'
)
def test_initialize_repository_with_extra_borg_options_calls_borg_with_extra_options():
insert_info_command_not_found_mock()
insert_init_command_mock(INIT_COMMAND + ('--extra', '--options', 'repo'))
module.initialize_repository(
repository='repo',
storage_config={'extra_borg_options': {'init': '--extra --options'}},
encryption_mode='repokey',
)
+23 -11
View File
@@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock
def test_list_archives_calls_borg_with_parameters():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', 'repo'), output_log_level=logging.WARNING
('borg', 'list', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.list_archives(
@@ -22,7 +22,9 @@ def test_list_archives_calls_borg_with_parameters():
def test_list_archives_with_log_info_calls_borg_with_info_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--info', 'repo'), output_log_level=logging.WARNING
('borg', 'list', '--info', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
insert_logging_mock(logging.INFO)
@@ -35,7 +37,7 @@ def test_list_archives_with_log_info_calls_borg_with_info_parameter():
def test_list_archives_with_log_info_and_json_suppresses_most_borg_output():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--json', 'repo'), output_log_level=None
('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False
)
insert_logging_mock(logging.INFO)
@@ -48,7 +50,9 @@ def test_list_archives_with_log_info_and_json_suppresses_most_borg_output():
def test_list_archives_with_log_debug_calls_borg_with_debug_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--debug', '--show-rc', 'repo'), output_log_level=logging.WARNING
('borg', 'list', '--debug', '--show-rc', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
insert_logging_mock(logging.DEBUG)
@@ -61,7 +65,7 @@ def test_list_archives_with_log_debug_calls_borg_with_debug_parameter():
def test_list_archives_with_log_debug_and_json_suppresses_most_borg_output():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--json', 'repo'), output_log_level=None
('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False
)
insert_logging_mock(logging.DEBUG)
@@ -75,7 +79,9 @@ def test_list_archives_with_log_debug_and_json_suppresses_most_borg_output():
def test_list_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
storage_config = {'lock_wait': 5}
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--lock-wait', '5', 'repo'), output_log_level=logging.WARNING
('borg', 'list', '--lock-wait', '5', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.list_archives(
@@ -88,7 +94,7 @@ def test_list_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
def test_list_archives_with_archive_calls_borg_with_archive_parameter():
storage_config = {}
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', 'repo::archive'), output_log_level=logging.WARNING
('borg', 'list', 'repo::archive'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.list_archives(
@@ -100,7 +106,7 @@ def test_list_archives_with_archive_calls_borg_with_archive_parameter():
def test_list_archives_with_local_path_calls_borg_via_local_path():
flexmock(module).should_receive('execute_command').with_args(
('borg1', 'list', 'repo'), output_log_level=logging.WARNING
('borg1', 'list', 'repo'), output_log_level=logging.WARNING, error_on_warnings=False
)
module.list_archives(
@@ -113,7 +119,9 @@ def test_list_archives_with_local_path_calls_borg_via_local_path():
def test_list_archives_with_remote_path_calls_borg_with_remote_path_parameters():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--remote-path', 'borg1', 'repo'), output_log_level=logging.WARNING
('borg', 'list', '--remote-path', 'borg1', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
)
module.list_archives(
@@ -126,7 +134,9 @@ def test_list_archives_with_remote_path_calls_borg_with_remote_path_parameters()
def test_list_archives_with_short_calls_borg_with_short_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--short', 'repo'), output_log_level=logging.WARNING
('borg', 'list', '--short', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
).and_return('[]')
module.list_archives(
@@ -154,6 +164,7 @@ def test_list_archives_passes_through_arguments_to_borg(argument_name):
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
).and_return('[]')
module.list_archives(
@@ -169,6 +180,7 @@ def test_list_archives_with_successful_calls_borg_to_exclude_checkpoints():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--glob-archives', module.BORG_EXCLUDE_CHECKPOINTS_GLOB, 'repo'),
output_log_level=logging.WARNING,
error_on_warnings=False,
).and_return('[]')
module.list_archives(
@@ -180,7 +192,7 @@ def test_list_archives_with_successful_calls_borg_to_exclude_checkpoints():
def test_list_archives_with_json_calls_borg_with_json_parameter():
flexmock(module).should_receive('execute_command').with_args(
('borg', 'list', '--json', 'repo'), output_log_level=None
('borg', 'list', '--json', 'repo'), output_log_level=None, error_on_warnings=False
).and_return('[]')
json_output = module.list_archives(
+4 -2
View File
@@ -8,7 +8,9 @@ from ..test_verbosity import insert_logging_mock
def insert_execute_command_mock(command):
flexmock(module).should_receive('execute_command').with_args(command).once()
flexmock(module).should_receive('execute_command').with_args(
command, error_on_warnings=False
).once()
def test_mount_archive_calls_borg_with_required_parameters():
@@ -116,7 +118,7 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_parameters():
def test_mount_archive_calls_borg_with_foreground_parameter():
flexmock(module).should_receive('execute_command_without_capture').with_args(
('borg', 'mount', '--foreground', 'repo::archive', '/mnt')
('borg', 'mount', '--foreground', 'repo::archive', '/mnt'), error_on_warnings=False
).once()
module.mount_archive(
+16 -1
View File
@@ -10,7 +10,7 @@ from ..test_verbosity import insert_logging_mock
def insert_execute_command_mock(prune_command, output_log_level):
flexmock(module).should_receive('execute_command').with_args(
prune_command, output_log_level=output_log_level
prune_command, output_log_level=output_log_level, error_on_warnings=False
).once()
@@ -188,3 +188,18 @@ def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
storage_config=storage_config,
retention_config=retention_config,
)
def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options():
retention_config = flexmock()
flexmock(module).should_receive('_make_prune_flags').with_args(retention_config).and_return(
BASE_PRUNE_FLAGS
)
insert_execute_command_mock(PRUNE_COMMAND + ('--extra', '--options', 'repo'), logging.INFO)
module.prune_archives(
dry_run=False,
repository='repo',
storage_config={'extra_borg_options': {'prune': '--extra --options'}},
retention_config=retention_config,
)
+9 -7
View File
@@ -60,7 +60,7 @@ def test_ping_monitor_hits_ping_url_for_start_state():
flexmock(module).should_receive('Forgetful_buffering_handler')
ping_url = 'https://example.com'
flexmock(module.requests).should_receive('post').with_args(
'{}/{}'.format(ping_url, 'start'), data=''
'{}/{}'.format(ping_url, 'start'), data=''.encode('utf-8')
)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.START, dry_run=False)
@@ -68,19 +68,21 @@ def test_ping_monitor_hits_ping_url_for_start_state():
def test_ping_monitor_hits_ping_url_for_finish_state():
ping_url = 'https://example.com'
payload = flexmock()
payload = 'data'
flexmock(module).should_receive('format_buffered_logs_for_payload').and_return(payload)
flexmock(module.requests).should_receive('post').with_args(ping_url, data=payload)
flexmock(module.requests).should_receive('post').with_args(
ping_url, data=payload.encode('utf-8')
)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.FINISH, dry_run=False)
def test_ping_monitor_hits_ping_url_for_fail_state():
ping_url = 'https://example.com'
payload = flexmock()
payload = 'data'
flexmock(module).should_receive('format_buffered_logs_for_payload').and_return(payload)
flexmock(module.requests).should_receive('post').with_args(
'{}/{}'.format(ping_url, 'fail'), data=payload
'{}/{}'.format(ping_url, 'fail'), data=payload.encode('utf')
)
module.ping_monitor(ping_url, 'config.yaml', state=module.monitor.State.FAIL, dry_run=False)
@@ -88,10 +90,10 @@ def test_ping_monitor_hits_ping_url_for_fail_state():
def test_ping_monitor_with_ping_uuid_hits_corresponding_url():
ping_uuid = 'abcd-efgh-ijkl-mnop'
payload = flexmock()
payload = 'data'
flexmock(module).should_receive('format_buffered_logs_for_payload').and_return(payload)
flexmock(module.requests).should_receive('post').with_args(
'https://hc-ping.com/{}'.format(ping_uuid), data=payload
'https://hc-ping.com/{}'.format(ping_uuid), data=payload.encode('utf-8')
)
module.ping_monitor(ping_uuid, 'config.yaml', state=module.monitor.State.FINISH, dry_run=False)
+19 -35
View File
@@ -4,44 +4,28 @@ from flexmock import flexmock
from borgmatic import execute as module
def test_exit_code_indicates_error_with_borg_error_is_true():
assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 2)
def test_exit_code_indicates_error_with_borg_warning_is_false():
assert not module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 1)
def test_exit_code_indicates_error_with_borg_success_is_false():
assert not module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 0)
def test_exit_code_indicates_error_with_borg_error_and_error_on_warnings_is_true():
assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 2, error_on_warnings=True)
def test_exit_code_indicates_error_with_borg_warning_and_error_on_warnings_is_true():
assert module.exit_code_indicates_error(('/usr/bin/borg1', 'init'), 1, error_on_warnings=True)
def test_exit_code_indicates_error_with_borg_success_and_error_on_warnings_is_false():
assert not module.exit_code_indicates_error(
('/usr/bin/borg1', 'init'), 0, error_on_warnings=True
@pytest.mark.parametrize(
'exit_code,error_on_warnings,expected_result',
(
(2, True, True),
(2, False, True),
(1, True, True),
(1, False, False),
(0, True, False),
(0, False, False),
),
)
def test_exit_code_indicates_error_respects_exit_code_and_error_on_warnings(
exit_code, error_on_warnings, expected_result
):
assert (
module.exit_code_indicates_error(
('command',), exit_code, error_on_warnings=error_on_warnings
)
is expected_result
)
def test_exit_code_indicates_error_with_non_borg_error_is_true():
assert module.exit_code_indicates_error(('/usr/bin/command',), 2)
def test_exit_code_indicates_error_with_non_borg_warning_is_true():
assert module.exit_code_indicates_error(('/usr/bin/command',), 1)
def test_exit_code_indicates_error_with_non_borg_success_is_false():
assert not module.exit_code_indicates_error(('/usr/bin/command',), 0)
def test_execute_command_calls_full_command():
full_command = ['foo', 'bar']
flexmock(module.os, environ={'a': 'b'})