Add --validate action: Validate borgmatic configuration file and exit
the build failed
Details
the build failed
Details
Useful when generating the borgmatic configuration file with configuration management and before moving the generated file in place checking if it is actually valid. The added unit tests are currently incomplete.
This commit is contained in:
parent
1c88dda76a
commit
5b337e55ca
2
AUTHORS
2
AUTHORS
|
@ -7,6 +7,6 @@ Johannes Feichtner: Support for user hooks
|
|||
Michele Lazzeri: Custom archive names
|
||||
Nick Whyte: Support prefix filtering for archive consistency checks
|
||||
newtonne: Read encryption password from external file
|
||||
Robin `ypid` Schneider: Support additional options of Borg
|
||||
Robin `ypid` Schneider: Support additional options of Borg and add --validate action
|
||||
Scott Squires: Custom archive names
|
||||
Thomas LÉVEIL: Support for a keep_minutely prune option. Support for the --json option
|
||||
|
|
|
@ -47,6 +47,9 @@ def parse_arguments(*arguments):
|
|||
)
|
||||
|
||||
actions_group = parser.add_argument_group('actions')
|
||||
actions_group.add_argument(
|
||||
'-V', '--validate', dest='validate', action='store_true', help='Validate borgmatic configuration file and exit'
|
||||
)
|
||||
actions_group.add_argument(
|
||||
'-I', '--init', dest='init', action='store_true', help='Initialize an empty Borg repository'
|
||||
)
|
||||
|
@ -420,23 +423,24 @@ def collect_configuration_run_summary_logs(config_filenames, args):
|
|||
|
||||
# Execute the actions corresponding to each configuration file.
|
||||
json_results = []
|
||||
for config_filename, config in configs.items():
|
||||
try:
|
||||
json_results.extend(list(run_configuration(config_filename, config, args)))
|
||||
yield logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=logging.INFO,
|
||||
msg='{}: Successfully ran configuration file'.format(config_filename),
|
||||
if not args.validate:
|
||||
for config_filename, config in configs.items():
|
||||
try:
|
||||
json_results.extend(list(run_configuration(config_filename, config, args)))
|
||||
yield logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=logging.INFO,
|
||||
msg='{}: Successfully ran configuration file'.format(config_filename),
|
||||
)
|
||||
)
|
||||
)
|
||||
except (ValueError, OSError, CalledProcessError) as error:
|
||||
yield logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=logging.CRITICAL,
|
||||
msg='{}: Error running configuration file'.format(config_filename),
|
||||
except (ValueError, OSError, CalledProcessError) as error:
|
||||
yield logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=logging.CRITICAL,
|
||||
msg='{}: Error running configuration file'.format(config_filename),
|
||||
)
|
||||
)
|
||||
)
|
||||
yield logging.makeLogRecord(dict(levelno=logging.CRITICAL, msg=error))
|
||||
yield logging.makeLogRecord(dict(levelno=logging.CRITICAL, msg=error))
|
||||
|
||||
if json_results:
|
||||
sys.stdout.write(json.dumps(json_results))
|
||||
|
@ -475,6 +479,7 @@ def main(): # pragma: no cover
|
|||
sys.exit(0)
|
||||
|
||||
config_filenames = tuple(collect.collect_config_filenames(args.config_paths))
|
||||
|
||||
logger.debug('Ensuring legacy configuration is upgraded')
|
||||
convert.guard_configuration_upgraded(LEGACY_CONFIG_PATH, config_filenames)
|
||||
|
||||
|
@ -484,4 +489,9 @@ def main(): # pragma: no cover
|
|||
[logger.handle(log) for log in summary_logs if log.levelno >= logger.getEffectiveLevel()]
|
||||
|
||||
if any(log.levelno == logging.CRITICAL for log in summary_logs):
|
||||
if args.validate:
|
||||
sys.exit(1)
|
||||
exit_with_help_link()
|
||||
|
||||
if args.validate:
|
||||
print('Configuration files are valid.')
|
||||
|
|
|
@ -268,3 +268,19 @@ def test_borgmatic_version_matches_news_version():
|
|||
news_version = open('NEWS').readline()
|
||||
|
||||
assert borgmatic_version == news_version
|
||||
|
||||
|
||||
def test_borgmatic_validate_error():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
borgmatic_output = subprocess.check_output(('borgmatic', '--validate')).decode('ascii')
|
||||
|
||||
assert borgmatic_output == 'Configuration files are valid.'
|
||||
|
||||
|
||||
def test_borgmatic_validate_ok():
|
||||
flexmock(module.collect).should_receive('get_default_config_paths').and_return(['default'])
|
||||
|
||||
borgmatic_output = subprocess.check_output(('borgmatic', '--validate')).decode('ascii')
|
||||
|
||||
assert borgmatic_output == 'Configuration files are valid.'
|
||||
|
|
|
@ -6,7 +6,7 @@ from borgmatic.commands import borgmatic as module
|
|||
def test_collect_configuration_run_summary_logs_info_for_success():
|
||||
flexmock(module.validate).should_receive('parse_configuration').and_return({'test.yaml': {}})
|
||||
flexmock(module).should_receive('run_configuration').and_return([])
|
||||
args = flexmock(extract=False, list=False)
|
||||
args = flexmock(validate=False, extract=False, list=False)
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(('test.yaml',), args=args))
|
||||
|
||||
|
@ -17,7 +17,7 @@ def test_collect_configuration_run_summary_logs_info_for_success_with_extract():
|
|||
flexmock(module.validate).should_receive('parse_configuration').and_return({'test.yaml': {}})
|
||||
flexmock(module.validate).should_receive('guard_configuration_contains_repository')
|
||||
flexmock(module).should_receive('run_configuration').and_return([])
|
||||
args = flexmock(extract=True, list=False, repository='repo')
|
||||
args = flexmock(validate=False, extract=True, list=False, repository='repo')
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(('test.yaml',), args=args))
|
||||
|
||||
|
@ -51,7 +51,7 @@ def test_collect_configuration_run_summary_logs_critical_for_list_with_archive_a
|
|||
def test_collect_configuration_run_summary_logs_info_for_success_with_list():
|
||||
flexmock(module.validate).should_receive('parse_configuration').and_return({'test.yaml': {}})
|
||||
flexmock(module).should_receive('run_configuration').and_return([])
|
||||
args = flexmock(extract=False, list=True, repository='repo', archive=None)
|
||||
args = flexmock(validate=False, extract=False, list=True, repository='repo', archive=None)
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(('test.yaml',), args=args))
|
||||
|
||||
|
@ -60,7 +60,7 @@ def test_collect_configuration_run_summary_logs_info_for_success_with_list():
|
|||
|
||||
def test_collect_configuration_run_summary_logs_critical_for_parse_error():
|
||||
flexmock(module.validate).should_receive('parse_configuration').and_raise(ValueError)
|
||||
args = flexmock(extract=False, list=False)
|
||||
args = flexmock(validate=False, extract=False, list=False)
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(('test.yaml',), args=args))
|
||||
|
||||
|
@ -71,7 +71,7 @@ def test_collect_configuration_run_summary_logs_critical_for_run_error():
|
|||
flexmock(module.validate).should_receive('parse_configuration').and_return({'test.yaml': {}})
|
||||
flexmock(module.validate).should_receive('guard_configuration_contains_repository')
|
||||
flexmock(module).should_receive('run_configuration').and_raise(ValueError)
|
||||
args = flexmock(extract=False, list=False)
|
||||
args = flexmock(validate=False, extract=False, list=False)
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(('test.yaml',), args=args))
|
||||
|
||||
|
@ -81,7 +81,7 @@ def test_collect_configuration_run_summary_logs_critical_for_run_error():
|
|||
def test_collect_configuration_run_summary_logs_critical_for_missing_configs():
|
||||
flexmock(module.validate).should_receive('parse_configuration').and_return({'test.yaml': {}})
|
||||
flexmock(module).should_receive('run_configuration').and_return([])
|
||||
args = flexmock(config_paths=(), extract=False, list=False)
|
||||
args = flexmock(config_paths=(), validate=False, extract=False, list=False)
|
||||
|
||||
logs = tuple(module.collect_configuration_run_summary_logs(config_filenames=(), args=args))
|
||||
|
||||
|
@ -96,6 +96,6 @@ def test_collect_configuration_run_summary_logs_outputs_merged_json_results():
|
|||
['baz']
|
||||
)
|
||||
flexmock(module.sys.stdout).should_receive('write').with_args('["foo", "bar", "baz"]').once()
|
||||
args = flexmock(extract=False, list=False)
|
||||
args = flexmock(validate=False, extract=False, list=False)
|
||||
|
||||
tuple(module.collect_configuration_run_summary_logs(('test.yaml', 'test2.yaml'), args=args))
|
||||
|
|
Loading…
Reference in New Issue