Roberto Aloi
Roberto Aloi

Reputation: 30985

Accessing OS environment variables from Jinja2 template

Is it possible to access a OS environment variable directly from a Jinja2 template?

Upvotes: 29

Views: 47744

Answers (7)

P.Falls
P.Falls

Reputation: 1

The top answer parses env vars in the following format:

my_secret: "{{ 'default value' | env('ENV_VAR') }}"

I noticed other tools such as DBT use another format, such as:

my_secret: "{{ env('ENV_VAR', 'default value') }}"

I managed to implement a solution similar to the top answer by rendering the env function as a template variable and passing the args to os.getenv in a lambda function:

import os
import yaml
from jinja2 import Environment

def read_yaml_with_env(yaml_str: str) -> dict:
  # Apply Jinja Template and load environment variables
  env = Environment()
  template = env.from_string(yaml_str)
  yaml_vars = template.render(env=lambda x, y: os.getenv(x, y))

  # Load YAML
  json_from_yaml = yaml.safe_load(yaml_vars)
  
  return json_from_yaml

Upvotes: 0

northtree
northtree

Reputation: 9265

My simplest solution for FastAPI

templates.env.globals.update(getenv=os.getenv)

In Jinja2

{{ getenv("FOO") }}

Upvotes: 0

Matheus Torquato
Matheus Torquato

Reputation: 1629

Here is a list of variables that you can access from your template. I was trying to access some app.config variables and I managed to do it by calling config:

{% if current_user.id == config['ADMIN_ID'] %}
 ######## SOME HTML ########
{% endif %}

Flask-Login adds the current_user variable to your templates

Upvotes: 0

Jeremy Busk
Jeremy Busk

Reputation: 483

In bash let's setup our example

export MYENVVAR=foo

$ nano example.py

from jinja2 import Template
import os
template = Template("Hello {{ env['MYENVVAR'] or 'DefaultVal' }}")
r = template.render(env=os.environ, name='somethingelse')
print(r)

Run template

    $ python3 example.py

https://jinja.palletsprojects.com/en/2.11.x/intro/

Upvotes: 4

Roberto Aloi
Roberto Aloi

Reputation: 30985

Following @Renier's pointer about custom filters in the comments, I figured out a possible solution.

Define a custom filter:

def env_override(value, key):
  return os.getenv(key, value)

Install the filter in the environment:

env.filters['env_override'] = env_override

Use the filter as follows:

"test" : {{ "default" | env_override('CUSTOM') }}

Where the appropriate environment variable can be set as:

export CUSTOM=some_value

If the environment variable is set the output will be:

"test" : some_value

Otherwise:

"test" : default

Upvotes: 20

Fabian Ritzmann
Fabian Ritzmann

Reputation: 1715

The answer here works beautifully but you can still get rid of the useless use of cat and compress it to a single statement:

python -c 'import os
import sys
import jinja2
sys.stdout.write(
    jinja2.Template(sys.stdin.read()
).render(env=os.environ))' <$CONFIGTEMPLATE >$CONFIGFILE
  

P.S.: Stack Overflow does not allow formatted code in comments. Therefore I had to post this as a separate answer instead of commenting on https://stackoverflow.com/a/27984610/1070890.

Upvotes: 12

slm
slm

Reputation: 16416

I believe you can access environment variables like so:

{{ env['XMPP_DOMAIN'] or "localhost" }}

This is from an example in a config file that I saw recently for a Docker deployment of ejabberd.

hosts:
  - "{{ env['XMPP_DOMAIN'] or "localhost" }}"

NOTE: You can see the rest of the example in the run file from the Github repo.

As I understand things the heavy lifting is done by this bit of code:

readonly PYTHON_JINJA2="import os;
import sys;
import jinja2;
sys.stdout.write(
    jinja2.Template
        (sys.stdin.read()
    ).render(env=os.environ))
"""

And this code is what is used to generate a template file:

cat ${CONFIGTEMPLATE} \
      | python -c "${PYTHON_JINJA2}" \
      > ${CONFIGFILE}

References

Upvotes: 10

Related Questions