Last active
February 4, 2021 10:45
-
-
Save Nempickaxe/f0ac42e596c42a0ab62a3020b20c96aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import yaml | |
def parse_config(vars_dict, path=None, data=None, tag='!ENV'): | |
""" | |
Load a yaml configuration file and resolve any environment variables | |
The environment variables must have !ENV before them and be in this format | |
to be parsed: $<VAR_NAME>. | |
E.g.: | |
database: | |
host: !ENV $<HOST> | |
port: !ENV $<PORT> | |
app: | |
log_path: !ENV '/var/$<LOG_PATH>' | |
something_else: !ENV '$<AWESOME_ENV_VAR>/var/$<A_SECOND_AWESOME_VAR>' | |
:param str path: the path to the yaml file | |
:param str data: the yaml data itself as a stream | |
:param str tag: the tag to look for | |
:return: the dict configuration | |
:rtype: dict[str, T] | |
""" | |
# pattern for global vars: look for ${word} | |
pattern = re.compile('.*?\$\<(\w+)\>.*?') | |
loader = yaml.SafeLoader | |
# the tag will be used to mark where to start searching for the pattern | |
# e.g. somekey: !ENV somestring$<MYENVVAR>blah blah blah | |
loader.add_implicit_resolver(tag, pattern, None) | |
def constructor_env_variables(loader, node, vars_dict=vars_dict): | |
""" | |
Extracts the environment variable from the node's value | |
:param yaml.Loader loader: the yaml loader | |
:param node: the current node in the yaml | |
:return: the parsed string that contains the value of the environment | |
variable | |
""" | |
value = loader.construct_scalar(node) | |
match = pattern.findall(value) # to find all env variables in line | |
if match: | |
full_value = value | |
for g in match: | |
full_value = full_value.replace( | |
'$<{0}>'.format(g), vars_dict.get(g, g) | |
) | |
print(full_value) | |
return full_value | |
return value | |
loader.add_constructor(tag, constructor_env_variables) | |
if path: | |
with open(path) as conf_data: | |
return yaml.load(conf_data, Loader=loader) | |
elif data: | |
return yaml.load(data, Loader=loader) | |
else: | |
raise ValueError('Either a path or data should be defined as input') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment