Override configured consistency checks via "borgmatic check --only" command-line flag (#210).

This commit is contained in:
Dan Helfman 2019-09-19 11:43:53 -07:00
parent 4cdff74e9b
commit 81739791e0
6 changed files with 46 additions and 11 deletions

3
NEWS
View file

@ -1,5 +1,6 @@
1.3.16.dev0 1.3.16
* #210: Support for Borg check --verify-data flag via borgmatic "data" consistency check. * #210: Support for Borg check --verify-data flag via borgmatic "data" consistency check.
* #210: Override configured consistency checks via "borgmatic check --only" command-line flag.
* When generating sample configuration with generate-borgmatic-config, add a space after each "#" * When generating sample configuration with generate-borgmatic-config, add a space after each "#"
comment indicator. comment indicator.

View file

@ -10,9 +10,10 @@ DEFAULT_PREFIX = '{hostname}-'
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def _parse_checks(consistency_config): def _parse_checks(consistency_config, only_checks=None):
''' '''
Given a consistency config with a "checks" list, transform it to a tuple of named checks to run. Given a consistency config with a "checks" list, and an optional list of override checks,
transform them a tuple of named checks to run.
For example, given a retention config of: For example, given a retention config of:
@ -22,12 +23,14 @@ def _parse_checks(consistency_config):
('repository', 'archives') ('repository', 'archives')
If no "checks" option is present, return the DEFAULT_CHECKS. If the checks value is the string If no "checks" option is present in the config, return the DEFAULT_CHECKS. If the checks value
"disabled", return an empty tuple, meaning that no checks should be run. is the string "disabled", return an empty tuple, meaning that no checks should be run.
If the "data" option is present, then make sure the "archives" option is included as well. If the "data" option is present, then make sure the "archives" option is included as well.
''' '''
checks = [check.lower() for check in (consistency_config.get('checks', []) or [])] checks = [
check.lower() for check in (only_checks or consistency_config.get('checks', []) or [])
]
if checks == ['disabled']: if checks == ['disabled']:
return () return ()
@ -83,15 +86,21 @@ def _make_check_flags(checks, check_last=None, prefix=None):
def check_archives( def check_archives(
repository, storage_config, consistency_config, local_path='borg', remote_path=None repository,
storage_config,
consistency_config,
local_path='borg',
remote_path=None,
only_checks=None,
): ):
''' '''
Given a local or remote repository path, a storage config dict, a consistency config dict, Given a local or remote repository path, a storage config dict, a consistency config dict,
and a local/remote commands to run, check the contained Borg archives for consistency. local/remote commands to run, and an optional list of checks to use instead of configured
checks, check the contained Borg archives for consistency.
If there are no consistency checks to run, skip running them. If there are no consistency checks to run, skip running them.
''' '''
checks = _parse_checks(consistency_config) checks = _parse_checks(consistency_config, only_checks)
check_last = consistency_config.get('check_last', None) check_last = consistency_config.get('check_last', None)
lock_wait = None lock_wait = None

View file

@ -212,6 +212,14 @@ def parse_arguments(*unparsed_arguments):
add_help=False, add_help=False,
) )
check_group = check_parser.add_argument_group('check arguments') check_group = check_parser.add_argument_group('check arguments')
check_group.add_argument(
'--only',
metavar='CHECK',
choices=('repository', 'archives', 'data', 'extract'),
dest='only',
action='append',
help='Run a particular consistency check instead of configured checks (can specify multiple times)',
)
check_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') check_group.add_argument('-h', '--help', action='help', help='Show this help message and exit')
extract_parser = subparsers.add_parser( extract_parser = subparsers.add_parser(

View file

@ -147,7 +147,12 @@ def run_actions(
if 'check' in arguments and checks.repository_enabled_for_checks(repository, consistency): if 'check' in arguments and checks.repository_enabled_for_checks(repository, consistency):
logger.info('{}: Running consistency checks'.format(repository)) logger.info('{}: Running consistency checks'.format(repository))
borg_check.check_archives( borg_check.check_archives(
repository, storage, consistency, local_path=local_path, remote_path=remote_path repository,
storage,
consistency,
local_path=local_path,
remote_path=remote_path,
only_checks=arguments['check'].only,
) )
if 'extract' in arguments: if 'extract' in arguments:
if arguments['extract'].repository is None or repository == arguments['extract'].repository: if arguments['extract'].repository is None or repository == arguments['extract'].repository:

View file

@ -1,6 +1,6 @@
from setuptools import find_packages, setup from setuptools import find_packages, setup
VERSION = '1.3.16.dev0' VERSION = '1.3.16'
setup( setup(

View file

@ -58,6 +58,18 @@ def test_parse_checks_with_data_check_passes_through_archives():
assert checks == ('data', 'archives') assert checks == ('data', 'archives')
def test_parse_checks_prefers_override_checks_to_configured_checks():
checks = module._parse_checks({'checks': ['archives']}, only_checks=['repository', 'extract'])
assert checks == ('repository', 'extract')
def test_parse_checks_with_override_data_check_also_injects_archives():
checks = module._parse_checks({'checks': ['extract']}, only_checks=['data'])
assert checks == ('data', 'archives')
def test_make_check_flags_with_repository_check_returns_flag(): def test_make_check_flags_with_repository_check_returns_flag():
flags = module._make_check_flags(('repository',)) flags = module._make_check_flags(('repository',))