Make user-facing manifest loading error messages a little friendlier (#697).
This commit is contained in:
parent
0f9756e739
commit
beb899d6fb
3 changed files with 94 additions and 5 deletions
|
@ -21,6 +21,9 @@ def get_config_paths(bootstrap_arguments, global_arguments, local_borg_version):
|
|||
Return:
|
||||
The config paths from the manifest.json file in the borgmatic source directory after extracting it from the
|
||||
repository.
|
||||
|
||||
Raise ValueError if the manifest JSON is missing, can't be decoded, or doesn't contain the
|
||||
expected configuration path data.
|
||||
'''
|
||||
borgmatic_source_directory = (
|
||||
bootstrap_arguments.borgmatic_source_directory or DEFAULT_BORGMATIC_SOURCE_DIRECTORY
|
||||
|
@ -46,14 +49,31 @@ def get_config_paths(bootstrap_arguments, global_arguments, local_borg_version):
|
|||
extract_to_stdout=True,
|
||||
)
|
||||
|
||||
manifest_data = json.loads(extract_process.stdout.read())
|
||||
manifest_json = extract_process.stdout.read()
|
||||
if not manifest_json:
|
||||
raise ValueError(
|
||||
'Cannot read configuration paths from archive due to missing bootstrap manifest'
|
||||
)
|
||||
|
||||
try:
|
||||
manifest_data = json.loads(manifest_json)
|
||||
except json.JSONDecodeError as error:
|
||||
raise ValueError(
|
||||
f'Cannot read configuration paths from archive due to invalid bootstrap manifest JSON: {error}'
|
||||
)
|
||||
|
||||
try:
|
||||
return manifest_data['config_paths']
|
||||
except KeyError:
|
||||
raise ValueError('Cannot read configuration paths from archive due to invalid bootstrap manifest')
|
||||
|
||||
|
||||
def run_bootstrap(bootstrap_arguments, global_arguments, local_borg_version):
|
||||
'''
|
||||
Run the "bootstrap" action for the given repository.
|
||||
|
||||
Raise ValueError if the bootstrap configuration could not be loaded.
|
||||
Raise CalledProcessError or OSError if Borg could not be run.
|
||||
'''
|
||||
manifest_config_paths = get_config_paths(
|
||||
bootstrap_arguments, global_arguments, local_borg_version
|
||||
|
|
|
@ -647,10 +647,8 @@ def collect_configuration_run_summary_logs(configs, arguments):
|
|||
CalledProcessError,
|
||||
ValueError,
|
||||
OSError,
|
||||
json.JSONDecodeError,
|
||||
KeyError,
|
||||
) as error:
|
||||
yield from log_error_records('Error running bootstrap', error)
|
||||
yield from log_error_records(error)
|
||||
|
||||
return
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import pytest
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.config import bootstrap as module
|
||||
|
@ -29,6 +30,76 @@ def test_get_config_paths_returns_list_of_config_paths():
|
|||
]
|
||||
|
||||
|
||||
def test_get_config_paths_with_missing_manifest_raises_value_error():
|
||||
bootstrap_arguments = flexmock(
|
||||
borgmatic_source_directory=None,
|
||||
repository='repo',
|
||||
archive='archive',
|
||||
)
|
||||
global_arguments = flexmock(
|
||||
dry_run=False,
|
||||
)
|
||||
local_borg_version = flexmock()
|
||||
extract_process = flexmock(stdout=flexmock(read=lambda: ''))
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
extract_process
|
||||
)
|
||||
flexmock(module.borgmatic.borg.rlist).should_receive('resolve_archive_name').and_return(
|
||||
'archive'
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_config_paths(bootstrap_arguments, global_arguments, local_borg_version)
|
||||
|
||||
|
||||
def test_get_config_paths_with_broken_json_raises_value_error():
|
||||
bootstrap_arguments = flexmock(
|
||||
borgmatic_source_directory=None,
|
||||
repository='repo',
|
||||
archive='archive',
|
||||
)
|
||||
global_arguments = flexmock(
|
||||
dry_run=False,
|
||||
)
|
||||
local_borg_version = flexmock()
|
||||
extract_process = flexmock(
|
||||
stdout=flexmock(read=lambda: '{"config_paths": ["/oops'),
|
||||
)
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
extract_process
|
||||
)
|
||||
flexmock(module.borgmatic.borg.rlist).should_receive('resolve_archive_name').and_return(
|
||||
'archive'
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_config_paths(bootstrap_arguments, global_arguments, local_borg_version)
|
||||
|
||||
|
||||
def test_get_config_paths_with_json_missing_key_raises_value_error():
|
||||
bootstrap_arguments = flexmock(
|
||||
borgmatic_source_directory=None,
|
||||
repository='repo',
|
||||
archive='archive',
|
||||
)
|
||||
global_arguments = flexmock(
|
||||
dry_run=False,
|
||||
)
|
||||
local_borg_version = flexmock()
|
||||
extract_process = flexmock(
|
||||
stdout=flexmock(read=lambda: '{}'),
|
||||
)
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
extract_process
|
||||
)
|
||||
flexmock(module.borgmatic.borg.rlist).should_receive('resolve_archive_name').and_return(
|
||||
'archive'
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_config_paths(bootstrap_arguments, global_arguments, local_borg_version)
|
||||
|
||||
|
||||
def test_run_bootstrap_does_not_raise():
|
||||
bootstrap_arguments = flexmock(
|
||||
repository='repo',
|
||||
|
|
Loading…
Reference in a new issue