Add "key export" action to export a copy of the repository key (#345).
This commit is contained in:
parent
fd8c56c6be
commit
6dca7c1c15
9 changed files with 426 additions and 3 deletions
6
NEWS
6
NEWS
|
@ -1,9 +1,11 @@
|
||||||
1.8.2.dev0
|
1.8.2.dev0
|
||||||
|
* #345: Add "key export" action to export a copy of the repository key for safekeeping in case
|
||||||
|
the original goes missing or gets damaged.
|
||||||
* #727: Add a MariaDB database hook that uses native MariaDB commands instead of the deprecated
|
* #727: Add a MariaDB database hook that uses native MariaDB commands instead of the deprecated
|
||||||
MySQL ones. Be aware though that any existing backups made with the "mysql_databases:" hook are
|
MySQL ones. Be aware though that any existing backups made with the "mysql_databases:" hook are
|
||||||
only restorable with a "mysql_databases:" configuration.
|
only restorable with a "mysql_databases:" configuration.
|
||||||
* Add a source code reference for getting oriented with the borgmatic code as a developer:
|
* Add source code reference documentation for getting oriented with the borgmatic code as a
|
||||||
https://torsion.org/borgmatic/docs/reference/source-code/
|
developer: https://torsion.org/borgmatic/docs/reference/source-code/
|
||||||
|
|
||||||
1.8.1
|
1.8.1
|
||||||
* #326: Add documentation for restoring a database to an alternate host:
|
* #326: Add documentation for restoring a database to an alternate host:
|
||||||
|
|
33
borgmatic/actions/export_key.py
Normal file
33
borgmatic/actions/export_key.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import borgmatic.borg.export_key
|
||||||
|
import borgmatic.config.validate
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def run_export_key(
|
||||||
|
repository,
|
||||||
|
config,
|
||||||
|
local_borg_version,
|
||||||
|
export_arguments,
|
||||||
|
global_arguments,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Run the "key export" action for the given repository.
|
||||||
|
'''
|
||||||
|
if export_arguments.repository is None or borgmatic.config.validate.repositories_match(
|
||||||
|
repository, export_arguments.repository
|
||||||
|
):
|
||||||
|
logger.info(f'{repository.get("label", repository["path"])}: Exporting repository key')
|
||||||
|
borgmatic.borg.export_key.export_key(
|
||||||
|
repository['path'],
|
||||||
|
config,
|
||||||
|
local_borg_version,
|
||||||
|
export_arguments,
|
||||||
|
global_arguments,
|
||||||
|
local_path=local_path,
|
||||||
|
remote_path=remote_path,
|
||||||
|
)
|
70
borgmatic/borg/export_key.py
Normal file
70
borgmatic/borg/export_key.py
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import borgmatic.logger
|
||||||
|
from borgmatic.borg import environment, flags
|
||||||
|
from borgmatic.execute import DO_NOT_CAPTURE, execute_command
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def export_key(
|
||||||
|
repository_path,
|
||||||
|
config,
|
||||||
|
local_borg_version,
|
||||||
|
export_arguments,
|
||||||
|
global_arguments,
|
||||||
|
local_path='borg',
|
||||||
|
remote_path=None,
|
||||||
|
):
|
||||||
|
'''
|
||||||
|
Given a local or remote repository path, a configuration dict, the local Borg version, and
|
||||||
|
optional local and remote Borg paths, export the repository key to the destination path
|
||||||
|
indicated in the export arguments.
|
||||||
|
|
||||||
|
If the destination path is empty or "-", then print the key to stdout instead of to a file.
|
||||||
|
|
||||||
|
Raise FileExistsError if a path is given but it already exists on disk.
|
||||||
|
'''
|
||||||
|
borgmatic.logger.add_custom_log_levels()
|
||||||
|
umask = config.get('umask', None)
|
||||||
|
lock_wait = config.get('lock_wait', None)
|
||||||
|
|
||||||
|
if export_arguments.path and export_arguments.path != '-':
|
||||||
|
if os.path.exists(export_arguments.path):
|
||||||
|
raise FileExistsError(
|
||||||
|
f'Destination path {export_arguments.path} already exists. Aborting.'
|
||||||
|
)
|
||||||
|
|
||||||
|
output_file = None
|
||||||
|
else:
|
||||||
|
output_file = DO_NOT_CAPTURE
|
||||||
|
|
||||||
|
full_command = (
|
||||||
|
(local_path, 'key', 'export')
|
||||||
|
+ (('--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 ())
|
||||||
|
+ flags.make_flags('paper', export_arguments.paper)
|
||||||
|
+ flags.make_flags('qr-html', export_arguments.qr_html)
|
||||||
|
+ flags.make_repository_flags(
|
||||||
|
repository_path,
|
||||||
|
local_borg_version,
|
||||||
|
)
|
||||||
|
+ ((export_arguments.path,) if output_file is None else ())
|
||||||
|
)
|
||||||
|
|
||||||
|
if global_arguments.dry_run:
|
||||||
|
logging.info(f'{repository_path}: Skipping key export (dry run)')
|
||||||
|
return
|
||||||
|
|
||||||
|
execute_command(
|
||||||
|
full_command,
|
||||||
|
output_file=output_file,
|
||||||
|
output_log_level=logging.ANSWER,
|
||||||
|
borg_local_path=local_path,
|
||||||
|
extra_environment=environment.make_environment(config),
|
||||||
|
)
|
|
@ -23,6 +23,7 @@ ACTION_ALIASES = {
|
||||||
'info': ['-i'],
|
'info': ['-i'],
|
||||||
'transfer': [],
|
'transfer': [],
|
||||||
'break-lock': [],
|
'break-lock': [],
|
||||||
|
'key': [],
|
||||||
'borg': [],
|
'borg': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1176,6 +1177,51 @@ def make_parsers():
|
||||||
'-h', '--help', action='help', help='Show this help message and exit'
|
'-h', '--help', action='help', help='Show this help message and exit'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
key_parser = action_parsers.add_parser(
|
||||||
|
'key',
|
||||||
|
aliases=ACTION_ALIASES['key'],
|
||||||
|
help='Perform repository key related operations',
|
||||||
|
description='Perform repository key related operations',
|
||||||
|
add_help=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
key_group = key_parser.add_argument_group('key arguments')
|
||||||
|
key_group.add_argument('-h', '--help', action='help', help='Show this help message and exit')
|
||||||
|
|
||||||
|
key_parsers = key_parser.add_subparsers(
|
||||||
|
title='key sub-actions',
|
||||||
|
)
|
||||||
|
|
||||||
|
key_export_parser = key_parsers.add_parser(
|
||||||
|
'export',
|
||||||
|
help='Export a copy of the repository key for safekeeping in case the original goes missing or gets damaged',
|
||||||
|
description='Export a copy of the repository key for safekeeping in case the original goes missing or gets damaged',
|
||||||
|
add_help=False,
|
||||||
|
)
|
||||||
|
key_export_group = key_export_parser.add_argument_group('key export arguments')
|
||||||
|
key_export_group.add_argument(
|
||||||
|
'--paper',
|
||||||
|
action='store_true',
|
||||||
|
help='Export the key in a text format suitable for printing and later manual entry',
|
||||||
|
)
|
||||||
|
key_export_group.add_argument(
|
||||||
|
'--qr-html',
|
||||||
|
action='store_true',
|
||||||
|
help='Export the key in an HTML format suitable for printing and later manual entry or QR code scanning',
|
||||||
|
)
|
||||||
|
key_export_group.add_argument(
|
||||||
|
'--repository',
|
||||||
|
help='Path of repository to export the key for, defaults to the configured repository if there is only one',
|
||||||
|
)
|
||||||
|
key_export_group.add_argument(
|
||||||
|
'--path',
|
||||||
|
metavar='PATH',
|
||||||
|
help='Path to export the key to, defaults to stdout (but be careful about dirtying the output with --verbosity)',
|
||||||
|
)
|
||||||
|
key_export_group.add_argument(
|
||||||
|
'-h', '--help', action='help', help='Show this help message and exit'
|
||||||
|
)
|
||||||
|
|
||||||
borg_parser = action_parsers.add_parser(
|
borg_parser = action_parsers.add_parser(
|
||||||
'borg',
|
'borg',
|
||||||
aliases=ACTION_ALIASES['borg'],
|
aliases=ACTION_ALIASES['borg'],
|
||||||
|
|
|
@ -22,6 +22,7 @@ import borgmatic.actions.config.bootstrap
|
||||||
import borgmatic.actions.config.generate
|
import borgmatic.actions.config.generate
|
||||||
import borgmatic.actions.config.validate
|
import borgmatic.actions.config.validate
|
||||||
import borgmatic.actions.create
|
import borgmatic.actions.create
|
||||||
|
import borgmatic.actions.export_key
|
||||||
import borgmatic.actions.export_tar
|
import borgmatic.actions.export_tar
|
||||||
import borgmatic.actions.extract
|
import borgmatic.actions.extract
|
||||||
import borgmatic.actions.info
|
import borgmatic.actions.info
|
||||||
|
@ -448,6 +449,16 @@ def run_actions(
|
||||||
local_path,
|
local_path,
|
||||||
remote_path,
|
remote_path,
|
||||||
)
|
)
|
||||||
|
elif action_name == 'export':
|
||||||
|
borgmatic.actions.export_key.run_export_key(
|
||||||
|
repository,
|
||||||
|
config,
|
||||||
|
local_borg_version,
|
||||||
|
action_arguments,
|
||||||
|
global_arguments,
|
||||||
|
local_path,
|
||||||
|
remote_path,
|
||||||
|
)
|
||||||
elif action_name == 'borg':
|
elif action_name == 'borg':
|
||||||
borgmatic.actions.borg.run_borg(
|
borgmatic.actions.borg.run_borg(
|
||||||
repository,
|
repository,
|
||||||
|
|
|
@ -310,7 +310,8 @@ problem: the `restore` action figures out which repository to use.
|
||||||
|
|
||||||
But if you have multiple repositories configured, then you'll need to specify
|
But if you have multiple repositories configured, then you'll need to specify
|
||||||
the repository to use via the `--repository` flag. This can be done either
|
the repository to use via the `--repository` flag. This can be done either
|
||||||
with the repository's path or its label as configured in your borgmatic configuration file.
|
with the repository's path or its label as configured in your borgmatic
|
||||||
|
configuration file.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
borgmatic restore --repository repo.borg --archive host-2023-...
|
borgmatic restore --repository repo.borg --archive host-2023-...
|
||||||
|
|
20
tests/unit/actions/test_export_key.py
Normal file
20
tests/unit/actions/test_export_key.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
from flexmock import flexmock
|
||||||
|
|
||||||
|
from borgmatic.actions import export_key as module
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_export_key_does_not_raise():
|
||||||
|
flexmock(module.logger).answer = lambda message: None
|
||||||
|
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').and_return(True)
|
||||||
|
flexmock(module.borgmatic.borg.export_key).should_receive('export_key')
|
||||||
|
export_arguments = flexmock(repository=flexmock())
|
||||||
|
|
||||||
|
module.run_export_key(
|
||||||
|
repository={'path': 'repo'},
|
||||||
|
config={},
|
||||||
|
local_borg_version=None,
|
||||||
|
export_arguments=export_arguments,
|
||||||
|
global_arguments=flexmock(),
|
||||||
|
local_path=None,
|
||||||
|
remote_path=None,
|
||||||
|
)
|
222
tests/unit/borg/test_export_key.py
Normal file
222
tests/unit/borg/test_export_key.py
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from flexmock import flexmock
|
||||||
|
|
||||||
|
import borgmatic.logger
|
||||||
|
from borgmatic.borg import export_key as module
|
||||||
|
|
||||||
|
from ..test_verbosity import insert_logging_mock
|
||||||
|
|
||||||
|
|
||||||
|
def insert_execute_command_mock(command, output_file=module.DO_NOT_CAPTURE):
|
||||||
|
borgmatic.logger.add_custom_log_levels()
|
||||||
|
|
||||||
|
flexmock(module.environment).should_receive('make_environment')
|
||||||
|
flexmock(module).should_receive('execute_command').with_args(
|
||||||
|
command,
|
||||||
|
output_file=output_file,
|
||||||
|
output_log_level=module.logging.ANSWER,
|
||||||
|
borg_local_path='borg',
|
||||||
|
extra_environment=None,
|
||||||
|
).once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_required_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_remote_path_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--remote-path', 'borg1', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
remote_path='borg1',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_umask_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--umask', '0770', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={'umask': '0770'},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_log_json_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--log-json', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_lock_wait_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--lock-wait', '5', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={'lock_wait': '5'},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_with_log_info_calls_borg_with_info_parameter():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--info', 'repo'))
|
||||||
|
insert_logging_mock(logging.INFO)
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_with_log_debug_calls_borg_with_debug_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--debug', '--show-rc', 'repo'))
|
||||||
|
insert_logging_mock(logging.DEBUG)
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_paper_flags():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--paper', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=True, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_paper_flag():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--paper', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=True, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_qr_html_flag():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', '--qr-html', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=True, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_calls_borg_with_path_argument():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').and_return(False)
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', 'repo', 'dest'), output_file=None)
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path='dest'),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_with_already_existent_path_raises():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').and_return(True)
|
||||||
|
flexmock(module).should_receive('execute_command').never()
|
||||||
|
|
||||||
|
with pytest.raises(FileExistsError):
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path='dest'),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_with_stdout_path_calls_borg_without_path_argument():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
insert_execute_command_mock(('borg', 'key', 'export', 'repo'))
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path='-'),
|
||||||
|
global_arguments=flexmock(dry_run=False, log_json=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_export_key_with_dry_run_skip_borg_call():
|
||||||
|
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||||
|
flexmock(module.os.path).should_receive('exists').never()
|
||||||
|
flexmock(module).should_receive('execute_command').never()
|
||||||
|
|
||||||
|
module.export_key(
|
||||||
|
repository_path='repo',
|
||||||
|
config={},
|
||||||
|
local_borg_version='1.2.3',
|
||||||
|
export_arguments=flexmock(paper=False, qr_html=False, path=None),
|
||||||
|
global_arguments=flexmock(dry_run=True, log_json=False),
|
||||||
|
)
|
|
@ -748,6 +748,24 @@ def test_run_actions_runs_break_lock():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_run_actions_runs_export_key():
|
||||||
|
flexmock(module).should_receive('add_custom_log_levels')
|
||||||
|
flexmock(module.command).should_receive('execute_hook')
|
||||||
|
flexmock(borgmatic.actions.export_key).should_receive('run_export_key').once()
|
||||||
|
|
||||||
|
tuple(
|
||||||
|
module.run_actions(
|
||||||
|
arguments={'global': flexmock(dry_run=False, log_file='foo'), 'export': flexmock()},
|
||||||
|
config_filename=flexmock(),
|
||||||
|
config={'repositories': []},
|
||||||
|
local_path=flexmock(),
|
||||||
|
remote_path=flexmock(),
|
||||||
|
local_borg_version=flexmock(),
|
||||||
|
repository={'path': 'repo'},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_run_actions_runs_borg():
|
def test_run_actions_runs_borg():
|
||||||
flexmock(module).should_receive('add_custom_log_levels')
|
flexmock(module).should_receive('add_custom_log_levels')
|
||||||
flexmock(module.command).should_receive('execute_hook')
|
flexmock(module.command).should_receive('execute_hook')
|
||||||
|
|
Loading…
Reference in a new issue