117 lines
3.7 KiB
Markdown
117 lines
3.7 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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":
|
|
|
|
```yaml
|
|
- 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 templates
|
|
- `GET/POST /api/plugins/services/services/` — CRUD for services
|
|
- `POST /api/plugins/services/services/<id>/resolve/` — Resolve a service
|
|
- Body: `{"mode": "dry_run"}` or `{"mode": "commit"}`
|
|
|
|
## License
|
|
|
|
MIT
|