View the results of configuration file merging via "validate-borgmatic-config --show" flag (#673).
This commit is contained in:
parent
31a2ac914a
commit
4c0e2cab78
6 changed files with 67 additions and 5 deletions
3
NEWS
3
NEWS
|
@ -7,6 +7,9 @@
|
||||||
"match_archives" configuration option for the "transfer", "list", "rlist", and "info" actions.
|
"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"
|
* #668: Fix error when running the "prune" action with both "archive_name_format" and "prefix"
|
||||||
options set.
|
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
|
* Add optional support for running end-to-end tests and building documentation with rootless Podman
|
||||||
instead of Docker.
|
instead of Docker.
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import logging
|
||||||
import sys
|
import sys
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
import borgmatic.config.generate
|
||||||
from borgmatic.config import collect, validate
|
from borgmatic.config import collect, validate
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -23,16 +24,22 @@ def parse_arguments(*arguments):
|
||||||
default=config_paths,
|
default=config_paths,
|
||||||
help=f'Configuration filenames or directories, defaults to: {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)
|
return parser.parse_args(arguments)
|
||||||
|
|
||||||
|
|
||||||
def main(): # pragma: no cover
|
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')
|
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:
|
if len(config_filenames) == 0:
|
||||||
logger.critical('No files to validate found')
|
logger.critical('No files to validate found')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -40,13 +47,22 @@ def main(): # pragma: no cover
|
||||||
found_issues = False
|
found_issues = False
|
||||||
for config_filename in config_filenames:
|
for config_filename in config_filenames:
|
||||||
try:
|
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:
|
except (ValueError, OSError, validate.Validation_error) as error:
|
||||||
logging.critical(f'{config_filename}: Error parsing configuration file')
|
logging.critical(f'{config_filename}: Error parsing configuration file')
|
||||||
logging.critical(error)
|
logging.critical(error)
|
||||||
found_issues = True
|
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:
|
if found_issues:
|
||||||
sys.exit(1)
|
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)}")
|
||||||
|
|
|
@ -276,6 +276,23 @@ include, the local file's option takes precedence.
|
||||||
list values are appended together.
|
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
|
## Configuration overrides
|
||||||
|
|
||||||
In more complex multi-application setups, you may want to override particular
|
In more complex multi-application setups, you may want to override particular
|
||||||
|
|
|
@ -180,6 +180,9 @@ following command is available for that:
|
||||||
sudo validate-borgmatic-config
|
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
|
This command's exit status (`$?` in Bash) is zero when configuration is valid
|
||||||
and non-zero otherwise.
|
and non-zero otherwise.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
import tempfile
|
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(' '))
|
exit_code = subprocess.call(f'validate-borgmatic-config --config {config_path}'.split(' '))
|
||||||
|
|
||||||
assert exit_code == 1
|
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
|
||||||
|
|
|
@ -18,3 +18,12 @@ def test_parse_arguments_with_multiple_config_paths_parses_as_list():
|
||||||
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
|
parser = module.parse_arguments('--config', 'myconfig', 'otherconfig')
|
||||||
|
|
||||||
assert parser.config_paths == ['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
|
||||||
|
|
Loading…
Reference in a new issue