Tests#
Besides filters, Jinja also supports tests. Tests allow variables to be tested for a certain condition.
Jinja supports a large number of built-in tests. We will look at only a few of them. The rest of tests you can find in documentation.
defined#
Test defined
allows you to check if variable is present in the data dictionary.
Template example templates/test_defined.txt:
router ospf 1
{% if ref_bw is defined %}
auto-cost reference-bandwidth {{ ref_bw }}
{% else %}
auto-cost reference-bandwidth 10000
{% endif %}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
This example is more cumbersome than default
filter option, but this test
may be useful if depending on whether a variable is defined or not, different
commands need to be executed.
Data file (data_files/test_defined.yml):
ospf:
- network: 10.0.1.0 0.0.0.255
area: 0
- network: 10.0.2.0 0.0.0.255
area: 2
- network: 10.1.1.0 0.0.0.255
area: 0
The result of execution:
$ python cfg_gen.py templates/test_defined.txt data_files/test_defined.yml
router ospf 1
auto-cost reference-bandwidth 10000
network 10.0.1.0 0.0.0.255 area 0
network 10.0.2.0 0.0.0.255 area 2
network 10.1.1.0 0.0.0.255 area 0
iterable#
Test iterable
checks whether the object is an iterator.
Due to these checks, it is possible to make branches in template which will take
into account the type of variable.
Template templates/test_iterable.txt (indents made to make an idea of branches more clear):
{% for intf, params in trunks | dictsort %}
interface {{ intf }}
{% if params.vlans is iterable %}
{% if params.action == 'add' %}
switchport trunk allowed vlan add {{ params.vlans | join(',') }}
{% elif params.action == 'delete' %}
switchport trunk allowed vlan remove {{ params.vlans | join(',') }}
{% else %}
switchport trunk allowed vlan {{ params.vlans | join(',') }}
{% endif %}
{% else %}
{% if params.action == 'add' %}
switchport trunk allowed vlan add {{ params.vlans }}
{% elif params.action == 'delete' %}
switchport trunk allowed vlan remove {{ params.vlans }}
{% else %}
switchport trunk allowed vlan {{ params.vlans }}
{% endif %}
{% endif %}
{% endfor %}
Data file (data_files/test_iterable.yml):
trunks:
Fa0/1:
action: add
vlans:
- 10
- 20
Fa0/2:
action: only
vlans:
- 10
- 30
Fa0/3:
action: delete
vlans: 10
Note the last line: vlans: 10
. In this case, 10 is no longer in the list
and join
filter does not work. But, due to is iterable
test (in this
case the result will be false), in this case template goes into else
branch.
The result of execution:
$ python cfg_gen.py templates/test_iterable.txt data_files/test_iterable.yml
interface Fa0/1
switchport trunk allowed vlan add 10,20
interface Fa0/2
switchport trunk allowed vlan 10,30
interface Fa0/3
switchport trunk allowed vlan remove 10
Such indents appeared because the template uses indents but does not
have lstrip_blocks=True
installed (it removes spaces and tabs at the beginning of the line).