Design structure
The parts of a design, how its values are read, and how its objects match NetBox's.
A design is a YAML mapping with these keys:
name: Site Foundation
description: A site in a country, with a /16 supernet for its subnets.
netbox_versions: ["4.6.*", "4.7.*"]
variables:
site_name: $USER
status: active
infra:
- infra_type: Site
name: '{{ variables.site_name }}'
slug: '{{ variables.site_name | slugify }}'
status: '{{ variables.status }}'| Key | Required | Holds |
|---|---|---|
name | Yes | The design's title. Other designs refer to it by its catalogue name, not this |
description | No | What the design builds |
netbox_versions | Yes | The NetBox versions the design works with |
variables | Yes | The design's inputs and computed values; {} for none. See Variables |
infra | Yes | The objects the design builds |
netbox_versions
Designs refuses to plan a design against a NetBox whose version it doesn't list, and the catalogue refuses a design without the key. The value is "*", for a design that works with any version, or a list of version specifiers:
| Declaration | Matches |
|---|---|
"*" | Any NetBox version |
["4.7.*"] | Any 4.7 release |
["4.6.*", "4.7.*"] | Any 4.6 or 4.7 release |
[">=4.6,<4.8"] | 4.6.0 up to, but not including, 4.8.0 |
["4.7.0"] | Exactly 4.7.0 |
Objects
Each item in infra is an object. Its infra_type names the object type as NetBox's data model does, such as Site or DeviceType, and its other keys are the object's fields, as NetBox names them, such as site or device_type. Object types lists the types.
An object can hold other objects in a list under a key that isn't one of its fields, such as a region's regions, a site's racks, a rack's devices and cables, or a device's modules. Each item in the list is an object of its own, and inside it {{ parent }} refers to the object that holds it:
- infra_type: Site
name: DC1
slug: dc1
status: active
racks:
- infra_type: Rack
name: RACK-01
site: '{{ parent }}'
status: activeFields and empty values
A design owns only the fields it writes. A field you leave out is left alone in NetBox: it's never reported as drift and never written, even when NetBox gives it a default.
| You write | It means |
|---|---|
description: "Uplink" | Set the field |
description: "" | Clear a text field |
region: | Null, because an empty YAML value is null. Clears a field NetBox allows to be null, such as a reference |
| The field left out | Leave the field alone |
serial: '{{ variables.serial }}', where serial is a $USER_OPTIONAL variable you didn't give | Left out, as if the line weren't there |
The render refuses a value NetBox wouldn't keep as written, before a plan exists, and says what to write instead. The rules come from the data model of your NetBox's version:
- A null NetBox refuses, in most text fields:
description:with nothing after it. Write""to clear the field, or remove the line. - A blank NetBox refuses, such as
name: "". - A field NetBox drops without another set. NetBox removes an interface's
untagged_vlanunless itsmodeis set, and a rack'souter_unitunless an outer dimension is. - A value NetBox stores in another form. NetBox trims spaces from the ends of text, lower-cases an IP address's
dns_name, stores an empty VRFrdor asset tag as null, and writes MAC addresses in upper-case pairs joined by colons. Write the form the message gives. Acomments: |block ends in a newline NetBox strips: use|-.
A type from the Device Type Library isn't refused this way, because you can't edit it. Its values arrive as NetBox would store them.
References
A field that refers to another object accepts:
- Text, matched against that object's key, then its name, then its slug:
site: dc1,region: Latvia. When the object's key is one field, as a site's, a region's or a tenant's is, the text is resolved when you plan, against the objects in NetBox and in the design, and text that matches nothing, or more than one object, refuses the plan. When the key has several fields, as a device's name and site do, the text is resolved when you apply. - The object that holds this one, or one of its fields:
site: '{{ parent }}',site: '{{ parent.site }}'. - A mapping of its fields:
device: {name: SW-01}. The fields needn't be the object's key:group: {slug: branch-offices}names a site group, whose key is its name and parent, by its slug. A mapping that gives less than the key is resolved when you plan, against the objects in NetBox and in the design, and one that matches nothing, or more than one object, refuses the plan. - A function that finds it: see Functions.
A field that holds a list of references, such as tags or a VLAN group's scope-less vid_ranges, takes a list of any of these, and stays a field of the object rather than becoming children under it. An item written as an object, with an infra_type, is created by the design and referred to by the field:
- infra_type: Site
name: Acme APJ - Dunedin
slug: acme-apj-dunedin
status: active
tags:
- acme-apj
- {slug: branch-office}
- {infra_type: Tag, name: Dunedin, slug: dunedin}Fields that hold one of several types
Some fields hold an object of any of several types. An address's interface holds an interface, a VM interface or an FHRP group; a circuit termination's termination holds a site, a location, a region, a site group or a provider network; a cable's termination_a and termination_b hold any of the port types a cable can end on.
The plan reads which type a mapping means from its fields and from what NetBox and the design hold: interface: {name: xe-0/0/0, device: {name: RTR-01}} can only be an interface, and termination: {slug: hong-kong} is the site when a site has that slug and nothing else does. When a mapping could mean objects of two types, the plan is refused, naming both, and you say which you mean with _type:
- infra_type: CircuitTermination
circuit: {cid: ACME-HKG-01}
term_side: A
termination: {slug: acme-apj-hong-kong, _type: Site}_type takes the type's name as infra_type does. A _type the field can't hold refuses the render.
A cable ends on an interface, a front port, a rear port, a console port, a console server port, a power port, a power outlet, a power feed or a circuit termination. Its ends are its identity, so each end is a reference to a port the design or NetBox has, by function or by mapping:
- infra_type: Cable
status: connected
termination_a: "{{ nbd.lookup.endpoint('srv-01', 'PowerPort', 'psu1') }}"
termination_b: {name: feed-a, power_panel: {name: panel-1, site: {slug: dc1}}}Matching objects NetBox already has
A plan matches each object in the design with the object NetBox has under the same key. Each type's key is in Object types.
- A key field NetBox requires can be left out.
device: {name: SW-01}leaves out the device's site, and matches the one SW-01 whatever its site. When two sites each have an SW-01, the plan is refused, naming both. Add the site. - A key field NetBox allows to be empty means empty when left out. A prefix without
vrfis the global prefix, and a VLAN withoutgroupis the ungrouped one, which is also what NetBox stores when it creates them. - A device needs a name. Only its id tells one unnamed device from another, so the render refuses a design that declares one.