4. Template Editor

The Template Editor is a workspace inside the Developer Console for low-level template design.

Modular design practices are encouraged in this space to create a great application experience for operators. Recommended practices include the following key considerations.

  1. Single Purpose Templates - There is no limit to the number of templates that can be created. As such, it is recommended to use each template for one configuration task only. This will give power to the operator in choosing which configuration snippets they would like to combine. If a template performs multiple tasks, then it will be harder for an operator to utilize subsections of the template.
  2. Appropriate use of Conditional Logic - Developers can utilize Business Rules throughout their template design to create a modular environment. The use of conditional logic allows similar configuration tasks to be clustered into a single template and avoid duplication. With that said, however, developers should avoid using conditional logic in a way that violates the Single Purpose Template recommendation. For example, it would make sense for iBGP and eBGP configuration tasks to share the same template but an OSPF configuration task should be created in a separate template.
  3. Readable Variable Names - When creating an input variable, it is highly recommended to use a readable input ID which clearly expresses the referenced field. The input ID is displayed in the template markup so readable names will make for much greater legibility.

With these key recommendations in mind, let us now take a look at how we can create a template.

4.1 Launching the TE

The Template Editor is launched via the Developer Console. Simply click on the Create Template button or edit an existing template.

4.2 Template Info

The top area of the Template Editor contains the Template Info block. Each field inside this block is described below.

  1. Display Name - Sets a display name for the template.
  2. Description - Sets a description for the template. This field will be visible in the Generator Console when hovering the mouse over the information icon of a template.
  3. Business Rule - Sets a business rule for the template. The configuration snippet for this template will only be generated if the business rule is true. A blank entry for a business rule will implicitly evaluate to true. For more information, refer to 4.6 Business Rules
  4. ID - A unique identifier for the template. This field is auto-generated.
  5. Newest Version - The production template version. This field is auto-generated.
  6. Loaded Version - This field provides a drop-down list of all historical template versions. Users can roll back to any prior version by modifying the value selected for this field.
  7. Date Created - The date the template was first created. This field is auto-generated.
  8. Date Modified - The date the template was last updated. This field is auto-generated.
  9. Updated By - The user who last updated the template. This field is auto-generated.

4.3 Input Table

The second block inside the Template Editor is the Input Table, which lists all input variables created by the template. An input variable is a data field presented to the user as a form entry inside the Generator Console. Once an input variable has been created, it may be utilized inside template markup and referenced inside business rules.

There are two types of input variables.

  1. Text Input - A text input is a free-text field, which allows operators to provide any value they like for the variable.
  2. Select Input - A select input is a drop-down field, which allows operators to choose a variable value from a predefined list of options.

The screenshot below displays an example of an Input Table.

4.4 Creating an Input

To create an input variable, simply click on the Create New Input button. The user will then be presented with a form to define the details of the new variable.

Let us now take a look at the meaning of these fields.

  1. Input Name - Sets a display name for the input variable.
  2. Input ID - An identifier for the input variable. The Input ID is the value that will be used to reference the input in template markup and business rules.
  3. Description - Sets a description for the input variable. This field will be visible in the Generator Console when hovering the mouse over the information icon of the variable.
  4. Data Type - Sets a data type for the input variable. A "string" is suitable for most use cases. For Arrays, Objects, Integers, and Booleans, users can choose the "json" data type. This enables users to utilize the full potential of the Jinja2 language in their Template Markup. Features such as for loops and math require these data types.
  5. Form Type - Sets a form type for the input variable. This can be a free text field or a drop-down select field.
  6. Input Options - Defines a list of selectable values. Each option is separated by a new line. This field is only applicable for drop-down inputs. Each input option can have a business rule defined. If a business rule is defined, the corresponding option will only be selectable if the expression evaluates to true. For more information, refer to 4.6 Business Rules
  7. Default Value - Sets a default value for the input variable. When a template is activated in the Generator Console, the default value will be initialized.
  8. Priority - The priority value determines the display order of input fields as presented in the Generator Console. To modify this value, click on the Edit Input Priority button inside the Input Table; the display order of input fields can then be adjusted through a drag-and-drop interface.
  9. Read Only - Sets the read-only attribute as true or false. The value of a read-only input will always equal the default value.
  10. Global Variable - Sets the scope of the input variable. If the value is set to true, then the variable will be accessible when referenced from any active template. Otherwise, the variable will only be accessible from within the template which defined it. To keep templates modular, it is recommended to avoid using global variables wherever possible.
  11. Business Rule - Sets a business rule for the input variable. The input field will only be visible if the business rule evaluates to true. A blank business rule will always evaluate to true. For more information, refer to 4.6 Business Rules

The screenshots below illustrate these attributes in practice.

4.5 Template Markup

Configuration belonging to a template is represented inside the Template Markup. It is here that configuration is written in a markup form using the Jinja2 templating language.

To complete this section, begin by pasting in a piece of network configuration. Next, add in variables and logic as required.

Let's take a look at some examples.

Example 1

interface {{ INTERFACE_NAME }}
description {{ DESCRIPTION }}
ip address {{ IP_ADDRESS }} {{ SUBNET_MASK }}
no shutdown
exit
!

