- en
 - Language: ru
 
- Documentation version: latest
 
if/elif/else
if позволяет добавлять условие в шаблон. Например, можно использовать if, чтобы добавлять какие-то части шаблона в зависимости от наличия переменных в словаре с данными.
Конструкция if также должна находиться внутри {% %}.
Нужно явно указывать окончание условия:
{% if ospf %}
router ospf 1
 router-id 10.0.0.{{ id }}
 auto-cost reference-bandwidth 10000
{% endif %}
Пример шаблона templates/if.txt:
hostname {{ name }}
interface Loopback0
 ip address 10.0.0.{{ id }} 255.255.255.255
{% for vlan, name in vlans.items() %}
vlan {{ vlan }}
 name {{ name }}
{% endfor %}
{% if ospf %}
router ospf 1
 router-id 10.0.0.{{ id }}
 auto-cost reference-bandwidth 10000
 {% for networks in ospf %}
 network {{ networks.network }} area {{ networks.area }}
 {% endfor %}
{% endif %}
Выражение if ospf работает так же, как в Python: если переменная
существует и не пустая, результат будет True. Если переменной нет или
она пустая, результат будет False.
То есть, в этом шаблоне конфигурация OSPF генерируется только в том случае, если переменная ospf существует и не пустая.
Конфигурация будет генерироваться с двумя вариантами данных.
Сначала с файлом data_files/if.yml, в котором нет переменной ospf:
id: 3
name: R3
vlans:
  10: Marketing
  20: Voice
  30: Management
Результат будет таким:
$ python cfg_gen.py templates/if.txt data_files/if.yml
hostname R3
interface Loopback0
 ip address 10.0.0.3 255.255.255.255
vlan 10
 name Marketing
vlan 20
 name Voice
vlan 30
 name Management
Теперь аналогичный шаблон, но с файлом data_files/if_ospf.yml:
id: 3
name: R3
vlans:
  10: Marketing
  20: Voice
  30: Management
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
Теперь результат выполнения будет таким:
hostname R3
interface Loopback0
 ip address 10.0.0.3 255.255.255.255
vlan 10
 name Marketing
vlan 20
 name Voice
vlan 30
 name Management
router ospf 1
 router-id 10.0.0.3
 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
Как и в Python, в Jinja можно делать ответвления в условии.
Пример шаблона templates/if_vlans.txt:
{% for intf, params in trunks.items() %}
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 %}
Файл data_files/if_vlans.yml с данными:
trunks:
  Fa0/1:
    action: add
    vlans: 10,20
  Fa0/2:
    action: only
    vlans: 10,30
  Fa0/3:
    action: delete
    vlans: 10
В данном примере в зависимости от значения параметра action генерируются разные команды.
В шаблоне можно было использовать и такой вариант обращения к вложенным словарям:
{% for intf in trunks %}
interface {{ intf }}
 {% if trunks[intf]['action'] == 'add' %}
 switchport trunk allowed vlan add {{ trunks[intf]['vlans'] }}
 {% elif trunks[intf]['action'] == 'delete' %}
 switchport trunk allowed vlan remove {{ trunks[intf]['vlans'] }}
 {% else %}
 switchport trunk allowed vlan {{ trunks[intf]['vlans'] }}
 {% endif %}
{% endfor %}
В итоге будет сгенерирована такая конфигурация:
$ python cfg_gen.py templates/if_vlans.txt data_files/if_vlans.yml
interface Fa0/1
 switchport trunk allowed vlan add 10,20
interface Fa0/3
 switchport trunk allowed vlan remove 10
interface Fa0/2
 switchport trunk allowed vlan 10,30
Также с помощью if можно фильтровать, по каким элементам последовательности пройдется цикл for.
Пример шаблона templates/if_for.txt с фильтром в цикле for:
{% for vlan, name in vlans.items() if vlan > 15 %}
vlan {{ vlan }}
 name {{ name }}
{% endfor %}
Файл с данными (data_files/if_for.yml):
vlans:
  10: Marketing
  20: Voice
  30: Management
Результат выполнения:
$ python cfg_gen.py templates/if_for.txt data_files/if_for.yml
vlan 20
 name Voice
vlan 30
 name Management