Expressions and loops
Expressions, filters, arithmetic and loops in a design.
Expressions
An expression is written in {{ }} inside a YAML string, and can stand for a whole value or part of one. The string must be quoted: name: {{ variables.site_name }} without quotes is a YAML mapping to YAML, not text, and the Add design dialog says so at that line.
| Pattern | Example | Gives |
|---|---|---|
| A variable | '{{ variables.site_name }}' | The variable's value |
| The containing object | '{{ parent }}' | The object that holds this one |
| A field of it | '{{ parent.site }}' | That object's site |
| The loop's variable | '{{ loop.i }}' | The current pass of the loop |
| A filter | '{{ loop.i | zeropad }}' | 01, 02 and so on |
| Arithmetic | '{{ loop.i * 2 - 1 }}' | A number worked out per pass |
| A function | "{{ nbd.lookup.endpoint('SW-01', 'Interface', 'eth0') }}" | The object the function finds |
| Part of a value | '{{ variables.rack_name }}-TOR-01' | Text with the value in it |
A function stands for the whole value: "{{ nbd.lookup.endpoint(...) }}" with nothing around it. Text around a function is refused, since what a function finds is an object, not text. A function's arguments can hold expressions of their own, which are worked out first. Write the outer string in double quotes so its arguments can be in single quotes, as in the compute rack's cables.
Filters
A filter follows a value after |, one to an expression:
| Filter | Does | Example |
|---|---|---|
zeropad | Pads a number to two digits | 7 becomes 07 |
zeropad(N) | Pads a number to N digits | zeropad(3) makes 7 into 007 |
lower | Lower-cases text | DC1 becomes dc1 |
upper | Upper-cases text | dc1 becomes DC1 |
slugify | Makes a NetBox slug: lower-case letters and digits joined by single hyphens | Store 001 (US-West) becomes store-001-us-west |
host(N) | The Nth address of a prefix, written with the prefix's length, for an IP address's address | 10.0.0.8/31 | host(1) becomes 10.0.0.9/31 |
Any other filter, or two in one expression, refuses the render.
When an expression can't be worked out
An expression the render can't resolve refuses the render, naming the object and the field: a loop's variable outside its loop, a variable the design doesn't declare, or a chain of filters.
Braces that aren't one of these expressions are text, and NetBox gets them as written. A config template's own {{ device.name }} is text the design means.
Loops
nbd_loop repeats an object, or a group of objects, once per pass:
devices:
- nbd_loop:
over: {start: 1, end: 10}
as: i
infra_type: Device
name: 'SERVER-{{ loop.i | zeropad }}'over takes:
| Form | Passes |
|---|---|
{start: 1, end: 10} | 1 to 10, both included |
3 | 1 to 3 |
[red, green, blue] | Each item, in order |
'{{ variables.shelf_count }}' | As the variable says: a count, a {start, end} mapping, or a list |
A bound may be one of the design's variables, so one design covers a rack with six power shelves and one with eight: over: {start: 1, end: '{{ variables.shelf_count }}'} with shelf_count declared under variables and given on the deploy. Only the design's variables can set a bound: the loop expands before its own loop.*, the parent object or any function exists, and a bound naming those is refused saying so. A value that is not a whole number is refused too, naming the loop.
as names the loop's variable. Inside the loop, with as: i:
| Variable | Is |
|---|---|
loop.i | The pass number, or for a list, the item |
loop.index | The pass, counting from 1 |
loop.index0 | The pass, counting from 0 |
loop.first, loop.last | Whether this is the first or last pass |
loop.length | How many passes there are |
To repeat several objects together, list them under items:
cables:
- nbd_loop:
over: {start: 1, end: 3}
as: i
items:
- infra_type: Cable
label: 'CABLE-A-{{ loop.i }}'
- infra_type: Cable
label: 'CABLE-B-{{ loop.i }}'A loop can also repeat an included design: put design: and template_vars: beside nbd_loop, as the compute rack does for its servers.