This is what a Template Markup might look like for a basic IP interface. Wrapping an Input ID in double curly braces will indicate the field is referencing a variable.

Example 2

{% if STATIC_ROUTE == 'Yes' %}
ip route {{ DESTINATION_NETWORK }} {{ SUBNET_MASK }} {{ NEXT_HOP_ADDRESS }}
{% endif %}

Jinja2 is a powerful language for templating. We can easily embed conditional logic into our markup. In this example, the configuration will only be generated if the input "STATIC_ROUTE" has a value of "Yes".

Example 3

{% if PREFIX_LENGTH == '30' %}
ip route {{ DESTINATION_NETWORK }} 255.255.255.252 {{ NEXT_HOP_ADDRESS }}
{% elif PREFIX_LENGTH == '29' %}
ip route {{ DESTINATION_NETWORK }} 255.255.255.248 {{ NEXT_HOP_ADDRESS }}
{% else %}
ip route {{ DESTINATION_NETWORK }} 255.255.255.240 {{ NEXT_HOP_ADDRESS }}
{% endif %}

In this example, we demonstrate the use of the "elif" (else if) and "else" statements to convert a prefix length into a subnet mask.

Example 4

{% for protocol in PROTOCOLS %}
access-list {{ACL_ID}} deny tcp any any eq {{protocol}}
{% endfor %}
access-list {{ACL_ID}} permit ip any any
!
interface {{INTERFACE_NAME}}
ip access-group {{ACL_ID}} in
!

We can use the "for" statement to generate config in a loop. In this example, we're generating an access control list using an array of protocols. For this to work, the "PROTOCOLS" variable needs to have a Form Type of "json". A JSON array such as ["www","ftp","pop3"] could then be used when instantiating the template. This would generate a config like the one below.

access-list 101 deny tcp any any eq www
access-list 101 deny tcp any any eq ftp
access-list 101 deny tcp any any eq pop3
access-list 101 permit ip any any
!
interface GigabitEthernet0/0/0
ip access-group 101 in
!

Example 5

policy-map shaper-{{SHAPING_RATE}}M-out
class class-default
shape average {{1000000*SHAPING_RATE}}
!

Jinja2 supports math. In this example, a math expression is used to convert the shaping rate from megabits-per-second to bits-per-second. For this to work, the "SHAPING_RATE" variable needs to have a Form Type of "json". An integer such as 100 could then be supplied to generate the config shown below.

policy-map shaper-100M-out
class class-default
shape average 100000000
!

Example 6

<native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
<interface>
<GigabitEthernet>
<name xmlns:nc='urn:ietf:params:xml:ns:netconf:base:1.0'>{{ INTERFACE_INDEX }}</name>
<ip>
<address>
<primary>
<address>{{ IP_ADDRESS }}</address>
<mask>{{ SUBNET_MASK }}</mask>
</primary>
</address>
</ip>
</GigabitEthernet>
</interface>
</native>

The first three examples used CLI configuration. Ultra Config, however, is not limited to any specific configuration method. In this example, the markup will generate configuration for a NETCONF transaction.

Example 7

"Cisco-IOS-XE-native:GigabitEthernet": {
"ip": {
"address": {
"primary": {
"address": "{{ IP_ADDRESS }}",
"mask": "{{ SUBNET_MASK }}"
}
}
}
}

RESTCONF is a modern HTTP-based protocol for network management. In this example, the markup will generate configuration for a RESTCONF request.

These examples illustrate the most common features of Jinja2 that you'll encounter during template development.

Advanced users may wish to use more features of the Jinja2 language. For a detailed specification, check out the official Jinja2 docs.

4.6 Business Rules

Throughout the documentation, business rules are often mentioned. Business rules are at the core of conditional logic within the application. By utilizing the power of conditional logic, users can enforce all kinds of policies to show and hide form fields, configuration snippets, and input options.

A business rule will always evaluate to either true or false based on the values of input variables. Business rules are written in the Jinja2 language, which makes the rules very readable.

Let's take a look at some examples.

Example 1

WAN_TYPE == 'VDSL'

In this example, the expression will only evaluate to true if the WAN_TYPE variable is equal to VDSL.

Example 2

WAN_TYPE != 'VDSL'

In this example, the expression will only evaluate to true if the WAN_TYPE variable is not equal to VDSL.

Example 3

LICENSE == 'Advanced' and ENABLE_SHAPING == 'Yes'

In this example, the expression will only evaluate to true if both the LICENSE variable is set to Advanced and the ENABLE_SHAPING variable is set to Yes.

Example 4

LICENSE == 'Advanced' or ENABLE_SHAPING == 'Yes'

In this example, the expression will only evaluate to true if either the LICENSE variable is set to Advanced or the ENABLE_SHAPING variable is set to Yes.

Example 5

(LICENSE == 'Advanced' or ENABLE_SHAPING == 'Yes') and (WAN_TYPE == 'VDSL')

In this example, the expression will only evaluate to true if both the conditions in Example 1 and Example 4 are true. This example illustrates the use of parenthesis to nest expressions.

These examples conclude the documentation for the template editor. Armed with this information, you may now proceed to design and develop templates. If you have any questions, please lodge an enquiry with our support team.

Proceed to Next Page