New: draw a network as text and trace a packet through it hop by hop.Open the routing simulator

Config Automation Workbench

betaFrom vendor documentation

Render one Jinja-style template against an inventory of devices and get the full configuration for every one of them, then diff the result against what a device is already running before you push it.

Inventory

3 devices · BLOCKS format

Columns name, role, mgmt_ip, loopback, uplink, peer_name, peer, gateway, mgmt_acl, vlan, vlans

Template

Jinja-style, rendered once per device

Variables this template reads

gateway, group, loopback, mgmt_acl, name, peer, peer_name, role, uplink, vlan, vlans

Filters and syntax reference

Network filters

ip_network
Network address of an address or CIDR. "10.20.31.11/24" → 10.20.31.0
ip_cidr
Network address with the prefix kept. "10.20.31.11/24" → 10.20.31.0/24
ip_broadcast
Last address in the block. "10.20.31.11/24" → 10.20.31.255
ip_next / ip_prev
The neighbouring address, carried across octets. "192.168.1.255" | ip_next → 192.168.2.0
netmask
Dotted mask for a prefix length or a CIDR. 24 | netmask → 255.255.255.0
wildcard
Bitwise inverse of the mask, for ACLs. "10.20.0.0/16" | wildcard → 0.0.255.255
mac_cisco
Any MAC notation to Cisco dotted. "00:11:22:33:44:55" → 0011.2233.4455
vlan_range
Compact list of VLAN ids. [120,121,122,130] → 120-122,130

Syntax

{{ value }}
Substitute. An undefined name renders empty and is reported below.
{% if %} … {% elif %} … {% else %} … {% endif %}
Conditionals. `false`, `0` and `""` are all false.
{% for x in list %} … {% else %} … {% endfor %}
Loops. `loop.index`, `loop.first`, `loop.last` are available; `{% else %}` runs when the list is empty.
{% set name = value %}
Assignment. A counter set outside a loop survives it.
{{- value -}}
Trim the whitespace on that side. `{%-` works on block tags too.
a ~ b
String concatenation. `+` is arithmetic only — `1 + 1` is 2, not "11".
x | default("none")
Filters chain left to right, as in Jinja.

Same filters, other spellings

  • ip_netmask — the same as netmask
  • ip_wildcard — the same as wildcard
  • mac_colon — the same as mac_cisco

What is deliberately missing

Template inheritance, macros, import, with, raw and custom tests are not implemented. An unsupported tag is reported by name rather than ignored.

Run

Live — every keystroke re-renders every device

Devices parsed
3
Configs rendered
3
Template errors
0

core-1

Group core

core-1 — generated
! core-1 — generated from the inventory, group core
hostname core-1
!
interface Loopback0
 description core loopback
 ip address 10.255.0.1 255.255.255.255
!
interface GigabitEthernet0/1
 description uplink to core-2 (10.20.28.2)
!
ip route 0.0.0.0 0.0.0.0 10.20.28.254
!
ip access-list standard MGMT
 permit 10.20.0.0 0.0.255.255
!
interface GigabitEthernet0/1
 description spare
 shutdown
!
interface GigabitEthernet0/2
 description spare
 shutdown
!
end

Frequently asked

Is this real Jinja2?
It is a documented subset, written from scratch inside the calculation kernel. Output, comments, if/elif/else, for/else, set, filters and the whitespace markers behave as Jinja does. Template inheritance, macros, import, with and raw are not implemented, and an unsupported tag is reported by name rather than silently ignored.
What can a template do that a plain text substitution cannot?
Address arithmetic. The filters include ip_network, ip_broadcast, ip_next, ip_prev, netmask, wildcard, mac_cisco and vlan_range, so a template can derive a gateway, a wildcard mask for an ACL, or a compact VLAN list from the inventory rather than requiring every derived value to be written out by hand.
Why does the diff ignore timestamps?
A show run transcript carries a byte count and two timestamps that change on every read. Diffing those raw reports them as the change and buries the lines that matter. Both sides are normalised first, and the interface states exactly what was removed.
Can I use this to push configuration to devices?
No, and it will not. The workbench generates text and diffs text; it never opens a connection. You copy or download the result and apply it with your own tooling, after reviewing the diff.
Is one device ever left out silently?
No. A device that fails to parse is listed with its line number, a template error stops the whole run and names the line, and a variable the inventory does not define is listed by name instead of rendering as an empty string.