netbox-inventory-toolkit 0.1.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- netbox_inventory_toolkit-0.1.6/LICENSE +21 -0
- netbox_inventory_toolkit-0.1.6/PKG-INFO +186 -0
- netbox_inventory_toolkit-0.1.6/README.md +152 -0
- netbox_inventory_toolkit-0.1.6/pyproject.toml +60 -0
- netbox_inventory_toolkit-0.1.6/setup.cfg +4 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/__init__.py +8 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/__main__.py +6 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/cli.py +49 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/__init__.py +1 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/__main__.py +6 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/build.py +488 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/cli.py +236 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/config.py +69 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/context.py +80 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/hardware.py +312 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/identity.py +143 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/log.py +58 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/manual.py +117 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/pipeline.py +205 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/process.py +60 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/render.py +43 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/snmp_merge.py +813 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/__init__.py +1 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/base.py +57 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/ipmi.py +320 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/redfish.py +318 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/snmp.py +394 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/snmp_oids.py +141 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/talos.py +321 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/collect/sources/unifi.py +475 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/__init__.py +1 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/choices.py +614 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/fields.py +710 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/index.py +2011 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/keys.py +102 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/problems.py +76 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/racks.py +350 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/schema.py +38 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/inventory/util.py +106 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/lsp.py +375 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/__init__.py +1 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/__main__.py +6 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/api.py +57 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/catalog.py +366 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/cli.py +185 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/context.py +222 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/devices.py +405 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/dtl.py +311 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/images.py +206 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/inventory.py +298 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/meta.py +364 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/network.py +161 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/prune.py +230 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/reconciler.py +46 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/templates.py +89 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit/sync/validate.py +902 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/PKG-INFO +186 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/SOURCES.txt +74 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/dependency_links.txt +1 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/entry_points.txt +2 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/requires.txt +15 -0
- netbox_inventory_toolkit-0.1.6/src/netbox_inventory_toolkit.egg-info/top_level.txt +1 -0
- netbox_inventory_toolkit-0.1.6/tests/test_build_devices.py +76 -0
- netbox_inventory_toolkit-0.1.6/tests/test_catalog.py +206 -0
- netbox_inventory_toolkit-0.1.6/tests/test_collect_pipeline.py +214 -0
- netbox_inventory_toolkit-0.1.6/tests/test_collector_logging.py +46 -0
- netbox_inventory_toolkit-0.1.6/tests/test_identity.py +67 -0
- netbox_inventory_toolkit-0.1.6/tests/test_inventory_lint.py +412 -0
- netbox_inventory_toolkit-0.1.6/tests/test_ipmi.py +174 -0
- netbox_inventory_toolkit-0.1.6/tests/test_ownership.py +132 -0
- netbox_inventory_toolkit-0.1.6/tests/test_redfish.py +80 -0
- netbox_inventory_toolkit-0.1.6/tests/test_snmp.py +324 -0
- netbox_inventory_toolkit-0.1.6/tests/test_sources.py +64 -0
- netbox_inventory_toolkit-0.1.6/tests/test_sync_images.py +226 -0
- netbox_inventory_toolkit-0.1.6/tests/test_sync_inventory.py +34 -0
- netbox_inventory_toolkit-0.1.6/tests/test_unifi_mapping.py +35 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Blalange
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: netbox-inventory-toolkit
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: Collect, validate and reconcile a YAML inventory into NetBox
|
|
5
|
+
Author: Blalange
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/Blalange/netbox-inventory-toolkit
|
|
8
|
+
Project-URL: Issues, https://github.com/Blalange/netbox-inventory-toolkit/issues
|
|
9
|
+
Keywords: netbox,inventory,dcim,ipam,snmp,ipmi,yaml
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: System :: Systems Administration
|
|
18
|
+
Requires-Python: <3.14,>=3.12
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: pynetbox>=7.9.0
|
|
22
|
+
Requires-Dist: PyYAML>=6.0.3
|
|
23
|
+
Requires-Dist: requests>=2.32.5
|
|
24
|
+
Provides-Extra: snmp
|
|
25
|
+
Requires-Dist: pysnmp==7.1.22; extra == "snmp"
|
|
26
|
+
Provides-Extra: lsp
|
|
27
|
+
Requires-Dist: pygls<3,>=2.1; extra == "lsp"
|
|
28
|
+
Requires-Dist: lsprotocol; extra == "lsp"
|
|
29
|
+
Provides-Extra: all
|
|
30
|
+
Requires-Dist: pysnmp==7.1.22; extra == "all"
|
|
31
|
+
Requires-Dist: pygls<3,>=2.1; extra == "all"
|
|
32
|
+
Requires-Dist: lsprotocol; extra == "all"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# netbox-inventory-toolkit
|
|
36
|
+
|
|
37
|
+
Collect a declarative YAML inventory from optional live sources, validate it,
|
|
38
|
+
and reconcile it into [NetBox](https://netbox.dev).
|
|
39
|
+
|
|
40
|
+
The toolkit is deliberately source-agnostic. UniFi, SNMP, Talos, Redfish and
|
|
41
|
+
IPMI are optional adapters; an inventory that only uses SNMP and IPMI works
|
|
42
|
+
without UniFi, and a manual-only inventory works without any live source.
|
|
43
|
+
|
|
44
|
+
## What it includes
|
|
45
|
+
|
|
46
|
+
- **Collector** — merges live observations into a generated inventory layer.
|
|
47
|
+
- **Sync** — reconciles the manual + generated layers into NetBox over the REST
|
|
48
|
+
API, with optional Device Type Library enrichment and image uploads.
|
|
49
|
+
- **Language server** — diagnostics, completion, go-to-definition, hover and
|
|
50
|
+
rename for inventory YAML.
|
|
51
|
+
- **VS Code extension** — a thin client for the language server.
|
|
52
|
+
|
|
53
|
+
## Install
|
|
54
|
+
|
|
55
|
+
Use `uv` to run a pinned revision without installing anything globally:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
uvx --from "netbox-inventory-toolkit[all] @ git+https://github.com/Blalange/netbox-inventory-toolkit@v0.1.6" \
|
|
59
|
+
netbox-inventory-toolkit --help
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Or install it as a package from [PyPI](https://pypi.org/project/netbox-inventory-toolkit/):
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
pip install "netbox-inventory-toolkit[all]"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Tagged releases are published to PyPI from the `release.yml` workflow using
|
|
69
|
+
PyPI trusted publishing. The trusted publisher is configured for this
|
|
70
|
+
repository, workflow `release.yml`, and environment `pypi`.
|
|
71
|
+
|
|
72
|
+
## Quick start: SNMP + IPMI only
|
|
73
|
+
|
|
74
|
+
The repository contains a minimal example inventory with one SNMP switch and
|
|
75
|
+
one IPMI server:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
netbox-inventory-toolkit check --inventory examples/minimal --no-dtl
|
|
79
|
+
netbox-inventory-toolkit collect --inventory examples/minimal --sources snmp,ipmi
|
|
80
|
+
netbox-inventory-toolkit sync --inventory examples/minimal --check --no-dtl
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The collector reads `snmp_ip` and `ipmi_ip` from manual device entries. No
|
|
84
|
+
UniFi controller or Kubernetes cluster is required.
|
|
85
|
+
|
|
86
|
+
## Commands
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
netbox-inventory-toolkit collect --inventory inventory [--sources auto|all|none|list]
|
|
90
|
+
netbox-inventory-toolkit sync --inventory inventory --check
|
|
91
|
+
netbox-inventory-toolkit sync --inventory inventory --dry-run --prune
|
|
92
|
+
netbox-inventory-toolkit lsp --inventory inventory
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`--sources auto` enables a source only when its configuration and credentials
|
|
96
|
+
are present. Explicitly selecting a source that is not configured is an error;
|
|
97
|
+
`auto` and `all` skip it with a warning.
|
|
98
|
+
|
|
99
|
+
## Optional sources
|
|
100
|
+
|
|
101
|
+
| Source | Configuration |
|
|
102
|
+
|---|---|
|
|
103
|
+
| UniFi | `UNIFI_URL`, `UNIFI_USER`, `UNIFI_PASS` or `--unifi-secret NAMESPACE/NAME` |
|
|
104
|
+
| SNMP | manual devices with `snmp_ip`; optional `--snmp-community` |
|
|
105
|
+
| Talos | a working `kubectl`, `--nodes-json`, and optional `--talosctl` |
|
|
106
|
+
| Redfish | manual devices with `redfish_ip`; `REDFISH_USER` / `REDFISH_PASS` |
|
|
107
|
+
| IPMI | manual devices with `ipmi_ip`; `ipmitool` and `IPMI_USER` / `IPMI_PASS` |
|
|
108
|
+
|
|
109
|
+
Optional Python extras:
|
|
110
|
+
|
|
111
|
+
- `snmp` adds `pysnmp`.
|
|
112
|
+
- `lsp` adds `pygls` and `lsprotocol`.
|
|
113
|
+
- `all` adds both.
|
|
114
|
+
|
|
115
|
+
## Inventory model
|
|
116
|
+
|
|
117
|
+
The inventory root contains:
|
|
118
|
+
|
|
119
|
+
```text
|
|
120
|
+
inventory/
|
|
121
|
+
├── manual/ # hand-maintained objects; wins over generated values
|
|
122
|
+
├── generated/ # collector output; do not edit
|
|
123
|
+
└── images/ # device-type images referenced from manual device types
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
See [docs/inventory-schema.md](docs/inventory-schema.md) for the schema,
|
|
127
|
+
natural keys and provenance tags.
|
|
128
|
+
|
|
129
|
+
## Container image
|
|
130
|
+
|
|
131
|
+
The release workflow publishes:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
ghcr.io/blalange/netbox-inventory-toolkit:v0.1.6
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The release workflow tries to make the GHCR package public. If it remains
|
|
138
|
+
private, either change the package visibility in the GitHub package settings or
|
|
139
|
+
add an `imagePullSecrets` entry with a token that has `read:packages`.
|
|
140
|
+
|
|
141
|
+
The image entrypoint is `netbox-inventory-toolkit` and the default command is
|
|
142
|
+
`sync`. Mount the inventory at `/inventory`, images at `/images`, and a writable
|
|
143
|
+
cache/media volume at `/media`:
|
|
144
|
+
|
|
145
|
+
```yaml
|
|
146
|
+
containers:
|
|
147
|
+
- name: sync
|
|
148
|
+
image: ghcr.io/blalange/netbox-inventory-toolkit:v0.1.6
|
|
149
|
+
command: ["netbox-inventory-toolkit", "sync"]
|
|
150
|
+
env:
|
|
151
|
+
- name: NETBOX_URL
|
|
152
|
+
value: http://netbox.netbox.svc.cluster.local
|
|
153
|
+
- name: NETBOX_TOKEN
|
|
154
|
+
valueFrom:
|
|
155
|
+
secretKeyRef:
|
|
156
|
+
name: netbox-secrets
|
|
157
|
+
key: api_token_full
|
|
158
|
+
- name: NETBOX_INVENTORY_DIR
|
|
159
|
+
value: /inventory
|
|
160
|
+
- name: NETBOX_IMAGES_DIR
|
|
161
|
+
value: /images
|
|
162
|
+
- name: DTL_CACHE_DIR
|
|
163
|
+
value: /media/dtl-cache
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
See [docs/sync.md](docs/sync.md) for the full CronJob example and options.
|
|
167
|
+
|
|
168
|
+
## Development
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
uv sync --extra all --group dev
|
|
172
|
+
uv run ruff check .
|
|
173
|
+
uv run pytest
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Package the VS Code extension:
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
cd editors/vscode/netbox-inventory-toolkit
|
|
180
|
+
npm ci
|
|
181
|
+
npm run package
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# netbox-inventory-toolkit
|
|
2
|
+
|
|
3
|
+
Collect a declarative YAML inventory from optional live sources, validate it,
|
|
4
|
+
and reconcile it into [NetBox](https://netbox.dev).
|
|
5
|
+
|
|
6
|
+
The toolkit is deliberately source-agnostic. UniFi, SNMP, Talos, Redfish and
|
|
7
|
+
IPMI are optional adapters; an inventory that only uses SNMP and IPMI works
|
|
8
|
+
without UniFi, and a manual-only inventory works without any live source.
|
|
9
|
+
|
|
10
|
+
## What it includes
|
|
11
|
+
|
|
12
|
+
- **Collector** — merges live observations into a generated inventory layer.
|
|
13
|
+
- **Sync** — reconciles the manual + generated layers into NetBox over the REST
|
|
14
|
+
API, with optional Device Type Library enrichment and image uploads.
|
|
15
|
+
- **Language server** — diagnostics, completion, go-to-definition, hover and
|
|
16
|
+
rename for inventory YAML.
|
|
17
|
+
- **VS Code extension** — a thin client for the language server.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
Use `uv` to run a pinned revision without installing anything globally:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
uvx --from "netbox-inventory-toolkit[all] @ git+https://github.com/Blalange/netbox-inventory-toolkit@v0.1.6" \
|
|
25
|
+
netbox-inventory-toolkit --help
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or install it as a package from [PyPI](https://pypi.org/project/netbox-inventory-toolkit/):
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
pip install "netbox-inventory-toolkit[all]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Tagged releases are published to PyPI from the `release.yml` workflow using
|
|
35
|
+
PyPI trusted publishing. The trusted publisher is configured for this
|
|
36
|
+
repository, workflow `release.yml`, and environment `pypi`.
|
|
37
|
+
|
|
38
|
+
## Quick start: SNMP + IPMI only
|
|
39
|
+
|
|
40
|
+
The repository contains a minimal example inventory with one SNMP switch and
|
|
41
|
+
one IPMI server:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
netbox-inventory-toolkit check --inventory examples/minimal --no-dtl
|
|
45
|
+
netbox-inventory-toolkit collect --inventory examples/minimal --sources snmp,ipmi
|
|
46
|
+
netbox-inventory-toolkit sync --inventory examples/minimal --check --no-dtl
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The collector reads `snmp_ip` and `ipmi_ip` from manual device entries. No
|
|
50
|
+
UniFi controller or Kubernetes cluster is required.
|
|
51
|
+
|
|
52
|
+
## Commands
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
netbox-inventory-toolkit collect --inventory inventory [--sources auto|all|none|list]
|
|
56
|
+
netbox-inventory-toolkit sync --inventory inventory --check
|
|
57
|
+
netbox-inventory-toolkit sync --inventory inventory --dry-run --prune
|
|
58
|
+
netbox-inventory-toolkit lsp --inventory inventory
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`--sources auto` enables a source only when its configuration and credentials
|
|
62
|
+
are present. Explicitly selecting a source that is not configured is an error;
|
|
63
|
+
`auto` and `all` skip it with a warning.
|
|
64
|
+
|
|
65
|
+
## Optional sources
|
|
66
|
+
|
|
67
|
+
| Source | Configuration |
|
|
68
|
+
|---|---|
|
|
69
|
+
| UniFi | `UNIFI_URL`, `UNIFI_USER`, `UNIFI_PASS` or `--unifi-secret NAMESPACE/NAME` |
|
|
70
|
+
| SNMP | manual devices with `snmp_ip`; optional `--snmp-community` |
|
|
71
|
+
| Talos | a working `kubectl`, `--nodes-json`, and optional `--talosctl` |
|
|
72
|
+
| Redfish | manual devices with `redfish_ip`; `REDFISH_USER` / `REDFISH_PASS` |
|
|
73
|
+
| IPMI | manual devices with `ipmi_ip`; `ipmitool` and `IPMI_USER` / `IPMI_PASS` |
|
|
74
|
+
|
|
75
|
+
Optional Python extras:
|
|
76
|
+
|
|
77
|
+
- `snmp` adds `pysnmp`.
|
|
78
|
+
- `lsp` adds `pygls` and `lsprotocol`.
|
|
79
|
+
- `all` adds both.
|
|
80
|
+
|
|
81
|
+
## Inventory model
|
|
82
|
+
|
|
83
|
+
The inventory root contains:
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
inventory/
|
|
87
|
+
├── manual/ # hand-maintained objects; wins over generated values
|
|
88
|
+
├── generated/ # collector output; do not edit
|
|
89
|
+
└── images/ # device-type images referenced from manual device types
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
See [docs/inventory-schema.md](docs/inventory-schema.md) for the schema,
|
|
93
|
+
natural keys and provenance tags.
|
|
94
|
+
|
|
95
|
+
## Container image
|
|
96
|
+
|
|
97
|
+
The release workflow publishes:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
ghcr.io/blalange/netbox-inventory-toolkit:v0.1.6
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The release workflow tries to make the GHCR package public. If it remains
|
|
104
|
+
private, either change the package visibility in the GitHub package settings or
|
|
105
|
+
add an `imagePullSecrets` entry with a token that has `read:packages`.
|
|
106
|
+
|
|
107
|
+
The image entrypoint is `netbox-inventory-toolkit` and the default command is
|
|
108
|
+
`sync`. Mount the inventory at `/inventory`, images at `/images`, and a writable
|
|
109
|
+
cache/media volume at `/media`:
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
containers:
|
|
113
|
+
- name: sync
|
|
114
|
+
image: ghcr.io/blalange/netbox-inventory-toolkit:v0.1.6
|
|
115
|
+
command: ["netbox-inventory-toolkit", "sync"]
|
|
116
|
+
env:
|
|
117
|
+
- name: NETBOX_URL
|
|
118
|
+
value: http://netbox.netbox.svc.cluster.local
|
|
119
|
+
- name: NETBOX_TOKEN
|
|
120
|
+
valueFrom:
|
|
121
|
+
secretKeyRef:
|
|
122
|
+
name: netbox-secrets
|
|
123
|
+
key: api_token_full
|
|
124
|
+
- name: NETBOX_INVENTORY_DIR
|
|
125
|
+
value: /inventory
|
|
126
|
+
- name: NETBOX_IMAGES_DIR
|
|
127
|
+
value: /images
|
|
128
|
+
- name: DTL_CACHE_DIR
|
|
129
|
+
value: /media/dtl-cache
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
See [docs/sync.md](docs/sync.md) for the full CronJob example and options.
|
|
133
|
+
|
|
134
|
+
## Development
|
|
135
|
+
|
|
136
|
+
```sh
|
|
137
|
+
uv sync --extra all --group dev
|
|
138
|
+
uv run ruff check .
|
|
139
|
+
uv run pytest
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Package the VS Code extension:
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
cd editors/vscode/netbox-inventory-toolkit
|
|
146
|
+
npm ci
|
|
147
|
+
npm run package
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "netbox-inventory-toolkit"
|
|
7
|
+
version = "0.1.6"
|
|
8
|
+
description = "Collect, validate and reconcile a YAML inventory into NetBox"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12,<3.14"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "Blalange" }]
|
|
13
|
+
keywords = ["netbox", "inventory", "dcim", "ipam", "snmp", "ipmi", "yaml"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: System Administrators",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: System :: Systems Administration",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"pynetbox>=7.9.0",
|
|
26
|
+
"PyYAML>=6.0.3",
|
|
27
|
+
"requests>=2.32.5",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
snmp = ["pysnmp==7.1.22"]
|
|
32
|
+
lsp = ["pygls>=2.1,<3", "lsprotocol"]
|
|
33
|
+
all = ["pysnmp==7.1.22", "pygls>=2.1,<3", "lsprotocol"]
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
netbox-inventory-toolkit = "netbox_inventory_toolkit.cli:main"
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://github.com/Blalange/netbox-inventory-toolkit"
|
|
40
|
+
Issues = "https://github.com/Blalange/netbox-inventory-toolkit/issues"
|
|
41
|
+
|
|
42
|
+
[dependency-groups]
|
|
43
|
+
dev = [
|
|
44
|
+
"pytest>=8",
|
|
45
|
+
"ruff>=0.8",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
testpaths = ["tests"]
|
|
53
|
+
|
|
54
|
+
[tool.ruff]
|
|
55
|
+
line-length = 100
|
|
56
|
+
target-version = "py312"
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint]
|
|
59
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
60
|
+
ignore = ["E501"]
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""NetBox inventory toolkit."""
|
|
2
|
+
|
|
3
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
__version__ = version("netbox-inventory-toolkit")
|
|
7
|
+
except PackageNotFoundError: # running from a source tree without installed metadata
|
|
8
|
+
__version__ = "0.1.6"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Command line entry point for the NetBox inventory toolkit."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from . import __version__
|
|
8
|
+
|
|
9
|
+
USAGE = """\
|
|
10
|
+
usage: netbox-inventory-toolkit <command> [options]
|
|
11
|
+
|
|
12
|
+
commands:
|
|
13
|
+
collect collect live source data into the generated inventory layer
|
|
14
|
+
sync reconcile the inventory into NetBox
|
|
15
|
+
check validate the inventory without contacting NetBox
|
|
16
|
+
lsp run the inventory language server (stdio)
|
|
17
|
+
version print the package version
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main(argv: list[str] | None = None) -> int:
|
|
22
|
+
args = list(sys.argv[1:] if argv is None else argv)
|
|
23
|
+
if not args or args[0] in {"-h", "--help", "help"}:
|
|
24
|
+
print(USAGE, end="")
|
|
25
|
+
return 0
|
|
26
|
+
if args[0] in {"--version", "version"}:
|
|
27
|
+
print(f"netbox-inventory-toolkit {__version__}")
|
|
28
|
+
return 0
|
|
29
|
+
|
|
30
|
+
command, rest = args[0], args[1:]
|
|
31
|
+
if command == "collect":
|
|
32
|
+
from .collect.cli import main as collect_main
|
|
33
|
+
|
|
34
|
+
return collect_main(rest)
|
|
35
|
+
if command in {"sync", "check"}:
|
|
36
|
+
from .sync.cli import main as sync_main
|
|
37
|
+
|
|
38
|
+
return sync_main([*rest, "--check"] if command == "check" else rest)
|
|
39
|
+
if command == "lsp":
|
|
40
|
+
from .lsp import main as lsp_main
|
|
41
|
+
|
|
42
|
+
return lsp_main(rest)
|
|
43
|
+
|
|
44
|
+
print(f"error: unknown command {command!r}\n\n{USAGE}", file=sys.stderr, end="")
|
|
45
|
+
return 2
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Inventory collection pipeline."""
|