Allow defining custom variables in config file (#612).
Merge pull request #60 from diivi/feat/constants-support
This commit is contained in:
commit
1c51a8e229
3 changed files with 56 additions and 4 deletions
|
@ -1,4 +1,5 @@
|
||||||
import functools
|
import functools
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -81,7 +82,8 @@ class Include_constructor(ruamel.yaml.SafeConstructor):
|
||||||
def load_configuration(filename):
|
def load_configuration(filename):
|
||||||
'''
|
'''
|
||||||
Load the given configuration file and return its contents as a data structure of nested dicts
|
Load the given configuration file and return its contents as a data structure of nested dicts
|
||||||
and lists.
|
and lists. Also, replace any "{constant}" strings with the value of the "constant" key in the
|
||||||
|
"constants" section of the configuration file.
|
||||||
|
|
||||||
Raise ruamel.yaml.error.YAMLError if something goes wrong parsing the YAML, or RecursionError
|
Raise ruamel.yaml.error.YAMLError if something goes wrong parsing the YAML, or RecursionError
|
||||||
if there are too many recursive includes.
|
if there are too many recursive includes.
|
||||||
|
@ -98,7 +100,16 @@ def load_configuration(filename):
|
||||||
yaml = ruamel.yaml.YAML(typ='safe')
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
yaml.Constructor = Include_constructor_with_include_directory
|
yaml.Constructor = Include_constructor_with_include_directory
|
||||||
|
|
||||||
return yaml.load(open(filename))
|
with open(filename) as file:
|
||||||
|
file_contents = file.read()
|
||||||
|
config = yaml.load(file_contents)
|
||||||
|
if config and 'constants' in config:
|
||||||
|
for key, value in config['constants'].items():
|
||||||
|
value = json.dumps(value)
|
||||||
|
file_contents = file_contents.replace(f'{{{key}}}', value)
|
||||||
|
config = yaml.load(file_contents)
|
||||||
|
del config['constants']
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
DELETED_NODE = object()
|
DELETED_NODE = object()
|
||||||
|
|
|
@ -3,6 +3,17 @@ required:
|
||||||
- location
|
- location
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
|
constants:
|
||||||
|
type: object
|
||||||
|
description: |
|
||||||
|
Constants to use in the configuration file. All occurences of the
|
||||||
|
constant name within culy braces will be replaced with the value.
|
||||||
|
For example, if you have a constant named "hostname" with the value
|
||||||
|
"myhostname", then the string "{hostname}" will be replaced with
|
||||||
|
"myhostname" in the configuration file.
|
||||||
|
example:
|
||||||
|
hostname: myhostname
|
||||||
|
prefix: myprefix
|
||||||
location:
|
location:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -10,11 +10,41 @@ from borgmatic.config import load as module
|
||||||
|
|
||||||
def test_load_configuration_parses_contents():
|
def test_load_configuration_parses_contents():
|
||||||
builtins = flexmock(sys.modules['builtins'])
|
builtins = flexmock(sys.modules['builtins'])
|
||||||
builtins.should_receive('open').with_args('config.yaml').and_return('key: value')
|
config_file = io.StringIO('key: value')
|
||||||
|
config_file.name = 'config.yaml'
|
||||||
|
builtins.should_receive('open').with_args('config.yaml').and_return(config_file)
|
||||||
assert module.load_configuration('config.yaml') == {'key': 'value'}
|
assert module.load_configuration('config.yaml') == {'key': 'value'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_configuration_replaces_constants():
|
||||||
|
builtins = flexmock(sys.modules['builtins'])
|
||||||
|
config_file = io.StringIO(
|
||||||
|
'''
|
||||||
|
constants:
|
||||||
|
key: value
|
||||||
|
key: {key}
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
config_file.name = 'config.yaml'
|
||||||
|
builtins.should_receive('open').with_args('config.yaml').and_return(config_file)
|
||||||
|
assert module.load_configuration('config.yaml') == {'key': 'value'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_configuration_replaces_complex_constants():
|
||||||
|
builtins = flexmock(sys.modules['builtins'])
|
||||||
|
config_file = io.StringIO(
|
||||||
|
'''
|
||||||
|
constants:
|
||||||
|
key:
|
||||||
|
subkey: value
|
||||||
|
key: {key}
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
config_file.name = 'config.yaml'
|
||||||
|
builtins.should_receive('open').with_args('config.yaml').and_return(config_file)
|
||||||
|
assert module.load_configuration('config.yaml') == {'key': {'subkey': 'value'}}
|
||||||
|
|
||||||
|
|
||||||
def test_load_configuration_inlines_include_relative_to_current_directory():
|
def test_load_configuration_inlines_include_relative_to_current_directory():
|
||||||
builtins = flexmock(sys.modules['builtins'])
|
builtins = flexmock(sys.modules['builtins'])
|
||||||
flexmock(module.os).should_receive('getcwd').and_return('/tmp')
|
flexmock(module.os).should_receive('getcwd').and_return('/tmp')
|
||||||
|
|
Loading…
Reference in a new issue