salt.renderers.jinja

Jinja in States

The most basic usage of Jinja in state files is using control structures to wrap conditional or redundant state elements:

{% if grains['os'] != 'FreeBSD' %}
tcsh:
    pkg:
        - installed
{% endif %}

motd:
  file.managed:
    {% if grains['os'] == 'FreeBSD' %}
    - name: /etc/motd
    {% elif grains['os'] == 'Debian' %}
    - name: /etc/motd.tail
    {% endif %}
    - source: salt://motd

In this example, the first if block will only be evaluated on minions that aren't running FreeBSD, and the second block changes the file name based on the os grain.

Writing if-else blocks can lead to very redundant state files however. In this case, using pillars, or using a previously defined variable might be easier:

{% set motd = ['/etc/motd'] %}
{% if grains['os'] == 'Debian' %}
  {% set motd = ['/etc/motd.tail', '/var/run/motd'] %}
{% endif %}

{% for motdfile in motd %}
{{ motdfile }}:
  file.managed:
    - source: salt://motd
{% endfor %}

Using a variable set by the template, the for loop will iterate over the list of MOTD files to update, adding a state block for each file.

Passing Variables

It is also possible to pass additional variable context directly into a template, using the defaults and context mappings of the file.managed state:

/etc/motd:
  file.managed:
    - source: salt://motd
    - template: jinja
    - defaults:
      message: 'Foo'
    {% if grains['os'] == 'FreeBSD' %}
    - context:
      message: 'Bar'
    {% endif %}

The template will receive a variable message, which would be accessed in the template using {{ message }}. If the operating system is FreeBSD, the value of the variable message would be Bar, otherwise it is the default Foo

Include and Import

Includes and imports can be used to share common, reusable state configuration between state files and between files.

{% from 'lib.sls' import test %}

This would import the test template variable or macro, not the test state element, from the file lib.sls. In the case that the included file performs checks again grains, or something else that requires context, passing the context into the included file is required:

{% from 'lib.sls' import test with context %}

Template Inheritance

Template inheritance works fine from state files and files. The search path starts at the root of the state tree or pillar.

Macros

Macros are helpful for eliminating redundant code, however stripping whitespace from the template block, as well as contained blocks, may be necessary to emulate a variable return from the macro.

# init.sls
{% from 'lib.sls' import pythonpkg with context %}

python-virtualenv:
  pkg.installed:
    - name: {{ pythonpkg('virtualenv') }}

python-fabric:
  pkg.installed:
    - name: {{ pythonpkg('fabric') }}
# lib.sls
{% macro pythonpkg(pkg) -%}
  {%- if grains['os'] == 'FreeBSD' -%}
    py27-{{ pkg }}
  {%- elif grains['os'] == 'Debian' -%}
    python-{{ pkg }}
  {%- endif -%}
{%- endmacro %}

This would define a macro that would return a string of the full package name, depending on the packaging system's naming convention. The whitespace of the macro was eliminated, so that the macro would return a string without line breaks, using whitespace control.

Jinja in Files

Jinja can be used in the same way in managed files:

# redis.sls
/etc/redis/redis.conf:
    file.managed:
        - source: salt://redis.conf
        - template: jinja
        - context:
            bind: 127.0.0.1
# lib.sls
{% set port = 6379 %}
# redis.conf
{% from 'lib.sls' import port with context %}
port {{ port }}
bind {{ bind }}

As an example, configuration was pulled from the file context and from an external template file.

salt.renderers.jinja.render(template_file, env='', sls='', argline='', context=None, tmplpath=None, **kws)

Render the template_file, passing the functions and grains into the Jinja rendering system.

Return type:string

Table Of Contents

Previous topic

salt.renderers.yaml

Next topic

salt.renderers.json