NetBox Device Type Converter

SkillDev tools

Converts NetBox device-type and module-type definitions (the netbox-community devicetype-library format, also published via the NetBox Data Exchange / NDX) into Infrahub object templates as Infrahub object YAML, using a bundled Python converter driven by a schema mapping profile. TRIGGER when: importing NetBox device types or module types into Infrahub, converting devicetype-library YAML, building object templates from vendor device models, seeding Infrahub with device types from NDX, converting line cards / PSUs / transceivers from NetBox module types, turning NetBox hardware definitions into Template* objects. DO NOT TRIGGER when: importing CSV/TSV data (use infrahub-importing-data), authoring schemas from scratch (use infrahub-managing-schemas), writing ordinary object data files (use infrahub-managing-objects), or syncing live NetBox instances (that is infrahub-sync, a separate product).

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the NetBox Device Type Converter skill

What this skill tells your AI

The instructions your AI receives, as published by opsmill/infrahub-skills in skills/infrahub-converting-netbox-device-types/SKILL.md and read by ahel’s review.

Overview

Turns NetBox device-type YAML — the format used by netbox-community/devicetype-library and browsable at the NetBox Data Exchange — into Infrahub object templates: reusable blueprints that create a device with all its ports already in place.

The conversion is done by a bundled Python script, not by hand. Hand-converting a 48-port switch means transcribing 48 near-identical blocks, and the library has thousands of device types. The script is exact and repeatable; this skill is about pointing it at the right schema and reading what it tells you.

Project Context

Target schema files: !find . -name "*.yml" -path "*schema*" 2>/dev/null | head -10

Existing mapping profiles: !find . -name "*.yml" -path "*mappings*" 2>/dev/null | head -10

When to Use

  • Seeding a new Infrahub instance with vendor device models from the NetBox library
  • Converting a handful of device types for a specific project or lab topology
  • Re-running a conversion after the upstream library or the local schema changed
  • Building the mapping profile that binds NetBox fields to a custom Infrahub schema

Not for syncing a live NetBox instance into Infrahub — that is infrahub-sync, a separate product. This skill converts the static YAML definitions.

The Shape of the Conversion

One NetBox file becomes three Infrahub artifacts, because Infrahub splits what NetBox keeps together:

NetBoxInfrahubWhy
manufacturer: CiscoOrganizationManufacturer objectManufacturers are first-class objects
model, part_number, u_height, weightDcimDeviceType objectTemplates hold no model data
interfaces: and other component listsTemplateDcimDevice + component templatesThe reusable blueprint

The template links to the device type, so creating a device from the template also wires up its model.

Module types are a second input family — line cards, PSUs, and transceivers, in a sibling module-types/ directory. They carry no slug, which is how the converter tells the two apart, so a mixed tree converts in one pass. They follow the same split (a module type object, optionally a module template) and land in 04_module_types.yml / 05_module_templates.yml. Read extending-your-schema.md before promising much here: against the stock schema-library a module type has no component relationships, so its ports do not convert.

Module port names carry NetBox's {module} token, which no conversion can resolve — the bay position is only known once the module is installed. Once the schema-library module extensions are loaded so the ports import as DcimModulePort declarations, the bundled generator resolves the token per installed module and creates the real device interfaces. See generators-module-ports.md.

Three facts drive almost every surprise in this workflow — explain them rather than assuming them:

  1. Template* kinds are generated, not written. generate_template: true on a node creates them; without it they do not exist.
  2. Component templates come only from Component relationships. An Attribute relationship keeps pointing at real objects.
  3. Model data lives on the device type, not the template. That is why three files, in that order.

New to Infrahub's data model, or explaining it to someone who is? concepts.md covers these with links to the Infrahub docs.

Rule Categories

PriorityCategoryPrefixDescription
CRITICALWorkflowworkflow-generate_template must be enabled first
CRITICALMappingmapping-Names come from the schema, never guessed; competing fields declare precedence
CRITICALFormatformat-Envelope, Template<Kind>, nested components
HIGHNamingnaming-Slug-based, parent-namespaced, unique
HIGHCoveragecoverage-Report what did not convert
MEDIUMOutputoutput-Three files, load order, branch-first

Full index: rules/_sections.md.

Workflow

1. Confirm the schema generates templates

Template* kinds exist only where a node declares generate_template: true. Check the target schema rather than assuming either way — this is the most common reason a conversion loads nothing.

In the OpsMill schema-library the answer depends on the version: v2 and later enable it on DcimDevice in base/dcim.yml, while pre-v2 shipped the line commented out. Custom schemas usually have to add it.

Read rules/workflow-schema-prerequisites.md.

If it is not enabled, explain the change rather than making it silently: the flag generates TemplateDcimDevice plus a component template for every Component relationship, it is additive, and the schema has to be reloaded for the kinds to appear. Enabling it touches the user's source of truth, so it is their call — show the one-line diff and let them decide.

Docs: Object Templates overview · Create and load a schema

2. Choose or write a mapping profile

The converter binds NetBox fields to Infrahub attributes through a profile, so it never guesses a name.

  • Using the OpsMill schema-library? Start with scripts/mappings/schema-library.yml, or scripts/mappings/schema-library-modules.yml if you also want module types.
  • Custom schema? Copy scripts/mappings/_template.yml and fill it in by reading the schema YAML, kind by kind and attribute by attribute.

Read rules/mapping-profile-driven.md and reference.md for the full field inventory on both sides. Where two NetBox fields compete for one Infrahub attribute — description vs comments, interface label vs description — declare precedence with fallback rather than picking one and losing the other; see rules/mapping-fallback-sources.md.

Check for a node that already covers a gap before concluding one is missing. A console port is often modelled as a node inheriting the interface generic, in which case it rides the device's existing interfaces relationship and needs no schema change at all — only a profile entry. When two lists share one relationship, read rules/mapping-shared-relationships.md: getting that wrong discards the larger list silently. extending-your-schema.md lists what schema-library and infrahub-demo-dc already provide.

3. Get the input

The library is a git repo; NDX is its browsable front end. There is no public bulk API, so clone it — but sparsely. A plain --depth 1 clone pulls 1.6 GB, almost all of it rack elevation images the converter never reads. Restricting to device-types/ gets the same 5,900+ definitions in 29 MB:

git clone --depth 1 --filter=blob:none --sparse \
  https://github.com/netbox-community/devicetype-library.git
cd devicetype-library
git sparse-checkout set device-types module-types

Drop module-types from that list if you only want devices.

The converter accepts files, directories (walked recursively), and globs.

4. Run the converter

python skills/infrahub-converting-netbox-device-types/scripts/netbox_to_infrahub_templates.py \
  devicetype-library/device-types/Cisco/ \
  --mapping skills/infrahub-converting-netbox-device-types/scripts/mappings/schema-library.yml \
  --output-dir ./generated \
  --report ./generated/coverage-report.md

Exit codes: 0 converted, 1 bad profile or malformed input, 2 no files matched.

Before writing or hand-editing any emitted file, read rules/format-template-objects.md — the envelope, the Template<Kind> split, and the {kind, data} component wrapper are what makes the output loadable — and rules/naming-template-names.md, because component names collide across device types unless they are namespaced by their parent.

5. Read the coverage report, explain the loss, offer the fix

Against a typical schema, a large part of each NetBox file has nowhere to go. Open the report and, in the response:

  1. Name the biggest losses — which component lists and which fields, with counts. Do not just say a report exists.
  2. Explain why the schema could not hold them. "Skipped console-ports" is unactionable to someone who does not know component templates come only from Component relationships. Give the reason.
  3. Offer the concrete fix. A dropped field is one attribute; a skipped list is a node plus a Component/Parent pair. Both are additive. extending-your-schema.md has worked YAML per case, including which schema-library extensions already cover some of them.

Offer — do not unilaterally rewrite their schema. It is a migration against their source of truth.

Read rules/coverage-report-unmapped.md.

Two cases worth flagging by name when they apply:

  • Modular chassis — their ports live in module bays, so 13.5% of the published library converts to a template with no interfaces. On schema-library v2 the bays themselves convert (TemplateDcimModuleBay), which turns an empty template into a useful one; the schema-library-modules.yml profile maps them. On pre-v2, or a schema with no bay node, they are still reported as skipped. See extending-your-schema.md.
  • Console ports are usually a profile change, not a schema change — if the schema models them as a node inheriting the interface generic, they already ride the interfaces relationship.

6. Load onto a branch

infrahubctl branch create netbox-import
for file in generated/0*.yml; do
  infrahubctl object load "$file" --branch netbox-import
done

Load order is dependency order — manufacturers, then device types, then templates. Read rules/output-load-order.md. Never load a bulk import straight to the default branch.

Extending the Converter

Reach for the mapping profile first — it covers new kinds, renamed attributes, extra component lists, and conditional values without touching Python. Change the script only for a genuinely new mechanism (a transform kind that does not exist yet). Adding a schema-specific special case to the script is how it stops working for everyone else.

Its tests live at tests/scripts/test_netbox_to_infrahub_templates.py, and the module-port generator's at tests/scripts/test_materialize_module_ports.py. Run them after any change:

uv run invoke test

Supporting References

FileRead it when
concepts.mdThe Infrahub model is unfamiliar, or you need to explain it
extending-your-schema.mdTurning a reported gap into a schema change
generators-module-ports.mdModule ports imported as declarations and the {module} token needs resolving into real device interfaces
reference.mdLooking up a NetBox field or its Infrahub counterpart
examples.mdNeeding a worked conversion, profile, or schema patch
rules/Applying or checking a specific rule
../infrahub-managing-objects/rules/value-profiles-templates.mdAuthoring templates by hand, or choosing profiles vs templates
../infrahub-managing-schemas/rules/relationship-component-parent.mdAdding the component relationships templates are generated from

Infrahub Documentation

Link these when explaining a concept — a user who follows one link learns the feature, not just this conversion.

TopicPage
What object templates arehttps://docs.infrahub.app/object-templates/overview
Enabling and using themhttps://docs.infrahub.app/object-templates/use
Templates plus Profileshttps://docs.infrahub.app/object-templates/with-profiles
Per-object unique valueshttps://docs.infrahub.app/object-templates/allocate-resources-from-pools
Nodes and attributeshttps://docs.infrahub.app/schema/nodes-and-attributes
Relationships (Component vs Attribute)https://docs.infrahub.app/schema/relationships
Generics and inheritancehttps://docs.infrahub.app/schema/generics-and-inheritance
Extending a schema without forking ithttps://docs.infrahub.app/schema/extensions
Loading a schemahttps://docs.infrahub.app/schema/create-and-load
Schema migrations and their riskshttps://docs.infrahub.app/schema/migration
Schema property referencehttps://docs.infrahub.app/reference/schema/node
Profiles vs templateshttps://docs.infrahub.app/profiles/overview
Schema from scratch (tutorial)https://docs.infrahub.app/academy/tutorials/build-your-first-schema
Generators (resolving {module} after install)https://docs.infrahub.app/generators/overview

Signals

GitHub stars
26
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
infrahub-converting-netbox-device-types
Source
github.com/opsmill/infrahub-skills