Juniper Apstra offers the ability to dynamically modify a Configlet template through the use of Jinja templating and the Apstra Property Set feature. This approach enables the Configlets text to be context-sensitive and adaptable, providing the necessary flexibility when needed.
Before proceeding with this article, it is advisable to familiarize yourself with Jinja templating and Juniper Apstra Configlets . To enhance your understanding of the Configlet concepts and recommendations, we suggest reviewing the Configlet KB article in addition to the official documentation.
For simplicity, this article uses examples based solely on Juniper Junos configuration, though the concepts discussed are relevant to any vendor supported by Juniper Apstra.
This article describes two different ways of using Jinja and variables in a Configlet text.
The first method utilizes Apstra Device Context variables, which encompass a range of items specific to each device. These items, including device hostname, BGP sessions, IP addresses, interfaces, and more, are available for use as variables directly in the Configlet. The second method involves the use of the Apstra Property Set.
Starting with Juniper Apstra version 4.2.0, for any assistance or guidance on using Jinja, you can refer to the 'Jinja Function Reference'. This can be accessed by clicking the corresponding button in the 'Create Configlet' view. Please refer to the official Jinja documentation for information on earlier Apstra releases.
To view the available variables, navigate to your Apstra blueprint, select 'Staged' then 'Physical', and finally 'Topology'. Choose the device you're interested in, and then at the bottom right side, click on the 'Device Context' option.
To retrieve the value of a variable in a Configlet text, encase the variable name within double curly braces, like this: {{ variable }}. For instance, consider the variable 'management_ip'. If you aim to create a single Configlet that can be used for various devices, each with its unique management IP, you would refer to this variable. In the given Device Context for 'switch1', the desired outcome in our Config render would be to see the specific IP '10.28.156.13'.
{{ variable }}
Go to 'Design' in your Apstra UI, and create a new Configlet, this can be either hierarchical or 'set' type in Junos. Define the variable as follows in the Configlet text:
set system ntp source-address {{ management_ip }}
Proceed to your blueprint and import the Configlet by navigating to Staged > Catalog > Configlets. Once you apply it to the desired devices, the {{ management_ip }} variable will automatically be sourced from each specific device where this Configlet is applied, resulting in a configuration tailored to each device's individual value. It's important to note that Apstra does not check the syntax of the Configlet. Therefore, ensuring the accuracy of the configuration and conducting thorough testing before deploying it in a live environment is essential.
{{ management_ip }}
To check the resulting configuration, go to Staged > Physical > Topology, select the device to which the Configlet has been applied, and then, at the bottom right side, click on 'Incremental' config. In our example, you would observe the following:
------BEGIN SECTION SET AND DELETE BASED CONFIGLETS------
set system ntp source-address 10.28.156.13When a device context variable includes nested items within its structure, approach it as if it were a Python dictionary to access its child elements.
For instance, to render specific configurations for the interface xe-0/0/10, you can iterate over the interfaces of the device and make the necessary adjustments. In this example, for the sake of simplicity, we will only alter the description.
Our Configlet's text is as follows:
{% for iface, iface_values in interface.items() %}{% if iface_values['intfName'] == 'xe-0/0/10' %}set description This is interface xe-0/0/10{% endif %}{% endfor %}
And our incremental configuration is the following:
set description This is interface xe-0/0/10
Sometimes, the necessary variables might not be present in the Device Context, yet there's still a need for adaptability and an easy method to update variables. The Apstra Property Set offers a powerful solution to this challenge.
Property Sets should be created during the Design stage. They can then be imported into the blueprint from the Catalog, along with the Configlet. If there are any updates to the property set values at the Design stage, you only need to re-import them into the blueprint, without the need to modify the related Configlet.
Consider a Property Set as akin to a Python list or a list of dictionaries. You can reference a key in the Property Set in the same manner as you would in the Device Context, using {{ key }}, even for more complex or nested lists.
{{ key }}
It's important to note that the name of the Property Set is used solely for identifying which Property Set to import into the blueprint. This name is not directly accessible within the Configlet.
We could simply use the Property Set as a list:
And loop inside this list in the Configlet:
system {ntp {{% for ntp_server_value in ntp_server %}server {{ ntp_server_value }};{% endfor %}}}
-----CONFIGLETS-----system {ntp {server 172.0.0.1;server 172.0.0.2;}}
Or use it as a list of dictionaries. For example, suppose we have defined various IP addresses per hostname under a key named 'source_ips' in the property set:
Then, a Configlet is created with Junos style, and set or hierarchical depending on our configuration:
{% if hostname in source_ips %}set system ntp source-address {{ source_ips[hostname] }}set system tacplus-server 1.1.1.1 source-address {{ source_ips[hostname] }}{% endif %}
The above Jinja template will first check whether the hostname where this Configlet is applied appears in the property set, as we can see, and apply the respective value if applies. Reviewing the incremental config for leaf1, we will find that it appears as follows, since it derives the specific IP address value from the leaf1 key in the Property Set:
-----CONFIGLETS-----set system ntp source-address 192.168.0.1set system tacplus-server 1.1.1.1 source-address 192.168.0.1
To update, change, add, or delete any entry in the property set, simply make the necessary adjustments in the Global Catalog under Design > Property Set. Afterward, in the blueprint Catalog, navigate to Property Sets and select the 're-import' button from the Actions menu.
Note: Should there be any issues with retrieving variables or in the Jinja code, you may encounter build errors within your blueprint. Nevertheless, if the syntax and variables are correct, build errors will not occur even if there are mistakes in the Junos code. To prevent deployment errors, it's advisable to execute a 'commit check' (a feature available from Apstra 4.2.0 onwards).
To prevent potential conflicts with the Apstra render design, please refrain from modifying any configurations through configlet that could cause issues. If you consider making changes that might affect it, consult with the Juniper Apstra JTAC team beforehand.