Support for Borg check --verify-data flag via borgmatic "data" consistency check (#210).

This commit is contained in:
Dan Helfman 2019-09-18 16:52:27 -07:00
parent 11e830bb1d
commit 4cdff74e9b
4 changed files with 44 additions and 14 deletions

1
NEWS
View file

@ -1,4 +1,5 @@
1.3.16.dev0 1.3.16.dev0
* #210: Support for Borg check --verify-data flag via borgmatic "data" consistency check.
* 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

@ -24,14 +24,17 @@ def _parse_checks(consistency_config):
If no "checks" option is present, return the DEFAULT_CHECKS. If the checks value is the string If no "checks" option is present, return the DEFAULT_CHECKS. If the checks value is the string
"disabled", return an empty tuple, meaning that no checks should be run. "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.
''' '''
checks = consistency_config.get('checks', []) or [] checks = [check.lower() for check in (consistency_config.get('checks', []) or [])]
if checks == ['disabled']: if checks == ['disabled']:
return () return ()
return ( if 'data' in checks and 'archives' not in checks:
tuple(check for check in checks if check.lower() not in ('disabled', '')) or DEFAULT_CHECKS checks.append('archives')
)
return tuple(check for check in checks if check not in ('disabled', '')) or DEFAULT_CHECKS
def _make_check_flags(checks, check_last=None, prefix=None): def _make_check_flags(checks, check_last=None, prefix=None):
@ -68,13 +71,14 @@ def _make_check_flags(checks, check_last=None, prefix=None):
'Ignoring consistency prefix option, as "archives" is not in consistency checks.' 'Ignoring consistency prefix option, as "archives" is not in consistency checks.'
) )
common_flags = last_flags + prefix_flags + (('--verify-data',) if 'data' in checks else ())
if set(DEFAULT_CHECKS).issubset(set(checks)): if set(DEFAULT_CHECKS).issubset(set(checks)):
return last_flags + prefix_flags return common_flags
return ( return (
tuple('--{}-only'.format(check) for check in checks if check in DEFAULT_CHECKS) tuple('--{}-only'.format(check) for check in checks if check in DEFAULT_CHECKS)
+ last_flags + common_flags
+ prefix_flags
) )
@ -91,7 +95,7 @@ def check_archives(
check_last = consistency_config.get('check_last', None) check_last = consistency_config.get('check_last', None)
lock_wait = None lock_wait = None
if set(checks).intersection(set(DEFAULT_CHECKS)): if set(checks).intersection(set(DEFAULT_CHECKS + ('data',))):
remote_path_flags = ('--remote-path', remote_path) if remote_path else () remote_path_flags = ('--remote-path', remote_path) if remote_path else ()
lock_wait = storage_config.get('lock_wait', None) lock_wait = storage_config.get('lock_wait', None)
lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else () lock_wait_flags = ('--lock-wait', str(lock_wait)) if lock_wait else ()

View file

@ -290,14 +290,15 @@ map:
checks: checks:
seq: seq:
- type: str - type: str
enum: ['repository', 'archives', 'extract', 'disabled'] enum: ['repository', 'archives', 'data', 'extract', 'disabled']
unique: true unique: true
desc: | desc: |
List of one or more consistency checks to run: "repository", "archives", and/or List of one or more consistency checks to run: "repository", "archives", "data",
"extract". Defaults to "repository" and "archives". Set to "disabled" to disable and/or "extract". Defaults to "repository" and "archives". Set to "disabled" to
all consistency checks. "repository" checks the consistency of the repository, disable all consistency checks. "repository" checks the consistency of the
"archive" checks all of the archives, and "extract" does an extraction dry-run repository, "archives" checks all of the archives, "data" verifies the integrity
of the most recent archive. of the data within the archives, and "extract" does an extraction dry-run of the
most recent archive. Note that "data" implies "archives".
example: example:
- repository - repository
- archives - archives

View file

@ -46,12 +46,36 @@ def test_parse_checks_with_disabled_returns_no_checks():
assert checks == () assert checks == ()
def test_parse_checks_with_data_check_also_injects_archives():
checks = module._parse_checks({'checks': ['data']})
assert checks == ('data', 'archives')
def test_parse_checks_with_data_check_passes_through_archives():
checks = module._parse_checks({'checks': ['data', 'archives']})
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',))
assert flags == ('--repository-only',) assert flags == ('--repository-only',)
def test_make_check_flags_with_archives_check_returns_flag():
flags = module._make_check_flags(('archives',))
assert flags == ('--archives-only',)
def test_make_check_flags_with_data_check_returns_flag():
flags = module._make_check_flags(('data',))
assert flags == ('--verify-data',)
def test_make_check_flags_with_extract_omits_extract_flag(): def test_make_check_flags_with_extract_omits_extract_flag():
flags = module._make_check_flags(('extract',)) flags = module._make_check_flags(('extract',))