Update borg action for Borg 2 support (#557).
This commit is contained in:
parent
f36e38ec20
commit
30abd0e3de
3 changed files with 99 additions and 31 deletions
|
@ -1,24 +1,29 @@
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from borgmatic.borg import environment
|
from borgmatic.borg import environment, flags
|
||||||
from borgmatic.borg.flags import make_flags
|
|
||||||
from borgmatic.execute import execute_command
|
from borgmatic.execute import execute_command
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
REPOSITORYLESS_BORG_COMMANDS = {'serve', None}
|
REPOSITORYLESS_BORG_COMMANDS = {'serve', None}
|
||||||
BORG_COMMANDS_WITH_SUBCOMMANDS = {'key', 'debug'}
|
BORG_SUBCOMMANDS_WITH_SUBCOMMANDS = {'key', 'debug'}
|
||||||
BORG_SUBCOMMANDS_WITHOUT_REPOSITORY = (('debug', 'info'), ('debug', 'convert-profile'))
|
BORG_SUBCOMMANDS_WITHOUT_REPOSITORY = (('debug', 'info'), ('debug', 'convert-profile'), ())
|
||||||
|
|
||||||
|
|
||||||
def run_arbitrary_borg(
|
def run_arbitrary_borg(
|
||||||
repository, storage_config, options, archive=None, local_path='borg', remote_path=None
|
repository,
|
||||||
|
storage_config,
|
||||||
|
local_borg_version,
|
||||||
|
options,
|
||||||
|
archive=None,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
Given a local or remote repository path, a storage config dict, a sequence of arbitrary
|
Given a local or remote repository path, a storage config dict, the local Borg version, a
|
||||||
command-line Borg options, and an optional archive name, run an arbitrary Borg command on the
|
sequence of arbitrary command-line Borg options, and an optional archive name, run an arbitrary
|
||||||
given repository/archive.
|
Borg command on the given repository/archive.
|
||||||
'''
|
'''
|
||||||
lock_wait = storage_config.get('lock_wait', None)
|
lock_wait = storage_config.get('lock_wait', None)
|
||||||
|
|
||||||
|
@ -26,7 +31,7 @@ def run_arbitrary_borg(
|
||||||
options = options[1:] if options[0] == '--' else options
|
options = options[1:] if options[0] == '--' else options
|
||||||
|
|
||||||
# Borg commands like "key" have a sub-command ("export", etc.) that must follow it.
|
# Borg commands like "key" have a sub-command ("export", etc.) that must follow it.
|
||||||
command_options_start_index = 2 if options[0] in BORG_COMMANDS_WITH_SUBCOMMANDS else 1
|
command_options_start_index = 2 if options[0] in BORG_SUBCOMMANDS_WITH_SUBCOMMANDS else 1
|
||||||
borg_command = tuple(options[:command_options_start_index])
|
borg_command = tuple(options[:command_options_start_index])
|
||||||
command_options = tuple(options[command_options_start_index:])
|
command_options = tuple(options[command_options_start_index:])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -34,21 +39,23 @@ def run_arbitrary_borg(
|
||||||
command_options = ()
|
command_options = ()
|
||||||
|
|
||||||
if borg_command in BORG_SUBCOMMANDS_WITHOUT_REPOSITORY:
|
if borg_command in BORG_SUBCOMMANDS_WITHOUT_REPOSITORY:
|
||||||
repository_archive = None
|
repository_archive_flags = ()
|
||||||
else:
|
elif archive:
|
||||||
repository_archive = (
|
repository_archive_flags = flags.make_repository_archive_flags(
|
||||||
'::'.join((repository, archive)) if repository and archive else repository
|
repository, archive, local_borg_version
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
repository_archive_flags = flags.make_repository_flags(repository, local_borg_version)
|
||||||
|
|
||||||
full_command = (
|
full_command = (
|
||||||
(local_path,)
|
(local_path,)
|
||||||
+ borg_command
|
+ borg_command
|
||||||
+ ((repository_archive,) if borg_command and repository_archive else ())
|
+ repository_archive_flags
|
||||||
+ command_options
|
+ command_options
|
||||||
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
|
+ (('--info',) if logger.getEffectiveLevel() == logging.INFO else ())
|
||||||
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
|
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ())
|
||||||
+ make_flags('remote-path', remote_path)
|
+ flags.make_flags('remote-path', remote_path)
|
||||||
+ make_flags('lock-wait', lock_wait)
|
+ flags.make_flags('lock-wait', lock_wait)
|
||||||
)
|
)
|
||||||
|
|
||||||
return execute_command(
|
return execute_command(
|
||||||
|
|
|
@ -722,6 +722,7 @@ def run_actions(
|
||||||
borg_borg.run_arbitrary_borg(
|
borg_borg.run_arbitrary_borg(
|
||||||
repository,
|
repository,
|
||||||
storage,
|
storage,
|
||||||
|
local_borg_version,
|
||||||
options=arguments['borg'].options,
|
options=arguments['borg'].options,
|
||||||
archive=archive_name,
|
archive=archive_name,
|
||||||
local_path=local_path,
|
local_path=local_path,
|
||||||
|
|
|
@ -8,6 +8,8 @@ from ..test_verbosity import insert_logging_mock
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_calls_borg_with_parameters():
|
def test_run_arbitrary_borg_calls_borg_with_parameters():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo'),
|
('borg', 'break-lock', 'repo'),
|
||||||
|
@ -17,11 +19,13 @@ def test_run_arbitrary_borg_calls_borg_with_parameters():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['break-lock'],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
|
def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo', '--info'),
|
('borg', 'break-lock', 'repo', '--info'),
|
||||||
|
@ -32,11 +36,13 @@ def test_run_arbitrary_borg_with_log_info_calls_borg_with_info_parameter():
|
||||||
insert_logging_mock(logging.INFO)
|
insert_logging_mock(logging.INFO)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['break-lock'],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
|
def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo', '--debug', '--show-rc'),
|
('borg', 'break-lock', 'repo', '--debug', '--show-rc'),
|
||||||
|
@ -47,12 +53,16 @@ def test_run_arbitrary_borg_with_log_debug_calls_borg_with_debug_parameter():
|
||||||
insert_logging_mock(logging.DEBUG)
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['break-lock'],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=['break-lock'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters():
|
||||||
storage_config = {'lock_wait': 5}
|
storage_config = {'lock_wait': 5}
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(
|
||||||
|
('--lock-wait', '5')
|
||||||
|
)
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo', '--lock-wait', '5'),
|
('borg', 'break-lock', 'repo', '--lock-wait', '5'),
|
||||||
|
@ -62,12 +72,18 @@ def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_parameters(
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config=storage_config, options=['break-lock'],
|
repository='repo',
|
||||||
|
storage_config=storage_config,
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['break-lock'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
|
def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
|
||||||
storage_config = {}
|
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||||
|
('repo::archive',)
|
||||||
|
)
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo::archive'),
|
('borg', 'break-lock', 'repo::archive'),
|
||||||
|
@ -77,11 +93,17 @@ def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_parameter():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config=storage_config, options=['break-lock'], archive='archive',
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['break-lock'],
|
||||||
|
archive='archive',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
|
def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg1', 'break-lock', 'repo'),
|
('borg1', 'break-lock', 'repo'),
|
||||||
|
@ -91,11 +113,19 @@ def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['break-lock'], local_path='borg1',
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['break-lock'],
|
||||||
|
local_path='borg1',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_parameters():
|
def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_parameters():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(
|
||||||
|
('--remote-path', 'borg1')
|
||||||
|
).and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo', '--remote-path', 'borg1'),
|
('borg', 'break-lock', 'repo', '--remote-path', 'borg1'),
|
||||||
|
@ -105,11 +135,17 @@ def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_paramet
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['break-lock'], remote_path='borg1',
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['break-lock'],
|
||||||
|
remote_path='borg1',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
|
def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'list', 'repo', '--progress'),
|
('borg', 'list', 'repo', '--progress'),
|
||||||
|
@ -119,11 +155,16 @@ def test_run_arbitrary_borg_passes_borg_specific_parameters_to_borg():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['list', '--progress'],
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['list', '--progress'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
|
def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'break-lock', 'repo'),
|
('borg', 'break-lock', 'repo'),
|
||||||
|
@ -133,22 +174,29 @@ def test_run_arbitrary_borg_omits_dash_dash_in_parameters_passed_to_borg():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['--', 'break-lock'],
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['--', 'break-lock'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
|
def test_run_arbitrary_borg_without_borg_specific_parameters_does_not_raise():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').never()
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg',), output_log_level=logging.WARNING, borg_local_path='borg', extra_environment=None,
|
('borg',), output_log_level=logging.WARNING, borg_local_path='borg', extra_environment=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=[],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=[],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
|
def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'key', 'export', 'repo'),
|
('borg', 'key', 'export', 'repo'),
|
||||||
|
@ -158,11 +206,13 @@ def test_run_arbitrary_borg_passes_key_sub_command_to_borg_before_repository():
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['key', 'export'],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=['key', 'export'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository():
|
def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'debug', 'dump-manifest', 'repo', 'path'),
|
('borg', 'debug', 'dump-manifest', 'repo', 'path'),
|
||||||
|
@ -172,11 +222,16 @@ def test_run_arbitrary_borg_passes_debug_sub_command_to_borg_before_repository()
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['debug', 'dump-manifest', 'path'],
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['debug', 'dump-manifest', 'path'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository():
|
def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repository():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').never()
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'debug', 'info'),
|
('borg', 'debug', 'info'),
|
||||||
|
@ -186,11 +241,13 @@ def test_run_arbitrary_borg_with_debug_info_command_does_not_pass_borg_repositor
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['debug', 'info'],
|
repository='repo', storage_config={}, local_borg_version='1.2.3', options=['debug', 'info'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository():
|
def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_borg_repository():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').never()
|
||||||
|
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||||
flexmock(module.environment).should_receive('make_environment')
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
flexmock(module).should_receive('execute_command').with_args(
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
('borg', 'debug', 'convert-profile', 'in', 'out'),
|
('borg', 'debug', 'convert-profile', 'in', 'out'),
|
||||||
|
@ -200,5 +257,8 @@ def test_run_arbitrary_borg_with_debug_convert_profile_command_does_not_pass_bor
|
||||||
)
|
)
|
||||||
|
|
||||||
module.run_arbitrary_borg(
|
module.run_arbitrary_borg(
|
||||||
repository='repo', storage_config={}, options=['debug', 'convert-profile', 'in', 'out'],
|
repository='repo',
|
||||||
|
storage_config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
options=['debug', 'convert-profile', 'in', 'out'],
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue