Skip to main content

Create object templates from NetBox device types

Prompt an AI coding assistant to convert NetBox device types into Infrahub object templates, so every device you create from one starts with its interfaces already in place. Use it to import the device types from your own NetBox instance, or to seed Infrahub with vendor models from the published NetBox device type library.

Prerequisite

Requires an AI coding assistant with the Infrahub Skills installed, and infrahubctl configured against your instance. The bundled scripts need Python with PyYAML. Exporting from a running NetBox also needs pynetbox 7.0 or later and a NetBox API token with read access.

What it does​

Working from the NetBox Device Type Converter skill, your assistant runs two bundled Python scripts and reads what they report:

  • An exporter reads device types and module types from a running NetBox over its REST API, and writes them as files in the devicetype-library format.
  • A converter turns files in that format into Infrahub object YAML, driven by a mapping file that names the kinds, attributes, and relationships of your schema.

Infrahub stores a NetBox device type as several objects rather than one, so each input file produces several outputs:

NetBoxInfrahubWhy
manufacturerOrganizationManufacturer objectManufacturers are objects in their own right
model, part_number, u_height, weightDcimDeviceType objectModel data belongs to the device type, not the template
interfaces and other component listsTemplateDcimDevice with component templatesThe reusable definition you create devices from
Module types (line cards, power supplies, transceivers)DcimModuleType objectA second input family, converted in the same run with the module mapping file

Unmapped data is omitted from the generated YAML and listed in a coverage report. Your assistant explains each gap and proposes a mapping or schema change, but does not change your schema itself.

Choose between this and Infrahub Sync​

UseWhen
NetBox Device Type ConverterYou want the device type definitions as object templates. The result is a one-way snapshot into files you can read, diff, and keep in Git.
Infrahub SyncYou want NetBox records such as devices, sites, and prefixes replicated into Infrahub, and repeated on a schedule.

Import device types​

The commands below can be run by your assistant or manually. Run them from your project directory. Set SKILL to the installed skill directory:

SKILL="$PWD/.agents/skills/infrahub-converting-netbox-device-types"

This uses the project-local .agents/skills/ installation. If your installer used another directory, use the path shown by npx skills list.

Note: Keep exports, generated files, and custom mapping files outside the skill directory. Updating or reinstalling the skill can replace that directory.

1. Check that your schema generates templates​

Template kinds such as TemplateDcimDevice exist only for nodes that declare generate_template: true. When the flag is missing, the conversion produces files that have nothing to load into.

The infrahub/dcim schema on the Infrahub Marketplace already sets it on DcimDevice. The default mapping file targets that schema together with infrahub/organization. For module types, check the additional module schema requirements before continuing.

For a custom schema, your assistant checks the schema files, shows you the one-line change if the flag is missing, and waits for you to apply it. See Enable template support within the schema for what the flag generates.

2. Get the device types​

Export the device types you run from your own instance. The exporter reads the API token from NETBOX_TOKEN by default:

read -r -s NETBOX_TOKEN
export NETBOX_TOKEN

Enter your token when the command waits for input, then press Enter. It is hidden while you type.

Example prompt
Export the device types we use from https://netbox.example.com, including module types, and convert them into Infrahub object templates.

Your assistant runs the exporter:

python "$SKILL/scripts/netbox_export_device_types.py" \
--url https://netbox.example.com \
--in-use \
--module-types \
--output-dir ./netbox-export

The options control what the export includes and how it connects:

  • --in-use keeps only device types with at least one device, and module types with at least one module, going by the counts NetBox reports. On most instances this is a far smaller set than the full catalogue. A record for which NetBox reports no count is kept, and the report says how many.
  • --manufacturer restricts both device types and module types to a manufacturer slug. --slug restricts device types only, because module types have no slug.
  • --timeout sets the per-request timeout in seconds (default 30).
  • --insecure skips TLS verification for an instance with a self-signed certificate.

The export ends with a list of anything that did not transfer cleanly:

19 file(s) written to netbox-export

Not carried into the library format:
- AP7901: power-ports: 1 of 1 unset 'type', which the library schema requires

Read these notes before converting. They identify data the file format cannot represent and fields it requires that NetBox left empty. The export report reference explains every category of note, including unavailable endpoints and files removed from earlier exports. A failed run leaves the output directory unchanged.

3. Convert to object YAML​

Your assistant picks the mapping file that matches your schema. The skill includes four:

  • schema-library.yml converts device types with their interfaces.
  • schema-library-modules.yml also converts module bays and module types. See Module types and ports for its schema requirements.
  • schema-library-module-ports.yml also gives each module type a module template that holds its ports. See Module types and ports.
  • _template.yml is an annotated starting point for a custom schema. Your assistant copies it into your working directory, for example as ./mappings/my-schema.yml, and fills it in from your schema files. The converter refuses _template.yml until every placeholder kind is replaced.

Create a fresh output directory before each conversion:

OUTPUT_DIR=$(mktemp -d ./generated.XXXXXX)

Use the same OUTPUT_DIR for the conversion, report, and load steps. The converter does not remove old output files when a later run produces fewer kinds, so reusing a directory can load stale objects.

python "$SKILL/scripts/netbox_to_infrahub_templates.py" \
./netbox-export/ \
--mapping "$SKILL/scripts/mappings/schema-library-modules.yml" \
--output-dir "$OUTPUT_DIR" \
--report "$OUTPUT_DIR/coverage-report.md"

