Jinja2 is a templating framework that is extremely versatile and its usage is not limited to any particular field like networking or web development. In this post, we will see the power of Jinja2 for network engineers.
This flow chart gives the overall concept of jinja2
Let’s take an example to make this more clear. If we want to generate the below piece of config using the jinja templating engine.
hostname my-rtr-01
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
!
vlan 10
name data
!
vlan 20
name voice
!
vlan 30
name mgmt
!
router ospf 1
router-id 1.1.1.1
auto-cost reference-bandwidth 10000
network 10.10.10.0 0.0.0.255 area 0
network 10.10.20.0 0.0.0.255 area 0
network 10.10.30.0 0.0.0.255 area 1
As per the diagram above, we need a base template, variable files, and a script that can use both to create the final output. Here is the sample variable YAML file
---
hostname: my-rtr-01
loopback: 1.1.1.1 255.255.255.255
vlans:
10: data
20: voice
30: mgmt
ospf:
- subnet: 10.10.10.0 0.0.0.255
area: 0
- subnet: 10.10.20.0 0.0.0.255
area: 0
- subnet: 10.10.30.0 0.0.0.255
area: 1
Python script to read the YAML variable file.
import yaml
from rich import print
from jinja2 import Environment, FileSystemLoader
variable_data = yaml.load(open('variables.yaml'), Loader=yaml.FullLoader)
print(variable_data)
╰─ python3 script1.py ─╯
{
'hostname': 'my-rtr-01',
'loopback': '1.1.1.1 255.255.255.255',
'vlans': {10: 'data', 20: 'voice', 30: 'mgmt'},
'ospf': [{'subnet': '10.10.10.0 0.0.0.255', 'area': 0}, {'subnet': '10.10.20.0 0.0.0.255', 'area': 0}, {'subnet': '10.10.30.0 0.0.0.255', 'area': 1}]
}
Now we need a template that can subsite the values that the python script has read from the YAML file. While reading the below j2 template, keep in mind the end configuration that we want to generate.
- {{ }} variable name inside these brackets is the variable name inside the yaml file.
- Each key-value pair in yaml is read as a dictionary by python while loading yaml.
- Key values denoted by ‘ — ‘ are regarded as elements of the same list. So ospf key contains a list of dictionaries
hostname {{ hostname }}
!
interface Loopback0
ip address {{ loopback }}
!
{% for vlan, name in vlans.items() %}
vlan {{ vlan }}
name {{ name }}
!
{% endfor %}
router ospf 1
auto-cost reference-bandwidth 10000
{% for networks in ospf %}
network {{ networks.network }} area {{ networks.area }}
{% endfor %}
!
Let’s modify the python script to load the template and pass the variable data to that template to render the final output.
import yaml
from rich import print
from jinja2 import Environment, FileSystemLoader
variable_data = yaml.load(open('variables.yaml'), Loader=yaml.FullLoader)
print(variable_data)
env = Environment(loader = FileSystemLoader('./'), trim_blocks=True, lstrip_blocks=True)
template = env.get_template('template.j2')
print(template)
print(template.render(variable_data))
╰─ python3 script1.py ─╯
{
'hostname': 'my-rtr-01',
'loopback': '1.1.1.1 255.255.255.255',
'vlans': {10: 'data', 20: 'voice', 30: 'mgmt'},
'ospf': [{'subnet': '10.10.10.0 0.0.0.255', 'area': 0}, {'subnet': '10.10.20.0 0.0.0.255', 'area': 0}, {'subnet': '10.10.30.0 0.0.0.255', 'area': 1}]
}
<Template 'template.j2'>
hostname my-rtr-01
!
interface Loopback0
ip address 1.1.1.1 255.255.255.255
!
vlan 10
name data
!
vlan 20
name voice
!
vlan 30
name mgmt
!
router ospf 1
auto-cost reference-bandwidth 10000
network area 0
network area 0
network area 1
!
I hope this helps in understanding the power of templates. This was a very simple example just to get familiarized with jinja2 templates but the possibilities with jinja2 are endless especially when it comes to network automation and engineering.
Please feel free to put your suggestions and comments below.
1 thought on “Python Jinja2 For Network Engineers”