Skip to content

Commit

Permalink
Merge pull request #7 from neuroforgede/packaging
Browse files Browse the repository at this point in the history
Add support for templating of string variables via env vars via {{ nothelm.env.VARIABLE_NAME }}
  • Loading branch information
s4ke authored Jul 16, 2024
2 parents 2f7246c + 4014628 commit d95e4fd
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 4 deletions.
2 changes: 2 additions & 0 deletions example/project/templates/sample-stack.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ services:
{% raw %}
hostname: "hello-{{ .Task.Slot }}"
{% endraw %}
environment:
- "SOME_HOME={{ home_dir }}"
deploy:
mode: replicated
replicas: {{ replica_count }}
Expand Down
3 changes: 0 additions & 3 deletions example/project/values.yaml

This file was deleted.

4 changes: 4 additions & 0 deletions example/project/values.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# no default variables here
replica_count: 2
outside_port: 8899
home_dir: "{{ nothelm.env.HOME }}/hi"
38 changes: 38 additions & 0 deletions nothelm/lib/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,39 @@
import subprocess
from functools import reduce

def interpolate_env_vars_recursively(values: Dict[str, Any]) -> Dict[str, Any]:
def interpolate(value: Any) -> Any:
if isinstance(value, dict):
return interpolate_dict(value)
elif isinstance(value, list):
return interpolate_list(value)
elif isinstance(value, str):
return interpolate_string(value)
else:
return value

def interpolate_dict(d: Dict[str, Any]) -> Dict[str, Any]:
return {key: interpolate(value) for key, value in d.items()}

def interpolate_list(l: List[Any]) -> List[Any]:
return [interpolate(value) for value in l]

# expand environment variables, they are available in "jinja" format {{ nothelm.env.VARIABLE_NAME }}
def interpolate_jinja(s: str) -> str:
env = Environment()
template = env.from_string(s)
return template.render(nothelm={"env": os.environ})

def interpolate_string(s: str) -> str:
# check if we need to interpolate the string
if "{{" in s:
return interpolate_jinja(s)

return os.path.expandvars(s)

return interpolate_dict(values)


def load_values(path: str) -> Dict[str, Any]:
with open(path, "r") as stream:
variables = yaml.safe_load(stream)
Expand All @@ -17,6 +50,9 @@ def load_values(path: str) -> Dict[str, Any]:
if not isinstance(variables, dict):
raise ValueError(f"file at {path} did not contain a YAML dictionary at top level")

if path.endswith('.j2') or path.endswith('.jinja2'):
variables = interpolate_env_vars_recursively(variables)

return variables


Expand Down Expand Up @@ -45,6 +81,8 @@ def template_project(

if os.path.exists(f'{project_dir}/values.yaml'):
default_values = load_values(f'{project_dir}/values.yaml')
elif os.path.exists(f'{project_dir}/values.yaml.j2'):
default_values = load_values(f'{project_dir}/values.yaml.j2')
else:
default_values = dict()

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def cli_test_suite():
setuptools.setup(
name="nothelm.py",
scripts=["bin/nothelm"],
version="0.2.1",
version="0.2.2",
author="NeuroForge GmbH & Co. KG",
author_email="[email protected]",
description="nothelm.py",
Expand Down

0 comments on commit d95e4fd

Please sign in to comment.