file_from_template_jinja2
Build a file from a jinja2 template.
⚙️ Compatible targets: Linux
Parameters
Name | Documentation |
---|---|
source_template | Source file containing a template to be expanded (absolute path on the target node). This parameter is required. |
path | Destination file (absolute path on the target node). This parameter is required. |
Outcome conditions
You need to replace ${path}
with its actual canonified value.
- ✅ Ok:
file_from_template_${path}_ok
- ☑️ Already compliant:
file_from_template_${path}_kept
- 🟨 Repaired:
file_from_template_${path}_repaired
- ☑️ Already compliant:
- ❌ Error:
file_from_template_${path}_error
Example
method: file_from_template_jinja2
params:
source_template: VALUE
path: VALUE
Documentation
See file_from_template_type for general documentation about templates usage.
This generic method will build a file from a jinja2 template using data (conditions and variables) found in the execution context.
Setup
It requires to have the jinja2 python module installed on the node, it can usually be done in ncf with
package_present("python-jinja2", "", "", "")
.
WARNING: If you are using a jinja2 version older than 2.7 trailing newlines will not be preserved in the destination file.
Syntax
Jinja2 is a powerful templating language, running in Python. The Jinja2 syntax reference documentation is http://jinja.pocoo.org/docs/dev/templates/ which will likely be useful, as Jinja2 is very rich and allows a lot more that what is explained here.
This section presents some simple cases that cover what can be done with mustache templating, and the way the agent data is provided to the templating engine.
The main specificity of jinja2 templating is the use of two root containers:
classes
to access currently defined conditionsvars
to access all currently defined variables
Note: You can add comments in the template, that will not be rendered in the output file with
{# ... #}
.
You can extend the Jinja2 templating engine by adding custom FILTERS and TESTS in the script
/var/rudder/configuration-repository/ncf/10_ncf_internals/modules/extensions/jinja2_custom.py
For instance, to add a filter to uppercase a string and a test if a number is odd, you can create
the file /var/rudder/configuration-repository/ncf/10_ncf_internals/modules/extensions/jinja2_custom.py
on your Rudder server with the following content:
def uppercase(input):
return input.upper()
def odd(value):
return True if (value % 2) else False
FILTERS = {'uppercase': uppercase}
TESTS = {'odd': odd}
These filters and tests will be usable in your jinja2 templates automatically.
Conditions
To display content based on conditions definition:
{% if classes.my_condition is defined %}
display this if defined
{% endif %}
{% if not classes.my_condition is defined %}
display this if not defined
{% endif %}
Note: You cannot use condition expressions here.
You can also use other tests, for example other built-in ones or
those defined in jinja2_custom.py
:
{% if vars.variable_prefix.my_number is odd %}
display if my_number is odd
{% endif %}
Scalar variables
Here is how to display a scalar variable value (integer, string, ...),
if you have defined variable_string("variable_prefix", "my_variable", "my_value")
:
{{ vars.variable_prefix.my_variable }}
You can also modify what is displayed by using filters. The built-in filters
can be extended in jinja2_custom.py
:
{{ vars.variable_prefix.my_variable | uppercase }}
Will display the variable in uppercase.
Iteration
To iterate over a list, for example defined with:
variable_iterator("variable_prefix", "iterator_name", "a,b,c", ",")
Use the following file:
{% for item in vars.variable_prefix.iterator_name %}
{{ item }} is the current iterator_name value
{% endfor %}
Which will be expanded as:
a is the current iterator_name value
b is the current iterator_name value
c is the current iterator_name value
To iterate over a container defined by the following json file, loaded with
variable_dict_from_file("variable_prefix", "dict_name", "path")
:
{
"hosts": [
"host1",
"host2"
],
"files": [
{"name": "file1", "path": "/path1", "users": [ "user1", "user11" ] },
{"name": "file2", "path": "/path2", "users": [ "user2" ] }
],
"properties": {
"prop1": "value1",
"prop2": "value2"
}
}
Use the following template:
{% for item in vars.variable_prefix.dict_name.hosts %}
{{ item }} is the current hosts value
{% endfor %}
# will display the name and path of the current file
{% for file in vars.variable_prefix.dict_name.files %}
{{ file.name }}: {{ file.path }}
{% endfor %}
# will display the users list of each file
{% for file in vars.variable_prefix.dict_name.files %}
{{ file.name }}: {{ file.users|join(' ') }}
{% endfor %}
# will display the current properties key/value pair
{% for key, value in vars.variable_prefix.dict_name.properties.items() %}
{{ key }} -> {{ value }}
{% endfor %}
Which will be expanded as:
host1 is the current hosts value
host2 is the current hosts value
# will display the name and path of the current file
file1: /path1
file2: /path2
# will display the users list of each file
file1: user1 user11
file2: user2
# will display the current properties key/value pair
prop1 -> value1
prop2 -> value2
System variables
Some sys
dict variables (like sys.ipv4
) are also accessible as string, for example:
${sys.ipv4}
gives54.32.12.4
$[sys.ipv4[ethO]}
gives54.32.12.4
$[sys.ipv4[eth1]}
gives10.45.3.2
These variables are not accessible as dict in the templating data, but are represented as string:
ipv4
is a string variable in thesys
dict with value54.32.12.4
ipv4[ethO]
is a string variable in thesys
dict with value54.32.12.4
ipv4
is not accessible as a dict in the template
To access these value, use the following syntax in your jinja2 templates:
vars.sys['ipv4[eth0]']