Generate new device configurations using Jinja2 templates, and use templates to manage existing devices.
The arista.eos and cisco.ios Ansible Content Collections provide a number of modules that you can use to modify existing configurations.
These include modules to configure interfaces and access lists, among others.
An alternative way to deploy network device configurations is to template them. With this method, you can write a template configuration file that is automatically customized for the managed network device when the configuration is deployed. Templates typically use Ansible variables and facts.
Ansible uses the Jinja2 templating system for template files. Ansible also uses Jinja2 syntax to reference variables in playbooks.
Variables and logic expressions are placed between tags, or delimiters.
When a Jinja2 template is evaluated, the expression {{ is replaced with the results of that expression or variable.
Jinja2 templates use the EXPR }}{% syntax for special control structures or logic that loops over Jinja2 code or perform tests.
You can use the EXPR %}{# syntax to enclose comments that should not appear in the final file.COMMENT #}
The following example illustrates the use of the {# syntax in the first line of the Jinja2 template.
The variable reference in the second line is replaced with the value of the system facts being referenced.COMMENT #}
{# Obtain the hostname from facts #}
hostname {{ ansible_facts['net_hostname'] }}A Jinja2 template is composed of multiple elements: data, variables, and expressions.
Variables and expressions are replaced with their values when the Jinja2 template is rendered.
The variables used in the template can be specified in any location where you can specify variables.
These variables can include inventory variables, variables defined in included or imported files, and variables defined in the vars section of a play, block, or task.
You can also use gathered facts as variables in a template.
Template files are most commonly kept in the templates directory of the project for your playbook, and typically are assigned a .j2 file extension to make it clear that they are Jinja2 template files.
A file containing a Jinja2 template does not need to have any specific file extension (for example, .j2).
However, providing such a file extension might make it easier for you to remember that it is a template file.
The following example shows how to create a template for an Arista managed node with variables and facts retrieved by Ansible from the managed network device.
{# Hostname from facts #}
hostname {{ ansible_facts['net_hostname'] }}
ip name-server vrf default 172.25.250.220
!
spanning-tree mode mstp
!
system l1
unsupported speed action error
unsupported error-correction action error
!
interface Ethernet1
!
interface Loopback100
description Loopback100 Interface
ip address 10.10.10.100/32
!
{# Use Loopback101 info from variable #}
interface {{ interfaces[inventory_hostname][1]['name'] }}
description {{ interfaces[inventory_hostname][1]['name'] }} Interface
ip address {{ interfaces[inventory_hostname][1]['address'] }}
!
interface Management1
ip address 172.25.250.24/24
!Jinja2 templates provide a powerful way to customize configuration files to be deployed on managed nodes.
After you create a Jinja2 template, you can use the respective *_config module for the network OS to deploy the customized configuration to the managed node.
To deploy the network device configuration from a template to an Arista managed node, use the following syntax.
The value associated with the src key specifies the source Jinja2 template.
- name: Deploy configuration template on EOS
arista.eos.eos_config:
src: eos_configuration.j2
save_when: changedThe following example shows how to deploy a network device configuration from a template on Cisco IOS:
- name: Deploy configuration template on IOS
cisco.ios.ios_config:
src: ios_configuration.j2
save_when: changedThe previous examples use the save_when option to persistently save changes.
You might decide to omit this option and only save the running configuration to the startup configuration after you have validated the changes.
You can use Jinja2 control structures in template files to reduce repetitive typing, to enter entries for each managed node in a play dynamically, or conditionally insert text into a file.
Jinja2 uses for statements to provide looping functionality.
In the following example, the interfaces variable has a list of values.
The interface variable is replaced with all the values in the interfaces variable, one value per line.
{% for interface in interfaces %}
{{ interface }}
{% endfor %}The following example template uses a for statement and a conditional to run through all the values in the interfaces variable, replacing myinterface with each value, unless the value is Loopback100.
{# for statement #}
{% for myinterface in interfaces if not myinterface == "Loopback100" %}
Interface number {{ loop.index }} - {{ myinterface }}
{% endfor %}The loop.index variable expands to the index number that the loop is currently on.
It has a value of 1 the first time the loop executes, and it increments by 1 through each iteration.
As another example, this template also uses a for statement.
It assumes a mynodes variable that contains a list of managed nodes to be managed has been defined by the inventory being used.
If you put the following for statement in a Jinja2 template, all nodes in the mynodes group from the inventory would be listed in the resulting file:
{% for mynode in groups['mynodes'] %}
{{ mynode }}
{% endfor %}For a more practical example, you can use this example to configure access lists on an Arista managed node from a variable file. Assume that you have the following playbook:
---
- name: Configure access lists
hosts: arista01
vars_files:
- vars.yml
gather_facts: false
tasks:
- name: Deploy configuration
arista.eos.eos_config:
src: templates/acls.j2
save_when: changedAlso assume that the vars.yml file contains the following content:
---
acls:
- id: 10
address: 172.25.251.20
- id: 20
address: 172.25.251.21
- id: 30
address: 172.25.251.22
- id: 40
address: 172.25.251.23The following lines in the templates/acls.j2 template file configure all the access lists using a for statement:
{# for statement to deploy access lists #}
{% for acl in acls %}
{{ acl['id'] }} permit ip host {{ acl['address'] }} any log
{% endfor %}The preceding example results in the following lines in the managed node configuration:
10 permit ip host 172.25.251.20 any log 20 permit ip host 172.25.251.21 any log 30 permit ip host 172.25.251.22 any log 40 permit ip host 172.25.251.23 any log
Jinja2 uses if statements to provide conditional control.
This allows you to put a line in a deployed file if certain conditions are met.
In the following example, the value of the result variable is placed in the deployed file only if the value of the finished variable is true.
{% if finished %}
{{ result }}
{% endif %}