3.7 KiB
NetBox Services Plugin
A NetBox plugin for declarative service templates with requirement trees.
DISCLAIMER: THIS PROJECT IS VIBE CODED USING AN LLM.
Overview
This plugin lets you define service templates that specify what NetBox resources a service requires, without attaching any resources to the template itself. Templates contain a requirement tree — a stacked, declarative description of what objects are needed (devices, interfaces, IP addresses, etc.) and how to select or allocate them.
One or more services are then spawned from these templates. When a service is resolved, the resolver engine walks the requirement tree, evaluates selectors and allocators against live NetBox data, and creates resource bindings that link the service to real NetBox objects.
Key Concepts
- ServiceTemplate — Reusable template with a declarative requirement tree stored as JSON (editable as YAML or JSON in the UI). Locked once any service instances are spawned from it.
- Service — A concrete instance spawned from a ServiceTemplate. Requires a tenant.
- ServiceResourceBinding — Internal model (hidden from UI) that links a service to a real NetBox object via a generic foreign key.
Tree Structure
The requirement tree is a list of nodes. Each node specifies:
| Field | Description |
|---|---|
name |
Unique name for the node |
object_type |
NetBox model as app_label.model_name (e.g. dcim.device) |
quantity |
How many objects to select/allocate (default: 1) |
selector |
How to find existing objects (see Selector Types) |
allocation |
How to create new objects (see Allocation Strategies) |
scope |
service (resolve once) or parent (resolve per selected parent) |
children |
List of child nodes (recursive) |
A node must have either a selector or an allocation (not both).
Selector Types
| Type | Description |
|---|---|
netbox_filter |
Apply NetBox filter parameters to find existing objects |
reference |
Resolve a dotted context path (e.g. parent.site) |
prefix |
Find ipam.Prefix objects by filter or reference |
Allocation Strategies
| Strategy | Description |
|---|---|
first_free |
Allocate the first available IP from a resolved prefix |
specific |
Use a specific object by address or context path |
Reconciliation
When a service is re-resolved, the resolver performs set reconciliation:
- Objects in the new plan but not currently bound → added
- Objects currently bound but not in the new plan → removed (binding only; the underlying NetBox object is not deleted)
- Objects in both → kept unchanged
For allocation nodes, existing bound objects of the same type are reused before allocating new ones (avoids duplicate IPs on re-resolve).
Quick Start
cd dev/
podman-compose up -d
Access at http://localhost:8001 (admin/admin).
Example
A service template for "2 routers, each with a management IP from a prefix pool":
- name: routers
object_type: dcim.device
quantity: 2
selector:
type: netbox_filter
filters:
role: router
scope: service
children:
- name: mgmt-ip
object_type: ipam.ipaddress
quantity: 1
allocation:
strategy: first_free
prefix:
type: prefix
filters:
site: hq
tag: mgmt
scope: parent
REST API
GET/POST /api/plugins/services/service-templates/— CRUD for templatesGET/POST /api/plugins/services/services/— CRUD for servicesPOST /api/plugins/services/services/<id>/resolve/— Resolve a service- Body:
{"mode": "dry_run"}or{"mode": "commit"}
- Body:
License
MIT