From 92a2230a07e9e6e3a6024c3e86dbc3cfe7208187 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Mon, 8 May 2023 23:00:49 -0700 Subject: [PATCH] Add support for logging each log line as a JSON object via global "--log-json" flag (#680). --- NEWS | 1 + borgmatic/actions/borg.py | 2 + borgmatic/actions/break_lock.py | 2 + borgmatic/actions/check.py | 1 + borgmatic/actions/compact.py | 1 + borgmatic/actions/create.py | 1 + borgmatic/actions/export_tar.py | 2 + borgmatic/actions/extract.py | 2 + borgmatic/actions/info.py | 9 +- borgmatic/actions/list.py | 9 +- borgmatic/actions/mount.py | 3 + borgmatic/actions/prune.py | 1 + borgmatic/actions/rcreate.py | 1 + borgmatic/actions/restore.py | 11 +- borgmatic/actions/rinfo.py | 2 + borgmatic/actions/rlist.py | 2 + borgmatic/actions/transfer.py | 1 + borgmatic/borg/break_lock.py | 6 +- borgmatic/borg/check.py | 11 +- borgmatic/borg/compact.py | 2 + borgmatic/borg/create.py | 2 + borgmatic/borg/export_tar.py | 2 + borgmatic/borg/extract.py | 24 +++-- borgmatic/borg/info.py | 8 +- borgmatic/borg/list.py | 24 +++-- borgmatic/borg/mount.py | 6 +- borgmatic/borg/prune.py | 2 + borgmatic/borg/rcreate.py | 5 + borgmatic/borg/rinfo.py | 8 +- borgmatic/borg/rlist.py | 30 +++--- borgmatic/borg/transfer.py | 5 +- borgmatic/commands/arguments.py | 5 + borgmatic/commands/borgmatic.py | 11 +- tests/integration/borg/test_commands.py | 26 ++++- tests/unit/actions/test_borg.py | 1 + tests/unit/actions/test_break_lock.py | 1 + tests/unit/actions/test_info.py | 1 + tests/unit/actions/test_list.py | 1 + tests/unit/actions/test_mount.py | 1 + tests/unit/actions/test_restore.py | 3 + tests/unit/actions/test_rinfo.py | 1 + tests/unit/actions/test_rlist.py | 1 + tests/unit/borg/test_break_lock.py | 18 ++++ tests/unit/borg/test_check.py | 46 ++++++++ tests/unit/borg/test_compact.py | 45 +++++++- tests/unit/borg/test_create.py | 89 +++++++++++++++ tests/unit/borg/test_export_tar.py | 33 ++++++ tests/unit/borg/test_extract.py | 98 ++++++++++++++--- tests/unit/borg/test_info.py | 45 ++++++++ tests/unit/borg/test_list.py | 62 ++++++++++- tests/unit/borg/test_mount.py | 31 ++++++ tests/unit/borg/test_prune.py | 46 ++++++-- tests/unit/borg/test_rcreate.py | 57 ++++++++++ tests/unit/borg/test_rinfo.py | 49 +++++++-- tests/unit/borg/test_rlist.py | 138 +++++++++++++++++++++--- tests/unit/borg/test_transfer.py | 44 ++++++++ 56 files changed, 934 insertions(+), 105 deletions(-) diff --git a/NEWS b/NEWS index 8be142b9a..17560d7e9 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ commands with arguments. * #678: Fix calls to psql in PostgreSQL hook to ignore "~/.psqlrc", whose settings can break database dumping. + * #680: Add support for logging each log line as a JSON object via global "--log-json" flag. * #682: Fix "source_directories_must_exist" option to expand globs and tildes in source directories. * #684: Rename "master" development branch to "main" to use more inclusive language. You'll need to update your development checkouts accordingly. diff --git a/borgmatic/actions/borg.py b/borgmatic/actions/borg.py index 3d2998b66..ec445fbbc 100644 --- a/borgmatic/actions/borg.py +++ b/borgmatic/actions/borg.py @@ -12,6 +12,7 @@ def run_borg( storage, local_borg_version, borg_arguments, + global_arguments, local_path, remote_path, ): @@ -27,6 +28,7 @@ def run_borg( borg_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ) diff --git a/borgmatic/actions/break_lock.py b/borgmatic/actions/break_lock.py index 2174161ca..f049e7725 100644 --- a/borgmatic/actions/break_lock.py +++ b/borgmatic/actions/break_lock.py @@ -11,6 +11,7 @@ def run_break_lock( storage, local_borg_version, break_lock_arguments, + global_arguments, local_path, remote_path, ): @@ -25,6 +26,7 @@ def run_break_lock( repository['path'], storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, ) diff --git a/borgmatic/actions/check.py b/borgmatic/actions/check.py index 1696e07d5..aac536e3b 100644 --- a/borgmatic/actions/check.py +++ b/borgmatic/actions/check.py @@ -44,6 +44,7 @@ def run_check( storage, consistency, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, progress=check_arguments.progress, diff --git a/borgmatic/actions/compact.py b/borgmatic/actions/compact.py index 95334c526..24b30c0e1 100644 --- a/borgmatic/actions/compact.py +++ b/borgmatic/actions/compact.py @@ -45,6 +45,7 @@ def run_compact( repository['path'], storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, progress=compact_arguments.progress, diff --git a/borgmatic/actions/create.py b/borgmatic/actions/create.py index 3fbe31e64..a3f8da57c 100644 --- a/borgmatic/actions/create.py +++ b/borgmatic/actions/create.py @@ -67,6 +67,7 @@ def run_create( location, storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, progress=create_arguments.progress, diff --git a/borgmatic/actions/export_tar.py b/borgmatic/actions/export_tar.py index ff9f31baa..798bd418f 100644 --- a/borgmatic/actions/export_tar.py +++ b/borgmatic/actions/export_tar.py @@ -33,6 +33,7 @@ def run_export_tar( export_tar_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ), @@ -40,6 +41,7 @@ def run_export_tar( export_tar_arguments.destination, storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, tar_filter=export_tar_arguments.tar_filter, diff --git a/borgmatic/actions/extract.py b/borgmatic/actions/extract.py index cc1516cee..1f4317cd4 100644 --- a/borgmatic/actions/extract.py +++ b/borgmatic/actions/extract.py @@ -44,6 +44,7 @@ def run_extract( extract_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ), @@ -51,6 +52,7 @@ def run_extract( location, storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, destination_path=extract_arguments.destination, diff --git a/borgmatic/actions/info.py b/borgmatic/actions/info.py index 54023127e..d138dbd43 100644 --- a/borgmatic/actions/info.py +++ b/borgmatic/actions/info.py @@ -13,6 +13,7 @@ def run_info( storage, local_borg_version, info_arguments, + global_arguments, local_path, remote_path, ): @@ -31,6 +32,7 @@ def run_info( info_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ) @@ -38,9 +40,10 @@ def run_info( repository['path'], storage, local_borg_version, - info_arguments=info_arguments, - local_path=local_path, - remote_path=remote_path, + info_arguments, + global_arguments, + local_path, + remote_path, ) if json_output: # pragma: nocover yield json.loads(json_output) diff --git a/borgmatic/actions/list.py b/borgmatic/actions/list.py index 359f3b671..548f19796 100644 --- a/borgmatic/actions/list.py +++ b/borgmatic/actions/list.py @@ -12,6 +12,7 @@ def run_list( storage, local_borg_version, list_arguments, + global_arguments, local_path, remote_path, ): @@ -33,6 +34,7 @@ def run_list( list_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ) @@ -40,9 +42,10 @@ def run_list( repository['path'], storage, local_borg_version, - list_arguments=list_arguments, - local_path=local_path, - remote_path=remote_path, + list_arguments, + global_arguments, + local_path, + remote_path, ) if json_output: # pragma: nocover yield json.loads(json_output) diff --git a/borgmatic/actions/mount.py b/borgmatic/actions/mount.py index 72e321a0a..60f7f23c4 100644 --- a/borgmatic/actions/mount.py +++ b/borgmatic/actions/mount.py @@ -12,6 +12,7 @@ def run_mount( storage, local_borg_version, mount_arguments, + global_arguments, local_path, remote_path, ): @@ -33,6 +34,7 @@ def run_mount( mount_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ), @@ -42,6 +44,7 @@ def run_mount( mount_arguments.options, storage, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, ) diff --git a/borgmatic/actions/prune.py b/borgmatic/actions/prune.py index 9a5d936b8..2e25264bc 100644 --- a/borgmatic/actions/prune.py +++ b/borgmatic/actions/prune.py @@ -44,6 +44,7 @@ def run_prune( storage, retention, local_borg_version, + global_arguments, local_path=local_path, remote_path=remote_path, stats=prune_arguments.stats, diff --git a/borgmatic/actions/rcreate.py b/borgmatic/actions/rcreate.py index 62206318c..a3015c617 100644 --- a/borgmatic/actions/rcreate.py +++ b/borgmatic/actions/rcreate.py @@ -29,6 +29,7 @@ def run_rcreate( repository['path'], storage, local_borg_version, + global_arguments, rcreate_arguments.encryption_mode, rcreate_arguments.source_repository, rcreate_arguments.copy_crypt_key, diff --git a/borgmatic/actions/restore.py b/borgmatic/actions/restore.py index f061dca82..246c11a6e 100644 --- a/borgmatic/actions/restore.py +++ b/borgmatic/actions/restore.py @@ -93,6 +93,7 @@ def restore_single_database( location_config=location, storage_config=storage, local_borg_version=local_borg_version, + global_arguments=global_arguments, local_path=local_path, remote_path=remote_path, destination_path='/', @@ -119,14 +120,15 @@ def collect_archive_database_names( location, storage, local_borg_version, + global_arguments, local_path, remote_path, ): ''' Given a local or remote repository path, a resolved archive name, a location configuration dict, - a storage configuration dict, the local Borg version, and local and remote Borg paths, query the - archive for the names of databases it contains and return them as a dict from hook name to a - sequence of database names. + a storage configuration dict, the local Borg version, global_arguments an argparse.Namespace, + and local and remote Borg paths, query the archive for the names of databases it contains and + return them as a dict from hook name to a sequence of database names. ''' borgmatic_source_directory = os.path.expanduser( location.get( @@ -141,6 +143,7 @@ def collect_archive_database_names( archive, storage, local_borg_version, + global_arguments, list_path=parent_dump_path, local_path=local_path, remote_path=remote_path, @@ -279,6 +282,7 @@ def run_restore( restore_arguments.archive, storage, local_borg_version, + global_arguments, local_path, remote_path, ) @@ -288,6 +292,7 @@ def run_restore( location, storage, local_borg_version, + global_arguments, local_path, remote_path, ) diff --git a/borgmatic/actions/rinfo.py b/borgmatic/actions/rinfo.py index 0947ec3d8..279cd0e78 100644 --- a/borgmatic/actions/rinfo.py +++ b/borgmatic/actions/rinfo.py @@ -12,6 +12,7 @@ def run_rinfo( storage, local_borg_version, rinfo_arguments, + global_arguments, local_path, remote_path, ): @@ -31,6 +32,7 @@ def run_rinfo( storage, local_borg_version, rinfo_arguments=rinfo_arguments, + global_arguments=global_arguments, local_path=local_path, remote_path=remote_path, ) diff --git a/borgmatic/actions/rlist.py b/borgmatic/actions/rlist.py index 10d06a513..50c59b6f5 100644 --- a/borgmatic/actions/rlist.py +++ b/borgmatic/actions/rlist.py @@ -12,6 +12,7 @@ def run_rlist( storage, local_borg_version, rlist_arguments, + global_arguments, local_path, remote_path, ): @@ -31,6 +32,7 @@ def run_rlist( storage, local_borg_version, rlist_arguments=rlist_arguments, + global_arguments=global_arguments, local_path=local_path, remote_path=remote_path, ) diff --git a/borgmatic/actions/transfer.py b/borgmatic/actions/transfer.py index 8089fd4e2..36ac166de 100644 --- a/borgmatic/actions/transfer.py +++ b/borgmatic/actions/transfer.py @@ -24,6 +24,7 @@ def run_transfer( storage, local_borg_version, transfer_arguments, + global_arguments, local_path=local_path, remote_path=remote_path, ) diff --git a/borgmatic/borg/break_lock.py b/borgmatic/borg/break_lock.py index 7099af831..3c361956c 100644 --- a/borgmatic/borg/break_lock.py +++ b/borgmatic/borg/break_lock.py @@ -10,13 +10,14 @@ def break_lock( repository_path, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, a storage configuration dict, the local Borg version, - and optional local and remote Borg paths, break any repository and cache locks leftover from Borg - aborting. + an argparse.Namespace of global arguments, and optional local and remote Borg paths, break any + repository and cache locks leftover from Borg aborting. ''' umask = storage_config.get('umask', None) lock_wait = storage_config.get('lock_wait', None) @@ -25,6 +26,7 @@ def break_lock( (local_path, 'break-lock') + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) diff --git a/borgmatic/borg/check.py b/borgmatic/borg/check.py index cee9d923e..52d5208c1 100644 --- a/borgmatic/borg/check.py +++ b/borgmatic/borg/check.py @@ -259,6 +259,7 @@ def check_archives( storage_config, consistency_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, progress=None, @@ -283,6 +284,7 @@ def check_archives( storage_config, local_borg_version, argparse.Namespace(json=True), + global_arguments, local_path, remote_path, ) @@ -317,6 +319,7 @@ def check_archives( + (('--repair',) if repair else ()) + make_check_flags(local_borg_version, storage_config, checks, check_last, prefix) + (('--remote-path', remote_path) if remote_path else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + verbosity_flags + (('--progress',) if progress else ()) @@ -340,6 +343,12 @@ def check_archives( if 'extract' in checks: extract.extract_last_archive_dry_run( - storage_config, local_borg_version, repository_path, lock_wait, local_path, remote_path + storage_config, + local_borg_version, + global_arguments, + repository_path, + lock_wait, + local_path, + remote_path, ) write_check_time(make_check_time_path(location_config, borg_repository_id, 'extract')) diff --git a/borgmatic/borg/compact.py b/borgmatic/borg/compact.py index 0e9d3e89c..24f37ee30 100644 --- a/borgmatic/borg/compact.py +++ b/borgmatic/borg/compact.py @@ -11,6 +11,7 @@ def compact_segments( repository_path, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, progress=False, @@ -29,6 +30,7 @@ def compact_segments( (local_path, 'compact') + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--progress',) if progress else ()) + (('--cleanup-commits',) if cleanup_commits else ()) diff --git a/borgmatic/borg/create.py b/borgmatic/borg/create.py index 7413dfc5c..e3b70eb57 100644 --- a/borgmatic/borg/create.py +++ b/borgmatic/borg/create.py @@ -326,6 +326,7 @@ def create_archive( location_config, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, progress=False, @@ -438,6 +439,7 @@ def create_archive( + (('--files-cache', files_cache) if files_cache else ()) + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + ( ('--list', '--filter', list_filter_flags) diff --git a/borgmatic/borg/export_tar.py b/borgmatic/borg/export_tar.py index a624f07d6..b6d9a04c5 100644 --- a/borgmatic/borg/export_tar.py +++ b/borgmatic/borg/export_tar.py @@ -15,6 +15,7 @@ def export_tar_archive( destination_path, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, tar_filter=None, @@ -38,6 +39,7 @@ def export_tar_archive( (local_path, 'export-tar') + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--list',) if list_files else ()) diff --git a/borgmatic/borg/extract.py b/borgmatic/borg/extract.py index 1b10ba26e..d5465bb97 100644 --- a/borgmatic/borg/extract.py +++ b/borgmatic/borg/extract.py @@ -12,6 +12,7 @@ logger = logging.getLogger(__name__) def extract_last_archive_dry_run( storage_config, local_borg_version, + global_arguments, repository_path, lock_wait=None, local_path='borg', @@ -21,8 +22,6 @@ def extract_last_archive_dry_run( Perform an extraction dry-run of the most recent archive. If there are no archives, skip the dry-run. ''' - remote_path_flags = ('--remote-path', remote_path) if remote_path else () - lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else () verbosity_flags = () if logger.isEnabledFor(logging.DEBUG): verbosity_flags = ('--debug', '--show-rc') @@ -31,7 +30,13 @@ def extract_last_archive_dry_run( try: last_archive_name = rlist.resolve_archive_name( - repository_path, 'latest', storage_config, local_borg_version, local_path, remote_path + repository_path, + 'latest', + storage_config, + local_borg_version, + global_arguments, + local_path, + remote_path, ) except ValueError: logger.warning('No archives found. Skipping extract consistency check.') @@ -41,8 +46,9 @@ def extract_last_archive_dry_run( borg_environment = environment.make_environment(storage_config) full_extract_command = ( (local_path, 'extract', '--dry-run') - + remote_path_flags - + lock_wait_flags + + (('--remote-path', remote_path) if remote_path else ()) + + (('--log-json',) if global_arguments.log_json else ()) + + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + verbosity_flags + list_flag + flags.make_repository_archive_flags( @@ -63,6 +69,7 @@ def extract_archive( location_config, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, destination_path=None, @@ -72,9 +79,9 @@ def extract_archive( ): ''' Given a dry-run flag, a local or remote repository path, an archive name, zero or more paths to - restore from the archive, the local Borg version string, location/storage configuration dicts, - optional local and remote Borg paths, and an optional destination path to extract to, extract - the archive into the current directory. + restore from the archive, the local Borg version string, an argparse.Namespace of global + arguments, location/storage configuration dicts, optional local and remote Borg paths, and an + optional destination path to extract to, extract the archive into the current directory. If extract to stdout is True, then start the extraction streaming to stdout, and return that extract process as an instance of subprocess.Popen. @@ -102,6 +109,7 @@ def extract_archive( + (('--remote-path', remote_path) if remote_path else ()) + numeric_ids_flags + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--list', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) diff --git a/borgmatic/borg/info.py b/borgmatic/borg/info.py index ef2c0c44b..91520e00b 100644 --- a/borgmatic/borg/info.py +++ b/borgmatic/borg/info.py @@ -12,13 +12,14 @@ def display_archives_info( storage_config, local_borg_version, info_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' - Given a local or remote repository path, a storage config dict, the local Borg version, and the - arguments to the info action, display summary information for Borg archives in the repository or - return JSON summary information. + Given a local or remote repository path, a storage config dict, the local Borg version, global + arguments as an argparse.Namespace, and the arguments to the info action, display summary + information for Borg archives in the repository or return JSON summary information. ''' borgmatic.logger.add_custom_log_levels() lock_wait = storage_config.get('lock_wait', None) @@ -36,6 +37,7 @@ def display_archives_info( else () ) + flags.make_flags('remote-path', remote_path) + + flags.make_flags('log-json', global_arguments.log_json) + flags.make_flags('lock-wait', lock_wait) + ( ( diff --git a/borgmatic/borg/list.py b/borgmatic/borg/list.py index 908f8fef1..96a6a87f9 100644 --- a/borgmatic/borg/list.py +++ b/borgmatic/borg/list.py @@ -25,6 +25,7 @@ def make_list_command( storage_config, local_borg_version, list_arguments, + global_arguments, local_path='borg', remote_path=None, ): @@ -48,6 +49,7 @@ def make_list_command( else () ) + flags.make_flags('remote-path', remote_path) + + flags.make_flags('log-json', global_arguments.log_json) + flags.make_flags('lock-wait', lock_wait) + flags.make_flags_from_arguments(list_arguments, excludes=MAKE_FLAGS_EXCLUDES) + ( @@ -90,14 +92,16 @@ def capture_archive_listing( archive, storage_config, local_borg_version, + global_arguments, list_path=None, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, an archive name, a storage config dict, the local Borg - version, the archive path in which to list files, and local and remote Borg paths, capture the - output of listing that archive and return it as a list of file paths. + version, global arguments as an argparse.Namespace, the archive path in which to list files, and + local and remote Borg paths, capture the output of listing that archive and return it as a list + of file paths. ''' borg_environment = environment.make_environment(storage_config) @@ -115,6 +119,7 @@ def capture_archive_listing( json=None, format='{path}{NL}', # noqa: FS003 ), + global_arguments, local_path, remote_path, ), @@ -130,15 +135,17 @@ def list_archive( storage_config, local_borg_version, list_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' - Given a local or remote repository path, a storage config dict, the local Borg version, the - arguments to the list action, and local and remote Borg paths, display the output of listing - the files of a Borg archive (or return JSON output). If list_arguments.find_paths are given, - list the files by searching across multiple archives. If neither find_paths nor archive name - are given, instead list the archives in the given repository. + Given a local or remote repository path, a storage config dict, the local Borg version, global + arguments as an argparse.Namespace, the arguments to the list action as an argparse.Namespace, + and local and remote Borg paths, display the output of listing the files of a Borg archive (or + return JSON output). If list_arguments.find_paths are given, list the files by searching across + multiple archives. If neither find_paths nor archive name are given, instead list the archives + in the given repository. ''' borgmatic.logger.add_custom_log_levels() @@ -164,6 +171,7 @@ def list_archive( storage_config, local_borg_version, rlist_arguments, + global_arguments, local_path, remote_path, ) @@ -205,6 +213,7 @@ def list_archive( storage_config, local_borg_version, rlist_arguments, + global_arguments, local_path, remote_path, ), @@ -233,6 +242,7 @@ def list_archive( storage_config, local_borg_version, archive_arguments, + global_arguments, local_path, remote_path, ) + make_find_paths(list_arguments.find_paths) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 07a6c6321..6ce01a879 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -15,14 +15,15 @@ def mount_archive( options, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, an optional archive name, a filesystem mount point, zero or more paths to mount from the archive, extra Borg mount options, a storage configuration - dict, the local Borg version, and optional local and remote Borg paths, mount the archive onto - the mount point. + dict, the local Borg version, global arguments as an argparse.Namespace instance, and optional + local and remote Borg paths, mount the archive onto the mount point. ''' umask = storage_config.get('umask', None) lock_wait = storage_config.get('lock_wait', None) @@ -31,6 +32,7 @@ def mount_archive( (local_path, 'mount') + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index 3f06dc2d0..b6be75ba0 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -53,6 +53,7 @@ def prune_archives( storage_config, retention_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, stats=False, @@ -73,6 +74,7 @@ def prune_archives( + make_prune_flags(storage_config, retention_config, local_borg_version) + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + + (('--log-json',) if global_arguments.log_json else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--stats',) if stats and not dry_run else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) diff --git a/borgmatic/borg/rcreate.py b/borgmatic/borg/rcreate.py index 7510529dc..54a865c57 100644 --- a/borgmatic/borg/rcreate.py +++ b/borgmatic/borg/rcreate.py @@ -16,6 +16,7 @@ def create_repository( repository_path, storage_config, local_borg_version, + global_arguments, encryption_mode, source_repository=None, copy_crypt_key=False, @@ -37,6 +38,7 @@ def create_repository( storage_config, local_borg_version, argparse.Namespace(json=True), + global_arguments, local_path, remote_path, ) @@ -46,6 +48,7 @@ def create_repository( if error.returncode != RINFO_REPOSITORY_NOT_FOUND_EXIT_CODE: raise + lock_wait = storage_config.get('lock_wait') extra_borg_options = storage_config.get('extra_borg_options', {}).get('rcreate', '') rcreate_command = ( @@ -63,6 +66,8 @@ def create_repository( + (('--make-parent-dirs',) if make_parent_dirs else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug',) if logger.isEnabledFor(logging.DEBUG) else ()) + + (('--log-json',) if global_arguments.log_json else ()) + + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--remote-path', remote_path) if remote_path else ()) + (tuple(extra_borg_options.split(' ')) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) diff --git a/borgmatic/borg/rinfo.py b/borgmatic/borg/rinfo.py index 97d7a6667..e1542d282 100644 --- a/borgmatic/borg/rinfo.py +++ b/borgmatic/borg/rinfo.py @@ -12,13 +12,14 @@ def display_repository_info( storage_config, local_borg_version, rinfo_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' - Given a local or remote repository path, a storage config dict, the local Borg version, and the - arguments to the rinfo action, display summary information for the Borg repository or return - JSON summary information. + Given a local or remote repository path, a storage config dict, the local Borg version, the + arguments to the rinfo action, and global arguments as an argparse.Namespace, display summary + information for the Borg repository or return JSON summary information. ''' borgmatic.logger.add_custom_log_levels() lock_wait = storage_config.get('lock_wait', None) @@ -41,6 +42,7 @@ def display_repository_info( else () ) + flags.make_flags('remote-path', remote_path) + + flags.make_flags('log-json', global_arguments.log_json) + flags.make_flags('lock-wait', lock_wait) + (('--json',) if rinfo_arguments.json else ()) + flags.make_repository_flags(repository_path, local_borg_version) diff --git a/borgmatic/borg/rlist.py b/borgmatic/borg/rlist.py index 7f4687050..ba45aa0ab 100644 --- a/borgmatic/borg/rlist.py +++ b/borgmatic/borg/rlist.py @@ -12,28 +12,29 @@ def resolve_archive_name( archive, storage_config, local_borg_version, + global_arguments, local_path='borg', remote_path=None, ): ''' - Given a local or remote repository path, an archive name, a storage config dict, a local Borg - path, and a remote Borg path, return the archive name. But if the archive name is "latest", - then instead introspect the repository for the latest archive and return its name. + Given a local or remote repository path, an archive name, a storage config dict, the local Borg + version, global arguments as an argparse.Namespace, a local Borg path, and a remote Borg path, + return the archive name. But if the archive name is "latest", then instead introspect the + repository for the latest archive and return its name. Raise ValueError if "latest" is given but there are no archives in the repository. ''' if archive != 'latest': return archive - lock_wait = storage_config.get('lock_wait', None) - full_command = ( ( local_path, 'rlist' if feature.available(feature.Feature.RLIST, local_borg_version) else 'list', ) + flags.make_flags('remote-path', remote_path) - + flags.make_flags('lock-wait', lock_wait) + + flags.make_flags('log-json', global_arguments.log_json) + + flags.make_flags('lock-wait', storage_config.get('lock_wait')) + flags.make_flags('last', 1) + ('--short',) + flags.make_repository_flags(repository_path, local_borg_version) @@ -61,16 +62,15 @@ def make_rlist_command( storage_config, local_borg_version, rlist_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, a storage config dict, the local Borg version, the - arguments to the rlist action, and local and remote Borg paths, return a command as a tuple to - list archives with a repository. + arguments to the rlist action, global arguments as an argparse.Namespace instance, and local and + remote Borg paths, return a command as a tuple to list archives with a repository. ''' - lock_wait = storage_config.get('lock_wait', None) - return ( ( local_path, @@ -87,7 +87,8 @@ def make_rlist_command( else () ) + flags.make_flags('remote-path', remote_path) - + flags.make_flags('lock-wait', lock_wait) + + flags.make_flags('log-json', global_arguments.log_json) + + flags.make_flags('lock-wait', storage_config.get('lock_wait')) + ( ( flags.make_flags('match-archives', f'sh:{rlist_arguments.prefix}*') @@ -113,13 +114,15 @@ def list_repository( storage_config, local_borg_version, rlist_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' Given a local or remote repository path, a storage config dict, the local Borg version, the - arguments to the list action, and local and remote Borg paths, display the output of listing - Borg archives in the given repository (or return JSON output). + arguments to the list action, global arguments as an argparse.Namespace instance, and local and + remote Borg paths, display the output of listing Borg archives in the given repository (or + return JSON output). ''' borgmatic.logger.add_custom_log_levels() borg_environment = environment.make_environment(storage_config) @@ -129,6 +132,7 @@ def list_repository( storage_config, local_borg_version, rlist_arguments, + global_arguments, local_path, remote_path, ) diff --git a/borgmatic/borg/transfer.py b/borgmatic/borg/transfer.py index 9fd05b76a..d8f3978f7 100644 --- a/borgmatic/borg/transfer.py +++ b/borgmatic/borg/transfer.py @@ -13,12 +13,14 @@ def transfer_archives( storage_config, local_borg_version, transfer_arguments, + global_arguments, local_path='borg', remote_path=None, ): ''' Given a dry-run flag, a local or remote repository path, a storage config dict, the local Borg - version, and the arguments to the transfer action, transfer archives to the given repository. + version, the arguments to the transfer action, and global arguments as an argparse.Namespace + instance, transfer archives to the given repository. ''' borgmatic.logger.add_custom_log_levels() @@ -27,6 +29,7 @@ def transfer_archives( + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + flags.make_flags('remote-path', remote_path) + + flags.make_flags('log-json', global_arguments.log_json) + flags.make_flags('lock-wait', storage_config.get('lock_wait', None)) + ( flags.make_flags_from_arguments( diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index e5b99ec59..0812edead 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -187,6 +187,11 @@ def make_parsers(): type=str, help='Log format string used for log messages written to the log file', ) + global_group.add_argument( + '--log-json', + action='store_true', + help='Write log messages and console output as one JSON object per log line instead of formatted text', + ) global_group.add_argument( '--override', metavar='SECTION.OPTION=VALUE', diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index d5fedba74..44396cd4b 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -398,7 +398,8 @@ def run_actions( repository, storage, local_borg_version, - arguments['mount'], + action_arguments, + global_arguments, local_path, remote_path, ) @@ -420,6 +421,7 @@ def run_actions( storage, local_borg_version, action_arguments, + global_arguments, local_path, remote_path, ) @@ -429,6 +431,7 @@ def run_actions( storage, local_borg_version, action_arguments, + global_arguments, local_path, remote_path, ) @@ -438,6 +441,7 @@ def run_actions( storage, local_borg_version, action_arguments, + global_arguments, local_path, remote_path, ) @@ -447,6 +451,7 @@ def run_actions( storage, local_borg_version, action_arguments, + global_arguments, local_path, remote_path, ) @@ -455,7 +460,8 @@ def run_actions( repository, storage, local_borg_version, - arguments['break-lock'], + action_arguments, + global_arguments, local_path, remote_path, ) @@ -465,6 +471,7 @@ def run_actions( storage, local_borg_version, action_arguments, + global_arguments, local_path, remote_path, ) diff --git a/tests/integration/borg/test_commands.py b/tests/integration/borg/test_commands.py index 1afb0e0ff..444031938 100644 --- a/tests/integration/borg/test_commands.py +++ b/tests/integration/borg/test_commands.py @@ -1,3 +1,4 @@ +import argparse import copy from flexmock import flexmock @@ -58,7 +59,12 @@ def test_transfer_archives_command_does_not_duplicate_flags_or_raise(): continue borgmatic.borg.transfer.transfer_archives( - False, 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) + False, + 'repo', + {}, + '2.3.4', + fuzz_argument(arguments, argument_name), + global_arguments=flexmock(log_json=False), ) @@ -70,7 +76,11 @@ def test_make_list_command_does_not_duplicate_flags_or_raise(): continue command = borgmatic.borg.list.make_list_command( - 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) + 'repo', + {}, + '2.3.4', + fuzz_argument(arguments, argument_name), + argparse.Namespace(log_json=False), ) assert_command_does_not_duplicate_flags(command) @@ -84,7 +94,11 @@ def test_make_rlist_command_does_not_duplicate_flags_or_raise(): continue command = borgmatic.borg.rlist.make_rlist_command( - 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) + 'repo', + {}, + '2.3.4', + fuzz_argument(arguments, argument_name), + global_arguments=flexmock(log_json=True), ) assert_command_does_not_duplicate_flags(command) @@ -104,5 +118,9 @@ def test_display_archives_info_command_does_not_duplicate_flags_or_raise(): continue borgmatic.borg.info.display_archives_info( - 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) + 'repo', + {}, + '2.3.4', + fuzz_argument(arguments, argument_name), + argparse.Namespace(log_json=False), ) diff --git a/tests/unit/actions/test_borg.py b/tests/unit/actions/test_borg.py index f597acbf9..2e03ec9c9 100644 --- a/tests/unit/actions/test_borg.py +++ b/tests/unit/actions/test_borg.py @@ -16,6 +16,7 @@ def test_run_borg_does_not_raise(): repository={'path': 'repos'}, storage={}, local_borg_version=None, + global_arguments=flexmock(log_json=False), borg_arguments=borg_arguments, local_path=None, remote_path=None, diff --git a/tests/unit/actions/test_break_lock.py b/tests/unit/actions/test_break_lock.py index 6dc2470e3..5949d7c1d 100644 --- a/tests/unit/actions/test_break_lock.py +++ b/tests/unit/actions/test_break_lock.py @@ -14,6 +14,7 @@ def test_run_break_lock_does_not_raise(): storage={}, local_borg_version=None, break_lock_arguments=break_lock_arguments, + global_arguments=flexmock(), local_path=None, remote_path=None, ) diff --git a/tests/unit/actions/test_info.py b/tests/unit/actions/test_info.py index a4f1d5449..971619681 100644 --- a/tests/unit/actions/test_info.py +++ b/tests/unit/actions/test_info.py @@ -18,6 +18,7 @@ def test_run_info_does_not_raise(): storage={}, local_borg_version=None, info_arguments=info_arguments, + global_arguments=flexmock(log_json=False), local_path=None, remote_path=None, ) diff --git a/tests/unit/actions/test_list.py b/tests/unit/actions/test_list.py index bfdfd010d..5ee722517 100644 --- a/tests/unit/actions/test_list.py +++ b/tests/unit/actions/test_list.py @@ -18,6 +18,7 @@ def test_run_list_does_not_raise(): storage={}, local_borg_version=None, list_arguments=list_arguments, + global_arguments=flexmock(log_json=False), local_path=None, remote_path=None, ) diff --git a/tests/unit/actions/test_mount.py b/tests/unit/actions/test_mount.py index 7eadfca1f..743747d2b 100644 --- a/tests/unit/actions/test_mount.py +++ b/tests/unit/actions/test_mount.py @@ -21,6 +21,7 @@ def test_run_mount_does_not_raise(): storage={}, local_borg_version=None, mount_arguments=mount_arguments, + global_arguments=flexmock(log_json=False), local_path=None, remote_path=None, ) diff --git a/tests/unit/actions/test_restore.py b/tests/unit/actions/test_restore.py index 16fe2920e..4bad6f825 100644 --- a/tests/unit/actions/test_restore.py +++ b/tests/unit/actions/test_restore.py @@ -72,6 +72,7 @@ def test_collect_archive_database_names_parses_archive_paths(): location={'borgmatic_source_directory': '.borgmatic'}, storage=flexmock(), local_borg_version=flexmock(), + global_arguments=flexmock(log_json=False), local_path=flexmock(), remote_path=flexmock(), ) @@ -97,6 +98,7 @@ def test_collect_archive_database_names_parses_directory_format_archive_paths(): location={'borgmatic_source_directory': '.borgmatic'}, storage=flexmock(), local_borg_version=flexmock(), + global_arguments=flexmock(log_json=False), local_path=flexmock(), remote_path=flexmock(), ) @@ -118,6 +120,7 @@ def test_collect_archive_database_names_skips_bad_archive_paths(): location={'borgmatic_source_directory': '.borgmatic'}, storage=flexmock(), local_borg_version=flexmock(), + global_arguments=flexmock(log_json=False), local_path=flexmock(), remote_path=flexmock(), ) diff --git a/tests/unit/actions/test_rinfo.py b/tests/unit/actions/test_rinfo.py index 133e61ac0..7b2371a37 100644 --- a/tests/unit/actions/test_rinfo.py +++ b/tests/unit/actions/test_rinfo.py @@ -15,6 +15,7 @@ def test_run_rinfo_does_not_raise(): storage={}, local_borg_version=None, rinfo_arguments=rinfo_arguments, + global_arguments=flexmock(log_json=False), local_path=None, remote_path=None, ) diff --git a/tests/unit/actions/test_rlist.py b/tests/unit/actions/test_rlist.py index 7f8b58aab..4a59dc304 100644 --- a/tests/unit/actions/test_rlist.py +++ b/tests/unit/actions/test_rlist.py @@ -15,6 +15,7 @@ def test_run_rlist_does_not_raise(): storage={}, local_borg_version=None, rlist_arguments=rlist_arguments, + global_arguments=flexmock(), local_path=None, remote_path=None, ) diff --git a/tests/unit/borg/test_break_lock.py b/tests/unit/borg/test_break_lock.py index 509fc1b85..3dc55672f 100644 --- a/tests/unit/borg/test_break_lock.py +++ b/tests/unit/borg/test_break_lock.py @@ -24,6 +24,7 @@ def test_break_lock_calls_borg_with_required_flags(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -35,6 +36,7 @@ def test_break_lock_calls_borg_with_remote_path_flags(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -47,6 +49,19 @@ def test_break_lock_calls_borg_with_umask_flags(): repository_path='repo', storage_config={'umask': '0770'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) + + +def test_break_lock_calls_borg_with_log_json_flags(): + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock(('borg', 'break-lock', '--log-json', 'repo')) + + module.break_lock( + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), ) @@ -58,6 +73,7 @@ def test_break_lock_calls_borg_with_lock_wait_flags(): repository_path='repo', storage_config={'lock_wait': '5'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -70,6 +86,7 @@ def test_break_lock_with_log_info_calls_borg_with_info_parameter(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -82,4 +99,5 @@ def test_break_lock_with_log_debug_calls_borg_with_debug_flags(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_check.py b/tests/unit/borg/test_check.py index 1f992d3d5..4cd6aa770 100644 --- a/tests/unit/borg/test_check.py +++ b/tests/unit/borg/test_check.py @@ -421,6 +421,7 @@ def test_check_archives_with_progress_calls_borg_with_progress_parameter(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, ) @@ -451,6 +452,7 @@ def test_check_archives_with_repair_calls_borg_with_repair_parameter(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), repair=True, ) @@ -490,6 +492,7 @@ def test_check_archives_calls_borg_with_parameters(checks): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -510,6 +513,7 @@ def test_check_archives_with_json_error_raises(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -528,6 +532,7 @@ def test_check_archives_with_missing_json_keys_raises(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -552,6 +557,7 @@ def test_check_archives_with_extract_check_calls_extract_only(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -576,6 +582,7 @@ def test_check_archives_with_log_info_calls_borg_with_info_parameter(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -600,6 +607,7 @@ def test_check_archives_with_log_debug_calls_borg_with_debug_parameter(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -618,6 +626,7 @@ def test_check_archives_without_any_checks_bails(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -648,6 +657,7 @@ def test_check_archives_with_local_path_calls_borg_via_local_path(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), local_path='borg1', ) @@ -679,10 +689,43 @@ def test_check_archives_with_remote_path_calls_borg_with_remote_path_parameters( storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) +def test_check_archives_with_log_json_calls_borg_with_log_json_parameters(): + checks = ('repository',) + check_last = flexmock() + storage_config = {} + consistency_config = {'check_last': check_last} + flexmock(module).should_receive('parse_checks') + flexmock(module).should_receive('filter_checks_on_frequency').and_return(checks) + flexmock(module.rinfo).should_receive('display_repository_info').and_return( + '{"repository": {"id": "repo"}}' + ) + flexmock(module).should_receive('make_check_flags').with_args( + '1.2.3', + storage_config, + checks, + check_last, + None, + ).and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock(('borg', 'check', '--log-json', 'repo')) + flexmock(module).should_receive('make_check_time_path') + flexmock(module).should_receive('write_check_time') + + module.check_archives( + repository_path='repo', + location_config={}, + storage_config=storage_config, + consistency_config=consistency_config, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), + ) + + def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): checks = ('repository',) check_last = flexmock() @@ -711,6 +754,7 @@ def test_check_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): storage_config=storage_config, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -738,6 +782,7 @@ def test_check_archives_with_retention_prefix(): storage_config={}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -761,4 +806,5 @@ def test_check_archives_with_extra_borg_options_calls_borg_with_extra_options(): storage_config={'extra_borg_options': {'check': '--extra --options'}}, consistency_config=consistency_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_compact.py b/tests/unit/borg/test_compact.py index 60447db6b..beacf5475 100644 --- a/tests/unit/borg/test_compact.py +++ b/tests/unit/borg/test_compact.py @@ -25,7 +25,11 @@ def test_compact_segments_calls_borg_with_parameters(): insert_execute_command_mock(COMPACT_COMMAND + ('repo',), logging.INFO) module.compact_segments( - dry_run=False, repository_path='repo', storage_config={}, local_borg_version='1.2.3' + dry_run=False, + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -35,7 +39,11 @@ def test_compact_segments_with_log_info_calls_borg_with_info_parameter(): insert_logging_mock(logging.INFO) module.compact_segments( - repository_path='repo', storage_config={}, local_borg_version='1.2.3', dry_run=False + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + dry_run=False, ) @@ -45,7 +53,11 @@ def test_compact_segments_with_log_debug_calls_borg_with_debug_parameter(): insert_logging_mock(logging.DEBUG) module.compact_segments( - repository_path='repo', storage_config={}, local_borg_version='1.2.3', dry_run=False + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + dry_run=False, ) @@ -53,7 +65,11 @@ def test_compact_segments_with_dry_run_skips_borg_call(): flexmock(module).should_receive('execute_command').never() module.compact_segments( - repository_path='repo', storage_config={}, local_borg_version='1.2.3', dry_run=True + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + dry_run=True, ) @@ -66,6 +82,7 @@ def test_compact_segments_with_local_path_calls_borg_via_local_path(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), local_path='borg1', ) @@ -79,6 +96,7 @@ def test_compact_segments_with_remote_path_calls_borg_with_remote_path_parameter repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -92,6 +110,7 @@ def test_compact_segments_with_progress_calls_borg_with_progress_parameter(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, ) @@ -105,6 +124,7 @@ def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_p repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), cleanup_commits=True, ) @@ -118,6 +138,7 @@ def test_compact_segments_with_threshold_calls_borg_with_threshold_parameter(): repository_path='repo', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), threshold=20, ) @@ -132,6 +153,20 @@ def test_compact_segments_with_umask_calls_borg_with_umask_parameters(): repository_path='repo', storage_config=storage_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) + + +def test_compact_segments_with_log_json_calls_borg_with_log_json_parameters(): + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock(COMPACT_COMMAND + ('--log-json', 'repo'), logging.INFO) + + module.compact_segments( + dry_run=False, + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), ) @@ -145,6 +180,7 @@ def test_compact_segments_with_lock_wait_calls_borg_with_lock_wait_parameters(): repository_path='repo', storage_config=storage_config, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -157,4 +193,5 @@ def test_compact_segments_with_extra_borg_options_calls_borg_with_extra_options( repository_path='repo', storage_config={'extra_borg_options': {'compact': '--extra --options'}}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_create.py b/tests/unit/borg/test_create.py index 3728a0bf2..e0462e2dc 100644 --- a/tests/unit/borg/test_create.py +++ b/tests/unit/borg/test_create.py @@ -492,6 +492,7 @@ def test_create_archive_calls_borg_with_parameters(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -535,6 +536,7 @@ def test_create_archive_calls_borg_with_environment(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -580,6 +582,7 @@ def test_create_archive_with_patterns_calls_borg_with_patterns_including_convert }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -625,6 +628,7 @@ def test_create_archive_with_exclude_patterns_calls_borg_with_excludes(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -668,6 +672,7 @@ def test_create_archive_with_log_info_calls_borg_with_info_parameter(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -708,6 +713,7 @@ def test_create_archive_with_log_info_and_json_suppresses_most_borg_output(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), json=True, ) @@ -752,6 +758,7 @@ def test_create_archive_with_log_debug_calls_borg_with_debug_parameter(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -792,6 +799,7 @@ def test_create_archive_with_log_debug_and_json_suppresses_most_borg_output(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), json=True, ) @@ -835,6 +843,7 @@ def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -880,6 +889,7 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats_paramete }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stats=True, ) @@ -923,6 +933,7 @@ def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_inte }, storage_config={'checkpoint_interval': 600}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -965,6 +976,7 @@ def test_create_archive_with_checkpoint_volume_calls_borg_with_checkpoint_volume }, storage_config={'checkpoint_volume': 1024}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1007,6 +1019,7 @@ def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_param }, storage_config={'chunker_params': '1,2,3,4'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1049,6 +1062,7 @@ def test_create_archive_with_compression_calls_borg_with_compression_parameters( }, storage_config={'compression': 'rle'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1097,6 +1111,7 @@ def test_create_archive_with_upload_rate_limit_calls_borg_with_upload_ratelimit_ }, storage_config={'upload_rate_limit': 100}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1142,6 +1157,7 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1185,6 +1201,7 @@ def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_par }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1234,6 +1251,7 @@ def test_create_archive_with_numeric_ids_calls_borg_with_numeric_ids_parameter( }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1287,6 +1305,7 @@ def test_create_archive_with_read_special_calls_borg_with_read_special_parameter }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1342,6 +1361,7 @@ def test_create_archive_with_basic_option_calls_borg_with_corresponding_paramete }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1396,6 +1416,7 @@ def test_create_archive_with_atime_option_calls_borg_with_corresponding_paramete }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1450,6 +1471,7 @@ def test_create_archive_with_flags_option_calls_borg_with_corresponding_paramete }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1493,6 +1515,7 @@ def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters( }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1535,6 +1558,7 @@ def test_create_archive_with_local_path_calls_borg_via_local_path(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), local_path='borg1', ) @@ -1578,6 +1602,7 @@ def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters( }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -1621,6 +1646,50 @@ def test_create_archive_with_umask_calls_borg_with_umask_parameters(): }, storage_config={'umask': 740}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) + + +def test_create_archive_with_log_json_calls_borg_with_log_json_parameters(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module).should_receive('collect_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('pattern_root_directories').and_return([]) + flexmock(module.os.path).should_receive('expanduser').and_raise(TypeError) + flexmock(module).should_receive('expand_home_directories').and_return(()) + flexmock(module).should_receive('write_pattern_file').and_return(None) + flexmock(module).should_receive('make_list_filter_flags').and_return('FOO') + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module).should_receive('ensure_files_readable') + flexmock(module).should_receive('make_pattern_flags').and_return(()) + flexmock(module).should_receive('make_exclude_flags').and_return(()) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + (f'repo::{DEFAULT_ARCHIVE_NAME}',) + ) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'create', '--log-json') + REPO_ARCHIVE_WITH_PATHS, + output_log_level=logging.INFO, + output_file=None, + borg_local_path='borg', + working_directory=None, + extra_environment=None, + ) + + module.create_archive( + dry_run=False, + repository_path='repo', + location_config={ + 'source_directories': ['foo', 'bar'], + 'repositories': ['repo'], + 'exclude_patterns': None, + }, + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), ) @@ -1663,6 +1732,7 @@ def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters(): }, storage_config={'lock_wait': 5}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -1705,6 +1775,7 @@ def test_create_archive_with_stats_calls_borg_with_stats_parameter_and_answer_ou }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stats=True, ) @@ -1748,6 +1819,7 @@ def test_create_archive_with_files_calls_borg_with_list_parameter_and_answer_out }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), list_files=True, ) @@ -1797,6 +1869,7 @@ def test_create_archive_with_progress_and_log_info_calls_borg_with_progress_para }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, ) @@ -1840,6 +1913,7 @@ def test_create_archive_with_progress_calls_borg_with_progress_parameter(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, ) @@ -1900,6 +1974,7 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, stream_processes=processes, ) @@ -1964,6 +2039,7 @@ def test_create_archive_with_stream_processes_ignores_read_special_false_and_log }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stream_processes=processes, ) @@ -2031,6 +2107,7 @@ def test_create_archive_with_stream_processes_adds_special_files_to_excludes(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stream_processes=processes, ) @@ -2095,6 +2172,7 @@ def test_create_archive_with_stream_processes_and_read_special_does_not_add_spec }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stream_processes=processes, ) @@ -2135,6 +2213,7 @@ def test_create_archive_with_json_calls_borg_with_json_parameter(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), json=True, ) @@ -2177,6 +2256,7 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_parameter() }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), json=True, stats=True, ) @@ -2224,6 +2304,7 @@ def test_create_archive_with_source_directories_glob_expands(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2267,6 +2348,7 @@ def test_create_archive_with_non_matching_source_directories_glob_passes_through }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2309,6 +2391,7 @@ def test_create_archive_with_glob_calls_borg_with_expanded_directories(): }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2351,6 +2434,7 @@ def test_create_archive_with_archive_name_format_calls_borg_with_archive_name(): }, storage_config={'archive_name_format': 'ARCHIVE_NAME'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2394,6 +2478,7 @@ def test_create_archive_with_archive_name_format_accepts_borg_placeholders(): }, storage_config={'archive_name_format': 'Documents_{hostname}-{now}'}, # noqa: FS003 local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2437,6 +2522,7 @@ def test_create_archive_with_repository_accepts_borg_placeholders(): }, storage_config={'archive_name_format': 'Documents_{hostname}-{now}'}, # noqa: FS003 local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2479,6 +2565,7 @@ def test_create_archive_with_extra_borg_options_calls_borg_with_extra_options(): }, storage_config={'extra_borg_options': {'create': '--extra --options'}}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -2539,6 +2626,7 @@ def test_create_archive_with_stream_processes_calls_borg_with_processes_and_read }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stream_processes=processes, ) @@ -2564,6 +2652,7 @@ def test_create_archive_with_non_existent_directory_and_source_directories_must_ }, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_export_tar.py b/tests/unit/borg/test_export_tar.py index 92776dd40..5fb7bff2a 100644 --- a/tests/unit/borg/test_export_tar.py +++ b/tests/unit/borg/test_export_tar.py @@ -38,6 +38,7 @@ def test_export_tar_archive_calls_borg_with_path_parameters(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -59,6 +60,7 @@ def test_export_tar_archive_calls_borg_with_local_path_parameters(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), local_path='borg1', ) @@ -81,6 +83,7 @@ def test_export_tar_archive_calls_borg_with_remote_path_parameters(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -103,6 +106,27 @@ def test_export_tar_archive_calls_borg_with_umask_parameters(): destination_path='test.tar', storage_config={'umask': '0770'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) + + +def test_export_tar_archive_calls_borg_with_log_json_parameter(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) + insert_execute_command_mock(('borg', 'export-tar', '--log-json', 'repo::archive', 'test.tar')) + + module.export_tar_archive( + dry_run=False, + repository_path='repo', + archive='archive', + paths=None, + destination_path='test.tar', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), ) @@ -124,6 +148,7 @@ def test_export_tar_archive_calls_borg_with_lock_wait_parameters(): destination_path='test.tar', storage_config={'lock_wait': '5'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -144,6 +169,7 @@ def test_export_tar_archive_with_log_info_calls_borg_with_info_parameter(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -166,6 +192,7 @@ def test_export_tar_archive_with_log_debug_calls_borg_with_debug_parameters(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -185,6 +212,7 @@ def test_export_tar_archive_calls_borg_with_dry_run_parameter(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -206,6 +234,7 @@ def test_export_tar_archive_calls_borg_with_tar_filter_parameters(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), tar_filter='bzip2', ) @@ -229,6 +258,7 @@ def test_export_tar_archive_calls_borg_with_list_parameter(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), list_files=True, ) @@ -251,6 +281,7 @@ def test_export_tar_archive_calls_borg_with_strip_components_parameter(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), strip_components=5, ) @@ -271,6 +302,7 @@ def test_export_tar_archive_skips_abspath_for_remote_repository_parameter(): destination_path='test.tar', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -290,4 +322,5 @@ def test_export_tar_archive_calls_borg_with_stdout_destination_path(): destination_path='-', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_extract.py b/tests/unit/borg/test_extract.py index 6517379e4..a4032f6ce 100644 --- a/tests/unit/borg/test_extract.py +++ b/tests/unit/borg/test_extract.py @@ -25,7 +25,11 @@ def test_extract_last_archive_dry_run_calls_borg_with_last_archive(): ) module.extract_last_archive_dry_run( - storage_config={}, local_borg_version='1.2.3', repository_path='repo', lock_wait=None + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + repository_path='repo', + lock_wait=None, ) @@ -34,7 +38,11 @@ def test_extract_last_archive_dry_run_without_any_archives_should_not_raise(): flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(('repo',)) module.extract_last_archive_dry_run( - storage_config={}, local_borg_version='1.2.3', repository_path='repo', lock_wait=None + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + repository_path='repo', + lock_wait=None, ) @@ -47,7 +55,11 @@ def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_paramet ) module.extract_last_archive_dry_run( - storage_config={}, local_borg_version='1.2.3', repository_path='repo', lock_wait=None + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + repository_path='repo', + lock_wait=None, ) @@ -62,7 +74,11 @@ def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_param ) module.extract_last_archive_dry_run( - storage_config={}, local_borg_version='1.2.3', repository_path='repo', lock_wait=None + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + repository_path='repo', + lock_wait=None, ) @@ -76,13 +92,14 @@ def test_extract_last_archive_dry_run_calls_borg_via_local_path(): module.extract_last_archive_dry_run( storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), repository_path='repo', lock_wait=None, local_path='borg1', ) -def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters(): +def test_extract_last_archive_dry_run_calls_borg_with_remote_path_flags(): flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive') insert_execute_command_mock( ('borg', 'extract', '--dry-run', '--remote-path', 'borg1', 'repo::archive') @@ -94,13 +111,30 @@ def test_extract_last_archive_dry_run_calls_borg_with_remote_path_parameters(): module.extract_last_archive_dry_run( storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), repository_path='repo', lock_wait=None, remote_path='borg1', ) -def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters(): +def test_extract_last_archive_dry_run_calls_borg_with_log_json_flag(): + flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive') + insert_execute_command_mock(('borg', 'extract', '--dry-run', '--log-json', 'repo::archive')) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) + + module.extract_last_archive_dry_run( + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), + repository_path='repo', + lock_wait=None, + ) + + +def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_flags(): flexmock(module.rlist).should_receive('resolve_archive_name').and_return('archive') insert_execute_command_mock( ('borg', 'extract', '--dry-run', '--lock-wait', '5', 'repo::archive') @@ -110,11 +144,15 @@ def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_parameters(): ) module.extract_last_archive_dry_run( - storage_config={}, local_borg_version='1.2.3', repository_path='repo', lock_wait=5 + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + repository_path='repo', + lock_wait=5, ) -def test_extract_archive_calls_borg_with_path_parameters(): +def test_extract_archive_calls_borg_with_path_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', 'repo::archive', 'path1', 'path2')) flexmock(module.feature).should_receive('available').and_return(True) @@ -133,10 +171,11 @@ def test_extract_archive_calls_borg_with_path_parameters(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_extract_archive_calls_borg_with_remote_path_parameters(): +def test_extract_archive_calls_borg_with_remote_path_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', '--remote-path', 'borg1', 'repo::archive')) flexmock(module.feature).should_receive('available').and_return(True) @@ -155,6 +194,7 @@ def test_extract_archive_calls_borg_with_remote_path_parameters(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -185,10 +225,11 @@ def test_extract_archive_calls_borg_with_numeric_ids_parameter(feature_available location_config={'numeric_ids': True}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_extract_archive_calls_borg_with_umask_parameters(): +def test_extract_archive_calls_borg_with_umask_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', '--umask', '0770', 'repo::archive')) flexmock(module.feature).should_receive('available').and_return(True) @@ -207,10 +248,31 @@ def test_extract_archive_calls_borg_with_umask_parameters(): location_config={}, storage_config={'umask': '0770'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_extract_archive_calls_borg_with_lock_wait_parameters(): +def test_extract_archive_calls_borg_with_log_json_flags(): + flexmock(module.os.path).should_receive('abspath').and_return('repo') + insert_execute_command_mock(('borg', 'extract', '--log-json', 'repo::archive')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) + + module.extract_archive( + dry_run=False, + repository='repo', + archive='archive', + paths=None, + location_config={}, + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), + ) + + +def test_extract_archive_calls_borg_with_lock_wait_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock(('borg', 'extract', '--lock-wait', '5', 'repo::archive')) flexmock(module.feature).should_receive('available').and_return(True) @@ -229,6 +291,7 @@ def test_extract_archive_calls_borg_with_lock_wait_parameters(): location_config={}, storage_config={'lock_wait': '5'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -252,10 +315,11 @@ def test_extract_archive_with_log_info_calls_borg_with_info_parameter(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_extract_archive_with_log_debug_calls_borg_with_debug_parameters(): +def test_extract_archive_with_log_debug_calls_borg_with_debug_flags(): flexmock(module.os.path).should_receive('abspath').and_return('repo') insert_execute_command_mock( ('borg', 'extract', '--debug', '--list', '--show-rc', 'repo::archive') @@ -277,6 +341,7 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_parameters(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -299,6 +364,7 @@ def test_extract_archive_calls_borg_with_dry_run_parameter(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -321,6 +387,7 @@ def test_extract_archive_calls_borg_with_destination_path(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), destination_path='/dest', ) @@ -344,6 +411,7 @@ def test_extract_archive_calls_borg_with_strip_components(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), strip_components=5, ) @@ -377,6 +445,7 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), strip_components='all', ) @@ -401,6 +470,7 @@ def test_extract_archive_with_strip_components_all_and_no_paths_raises(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), strip_components='all', ) @@ -430,6 +500,7 @@ def test_extract_archive_calls_borg_with_progress_parameter(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, ) @@ -446,6 +517,7 @@ def test_extract_archive_with_progress_and_extract_to_stdout_raises(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), progress=True, extract_to_stdout=True, ) @@ -479,6 +551,7 @@ def test_extract_archive_calls_borg_with_stdout_parameter_and_returns_process(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), extract_to_stdout=True, ) == process @@ -509,4 +582,5 @@ def test_extract_archive_skips_abspath_for_remote_repository(): location_config={}, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_info.py b/tests/unit/borg/test_info.py index 2eed4fead..112ef4c55 100644 --- a/tests/unit/borg/test_info.py +++ b/tests/unit/borg/test_info.py @@ -29,6 +29,7 @@ def test_display_archives_info_calls_borg_with_parameters(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -54,6 +55,7 @@ def test_display_archives_info_with_log_info_calls_borg_with_info_parameter(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -78,6 +80,7 @@ def test_display_archives_info_with_log_info_and_json_suppresses_most_borg_outpu repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None), ) @@ -106,6 +109,7 @@ def test_display_archives_info_with_log_debug_calls_borg_with_debug_parameter(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -130,6 +134,7 @@ def test_display_archives_info_with_log_debug_and_json_suppresses_most_borg_outp repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None), ) @@ -155,6 +160,7 @@ def test_display_archives_info_with_json_calls_borg_with_json_parameter(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=True, prefix=None, match_archives=None), ) @@ -182,6 +188,7 @@ def test_display_archives_info_with_archive_calls_borg_with_match_archives_param repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive='archive', json=False, prefix=None, match_archives=None), ) @@ -207,6 +214,7 @@ def test_display_archives_info_with_local_path_calls_borg_via_local_path(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), local_path='borg1', ) @@ -236,11 +244,41 @@ def test_display_archives_info_with_remote_path_calls_borg_with_remote_path_para repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), remote_path='borg1', ) +def test_display_archives_info_with_log_json_calls_borg_with_log_json_parameters(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags').with_args('log-json', True).and_return( + ('--log-json',) + ) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, None, '2.3.4' + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'info', '--log-json', '--repo', 'repo'), + output_log_level=module.borgmatic.logger.ANSWER, + borg_local_path='borg', + extra_environment=None, + ) + + module.display_archives_info( + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + global_arguments=flexmock(log_json=True), + info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), + ) + + def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_parameters(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER @@ -266,6 +304,7 @@ def test_display_archives_info_with_lock_wait_calls_borg_with_lock_wait_paramete repository_path='repo', storage_config=storage_config, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -294,6 +333,7 @@ def test_display_archives_info_transforms_prefix_into_match_archives_parameters( repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix='foo'), ) @@ -322,6 +362,7 @@ def test_display_archives_info_prefers_prefix_over_archive_name_format(): repository_path='repo', storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003 local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix='foo'), ) @@ -347,6 +388,7 @@ def test_display_archives_info_transforms_archive_name_format_into_match_archive repository_path='repo', storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003 local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -375,6 +417,7 @@ def test_display_archives_with_match_archives_option_calls_borg_with_match_archi 'match_archives': 'sh:foo-*', }, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives=None), ) @@ -400,6 +443,7 @@ def test_display_archives_with_match_archives_flag_calls_borg_with_match_archive repository_path='repo', storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003 local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock(archive=None, json=False, prefix=None, match_archives='sh:foo-*'), ) @@ -429,6 +473,7 @@ def test_display_archives_info_passes_through_arguments_to_borg(argument_name): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), info_arguments=flexmock( archive=None, json=False, prefix=None, match_archives=None, **{argument_name: 'value'} ), diff --git a/tests/unit/borg/test_list.py b/tests/unit/borg/test_list.py index 0a7db4cce..4e3a5f7c4 100644 --- a/tests/unit/borg/test_list.py +++ b/tests/unit/borg/test_list.py @@ -20,6 +20,7 @@ def test_make_list_command_includes_log_info(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--info', 'repo') @@ -36,6 +37,7 @@ def test_make_list_command_includes_json_but_not_info(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=True), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') @@ -52,6 +54,7 @@ def test_make_list_command_includes_log_debug(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--debug', '--show-rc', 'repo') @@ -68,6 +71,7 @@ def test_make_list_command_includes_json_but_not_debug(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=True), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') @@ -83,11 +87,28 @@ def test_make_list_command_includes_json(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=True), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') +def test_make_list_command_includes_log_json(): + flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(('--log-json',)) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + + command = module.make_list_command( + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=True), + ) + + assert command == ('borg', 'list', '--log-json', 'repo') + + def test_make_list_command_includes_lock_wait(): flexmock(module.flags).should_receive('make_flags').and_return(()).and_return( ('--lock-wait', '5') @@ -100,6 +121,7 @@ def test_make_list_command_includes_lock_wait(): storage_config={'lock_wait': 5}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--lock-wait', '5', 'repo') @@ -117,6 +139,7 @@ def test_make_list_command_includes_archive(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive='archive', paths=None, json=False), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', 'repo::archive') @@ -134,6 +157,7 @@ def test_make_list_command_includes_archive_and_path(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive='archive', paths=['var/lib'], json=False), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', 'repo::archive', 'var/lib') @@ -149,6 +173,7 @@ def test_make_list_command_includes_local_path(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=False), local_path='borg2', ) @@ -156,9 +181,13 @@ def test_make_list_command_includes_local_path(): def test_make_list_command_includes_remote_path(): - flexmock(module.flags).should_receive('make_flags').and_return( - ('--remote-path', 'borg2') - ).and_return(()) + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags').with_args( + 'remote-path', 'borg2' + ).and_return(('--remote-path', 'borg2')) + flexmock(module.flags).should_receive('make_flags').with_args('log-json', True).and_return( + ('--log-json') + ) flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) @@ -167,6 +196,7 @@ def test_make_list_command_includes_remote_path(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False), + global_arguments=flexmock(log_json=False), remote_path='borg2', ) @@ -183,6 +213,7 @@ def test_make_list_command_includes_short(): storage_config={}, local_borg_version='1.2.3', list_arguments=flexmock(archive=None, paths=None, json=False, short=True), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--short', 'repo') @@ -221,6 +252,7 @@ def test_make_list_command_includes_additional_flags(argument_name): format=None, **{argument_name: 'value'}, ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo') @@ -263,10 +295,11 @@ def test_capture_archive_listing_does_not_raise(): archive='archive', storage_config=flexmock(), local_borg_version=flexmock(), + global_arguments=flexmock(log_json=False), ) -def test_list_archive_calls_borg_with_parameters(): +def test_list_archive_calls_borg_with_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.logger).answer = lambda message: None @@ -281,6 +314,7 @@ def test_list_archive_calls_borg_with_parameters(): first=None, last=None, ) + global_arguments = flexmock(log_json=False) flexmock(module.feature).should_receive('available').and_return(False) flexmock(module).should_receive('make_list_command').with_args( @@ -288,6 +322,7 @@ def test_list_archive_calls_borg_with_parameters(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'list', 'repo::archive')) @@ -305,6 +340,7 @@ def test_list_archive_calls_borg_with_parameters(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, ) @@ -322,6 +358,7 @@ def test_list_archive_with_archive_and_json_errors(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=flexmock(log_json=False), ) @@ -340,6 +377,7 @@ def test_list_archive_calls_borg_with_local_path(): first=None, last=None, ) + global_arguments = flexmock(log_json=False) flexmock(module.feature).should_receive('available').and_return(False) flexmock(module).should_receive('make_list_command').with_args( @@ -347,6 +385,7 @@ def test_list_archive_calls_borg_with_local_path(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, local_path='borg2', remote_path=None, ).and_return(('borg2', 'list', 'repo::archive')) @@ -364,6 +403,7 @@ def test_list_archive_calls_borg_with_local_path(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, local_path='borg2', ) @@ -413,6 +453,7 @@ def test_list_archive_calls_borg_multiple_times_with_find_paths(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=flexmock(log_json=False), ) @@ -431,6 +472,7 @@ def test_list_archive_calls_borg_with_archive(): first=None, last=None, ) + global_arguments = flexmock(log_json=False) flexmock(module.feature).should_receive('available').and_return(False) flexmock(module).should_receive('make_list_command').with_args( @@ -438,6 +480,7 @@ def test_list_archive_calls_borg_with_archive(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'list', 'repo::archive')) @@ -455,6 +498,7 @@ def test_list_archive_calls_borg_with_archive(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=global_arguments, ) @@ -485,6 +529,7 @@ def test_list_archive_without_archive_delegates_to_list_repository(): storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=flexmock(log_json=False), ) @@ -515,6 +560,7 @@ def test_list_archive_with_borg_features_without_archive_delegates_to_list_repos storage_config={}, local_borg_version='1.2.3', list_arguments=list_arguments, + global_arguments=flexmock(log_json=False), ) @@ -534,6 +580,7 @@ def test_list_archive_with_archive_ignores_archive_filter_flag( flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.logger).answer = lambda message: None + global_arguments = flexmock(log_json=False) default_filter_flags = { 'prefix': None, 'match_archives': None, @@ -553,6 +600,7 @@ def test_list_archive_with_archive_ignores_archive_filter_flag( list_arguments=argparse.Namespace( archive='archive', paths=None, json=False, find_paths=None, **default_filter_flags ), + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'list', 'repo::archive')) @@ -572,6 +620,7 @@ def test_list_archive_with_archive_ignores_archive_filter_flag( list_arguments=argparse.Namespace( archive='archive', paths=None, json=False, find_paths=None, **altered_filter_flags ), + global_arguments=global_arguments, ) @@ -600,6 +649,7 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes } altered_filter_flags = {**default_filter_flags, **{archive_filter_flag: 'foo'}} glob_paths = ('**/*foo.txt*/**',) + global_arguments = flexmock(log_json=False) flexmock(module.feature).should_receive('available').and_return(True) flexmock(module.rlist).should_receive('make_rlist_command').with_args( @@ -609,6 +659,7 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes rlist_arguments=argparse.Namespace( repository='repo', short=True, format=None, json=None, **altered_filter_flags ), + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'rlist', '--repo', 'repo')) @@ -632,6 +683,7 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes find_paths=['foo.txt'], **default_filter_flags, ), + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'list', '--repo', 'repo', 'archive1')) @@ -650,6 +702,7 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes find_paths=['foo.txt'], **default_filter_flags, ), + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'list', '--repo', 'repo', 'archive2')) @@ -683,4 +736,5 @@ def test_list_archive_with_find_paths_allows_archive_filter_flag_but_only_passes find_paths=['foo.txt'], **altered_filter_flags, ), + global_arguments=global_arguments, ) diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index 658b2e527..cd1775117 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -30,6 +30,7 @@ def test_mount_archive_calls_borg_with_required_flags(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -54,6 +55,7 @@ def test_mount_archive_with_borg_features_calls_borg_with_repository_and_match_a options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -73,6 +75,7 @@ def test_mount_archive_without_archive_calls_borg_with_repository_flags_only(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -92,6 +95,7 @@ def test_mount_archive_calls_borg_with_path_flags(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -113,6 +117,7 @@ def test_mount_archive_calls_borg_with_remote_path_flags(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) @@ -133,6 +138,27 @@ def test_mount_archive_calls_borg_with_umask_flags(): options=None, storage_config={'umask': '0770'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) + + +def test_mount_archive_calls_borg_with_log_json_flags(): + flexmock(module.feature).should_receive('available').and_return(False) + flexmock(module.flags).should_receive('make_repository_archive_flags').and_return( + ('repo::archive',) + ) + insert_execute_command_mock(('borg', 'mount', '--log-json', 'repo::archive', '/mnt')) + + module.mount_archive( + repository_path='repo', + archive='archive', + mount_point='/mnt', + paths=None, + foreground=False, + options=None, + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), ) @@ -152,6 +178,7 @@ def test_mount_archive_calls_borg_with_lock_wait_flags(): options=None, storage_config={'lock_wait': '5'}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -172,6 +199,7 @@ def test_mount_archive_with_log_info_calls_borg_with_info_parameter(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -192,6 +220,7 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_flags(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -217,6 +246,7 @@ def test_mount_archive_calls_borg_with_foreground_parameter(): options=None, storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -236,4 +266,5 @@ def test_mount_archive_calls_borg_with_options_flags(): options='super_mount', storage_config={}, local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_prune.py b/tests/unit/borg/test_prune.py index 128bdc0a9..9028a0c78 100644 --- a/tests/unit/borg/test_prune.py +++ b/tests/unit/borg/test_prune.py @@ -110,7 +110,7 @@ def test_make_prune_flags_without_prefix_uses_archive_name_format_instead(): PRUNE_COMMAND = ('borg', 'prune', '--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3') -def test_prune_archives_calls_borg_with_parameters(): +def test_prune_archives_calls_borg_with_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -123,10 +123,11 @@ def test_prune_archives_calls_borg_with_parameters(): storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_prune_archives_with_log_info_calls_borg_with_info_parameter(): +def test_prune_archives_with_log_info_calls_borg_with_info_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -140,10 +141,11 @@ def test_prune_archives_with_log_info_calls_borg_with_info_parameter(): dry_run=False, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_prune_archives_with_log_debug_calls_borg_with_debug_parameter(): +def test_prune_archives_with_log_debug_calls_borg_with_debug_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -157,10 +159,11 @@ def test_prune_archives_with_log_debug_calls_borg_with_debug_parameter(): dry_run=False, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): +def test_prune_archives_with_dry_run_calls_borg_with_dry_run_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -173,6 +176,7 @@ def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): dry_run=True, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -189,11 +193,12 @@ def test_prune_archives_with_local_path_calls_borg_via_local_path(): storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), local_path='borg1', ) -def test_prune_archives_with_remote_path_calls_borg_with_remote_path_parameters(): +def test_prune_archives_with_remote_path_calls_borg_with_remote_path_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -206,11 +211,12 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_parameters( storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), remote_path='borg1', ) -def test_prune_archives_with_stats_calls_borg_with_stats_parameter_and_answer_output_log_level(): +def test_prune_archives_with_stats_calls_borg_with_stats_flag_and_answer_output_log_level(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -223,11 +229,12 @@ def test_prune_archives_with_stats_calls_borg_with_stats_parameter_and_answer_ou storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), stats=True, ) -def test_prune_archives_with_files_calls_borg_with_list_parameter_and_answer_output_log_level(): +def test_prune_archives_with_files_calls_borg_with_list_flag_and_answer_output_log_level(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) @@ -240,11 +247,12 @@ def test_prune_archives_with_files_calls_borg_with_list_parameter_and_answer_out storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), list_archives=True, ) -def test_prune_archives_with_umask_calls_borg_with_umask_parameters(): +def test_prune_archives_with_umask_calls_borg_with_umask_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER storage_config = {'umask': '077'} @@ -258,10 +266,28 @@ def test_prune_archives_with_umask_calls_borg_with_umask_parameters(): storage_config=storage_config, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) -def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): +def test_prune_archives_with_log_json_calls_borg_with_log_json_flag(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock(PRUNE_COMMAND + ('--log-json', 'repo'), logging.INFO) + + module.prune_archives( + dry_run=False, + repository_path='repo', + storage_config={}, + retention_config=flexmock(), + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), + ) + + +def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER storage_config = {'lock_wait': 5} @@ -275,6 +301,7 @@ def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): storage_config=storage_config, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) @@ -291,4 +318,5 @@ def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options(): storage_config={'extra_borg_options': {'prune': '--extra --options'}}, retention_config=flexmock(), local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_rcreate.py b/tests/unit/borg/test_rcreate.py index 4da04dffc..2f71a8ff5 100644 --- a/tests/unit/borg/test_rcreate.py +++ b/tests/unit/borg/test_rcreate.py @@ -48,6 +48,7 @@ def test_create_repository_calls_borg_with_flags(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -68,6 +69,7 @@ def test_create_repository_with_dry_run_skips_borg_call(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -92,6 +94,7 @@ def test_create_repository_raises_for_borg_rcreate_error(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -111,6 +114,7 @@ def test_create_repository_skips_creation_when_repository_already_exists(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -126,6 +130,7 @@ def test_create_repository_raises_for_unknown_rinfo_command_error(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -146,6 +151,7 @@ def test_create_repository_with_source_repository_calls_borg_with_other_repo_fla repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', source_repository='other.borg', ) @@ -167,6 +173,7 @@ def test_create_repository_with_copy_crypt_key_calls_borg_with_copy_crypt_key_fl repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', copy_crypt_key=True, ) @@ -188,6 +195,7 @@ def test_create_repository_with_append_only_calls_borg_with_append_only_flag(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', append_only=True, ) @@ -209,6 +217,7 @@ def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_flag repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', storage_quota='5G', ) @@ -230,6 +239,7 @@ def test_create_repository_with_make_parent_dirs_calls_borg_with_make_parent_dir repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', make_parent_dirs=True, ) @@ -252,6 +262,7 @@ def test_create_repository_with_log_info_calls_borg_with_info_flag(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -273,6 +284,49 @@ def test_create_repository_with_log_debug_calls_borg_with_debug_flag(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), + encryption_mode='repokey', + ) + + +def test_create_repository_with_log_json_calls_borg_with_log_json_flag(): + insert_rinfo_command_not_found_mock() + insert_rcreate_command_mock(RCREATE_COMMAND + ('--log-json', '--repo', 'repo')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return( + ( + '--repo', + 'repo', + ) + ) + + module.create_repository( + dry_run=False, + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + global_arguments=flexmock(log_json=True), + encryption_mode='repokey', + ) + + +def test_create_repository_with_lock_wait_calls_borg_with_lock_wait_flag(): + insert_rinfo_command_not_found_mock() + insert_rcreate_command_mock(RCREATE_COMMAND + ('--lock-wait', '5', '--repo', 'repo')) + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return( + ( + '--repo', + 'repo', + ) + ) + + module.create_repository( + dry_run=False, + repository_path='repo', + storage_config={'lock_wait': 5}, + local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) @@ -293,6 +347,7 @@ def test_create_repository_with_local_path_calls_borg_via_local_path(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', local_path='borg1', ) @@ -314,6 +369,7 @@ def test_create_repository_with_remote_path_calls_borg_with_remote_path_flag(): repository_path='repo', storage_config={}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', remote_path='borg1', ) @@ -335,5 +391,6 @@ def test_create_repository_with_extra_borg_options_calls_borg_with_extra_options repository_path='repo', storage_config={'extra_borg_options': {'rcreate': '--extra --options'}}, local_borg_version='2.3.4', + global_arguments=flexmock(log_json=False), encryption_mode='repokey', ) diff --git a/tests/unit/borg/test_rinfo.py b/tests/unit/borg/test_rinfo.py index 979b253e8..a6e3f08c1 100644 --- a/tests/unit/borg/test_rinfo.py +++ b/tests/unit/borg/test_rinfo.py @@ -7,7 +7,7 @@ from borgmatic.borg import rinfo as module from ..test_verbosity import insert_logging_mock -def test_display_repository_info_calls_borg_with_parameters(): +def test_display_repository_info_calls_borg_with_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.feature).should_receive('available').and_return(True) @@ -30,6 +30,7 @@ def test_display_repository_info_calls_borg_with_parameters(): storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), ) @@ -51,10 +52,11 @@ def test_display_repository_info_without_borg_features_calls_borg_with_info_sub_ storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), ) -def test_display_repository_info_with_log_info_calls_borg_with_info_parameter(): +def test_display_repository_info_with_log_info_calls_borg_with_info_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.feature).should_receive('available').and_return(True) @@ -77,6 +79,7 @@ def test_display_repository_info_with_log_info_calls_borg_with_info_parameter(): storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), ) @@ -102,12 +105,13 @@ def test_display_repository_info_with_log_info_and_json_suppresses_most_borg_out storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=True), + global_arguments=flexmock(log_json=False), ) assert json_output == '[]' -def test_display_repository_info_with_log_debug_calls_borg_with_debug_parameter(): +def test_display_repository_info_with_log_debug_calls_borg_with_debug_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.feature).should_receive('available').and_return(True) @@ -131,6 +135,7 @@ def test_display_repository_info_with_log_debug_calls_borg_with_debug_parameter( storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), ) @@ -156,12 +161,13 @@ def test_display_repository_info_with_log_debug_and_json_suppresses_most_borg_ou storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=True), + global_arguments=flexmock(log_json=False), ) assert json_output == '[]' -def test_display_repository_info_with_json_calls_borg_with_json_parameter(): +def test_display_repository_info_with_json_calls_borg_with_json_flag(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.feature).should_receive('available').and_return(True) @@ -182,6 +188,7 @@ def test_display_repository_info_with_json_calls_borg_with_json_parameter(): storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=True), + global_arguments=flexmock(log_json=False), ) assert json_output == '[]' @@ -210,11 +217,12 @@ def test_display_repository_info_with_local_path_calls_borg_via_local_path(): storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), local_path='borg1', ) -def test_display_repository_info_with_remote_path_calls_borg_with_remote_path_parameters(): +def test_display_repository_info_with_remote_path_calls_borg_with_remote_path_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER flexmock(module.feature).should_receive('available').and_return(True) @@ -237,11 +245,39 @@ def test_display_repository_info_with_remote_path_calls_borg_with_remote_path_pa storage_config={}, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), remote_path='borg1', ) -def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_parameters(): +def test_display_repository_info_with_log_json_calls_borg_with_log_json_flags(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return( + ( + '--repo', + 'repo', + ) + ) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'rinfo', '--log-json', '--repo', 'repo'), + output_log_level=module.borgmatic.logger.ANSWER, + borg_local_path='borg', + extra_environment=None, + ) + + module.display_repository_info( + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=True), + ) + + +def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER storage_config = {'lock_wait': 5} @@ -265,4 +301,5 @@ def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_parame storage_config=storage_config, local_borg_version='2.3.4', rinfo_arguments=flexmock(json=False), + global_arguments=flexmock(log_json=False), ) diff --git a/tests/unit/borg/test_rlist.py b/tests/unit/borg/test_rlist.py index b83ba6158..e1e04f8bc 100644 --- a/tests/unit/borg/test_rlist.py +++ b/tests/unit/borg/test_rlist.py @@ -20,12 +20,18 @@ def test_resolve_archive_name_passes_through_non_latest_archive_name(): archive = 'myhost-2030-01-01T14:41:17.647620' assert ( - module.resolve_archive_name('repo', archive, storage_config={}, local_borg_version='1.2.3') + module.resolve_archive_name( + 'repo', + archive, + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) == archive ) -def test_resolve_archive_name_calls_borg_with_parameters(): +def test_resolve_archive_name_calls_borg_with_flags(): expected_archive = 'archive-name' flexmock(module.environment).should_receive('make_environment') flexmock(module).should_receive('execute_command_and_capture_output').with_args( @@ -34,12 +40,18 @@ def test_resolve_archive_name_calls_borg_with_parameters(): ).and_return(expected_archive + '\n') assert ( - module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3') + module.resolve_archive_name( + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) == expected_archive ) -def test_resolve_archive_name_with_log_info_calls_borg_without_info_parameter(): +def test_resolve_archive_name_with_log_info_calls_borg_without_info_flag(): expected_archive = 'archive-name' flexmock(module.environment).should_receive('make_environment') flexmock(module).should_receive('execute_command_and_capture_output').with_args( @@ -49,12 +61,18 @@ def test_resolve_archive_name_with_log_info_calls_borg_without_info_parameter(): insert_logging_mock(logging.INFO) assert ( - module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3') + module.resolve_archive_name( + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) == expected_archive ) -def test_resolve_archive_name_with_log_debug_calls_borg_without_debug_parameter(): +def test_resolve_archive_name_with_log_debug_calls_borg_without_debug_flag(): expected_archive = 'archive-name' flexmock(module.environment).should_receive('make_environment') flexmock(module).should_receive('execute_command_and_capture_output').with_args( @@ -64,7 +82,13 @@ def test_resolve_archive_name_with_log_debug_calls_borg_without_debug_parameter( insert_logging_mock(logging.DEBUG) assert ( - module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3') + module.resolve_archive_name( + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) == expected_archive ) @@ -79,13 +103,18 @@ def test_resolve_archive_name_with_local_path_calls_borg_via_local_path(): assert ( module.resolve_archive_name( - 'repo', 'latest', storage_config={}, local_borg_version='1.2.3', local_path='borg1' + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + local_path='borg1', ) == expected_archive ) -def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_parameters(): +def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_flags(): expected_archive = 'archive-name' flexmock(module.environment).should_receive('make_environment') flexmock(module).should_receive('execute_command_and_capture_output').with_args( @@ -95,7 +124,12 @@ def test_resolve_archive_name_with_remote_path_calls_borg_with_remote_path_param assert ( module.resolve_archive_name( - 'repo', 'latest', storage_config={}, local_borg_version='1.2.3', remote_path='borg1' + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + remote_path='borg1', ) == expected_archive ) @@ -109,10 +143,37 @@ def test_resolve_archive_name_without_archives_raises(): ).and_return('') with pytest.raises(ValueError): - module.resolve_archive_name('repo', 'latest', storage_config={}, local_borg_version='1.2.3') + module.resolve_archive_name( + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), + ) -def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameters(): +def test_resolve_archive_name_with_log_json_calls_borg_with_log_json_flags(): + expected_archive = 'archive-name' + + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command_and_capture_output').with_args( + ('borg', 'list', '--log-json') + BORG_LIST_LATEST_ARGUMENTS, + extra_environment=None, + ).and_return(expected_archive + '\n') + + assert ( + module.resolve_archive_name( + 'repo', + 'latest', + storage_config={}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=True), + ) + == expected_archive + ) + + +def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_flags(): expected_archive = 'archive-name' flexmock(module.environment).should_receive('make_environment') @@ -123,7 +184,11 @@ def test_resolve_archive_name_with_lock_wait_calls_borg_with_lock_wait_parameter assert ( module.resolve_archive_name( - 'repo', 'latest', storage_config={'lock_wait': 'okay'}, local_borg_version='1.2.3' + 'repo', + 'latest', + storage_config={'lock_wait': 'okay'}, + local_borg_version='1.2.3', + global_arguments=flexmock(log_json=False), ) == expected_archive ) @@ -145,6 +210,7 @@ def test_make_rlist_command_includes_log_info(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--info', 'repo') @@ -166,6 +232,7 @@ def test_make_rlist_command_includes_json_but_not_info(): rlist_arguments=flexmock( archive=None, paths=None, json=True, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') @@ -187,6 +254,7 @@ def test_make_rlist_command_includes_log_debug(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--debug', '--show-rc', 'repo') @@ -208,6 +276,7 @@ def test_make_rlist_command_includes_json_but_not_debug(): rlist_arguments=flexmock( archive=None, paths=None, json=True, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') @@ -228,11 +297,35 @@ def test_make_rlist_command_includes_json(): rlist_arguments=flexmock( archive=None, paths=None, json=True, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--json', 'repo') +def test_make_rlist_command_includes_log_json(): + flexmock(module.flags).should_receive('make_flags').and_return(()).and_return( + ('--log-json',) + ).and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, None, '1.2.3' + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + + command = module.make_rlist_command( + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + rlist_arguments=flexmock( + archive=None, paths=None, json=False, prefix=None, match_archives=None + ), + global_arguments=flexmock(log_json=True), + ) + + assert command == ('borg', 'list', '--log-json', 'repo') + + def test_make_rlist_command_includes_lock_wait(): flexmock(module.flags).should_receive('make_flags').and_return(()).and_return( ('--lock-wait', '5') @@ -250,6 +343,7 @@ def test_make_rlist_command_includes_lock_wait(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--lock-wait', '5', 'repo') @@ -270,6 +364,7 @@ def test_make_rlist_command_includes_local_path(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), local_path='borg2', ) @@ -293,6 +388,7 @@ def test_make_rlist_command_includes_remote_path(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), remote_path='borg2', ) @@ -314,6 +410,7 @@ def test_make_rlist_command_transforms_prefix_into_match_archives(): storage_config={}, local_borg_version='1.2.3', rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix='foo'), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--match-archives', 'sh:foo*', 'repo') @@ -332,6 +429,7 @@ def test_make_rlist_command_prefers_prefix_over_archive_name_format(): storage_config={'archive_name_format': 'bar-{now}'}, # noqa: FS003 local_borg_version='1.2.3', rlist_arguments=flexmock(archive=None, paths=None, json=False, prefix='foo'), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--match-archives', 'sh:foo*', 'repo') @@ -352,6 +450,7 @@ def test_make_rlist_command_transforms_archive_name_format_into_match_archives() rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--match-archives', 'sh:bar-*', 'repo') @@ -372,6 +471,7 @@ def test_make_rlist_command_includes_short(): rlist_arguments=flexmock( archive=None, paths=None, json=False, prefix=None, match_archives=None, short=True ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--short', 'repo') @@ -413,12 +513,13 @@ def test_make_rlist_command_includes_additional_flags(argument_name): format=None, **{argument_name: 'value'}, ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--' + argument_name.replace('_', '-'), 'value', 'repo') -def test_make_rlist_command_with_match_archives_calls_borg_with_match_archives_parameters(): +def test_make_rlist_command_with_match_archives_calls_borg_with_match_archives_flags(): flexmock(module.flags).should_receive('make_flags').and_return(()) flexmock(module.flags).should_receive('make_match_archives_flags').with_args( None, None, '1.2.3' @@ -444,15 +545,17 @@ def test_make_rlist_command_with_match_archives_calls_borg_with_match_archives_p find_paths=None, format=None, ), + global_arguments=flexmock(log_json=False), ) assert command == ('borg', 'list', '--match-archives', 'foo-*', 'repo') -def test_list_repository_calls_borg_with_parameters(): +def test_list_repository_calls_borg_with_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER rlist_arguments = argparse.Namespace(json=False) + global_arguments = flexmock() flexmock(module.feature).should_receive('available').and_return(False) flexmock(module).should_receive('make_rlist_command').with_args( @@ -460,6 +563,7 @@ def test_list_repository_calls_borg_with_parameters(): storage_config={}, local_borg_version='1.2.3', rlist_arguments=rlist_arguments, + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'rlist', 'repo')) @@ -476,6 +580,7 @@ def test_list_repository_calls_borg_with_parameters(): storage_config={}, local_borg_version='1.2.3', rlist_arguments=rlist_arguments, + global_arguments=global_arguments, ) @@ -483,6 +588,7 @@ def test_list_repository_with_json_returns_borg_output(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER rlist_arguments = argparse.Namespace(json=True) + global_arguments = flexmock() json_output = flexmock() flexmock(module.feature).should_receive('available').and_return(False) @@ -491,6 +597,7 @@ def test_list_repository_with_json_returns_borg_output(): storage_config={}, local_borg_version='1.2.3', rlist_arguments=rlist_arguments, + global_arguments=global_arguments, local_path='borg', remote_path=None, ).and_return(('borg', 'rlist', 'repo')) @@ -503,6 +610,7 @@ def test_list_repository_with_json_returns_borg_output(): storage_config={}, local_borg_version='1.2.3', rlist_arguments=rlist_arguments, + global_arguments=global_arguments, ) == json_output ) diff --git a/tests/unit/borg/test_transfer.py b/tests/unit/borg/test_transfer.py index 8f41bf5ab..e85729eac 100644 --- a/tests/unit/borg/test_transfer.py +++ b/tests/unit/borg/test_transfer.py @@ -32,6 +32,7 @@ def test_transfer_archives_calls_borg_with_flags(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -62,6 +63,7 @@ def test_transfer_archives_with_dry_run_calls_borg_with_dry_run_flag(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -89,6 +91,7 @@ def test_transfer_archives_with_log_info_calls_borg_with_info_flag(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -117,6 +120,7 @@ def test_transfer_archives_with_log_debug_calls_borg_with_debug_flag(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -146,6 +150,7 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag(): transfer_arguments=flexmock( archive='archive', progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -175,6 +180,7 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl transfer_arguments=flexmock( archive=None, progress=None, match_archives='sh:foo*', source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -204,6 +210,7 @@ def test_transfer_archives_with_archive_name_format_calls_borg_with_match_archiv transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -231,6 +238,7 @@ def test_transfer_archives_with_local_path_calls_borg_via_local_path(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), local_path='borg2', ) @@ -262,10 +270,42 @@ def test_transfer_archives_with_remote_path_calls_borg_with_remote_path_flags(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), remote_path='borg2', ) +def test_transfer_archives_with_log_json_calls_borg_with_log_json_flags(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags').with_args('log-json', True).and_return( + ('--log-json',) + ) + flexmock(module.flags).should_receive('make_match_archives_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(()) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ('borg', 'transfer', '--log-json', '--repo', 'repo'), + output_log_level=module.borgmatic.logger.ANSWER, + output_file=None, + borg_local_path='borg', + extra_environment=None, + ) + + module.transfer_archives( + dry_run=False, + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + transfer_arguments=flexmock( + archive=None, progress=None, match_archives=None, source_repository=None + ), + global_arguments=flexmock(log_json=True), + ) + + def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER @@ -294,6 +334,7 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags(): transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -321,6 +362,7 @@ def test_transfer_archives_with_progress_calls_borg_with_progress_flag(): transfer_arguments=flexmock( archive=None, progress=True, match_archives=None, source_repository=None ), + global_arguments=flexmock(log_json=False), ) @@ -356,6 +398,7 @@ def test_transfer_archives_passes_through_arguments_to_borg(argument_name): source_repository=None, **{argument_name: 'value'}, ), + global_arguments=flexmock(log_json=False), ) @@ -385,4 +428,5 @@ def test_transfer_archives_with_source_repository_calls_borg_with_other_repo_fla transfer_arguments=flexmock( archive=None, progress=None, match_archives=None, source_repository='other' ), + global_arguments=flexmock(log_json=False), )