AutoNetOps

Cover Image for Jinja2 Fast Reference Handbook

Jinja2 Fast Reference Handbook

·

3 min read

Documentation as Code

Jinja2 templates are mainly used for configuration templates. You can also use Jinja2 to format raw or parsed data into text reports, CSV, JSON files, or Markdown documents.

Using it together with Python to gather/push information from/to the network can be a powerful and useful skill to add to your portfolio. Let's quickly take a look.


Documentation

Jinja

Installation

Jinja supports Python 3.7 and newer

pip install jinja2

Template content

Jinja2 templates consist of the following elements:

  • literal text that you want to add to the output or result.

  • variables that are either locally defined within the script or template, or provided automatically based on the context in which the template is used.

  • filters that can manipulate text or modify the content of variables or text strings, such as join, replace, trim

  • delimiters such as {{...}} and pipes |, which are used to enclose variables and define filter expressions.

Filters
To use a filter, you would typically follow the syntax {{<source_value>|<filter_name>}}.
snmp_logg_ntp.j2
-----------------------------------------------

snmp-server community {{ snmp_ro_community }} RO 

{% for server in syslog_servers %}
logging host {{ server }} transport udp port 1514
{%- endfor %}

{% for server in ntp_servers %}
ntp server {{ server }}
{%- endfor %}

We need a place where we will store the data to be replaced in this template. Let's do it with a YAML file for simplicity:

---
server:
  name: "SERVER1"
  snmp_ro_community: "COMMUNITY"    
  syslog_servers: 
    - "10.10.10.1"
    - "10.10.10.2"
  ntp_servers: 
    - "1.1.1.1"
    - "8.8.8.8"

Let's load this in our Python script to use it later.

import yaml

with open('server.yaml') as file:
    server_data = yaml.safe_load(file)

Building Blocks

Environment

Jinja uses a central object called the template Environment. Instances of this class are used to store the configuration and global objects and are used to load templates from the file system or other locations.

Loader

Loaders are responsible for loading the created templates from a resource, such as the file system.

FileSystemLoader
Load templates from a directory in the file system. The path can be relative or absolute, with relative paths based on the current working directory.
--------------------------------------
$pwd
    /home/user/jinja
$ls
    server.yaml
    jinja_example.py
    /templates
        snmp_logg_ntp.j2
        interfaces.j2
        dns.j2
from jinja2 import Environment, FileSystemLoader

env = Environment(
    loader=FileSystemLoader("templates"),
)

template = env.get_templates("snmp_logg_ntp.j2")

Render

Here is how we will pass our variables to the Template and create the final string outcome:

for server, data in server_data.items():
    config = template.render(data)
    print(config)
snmp-server community COMMUNITY RO 

logging host 10.10.10.1 transport udp port 1514
logging host 10.10.10.2 transport udp port 1514

ntp server 1.1.1.1
ntp server 8.8.8.8

Full Code Example

from jinja2 import Environment, FileSystemLoader
import yaml

with open('server.yaml') as file:
    server_data = yaml.safe_load(file)


env = Environment(
    loader=FileSystemLoader("templates"),
)

template = env.get_templates("snmp_logg_ntp.j2")

for server, data in server_data.items():
    config = template.render(data)
    print(config)

Helping Tools

This tool can be very useful if you want to quickly test your templates.

Packet Coders Jinja Render