YAML config file with environment variables
1
import os
2
import re
3
import yaml
4
5
6
def parse_config(path=None, data=None, tag='!ENV'):
7
"""
8
Load a yaml configuration file and resolve any environment variables
9
The environment variables must have !ENV before them and be in this format
10
to be parsed: ${VAR_NAME}.
11
E.g.:
12
database:
13
host: !ENV ${HOST}
14
port: !ENV ${PORT}
15
app:
16
log_path: !ENV '/var/${LOG_PATH}'
17
something_else: !ENV '${AWESOME_ENV_VAR}/var/${A_SECOND_AWESOME_VAR}'
18
:param str path: the path to the yaml file
19
:param str data: the yaml data itself as a stream
20
:param str tag: the tag to look for
21
:return: the dict configuration
22
:rtype: dict[str, T]
23
"""
24
# pattern for global vars: look for ${word}
25
pattern = re.compile('.*?\${(\w+)}.*?')
26
loader = yaml.SafeLoader
27
28
# the tag will be used to mark where to start searching for the pattern
29
# e.g. somekey: !ENV somestring${MYENVVAR}blah blah blah
30
loader.add_implicit_resolver(tag, pattern, None)
31
32
def constructor_env_variables(loader, node):
33
"""
34
Extracts the environment variable from the node's value
35
:param yaml.Loader loader: the yaml loader
36
:param node: the current node in the yaml
37
:return: the parsed string that contains the value of the environment
38
variable
39
"""
40
value = loader.construct_scalar(node)
41
match = pattern.findall(value) # to find all env variables in line
42
if match:
43
full_value = value
44
for g in match:
45
full_value = full_value.replace(
46
f'${{{g}}}', os.environ.get(g, g)
47
)
48
return full_value
49
return value
50
51
loader.add_constructor(tag, constructor_env_variables)
52
53
if path:
54
with open(path) as conf_data:
55
return yaml.load(conf_data, Loader=loader)
56
elif data:
57
return yaml.load(data, Loader=loader)
58
else:
59
raise ValueError('Either a path or data should be defined as input')
Copied!
Example of a YAML configuration with environment variables:
config.yaml
1
database:
2
name: database_name
3
user: !ENV ${DB_USER}
4
password: !ENV ${DB_PASS}
5
host: !ENV ${DB_HOST}
6
port: 5432ws:
7
user: !ENV ${WS_USER}
8
password: !ENV ${WS_PASS}
9
host: !ENV ‘https://${CURR_ENV}.ws.com.local'
Copied!

Usage

Read from file
Read from string
1
CONFIG = parse_config(path='config.yaml')
Copied!
1
content = """
2
database:
3
name: database_name
4
user: !ENV ${DB_USER}
5
password: !ENV ${DB_PASS}
6
"""
7
CONFIG = parse_config(data=content)
Copied!
Last modified 1yr ago
Copy link
Contents
Usage