Filters#
In Jinja, variables can be changed by filters. Filters are separated from
variable by a vertical line (pipe |
) and may contain additional arguments.
In addition, several filters can be applied to variable. In this case,
filters are simply written consecutively and each of them is separated by a vertical line.
Jinja supports a large number of built-in filters. We will look at only a few of them. Other filters can be found in documentation.
You can also easily create your own filters. We will not cover this possibility but it is well documented.
default#
Filter default
allows you to set default value for variable. If variable
is defined, it will be displayed, if variable is not defined, the value
specified in default filter will be displayed.
Template example templates/filter_default.txt:
router ospf 1
auto-cost reference-bandwidth {{ ref_bw | default(10000) }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
If variable ref_bw is defined in dictionary, its value will be set. If there is no variable, the value of 10000 will be substituted.
Data file (data_files/filter_default.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/filter_default.txt data_files/filter_default.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
By default, if variable is defined and its value is empty, it will be assumed that variable and its value exist.
If you want default value to be set also when variable is empty
(i.e., treated as False in Python), you need to specify additional
parameter boolean=true
.
For example, if data file is:
ref_bw: ''
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 will be:
$ python cfg_gen.py templates/filter_default.txt data_files/filter_default.yml
router ospf 1
auto-cost reference-bandwidth
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
If with the same data file the template will be changed as follows:
router ospf 1
auto-cost reference-bandwidth {{ ref_bw | default(10000, boolean=true) }}
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
Note
Instead of default(10000, boolean=true)
you can write
default(10000, true)
The result will be (default value is set):
$ python cfg_gen.py templates/filter_default.txt data_files/filter_default.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
dictsort#
Filter dictsort
allows you to sort the dictionary. By default, sorting is
done by keys but by changing filter parameters you can sort by values.
Filter syntax:
dictsort(value, case_sensitive=False, by='key')
After dictsort
sorts the dictionary, it returns a list of tuples, not a dictionary.
Template example templates/filter_dictsort.txt using dictsort
filter:
{% for intf, params in trunks | dictsort %}
interface {{ intf }}
{% 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 %}
{% endfor %}
Note that filter awaits a dictionary, not a list of tuples or iterator.
Data file (data_files/filter_dictsort.yml):
trunks:
Fa0/2:
action: only
vlans: 10,30
Fa0/3:
action: delete
vlans: 10
Fa0/1:
action: add
vlans: 10,20
The result of execution will be (interfaces are ordered):
$ python cfg_gen.py templates/filter_dictsort.txt data_files/filter_dictsort.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
join#
Filter join
works just like join
method in Python.
With join
filter you can combine sequence of elements into a string with
an optional separator between elements.
Template example templates/filter_join.txt using join
filter:
{% for intf, params in trunks | dictsort %}
interface {{ intf }}
{% 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 %}
{% endfor %}
Data file (data_files/filter_join.yml):
trunks:
Fa0/1:
action: add
vlans:
- 10
- 20
Fa0/2:
action: only
vlans:
- 10
- 30
Fa0/3:
action: delete
vlans:
- 10
The result of execution:
$ python cfg_gen.py templates/filter_join.txt data_files/filter_join.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