View the results of configuration file merging via "validate-borgmatic-config --show" flag (#673).

This commit is contained in:
Dan Helfman 2023-04-11 10:49:09 -07:00
parent 31a2ac914a
commit 4c0e2cab78
6 changed files with 67 additions and 5 deletions

3
NEWS
View file

@ -7,6 +7,9 @@
"match_archives" configuration option for the "transfer", "list", "rlist", and "info" actions.
* #668: Fix error when running the "prune" action with both "archive_name_format" and "prefix"
options set.
* #673: View the results of configuration file merging via "validate-borgmatic-config --show" flag.
See the documentation for more information:
https://torsion.org/borgmatic/docs/how-to/make-per-application-backups/#debugging-includes
* Add optional support for running end-to-end tests and building documentation with rootless Podman
instead of Docker.

View file

@ -2,6 +2,7 @@ import logging
import sys
from argparse import ArgumentParser
import borgmatic.config.generate
from borgmatic.config import collect, validate
logger = logging.getLogger(__name__)
@ -23,16 +24,22 @@ def parse_arguments(*arguments):
default=config_paths,
help=f'Configuration filenames or directories, defaults to: {config_paths}',
)
parser.add_argument(
'-s',
'--show',
action='store_true',
help='Show the validated configuration after all include merging has occurred',
)
return parser.parse_args(arguments)
def main(): # pragma: no cover
args = parse_arguments(*sys.argv[1:])
arguments = parse_arguments(*sys.argv[1:])
logging.basicConfig(level=logging.INFO, format='%(message)s')
config_filenames = tuple(collect.collect_config_filenames(args.config_paths))
config_filenames = tuple(collect.collect_config_filenames(arguments.config_paths))
if len(config_filenames) == 0:
logger.critical('No files to validate found')
sys.exit(1)
@ -40,13 +47,22 @@ def main(): # pragma: no cover
found_issues = False
for config_filename in config_filenames:
try:
validate.parse_configuration(config_filename, validate.schema_filename())
config, parse_logs = validate.parse_configuration(
config_filename, validate.schema_filename()
)
except (ValueError, OSError, validate.Validation_error) as error:
logging.critical(f'{config_filename}: Error parsing configuration file')
logging.critical(error)
found_issues = True
else:
for log in parse_logs:
logger.handle(log)
if arguments.show:
print('---')
print(borgmatic.config.generate.render_configuration(config))
if found_issues:
sys.exit(1)
else:
logger.info(f"All given configuration files are valid: {', '.join(config_filenames)}")
logger.info(f"All given configuration files are valid: {', '.join(config_filenames)}")

View file

@ -276,6 +276,23 @@ include, the local file's option takes precedence.
list values are appended together.
## Debugging includes
<span class="minilink minilink-addedin">New in version 1.7.12</span> If you'd
like to see what the loaded configuration looks like after includes get merged
in, run `validate-borgmatic-config` on your configuration file:
```bash
sudo validate-borgmatic-config --show
```
You'll need to specify your configuration file with `--config` if it's not in
a default location.
This will output the merged configuration as borgmatic sees it, which can be
helpful for understanding how your includes work in practice.
## Configuration overrides
In more complex multi-application setups, you may want to override particular

View file

@ -180,6 +180,9 @@ following command is available for that:
sudo validate-borgmatic-config
```
You'll need to specify your configuration file with `--config` if it's not in
a default location.
This command's exit status (`$?` in Bash) is zero when configuration is valid
and non-zero otherwise.

View file

@ -1,5 +1,6 @@
import os
import subprocess
import sys
import tempfile
@ -26,3 +27,16 @@ def test_validate_config_command_with_invalid_configuration_fails():
exit_code = subprocess.call(f'validate-borgmatic-config --config {config_path}'.split(' '))
assert exit_code == 1
def test_validate_config_command_with_show_flag_displays_configuration():
with tempfile.TemporaryDirectory() as temporary_directory:
config_path = os.path.join(temporary_directory, 'test.yaml')
subprocess.check_call(f'generate-borgmatic-config --destination {config_path}'.split(' '))
output = subprocess.check_output(
f'validate-borgmatic-config --config {config_path} --show'.split(' ')
).decode(sys.stdout.encoding)
assert 'location:' in output
assert 'repositories:' in output

View file

@ -18,3 +18,12 @@ def test_parse_arguments_with_multiple_config_paths_parses_as_list():
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
assert parser.config_paths == ['myconfig', 'otherconfig']
def test_parse_arguments_supports_show_flag():
config_paths = ['default']
flexmock(module.collect).should_receive('get_default_config_paths').and_return(config_paths)
parser = module.parse_arguments('--config', 'myconfig', '--show')
assert parser.show