Last active
November 12, 2020 02:44
-
-
Save waylan/1b288be67c0d128f5e314bf034215182 to your computer and use it in GitHub Desktop.
A custom YAML tag for referencing environment variables in YAML files. The content of the env var will be resolved to one of YAML's implicit types (bool, float, int, timestamp, null, value). The content of the env var is always assumed to be a Scalar node, so sequence and mappings are ignored and simply passed through as a string.
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
foo: !ENV FOO | |
bar: !ENV [BAR] | |
baz: !ENV [BAZ, ~] | |
fbb: !ENV [FOO, BAR, BAZ, ~] |
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
# A Python clone of https://github.com/jirutka/yaml-env-tag | |
import os | |
import yaml | |
from typing import Any | |
def construct_env_tag(loader: yaml.Loader, node: yaml.Node) -> Any: | |
"""Assign value of ENV variable referenced at node.""" | |
default = None | |
if isinstance(node, yaml.nodes.ScalarNode): | |
vars = [loader.construct_scalar(node)] | |
elif isinstance(node, yaml.nodes.SequenceNode): | |
child_nodes = node.value | |
if len(child_nodes) > 1: | |
# default is resvoled using YAML's (implicit) types. | |
default = loader.construct_object(child_nodes[-1]) | |
child_nodes = child_nodes[:-1] | |
# Env Vars are resolved as string values, ignoring (implicit) types. | |
vars = [loader.construct_scalar(child) for child in child_nodes] | |
else: | |
raise yaml.constructor.ConstructorError(None, None, | |
f'expected a scalar or sequence node, but found {node.id}', | |
node.start_mark) | |
for var in vars: | |
if var in os.environ: | |
value = os.environ[var] | |
# Resolve value to value of type using YAML's implicit resolvers | |
tag = loader.resolve(yaml.nodes.ScalarNode, value, (True, False)) | |
return loader.construct_object(yaml.nodes.ScalarNode(tag, value)) | |
return default | |
yaml.add_constructor('!ENV', construct_env_tag) | |
if __name__ == '__main__': | |
with open('example.yml', 'r') as f: | |
data = yaml.load(f, Loader=yaml.Loader) | |
print(data) |
A fully tested version of this now lives at waylan/pyyaml-env-tag and is available to install from PyPI.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a Python clone of the ruby lib yaml-env-tag.
See some alternative implementations at pyyaml-tags and python_yaml_environment_variables.py, each of which insert env vars in a template string.