Code Style
AVD Coding style¶
This page provides a list of guidelines to apply when developing the Jinja2 template in the AVD context. These rules apply for either creation or update of any J2 file available in aristanetworks/ansible-avd repository.
Python code style¶
As AVD is an Ansible collection, we are required to follow guidelines from ansible documentation for all Python code.
YAML Syntax guidelines¶
SYNTAX-1 - Use variable in Jinja¶
- Description
A single space shall be added between Jinja2 curly brackets and a variable’s name
- Example
{{ ethernet_interface }}
SYNTAX-2 - Filter syntax¶
- Description
When variables are used in combination with a filter, |
shall be enclosed by space
- Example
{{ my_value | to_json }}
SYNTAX-3 - Indentation for statement blocks¶
- Description
Nested jinja code block shall follow the next rules:
- All J2 statements must be enclosed by 1 space
- All J2 statements must be indented by 4 more spaces within the jinja delimiter
- To close a control, the end tag must have the same indentation level as the opening tag
- Indentation must be 4 spaces and NOT tabulation
- Example
{# Initial block indentation #}
{% if my_variable is arista.avd.defined %}
{# Nested block indentation #}
{% for ethernet_interface in ethernet_interfaces %}
{% if ethernet_interface.name is arista.avd.defined %}
{% set result = ethernet_interface.name %}
{# ..... output truncated ..... #}
{% endif %}
{% endfor %}
SYNTAX-4 - Expand list on a single line¶
- Description
Instead of doing a for loop on a single line, the join
filter should be leveraged as much as possible
- Example
{{ ciphers | join(", ") }}
SYNTAX-5 - Test if a variable in a list¶
Description
To test if a variable is part of a list, the in
operator should be used as much as possible to avoid long if/elif/else
block.
Example
{% if underlay_routing_protocol is arista.avd.defined and underlay_routing_protocol in ['isis', 'ospf'] %}
SYNTAX-6 - Render long CLI¶
- Description
When a long CLI with multiple options needs to be built, use pure J2 logic and then print
- Example
{% for ip_helper in vlan_interfaces[vlan_interface].ip_helpers | arista.avd.natural_sort %}
{% set ip_helper_cli = "ip helper-address " ~ ip_helper %}
{% if vlan_interfaces[vlan_interface].ip_helpers[ip_helper].vrf is arista.avd.defined %}
{% set ip_helper_cli = ip_helper_cli ~ " vrf " ~ vlan_interfaces[vlan_interface].ip_helpers[ip_helper].vrf %}
{% endif %}
{% if vlan_interfaces[vlan_interface].ip_helpers[ip_helper].source_interface is arista.avd.defined %}
{% set ip_helper_cli = ip_helper_cli ~ " source-interface " ~ vlan_interfaces[vlan_interface].ip_helpers[ip_helper].source_interface %}
{% endif %}
{{ ip_helper_cli }}
{% endfor %}
YAML Variable definition¶
VAR-1 - Variable name case¶
- Description
All variables shall use lower case
- Example
{{ variable }}
VAR-2 - Variable name format¶
- Description
If a variable is multi-words, underscore _
shall be used as a separator.
- Example
{{ my_variable_name }}
VAR-3 - Iterable Variables¶
- Description
For an iterable variable, the plural form shall be used
- Example
{{ ethernet_interfaces }}
VAR-4 - Variables in a For Loop¶
- Description
For variables in a for loop, the singular form shall be used
- Example
{{ ethernet_interfaces[ethernet_interface] }}
VAR-5 - Variables concatenation¶
Description
Tilde ~
should be used for string concatenation as it automatically converts variables to a string.
Example
{% set ip_helper_cli = ip_helper_cli ~ " source-interface " ~ vlan_interfaces[vlan_interface].ip_helpers[ip_helper].source_interface %}
VAR-6 - Variable type comparison¶
Description
To test the type of a variable, it is recommended to use is
/is not
keywords
Example
{# Test if variable is string #}
{% if ethernet_interface is string %}
{# Test if variable is not a string #}
{% if ethernet_interface is not string %}
VAR-7 - Variable content comparison¶
Description
To test the content of a variable, it is recommended to use ==
/!=
keywords
Example
{# Test if variable is equal to 'Ethernet1' #}
{% if ethernet_interface == 'Ethernet1' %}
{# Test if variable is not equal to 'Ethernet1' #}
{% if ethernet_interface != 'Ethernet1' %}
Info
Also PLUGIN-2 can do a test if the variable is defined and has a specific value
VAR-8 - String comparison¶
Description
All strings should be compared based on lowercase format.
Example
{% if underlay_routing_protocol is arista.avd.defined and underlay_routing_protocol | lower in ['isis', 'ospf'] %}
AVD Plugins usage¶
Plugins documentation is available here
PLUGIN-1 - Test if a variable exists¶
- Description
All tests to check if a variable is defined shall be done with arista.avd.defined
.
Test also does a deep test and does not require to do test at upper level.
- Example
{# Simple test #}
{% if ethernet_interfaces is arista.avd.defined %}
{# Deep test #}
{% if router_bgp.vrfs[vrf].rd is arista.avd.defined %}
PLUGIN-2 - Test if variable exists with a given value¶
- Description
To test if a variable is defined and has a specific value, the test arista.avd.defined
shall be used
- Example
{% if vlan.name is arista.avd.defined('test') %}
PLUGIN-3 - Default value¶
- Description
If a default value must be used, the arista.avd.default
plugin shall be used instead of a if/else
block.
The plugin can be used to fallback to different value(s) until one of them is defined and valid
- Example
{# Simple default test with one default value #}
{{ vlan.name | arista.avd.default('test_vlan') }}
{# Default test with a list of default options #}
{{ vlan.name | arista.avd.default(default.vlan.name, 'test_vlan') }}