Jinja2 template inheritance is probably the most powerful feature of the Jinja2 templating library that makes it super easy to scale in large projects and at the same time making it modular and easy to maintain. Most of the time you will find the concept of inheritance explained in the context of web development as HTML files but here I will try to explain the concept keeping it relevant to the work of network engineers.
Source documentation of Jinja2 Template Inheritance
https://jinja.palletsprojects.com/en/3.0.x/templates/#template-inheritance
If you look at the running configuration of a device, it is mostly broken down into subsections.
Building configuration...
!
hostname <>
!
vrf config
!
AAA config
!
netflow config
!
object groups / acls
!
usernames
!
ipsec config
!
interface running config
!
routing configuration
!
nat
!
static routes
!
route-maps
!
snmp
!
tacacs
!
banners
!
line vty
!
The idea is that the configuration itself is modular. Now if you were given the task of writing a jinja2 template for the entire running configuration for a site at initial deployment, it might be extremely complicated to pack in the entire running configuration into a single template file. It will probably be much easier to divide the template into smaller sub-sections which can then be imported into a single main template file.
There are 2 main constructs that jinja2 templates inheritance gives that allow achieving this result.
- Include
- Import
#simplified running config in final_configuration template
{% include 'common.j2' %}
{% include 'aaa.j2' %}
{% include 'interfaces.j2' %}
{% include 'ospf.j2' %}
{% include 'bgp.j2' %}
As you can clearly see from here, the final product that we want to see has been broken down into smaller modules that can be taken care of with more ease. We have already talked about how to leverage the true power of DevOps with
- CI/CD
- Digital Twins
- Git
These templates/structures can be easily maintained under a git project which can be leveraged by a wider team to make full use of DevOps.
When you call the above templates with python script and the YAML variable file, you get below final output.
import yaml
from rich import print
from jinja2 import Environment, FileSystemLoader
env = Environment(loader = FileSystemLoader('./templates'), lstrip_blocks=True, trim_blocks=True)
template = env.get_template('final_config.j2')
data = yaml.load(open('variables.yaml'), Loader=yaml.FullLoader)
print(template.render(data))
# YAML variables.yaml
hostname: 'rtr-001-ce01'
enable_secret: cisco
domain_name: cisco.com
tacacs_group: 'TACACS_GROUP'
server_name: ['TACACS_1', 'TACACS_2', 'TACACS_3']
interfaces:
-
number: 'GigabitEthernet 0/1'
description: 'WAN INTERFACE1'
ip: 10.10.10.1
mask: 255.255.255.0
state: 'no shut'
-
number: 'GigabitEthernet 0/2'
description: 'WAN INTERFACE2'
ip: 10.10.20.1
mask: 255.255.255.0
state: 'no shut'
-
number: 'GigabitEthernet 1/0'
description: 'LAN INTERFACE1'
ip: 10.10.30.1
mask: 255.255.255.0
state: 'no shut'
ospf:
process_id: 1
router_id: 1.1.1.1
network_id:
- 10.10.10.1 0.0.0.0 area 0
- 10.10.20.1 0.0.0.0 area 0
- 10.10.30.1 0.0.0.0 area 1
bgp:
local_as: 65000
router_id: 1.1.1.1
peer_groups:
-
name: RR
remote_as: 65001
password: cisco
update_source: loopback0
route_map: FROM-RR
neighbor_ip:
- 11.11.11.1
- 13.13.13.1
-
name: EBGP-PEER
remote_as: 65002
password: cisco
update_source: loopback0
route_map: FROM-RR
neighbor_ip:
- 100.100.100.1
service tcp-keepalives-in
service tcp-keepalives-out
service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec localtime show-timezone
service password-encryption
platform qfp utilization monitor load 80
no platform punt-keepalive disable-kernel-core
!
hostname rtr-001-ce01
!
security authentication failure rate 3 log
security passwords min-length 8
logging buffered 16384
no logging console
enable secret cisco
!
ip domain name cisco.com
!
aaa new-model
!
aaa group server tacacs+ TACACS_GROUP
server name TACACS_1
server name TACACS_2
server name TACACS_3
!
aaa authentication login default group TACACS_GROUP local
aaa authentication enable default group TACACS_GROUP enable
aaa authorization console
aaa authorization config-commands
aaa authorization exec default group TACACS_GROUP if-authenticated
aaa authorization commands 15 default group TACACS_GROUP none
aaa accounting exec default start-stop group TACACS_GROUP
aaa accounting commands 0 default start-stop group TACACS_GROUP
aaa accounting commands 1 default start-stop group TACACS_GROUP
aaa accounting commands 2 default start-stop group TACACS_GROUP
aaa accounting commands 5 default start-stop group TACACS_GROUP
aaa accounting commands 15 default start-stop group TACACS_GROUP
aaa accounting network default start-stop group TACACS_GROUP
aaa accounting connection default start-stop group TACACS_GROUP
aaa accounting system default start-stop group TACACS_GROUP
!
interface GigabitEthernet 0/1
description WAN INTERFACE1
bandwidth 1000000
ip address 10.10.10.1 255.255.255.0
no ip redirects
no ip unreachables
no ip proxy-arp
media-type rj45
speed 1000
no negotiation auto
!
interface GigabitEthernet 0/2
description WAN INTERFACE2
bandwidth 1000000
ip address 10.10.20.1 255.255.255.0
no ip redirects
no ip unreachables
no ip proxy-arp
media-type rj45
speed 1000
no negotiation auto
!
interface GigabitEthernet 1/0
description LAN INTERFACE1
bandwidth 1000000
ip address 10.10.30.1 255.255.255.0
no ip redirects
no ip unreachables
no ip proxy-arp
media-type rj45
speed 1000
no negotiation auto
!
router bgp 65000
bgp router-id 1.1.1.1
bgp log-neighbor-changes
neighbor RR peer-group
neighbor RR remote-as 65001
neighbor RR password 7 cisco
neighbor RR update-source loopback0
neighbor RR timers 15 45
neighbor RR next-hop-self
neighbor RR send-community both
neighbor RR soft-reconfiguration inbound
neighbor RR route-map FROM-RR in
neighbor 11.11.11.1 peer-group RR
neighbor 13.13.13.1 peer-group RR
!
neighbor EBGP-PEER peer-group
neighbor EBGP-PEER remote-as 65002
neighbor EBGP-PEER password 7 cisco
neighbor EBGP-PEER update-source loopback0
neighbor EBGP-PEER timers 15 45
neighbor EBGP-PEER next-hop-self
neighbor EBGP-PEER send-community both
neighbor EBGP-PEER soft-reconfiguration inbound
neighbor EBGP-PEER route-map FROM-RR in
neighbor 100.100.100.1 peer-group EBGP-PEER
!
!
[Finished in 439ms]
Please use the search box on top right for more information regarding Jinja2 and DevOps for network automation.
This is really good Gurpreet !! Now that you have got a lot of blogs on very good & relevant topics, let me socialize this blog site to my team and other contacts. …. Once again, this is real good stuff !! Keep it up !
Thank you so much sir. I am still learning and there is a lot to learn. The fact that you are still cracking newer certifications is inspiring for me.