The NetBox command reads device-types/ and module-types/ together. The library command converts the Cisco model used in the examples below. Each command writes one file per kind into OUTPUT_DIR, numbered in dependency order. A mixed export can produce these files; kinds with no objects are omitted:

01_manufacturers.yml OrganizationManufacturer
02_device_types.yml DcimDeviceType
03_device_templates.yml TemplateDcimDevice
04_module_types.yml DcimModuleType

Interface component templates include the parent template's name so that names stay unique across vendors. This single-interface example shows the object YAML structure:

03_device_templates.yml
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: TemplateDcimDevice
data:
- template_name: cisco-c9300-48p
device_type: Catalyst 9300-48P
status: active
interfaces:
kind: TemplateInterfacePhysical
data:
- template_name: cisco-c9300-48p__GigabitEthernet1/0/1
name: GigabitEthernet1/0/1
status: active

The converter includes every mapped interface in the generated template.

4. Review the coverage report​

The coverage report lists, per device type, what the mapping file had nowhere to put:

coverage-report.md
### `cisco-c9300-48p`

- Dropped from `device_type`: `airflow`
- Dropped from `interfaces`: `poe_mode`, `poe_type`, `type`
  • Skipped means the mapping file maps a whole component list nowhere.
  • Dropped means the mapping file maps a field nowhere.
  • Shadowed means two NetBox fields compete for one attribute, and the fallback declared in the mapping file kept one of them.

A skipped list or dropped field has one of two causes: the mapping file has no entry for it, or your schema has no node or attribute to hold it. A console port, for example, often needs only a mapping entry, because many schemas already model it as an interface.

Against the default schema-library.yml mapping file, most NetBox component lists have no matching node, so a report full of unmapped entries is normal rather than an error. Your assistant names the largest losses, explains why each one could not be placed, and offers the mapping or schema change that closes it. Decide which gaps matter before you load; closing one later means extending the schema and running the conversion again.

5. Load onto a branch​

Load the files in order, onto a branch rather than the default branch:

(
set -e
infrahubctl branch create netbox-import
for file in "$OUTPUT_DIR"/0*.yml; do
infrahubctl object load "$file" --branch netbox-import
done
)

The command block stops at the first failure, including a failed branch creation. Each file references objects from the ones before it, so manufacturers load first, then device types, then templates. If loading fails, discard the partial branch as described under What to watch for.

6. Create a device and open a Proposed Change​

Create a device on netbox-import from one of the new templates to check the result. In the web interface, select the template when you add a device, as described in Use object templates. In an object file, reference the template by its template_name:

---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: DcimDevice
data:
- name: leaf-01
object_template: cisco-c9300-48p
location: par1
serial_number: FCW2140L0GH

This uses the Cisco template produced by the library example. If you exported from your own NetBox, choose a template from that export instead. location is mandatory on DcimDevice in the infrahub/dcim schema, and must reference a location that already exists on the branch.

The device is created with the interfaces defined in its template. When the templates look right, open a Proposed Change to merge the branch. See Proposed Changes for the review workflow.

What to watch for​

  • Weights are whole numbers. Infrahub has no decimal attribute kind, so the default mapping file rounds weight to whole kilograms, and hardware under 500 g becomes 0. Each one is named in the coverage report. Map weight to an attribute in grams instead if light hardware matters to you.
  • Modular chassis need the module mapping file. Their ports live in module bays, so with schema-library.yml they convert to templates with no interfaces. schema-library-modules.yml converts the bays themselves.
  • Two device types cannot share a model. A device template references its device type by model, so loading two device types with the same model would overwrite one with the other without an error. The converter refuses the run and lists every pair. Leave one of each pair out of the input. The published library has a few such pairs, shared between vendors.
  • Changing a template does not change existing devices. Changes to a template do not apply to devices already created from it, so loading a later conversion affects only the devices you create afterwards.
  • Loading is not transactional across files. If a file fails partway through, the branch keeps the earlier files and whatever part of the failing file loaded. Delete the branch and load again onto a new one.

Module types and ports​

To convert module types and module bays, use the schema-library main branch with its device_module extension loaded, and convert with schema-library-modules.yml. This creates module type objects and module bay templates. Module ports need the additional schema support below.

NetBox names module ports with a {module} token, such as Ethernet{module}/1, that depends on the bay the module is installed in. No conversion can resolve it, so with schema-library-modules.yml module ports are reported as skipped.

To keep them, your schema needs a module template, and the conversion needs the mapping file that fills it:

  1. Load the schema-library device_module and module_port extensions, then a schema extension that sets generate_template: true on DcimModule. This generates TemplateDcimModule and TemplateDcimModulePort.
  2. Convert with schema-library-module-ports.yml. Each module type gets a module template that holds its interfaces, console ports, and power ports as DcimModulePort declarations, with the {module} token kept in their names.
  3. Create each module from its template with object_template, and install it by setting its module_bay. A module created without object_template has no ports.
  4. Run the Generator bundled with the skill. For each installed module, it replaces {module} with the bay position and creates the device interfaces.

Only interface ports become device interfaces. Console ports need a console interface kind in your schema, and power ports stay declarations on the module. Use the module template schema extension, then follow the Generator registration and module installation instructions.