netbox-plugin-prometheus-sd 2.0.0__tar.gz → 2.1.0__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.
Files changed (19) hide show
  1. netbox_plugin_prometheus_sd-2.1.0/PKG-INFO +296 -0
  2. netbox_plugin_prometheus_sd-2.1.0/README.md +277 -0
  3. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/__init__.py +1 -1
  4. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/filtersets.py +9 -2
  5. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/test_filtersets.py +8 -2
  6. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/test_serializers.py +13 -2
  7. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/utils.py +18 -4
  8. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/pyproject.toml +1 -1
  9. netbox_plugin_prometheus_sd-2.0.0/PKG-INFO +0 -158
  10. netbox_plugin_prometheus_sd-2.0.0/README.md +0 -141
  11. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/LICENSE +0 -0
  12. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/api/__init__.py +0 -0
  13. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/api/serializers.py +0 -0
  14. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/api/urls.py +0 -0
  15. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/api/utils.py +0 -0
  16. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/api/views.py +0 -0
  17. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/__init__.py +0 -0
  18. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/test_api.py +0 -0
  19. {netbox_plugin_prometheus_sd-2.0.0 → netbox_plugin_prometheus_sd-2.1.0}/netbox_prometheus_sd/tests/test_utils.py +0 -0
@@ -0,0 +1,296 @@
1
+ Metadata-Version: 2.4
2
+ Name: netbox-plugin-prometheus-sd
3
+ Version: 2.1.0
4
+ Summary: A Netbox plugin to provide Netbox entires to Prometheus HTTP service discovery
5
+ License: MIT
6
+ License-File: LICENSE
7
+ Author: Felix Peters
8
+ Author-email: felix.peters@breuninger.de
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Description-Content-Type: text/markdown
18
+
19
+ # netbox-plugin-prometheus-sd
20
+
21
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
22
+ [![CI](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/workflows/CI/badge.svg?event=push)](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/actions?query=workflow%3ACI)
23
+ [![PyPI](https://img.shields.io/pypi/v/netbox-plugin-prometheus-sd)](https://pypi.org/project/netbox-plugin-prometheus-sd/)
24
+
25
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/flxpeters)
26
+
27
+ Provide Prometheus `http_sd` compatible API Endpoint with data from Netbox.
28
+
29
+ HTTP SD is a feature since Prometheus 2.28.0 that allows hosts to be found via a URL instead of just files.
30
+ This plugin implements API endpoints in Netbox to make devices, services, IPs and virtual machines available to Prometheus.
31
+
32
+ ## Compatibility
33
+
34
+ We aim to support the latest major versions of Netbox.
35
+
36
+ | Plugin | Netbox |
37
+ |---|---|
38
+ | `2.x` | `>= 4.0` |
39
+ | `1.x` | `3.x` (no longer maintained) |
40
+
41
+ Check the `.github/workflows/ci.yml` pipeline for the current tested builds.
42
+ Other versions may work, but we do not test them explicitly. All relevant target versions are tested in CI.
43
+
44
+ Plugin `2.0` also fixed a set of N+1 queries that made the endpoints very slow on
45
+ larger installations ([#265](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/issues/265)).
46
+ If service discovery is putting noticeable load on your Netbox database, upgrading
47
+ is worthwhile.
48
+
49
+ ## Installation
50
+
51
+ The plugin is available as a Python package in pypi and can be installed with pip
52
+
53
+ ```bash
54
+ pip install netbox-plugin-prometheus-sd
55
+ ```
56
+
57
+ Enable the plugin in /opt/netbox/netbox/netbox/configuration.py:
58
+
59
+ ```python
60
+ PLUGINS = ['netbox_prometheus_sd']
61
+ ```
62
+
63
+ The plugin has not further plugin configuration.
64
+
65
+ ## Usage
66
+
67
+ The plugin only provides a new API endpoint on the Netbox API. There is no further action required after installation.
68
+
69
+ ### API
70
+
71
+ The plugin reuses Netbox API view sets with new serializers for Prometheus.
72
+ This means that all filters that can be used on the Netbox API can also be used to filter Prometheus targets.
73
+ Paging is disabled because Prometheus does not support paged results.
74
+
75
+ The plugin also reuses the Netbox authentication and permission model.
76
+ Depending on the Netbox configuration, a token with valid object permissions must be passed to Netbox.
77
+
78
+ ```
79
+ GET /api/plugins/prometheus-sd/devices/ Get a list of devices in a prometheus compatible format
80
+ GET /api/plugins/prometheus-sd/virtual-machines/ Get a list of vms in a prometheus compatible format
81
+ GET /api/plugins/prometheus-sd/services/ Get a list of services in a prometheus compatible format
82
+ GET /api/plugins/prometheus-sd/ip-addresses/ Get a list of ip in a prometheus compatible format
83
+ ```
84
+
85
+ #### Extended services filters
86
+
87
+ Apart from standard Netbox filters, services endpoint also supports `tenant=<slug>` or `tenant_id=<id>` parameters.
88
+ The lookup is only executed against the `tenant` attribute of the object associated with the service.
89
+
90
+ #### Filtering and response size
91
+
92
+ Because paging is disabled, one request serializes every object the token is
93
+ allowed to see. Filtering with the standard Netbox query parameters is the
94
+ supported way to keep responses small, and it is usually what you want anyway —
95
+ Prometheus should not be told about decommissioned hardware:
96
+
97
+ ```
98
+ /api/plugins/prometheus-sd/devices/?status=active&tag=monitoring&site=dc1
99
+ ```
100
+
101
+ ### Labels
102
+
103
+ Every target carries `__meta_netbox_*` labels describing the Netbox object.
104
+ **Prometheus discards labels starting with `__` after service discovery**, so
105
+ they have to be copied into real labels with `relabel_configs` (see below) if you
106
+ want them on your metrics.
107
+
108
+ A label is only present when the underlying field is populated — a device with no
109
+ tenant has no `__meta_netbox_tenant`.
110
+
111
+ | Label | Devices | VMs | Services | IPs |
112
+ |---|:-:|:-:|:-:|:-:|
113
+ | `id`, `name`, `status`, `model` | ✓ | ✓ | id/name only | ✓ (no name) |
114
+ | `primary_ip`, `primary_ip4`, `primary_ip6` | ✓ | ✓ | from parent | |
115
+ | `oob_ip` | ✓ | | from parent | |
116
+ | `ip` | | | | ✓ |
117
+ | `role`, `role_slug` | ✓ | ✓ | | `role` only |
118
+ | `platform`, `platform_slug` | ✓ | ✓ | | |
119
+ | `device_type`, `device_type_slug` | ✓ | | | |
120
+ | `site`, `site_slug` | ✓ | ✓ | from parent | |
121
+ | `scope`, `scope_slug` | | ✓ ¹ | | |
122
+ | `location`, `location_slug` | ✓ | | | |
123
+ | `rack`, `rack_u_position` | ✓ | | | |
124
+ | `cluster`, `cluster_group`, `cluster_type` | ✓ ² | ✓ | | |
125
+ | `tenant`, `tenant_slug` | ✓ | ✓ | from parent | ✓ |
126
+ | `tenant_group`, `tenant_group_slug` | ✓ | ✓ | from parent | ✓ |
127
+ | `tags`, `tag_slugs` | ✓ | ✓ | ✓ | ✓ |
128
+ | `services` | ✓ | ✓ | | |
129
+ | `contact_<priority>_{name,email,comments,role}` | ✓ | ✓ | from parent | |
130
+ | `custom_field_<name>` | ✓ | ✓ | ✓ | ✓ |
131
+ | `description` | ✓ | | | |
132
+ | `parent`, `display`, `ports`, `ipaddresses` | | | ✓ | |
133
+
134
+ ¹ Netbox 4.2 replaced the cluster's site with a generic `scope`. On 4.2+ a VM
135
+ emits `scope`/`scope_slug` for the cluster, and `site`/`site_slug` for its own
136
+ site; below 4.2 the cluster's site is reported as `site`.
137
+ ² Only when the device is assigned to a cluster.
138
+
139
+ Config context can additionally set `__metrics_path__` and `__scheme__`, which
140
+ Prometheus consumes directly (see [Config context](#config-context)).
141
+
142
+ ### Relabeling
143
+
144
+ The `__meta_netbox_*` labels are dropped unless you map them. A typical device job
145
+ scraping node_exporter on the primary IP:
146
+
147
+ ```yaml
148
+ scrape_configs:
149
+ - job_name: netbox-devices
150
+ http_sd_configs:
151
+ - url: http://netbox:8080/api/plugins/prometheus-sd/devices/?status=active&tag=monitoring
152
+ refresh_interval: 60s
153
+ authorization:
154
+ type: Token
155
+ credentials: "<your-netbox-api-token>"
156
+
157
+ relabel_configs:
158
+ # Skip anything without a primary IPv4, otherwise the address below is empty.
159
+ - source_labels: [__meta_netbox_primary_ip4]
160
+ regex: ^$
161
+ action: drop
162
+
163
+ # Scrape the primary IP instead of the device name, which may not resolve.
164
+ - source_labels: [__meta_netbox_primary_ip4]
165
+ target_label: __address__
166
+ replacement: "$1:9100"
167
+
168
+ # Keep the Netbox name as the instance label rather than the IP.
169
+ - source_labels: [__meta_netbox_name]
170
+ target_label: instance
171
+
172
+ # Promote the dimensions worth alerting and grouping on.
173
+ - source_labels: [__meta_netbox_site_slug]
174
+ target_label: site
175
+ - source_labels: [__meta_netbox_role_slug]
176
+ target_label: role
177
+ - source_labels: [__meta_netbox_tenant_slug]
178
+ target_label: tenant
179
+ ```
180
+
181
+ Two things worth knowing:
182
+
183
+ - `tags` and `tag_slugs` are comma-joined, so match them with `.*,?value,?.*`
184
+ rather than `=`.
185
+ - Devices and VMs use the same label names, so one set of `relabel_configs` can
186
+ be reused across both jobs.
187
+
188
+ ### Config context
189
+
190
+ The plugin can also discover extra config to inject in the HTTP SD JSON from the config context of the devices/virtual machines.
191
+ If you have a `prometheus-plugin-prometheus-sd` entry in your config context with the following schema it will be automatically picked up:
192
+
193
+ ```yaml
194
+ prometheus-plugin-prometheus-sd:
195
+ - metrics_path: /not/metrics
196
+ port: 4242
197
+ scheme: https
198
+ - port: 4243
199
+ ```
200
+
201
+ This allow you to configure those values directly into netbox instead of doing that inside the Prometheus
202
+ config and filtering each scenario by a specific tag for instance.
203
+
204
+ If there is only one entry you can also use this form:
205
+
206
+ ```yaml
207
+ prometheus-plugin-prometheus-sd:
208
+ metrics_path: /not/metrics
209
+ port: 4242
210
+ scheme: https
211
+ ```
212
+
213
+ ### Example
214
+
215
+ [`example/prometheus.yml`](example/prometheus.yml) is a complete Prometheus
216
+ configuration covering all four endpoints, with `relabel_configs` mapping the
217
+ `__meta_netbox_*` labels onto real ones.
218
+
219
+ It is not a snippet that happens to be in the repository: the test suite runs
220
+ Prometheus against this exact file and asserts that the expected targets and
221
+ labels are discovered, so it cannot quietly stop working.
222
+
223
+ To see it running, with a Netbox that has demo data already loaded:
224
+
225
+ ```bash
226
+ poetry run invoke build-dev
227
+ ```
228
+
229
+ - Netbox: <http://localhost:8000> (`admin` / `admin`)
230
+ - Prometheus: <http://localhost:9090> — discovered targets are under
231
+ Status → Target health, and expanding one shows the raw `__meta_netbox_*`
232
+ labels before relabeling.
233
+
234
+ The demo data is the unit-test fixtures, so it also exercises config context
235
+ (the VMs get two targets each, on different ports), services, contacts and tags.
236
+
237
+ ## Development
238
+
239
+ We use [Poetry](https://python-poetry.org/) for dependency management and [invoke](https://www.pyinvoke.org/) as task runner.
240
+ To test the plugin in an isolated environment, we use [testcontainers](https://testcontainers.com/?language=python)
241
+ which creates "throwaway, lightweight" Netbox Docker containers.
242
+
243
+ Install the dependencies with `poetry install`, then run the tasks through
244
+ `poetry run` (this works on every Poetry version, whereas `poetry shell` was moved
245
+ into a separate plugin in Poetry 2.0):
246
+
247
+ ```bash
248
+ # Unit tests plus the Prometheus end-to-end check
249
+ poetry run invoke test
250
+
251
+ # Test against a specific Netbox release (default: latest)
252
+ NETBOX_VER=v4.6.5 poetry run invoke test
253
+
254
+ # Either half on its own
255
+ poetry run invoke unittest
256
+ poetry run invoke test-prometheus
257
+ ```
258
+
259
+ The Netbox image is built from the `Dockerfile` in the repository root.
260
+
261
+ Testing has two layers:
262
+
263
+ - **Unit tests** — plain Django tests under `netbox_prometheus_sd/tests/`,
264
+ executed inside the Netbox container. These cover the serializers and the
265
+ label output.
266
+ - **Prometheus end-to-end** — Netbox serving real HTTP with seeded data, and a
267
+ real Prometheus configured from `example/prometheus.yml`. It asserts that the
268
+ expected jobs discover targets and that relabeling produced the expected
269
+ labels.
270
+
271
+ The second layer exists because "valid JSON with targets and labels" is not the
272
+ same as "Prometheus accepts this as an `http_sd` source". A response that
273
+ Prometheus rejects would pass every unit test in this repository. It also keeps
274
+ the documented example honest, since it is the file under test.
275
+
276
+ Features should be covered by a test, but sometimes it is easier to develop
277
+ against a running system:
278
+
279
+ ```bash
280
+ # Netbox + Prometheus with demo data, left running until Ctrl+C
281
+ poetry run invoke build-dev
282
+ ```
283
+
284
+ Netbox is on <http://localhost:8000> (`admin` / `admin`) and Prometheus on
285
+ <http://localhost:9090>, already scraping it.
286
+
287
+ API endpoints for testing can be found at http://localhost:8000/api/plugins/prometheus-sd/
288
+
289
+ ## Conventional Commits
290
+
291
+ This repository follows the Conventional Commits specification for versioning and changelog generation.
292
+ Conventional Commits provide a standardized way of writing commit messages to convey semantic meaning
293
+ about the changes made. Each commit message follows a defined format that includes a type,
294
+ an optional scope, and a message. The types typically include features, fixes, documentation, and more.
295
+ By adhering to this convention, we ensure clear and automated versioning, release notes, and changelog generation.
296
+
@@ -0,0 +1,277 @@
1
+ # netbox-plugin-prometheus-sd
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![CI](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/workflows/CI/badge.svg?event=push)](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/actions?query=workflow%3ACI)
5
+ [![PyPI](https://img.shields.io/pypi/v/netbox-plugin-prometheus-sd)](https://pypi.org/project/netbox-plugin-prometheus-sd/)
6
+
7
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/flxpeters)
8
+
9
+ Provide Prometheus `http_sd` compatible API Endpoint with data from Netbox.
10
+
11
+ HTTP SD is a feature since Prometheus 2.28.0 that allows hosts to be found via a URL instead of just files.
12
+ This plugin implements API endpoints in Netbox to make devices, services, IPs and virtual machines available to Prometheus.
13
+
14
+ ## Compatibility
15
+
16
+ We aim to support the latest major versions of Netbox.
17
+
18
+ | Plugin | Netbox |
19
+ |---|---|
20
+ | `2.x` | `>= 4.0` |
21
+ | `1.x` | `3.x` (no longer maintained) |
22
+
23
+ Check the `.github/workflows/ci.yml` pipeline for the current tested builds.
24
+ Other versions may work, but we do not test them explicitly. All relevant target versions are tested in CI.
25
+
26
+ Plugin `2.0` also fixed a set of N+1 queries that made the endpoints very slow on
27
+ larger installations ([#265](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/issues/265)).
28
+ If service discovery is putting noticeable load on your Netbox database, upgrading
29
+ is worthwhile.
30
+
31
+ ## Installation
32
+
33
+ The plugin is available as a Python package in pypi and can be installed with pip
34
+
35
+ ```bash
36
+ pip install netbox-plugin-prometheus-sd
37
+ ```
38
+
39
+ Enable the plugin in /opt/netbox/netbox/netbox/configuration.py:
40
+
41
+ ```python
42
+ PLUGINS = ['netbox_prometheus_sd']
43
+ ```
44
+
45
+ The plugin has not further plugin configuration.
46
+
47
+ ## Usage
48
+
49
+ The plugin only provides a new API endpoint on the Netbox API. There is no further action required after installation.
50
+
51
+ ### API
52
+
53
+ The plugin reuses Netbox API view sets with new serializers for Prometheus.
54
+ This means that all filters that can be used on the Netbox API can also be used to filter Prometheus targets.
55
+ Paging is disabled because Prometheus does not support paged results.
56
+
57
+ The plugin also reuses the Netbox authentication and permission model.
58
+ Depending on the Netbox configuration, a token with valid object permissions must be passed to Netbox.
59
+
60
+ ```
61
+ GET /api/plugins/prometheus-sd/devices/ Get a list of devices in a prometheus compatible format
62
+ GET /api/plugins/prometheus-sd/virtual-machines/ Get a list of vms in a prometheus compatible format
63
+ GET /api/plugins/prometheus-sd/services/ Get a list of services in a prometheus compatible format
64
+ GET /api/plugins/prometheus-sd/ip-addresses/ Get a list of ip in a prometheus compatible format
65
+ ```
66
+
67
+ #### Extended services filters
68
+
69
+ Apart from standard Netbox filters, services endpoint also supports `tenant=<slug>` or `tenant_id=<id>` parameters.
70
+ The lookup is only executed against the `tenant` attribute of the object associated with the service.
71
+
72
+ #### Filtering and response size
73
+
74
+ Because paging is disabled, one request serializes every object the token is
75
+ allowed to see. Filtering with the standard Netbox query parameters is the
76
+ supported way to keep responses small, and it is usually what you want anyway —
77
+ Prometheus should not be told about decommissioned hardware:
78
+
79
+ ```
80
+ /api/plugins/prometheus-sd/devices/?status=active&tag=monitoring&site=dc1
81
+ ```
82
+
83
+ ### Labels
84
+
85
+ Every target carries `__meta_netbox_*` labels describing the Netbox object.
86
+ **Prometheus discards labels starting with `__` after service discovery**, so
87
+ they have to be copied into real labels with `relabel_configs` (see below) if you
88
+ want them on your metrics.
89
+
90
+ A label is only present when the underlying field is populated — a device with no
91
+ tenant has no `__meta_netbox_tenant`.
92
+
93
+ | Label | Devices | VMs | Services | IPs |
94
+ |---|:-:|:-:|:-:|:-:|
95
+ | `id`, `name`, `status`, `model` | ✓ | ✓ | id/name only | ✓ (no name) |
96
+ | `primary_ip`, `primary_ip4`, `primary_ip6` | ✓ | ✓ | from parent | |
97
+ | `oob_ip` | ✓ | | from parent | |
98
+ | `ip` | | | | ✓ |
99
+ | `role`, `role_slug` | ✓ | ✓ | | `role` only |
100
+ | `platform`, `platform_slug` | ✓ | ✓ | | |
101
+ | `device_type`, `device_type_slug` | ✓ | | | |
102
+ | `site`, `site_slug` | ✓ | ✓ | from parent | |
103
+ | `scope`, `scope_slug` | | ✓ ¹ | | |
104
+ | `location`, `location_slug` | ✓ | | | |
105
+ | `rack`, `rack_u_position` | ✓ | | | |
106
+ | `cluster`, `cluster_group`, `cluster_type` | ✓ ² | ✓ | | |
107
+ | `tenant`, `tenant_slug` | ✓ | ✓ | from parent | ✓ |
108
+ | `tenant_group`, `tenant_group_slug` | ✓ | ✓ | from parent | ✓ |
109
+ | `tags`, `tag_slugs` | ✓ | ✓ | ✓ | ✓ |
110
+ | `services` | ✓ | ✓ | | |
111
+ | `contact_<priority>_{name,email,comments,role}` | ✓ | ✓ | from parent | |
112
+ | `custom_field_<name>` | ✓ | ✓ | ✓ | ✓ |
113
+ | `description` | ✓ | | | |
114
+ | `parent`, `display`, `ports`, `ipaddresses` | | | ✓ | |
115
+
116
+ ¹ Netbox 4.2 replaced the cluster's site with a generic `scope`. On 4.2+ a VM
117
+ emits `scope`/`scope_slug` for the cluster, and `site`/`site_slug` for its own
118
+ site; below 4.2 the cluster's site is reported as `site`.
119
+ ² Only when the device is assigned to a cluster.
120
+
121
+ Config context can additionally set `__metrics_path__` and `__scheme__`, which
122
+ Prometheus consumes directly (see [Config context](#config-context)).
123
+
124
+ ### Relabeling
125
+
126
+ The `__meta_netbox_*` labels are dropped unless you map them. A typical device job
127
+ scraping node_exporter on the primary IP:
128
+
129
+ ```yaml
130
+ scrape_configs:
131
+ - job_name: netbox-devices
132
+ http_sd_configs:
133
+ - url: http://netbox:8080/api/plugins/prometheus-sd/devices/?status=active&tag=monitoring
134
+ refresh_interval: 60s
135
+ authorization:
136
+ type: Token
137
+ credentials: "<your-netbox-api-token>"
138
+
139
+ relabel_configs:
140
+ # Skip anything without a primary IPv4, otherwise the address below is empty.
141
+ - source_labels: [__meta_netbox_primary_ip4]
142
+ regex: ^$
143
+ action: drop
144
+
145
+ # Scrape the primary IP instead of the device name, which may not resolve.
146
+ - source_labels: [__meta_netbox_primary_ip4]
147
+ target_label: __address__
148
+ replacement: "$1:9100"
149
+
150
+ # Keep the Netbox name as the instance label rather than the IP.
151
+ - source_labels: [__meta_netbox_name]
152
+ target_label: instance
153
+
154
+ # Promote the dimensions worth alerting and grouping on.
155
+ - source_labels: [__meta_netbox_site_slug]
156
+ target_label: site
157
+ - source_labels: [__meta_netbox_role_slug]
158
+ target_label: role
159
+ - source_labels: [__meta_netbox_tenant_slug]
160
+ target_label: tenant
161
+ ```
162
+
163
+ Two things worth knowing:
164
+
165
+ - `tags` and `tag_slugs` are comma-joined, so match them with `.*,?value,?.*`
166
+ rather than `=`.
167
+ - Devices and VMs use the same label names, so one set of `relabel_configs` can
168
+ be reused across both jobs.
169
+
170
+ ### Config context
171
+
172
+ The plugin can also discover extra config to inject in the HTTP SD JSON from the config context of the devices/virtual machines.
173
+ If you have a `prometheus-plugin-prometheus-sd` entry in your config context with the following schema it will be automatically picked up:
174
+
175
+ ```yaml
176
+ prometheus-plugin-prometheus-sd:
177
+ - metrics_path: /not/metrics
178
+ port: 4242
179
+ scheme: https
180
+ - port: 4243
181
+ ```
182
+
183
+ This allow you to configure those values directly into netbox instead of doing that inside the Prometheus
184
+ config and filtering each scenario by a specific tag for instance.
185
+
186
+ If there is only one entry you can also use this form:
187
+
188
+ ```yaml
189
+ prometheus-plugin-prometheus-sd:
190
+ metrics_path: /not/metrics
191
+ port: 4242
192
+ scheme: https
193
+ ```
194
+
195
+ ### Example
196
+
197
+ [`example/prometheus.yml`](example/prometheus.yml) is a complete Prometheus
198
+ configuration covering all four endpoints, with `relabel_configs` mapping the
199
+ `__meta_netbox_*` labels onto real ones.
200
+
201
+ It is not a snippet that happens to be in the repository: the test suite runs
202
+ Prometheus against this exact file and asserts that the expected targets and
203
+ labels are discovered, so it cannot quietly stop working.
204
+
205
+ To see it running, with a Netbox that has demo data already loaded:
206
+
207
+ ```bash
208
+ poetry run invoke build-dev
209
+ ```
210
+
211
+ - Netbox: <http://localhost:8000> (`admin` / `admin`)
212
+ - Prometheus: <http://localhost:9090> — discovered targets are under
213
+ Status → Target health, and expanding one shows the raw `__meta_netbox_*`
214
+ labels before relabeling.
215
+
216
+ The demo data is the unit-test fixtures, so it also exercises config context
217
+ (the VMs get two targets each, on different ports), services, contacts and tags.
218
+
219
+ ## Development
220
+
221
+ We use [Poetry](https://python-poetry.org/) for dependency management and [invoke](https://www.pyinvoke.org/) as task runner.
222
+ To test the plugin in an isolated environment, we use [testcontainers](https://testcontainers.com/?language=python)
223
+ which creates "throwaway, lightweight" Netbox Docker containers.
224
+
225
+ Install the dependencies with `poetry install`, then run the tasks through
226
+ `poetry run` (this works on every Poetry version, whereas `poetry shell` was moved
227
+ into a separate plugin in Poetry 2.0):
228
+
229
+ ```bash
230
+ # Unit tests plus the Prometheus end-to-end check
231
+ poetry run invoke test
232
+
233
+ # Test against a specific Netbox release (default: latest)
234
+ NETBOX_VER=v4.6.5 poetry run invoke test
235
+
236
+ # Either half on its own
237
+ poetry run invoke unittest
238
+ poetry run invoke test-prometheus
239
+ ```
240
+
241
+ The Netbox image is built from the `Dockerfile` in the repository root.
242
+
243
+ Testing has two layers:
244
+
245
+ - **Unit tests** — plain Django tests under `netbox_prometheus_sd/tests/`,
246
+ executed inside the Netbox container. These cover the serializers and the
247
+ label output.
248
+ - **Prometheus end-to-end** — Netbox serving real HTTP with seeded data, and a
249
+ real Prometheus configured from `example/prometheus.yml`. It asserts that the
250
+ expected jobs discover targets and that relabeling produced the expected
251
+ labels.
252
+
253
+ The second layer exists because "valid JSON with targets and labels" is not the
254
+ same as "Prometheus accepts this as an `http_sd` source". A response that
255
+ Prometheus rejects would pass every unit test in this repository. It also keeps
256
+ the documented example honest, since it is the file under test.
257
+
258
+ Features should be covered by a test, but sometimes it is easier to develop
259
+ against a running system:
260
+
261
+ ```bash
262
+ # Netbox + Prometheus with demo data, left running until Ctrl+C
263
+ poetry run invoke build-dev
264
+ ```
265
+
266
+ Netbox is on <http://localhost:8000> (`admin` / `admin`) and Prometheus on
267
+ <http://localhost:9090>, already scraping it.
268
+
269
+ API endpoints for testing can be found at http://localhost:8000/api/plugins/prometheus-sd/
270
+
271
+ ## Conventional Commits
272
+
273
+ This repository follows the Conventional Commits specification for versioning and changelog generation.
274
+ Conventional Commits provide a standardized way of writing commit messages to convey semantic meaning
275
+ about the changes made. Each commit message follows a defined format that includes a type,
276
+ an optional scope, and a message. The types typically include features, fixes, documentation, and more.
277
+ By adhering to this convention, we ensure clear and automated versioning, release notes, and changelog generation.
@@ -1,7 +1,7 @@
1
1
  from netbox.plugins import PluginConfig
2
2
 
3
3
  # Placeholder for semantic release
4
- __VERSION__ = "2.0.0"
4
+ __VERSION__ = "2.1.0"
5
5
 
6
6
 
7
7
  class PrometheusSD(PluginConfig):
@@ -8,6 +8,11 @@ from utilities.filters import (
8
8
  )
9
9
 
10
10
  from ipam.filtersets import ServiceFilterSet as NetboxServiceFilterSet
11
+ from ipam.models import Service
12
+
13
+ # Netbox 4.7 replaced the Service.ports ArrayField with `port_mappings`, and
14
+ # its filterset metaclass rejects a filter on a field that no longer exists.
15
+ SERVICE_HAS_PORTS_FIELD = any(f.name == "ports" for f in Service._meta.get_fields())
11
16
 
12
17
 
13
18
  class ServiceFilterSet(NetboxServiceFilterSet):
@@ -28,9 +33,11 @@ class ServiceFilterSet(NetboxServiceFilterSet):
28
33
  label=_("Tenant (slug)"),
29
34
  )
30
35
 
31
- # fix to make the test_missing_filters pass
36
+ # Netbox < 4.7 only exposes the ports array as `port`, but Netbox's
37
+ # test_missing_filters wants a filter named after the model field.
32
38
  # see: https://github.com/netbox-community/netbox/blob/master/netbox/utilities/testing/filtersets.py#L98
33
- ports = NumericArrayFilter(field_name="ports", lookup_expr="contains")
39
+ if SERVICE_HAS_PORTS_FIELD:
40
+ ports = NumericArrayFilter(field_name="ports", lookup_expr="contains")
34
41
 
35
42
  def filter_by_cluster_tenant_id(self, queryset, name, value):
36
43
  return queryset.filter(
@@ -2,13 +2,19 @@ from django.test import TestCase
2
2
 
3
3
  from ipam.models import Service
4
4
  from tenancy.models import Tenant
5
- from utilities.testing import ChangeLoggedFilterSetTests
5
+
6
+ try: # NetBox 4.7+
7
+ from utilities.testing import ChangeLoggedFilterSetTestMixin
8
+ except ImportError: # NetBox <4.7
9
+ from utilities.testing import (
10
+ ChangeLoggedFilterSetTests as ChangeLoggedFilterSetTestMixin,
11
+ )
6
12
 
7
13
  from . import utils
8
14
  from ..filtersets import ServiceFilterSet
9
15
 
10
16
 
11
- class ServiceTestCase(TestCase, ChangeLoggedFilterSetTests):
17
+ class ServiceTestCase(TestCase, ChangeLoggedFilterSetTestMixin):
12
18
  queryset = Service.objects.all()
13
19
  filterset = ServiceFilterSet
14
20
 
@@ -9,6 +9,7 @@ from . import utils
9
9
 
10
10
  from ..api.utils import NETBOX_RELEASE_CURRENT, NETBOX_RELEASE_41
11
11
 
12
+
12
13
  class PrometheusVirtualMachineSerializerTests(TestCase):
13
14
  def test_vm_minimal_to_target(self):
14
15
 
@@ -498,7 +499,12 @@ class PrometheusServiceSerializerTests(TestCase):
498
499
  )
499
500
  self.assertTrue(
500
501
  utils.dictContainsSubset(
501
- {"__meta_netbox_display": "ssh (TCP/22)"}, data["labels"]
502
+ {
503
+ "__meta_netbox_display": utils.expected_service_display(
504
+ "ssh", "TCP", 22
505
+ )
506
+ },
507
+ data["labels"],
502
508
  )
503
509
  )
504
510
  self.assertTrue(
@@ -562,7 +568,12 @@ class PrometheusServiceSerializerTests(TestCase):
562
568
  )
563
569
  self.assertTrue(
564
570
  utils.dictContainsSubset(
565
- {"__meta_netbox_display": "ssh (TCP/22)"}, data["labels"]
571
+ {
572
+ "__meta_netbox_display": utils.expected_service_display(
573
+ "ssh", "TCP", 22
574
+ )
575
+ },
576
+ data["labels"],
566
577
  )
567
578
  )
568
579
  self.assertTrue(
@@ -29,7 +29,7 @@ def dictContainsSubset(subset, fullset):
29
29
 
30
30
 
31
31
  def build_cluster():
32
- try: # NetBox 4.2+
32
+ try: # NetBox 4.2+
33
33
  scope_type = ContentType.objects.get_for_model(Site)
34
34
  return Cluster.objects.get_or_create(
35
35
  name="DC1",
@@ -38,7 +38,7 @@ def build_cluster():
38
38
  scope_type=scope_type,
39
39
  scope_id=Site.objects.get_or_create(name="Campus A", slug="campus-a")[0].id,
40
40
  )[0]
41
- except FieldError: # NetBox <4.2
41
+ except FieldError: # NetBox <4.2
42
42
  return Cluster.objects.get_or_create(
43
43
  name="DC1",
44
44
  group=ClusterGroup.objects.get_or_create(name="VMware")[0],
@@ -137,15 +137,29 @@ def build_vm_full(name, ip_octet=1):
137
137
  return vm
138
138
 
139
139
 
140
+ def expected_service_display(name, protocol, port):
141
+ """Netbox 4.7 reduced Service.__str__ to the bare name; older releases
142
+ append the protocol and port list."""
143
+ if hasattr(Service, "port_mappings"):
144
+ return name
145
+ return f"{name} ({protocol}/{port})"
146
+
147
+
140
148
  def build_service_for(parent, **kwargs):
141
149
  """Create a service bound to parent, with the parent's primary IPv4 attached.
142
150
 
143
151
  Netbox 4.3 replaced Service.device/Service.virtual_machine with a single
144
152
  generic `parent` relation, which is read-only on older releases.
153
+
154
+ Netbox 4.7 replaced Service.protocol/Service.ports with `port_mappings`
155
+ and rejects the legacy pair at the ORM level.
145
156
  """
146
- try: # NetBox 4.3+
157
+ if hasattr(Service, "port_mappings") and "ports" in kwargs:
158
+ protocol = kwargs.pop("protocol", "tcp")
159
+ kwargs["port_mappings"] = [f"{protocol}/{port}" for port in kwargs.pop("ports")]
160
+ try: # NetBox 4.3+
147
161
  service = Service.objects.create(parent=parent, **kwargs)
148
- except AttributeError: # NetBox <4.3
162
+ except AttributeError: # NetBox <4.3
149
163
  field = "device" if isinstance(parent, Device) else "virtual_machine"
150
164
  service = Service.objects.create(**{field: parent}, **kwargs)
151
165
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "netbox-plugin-prometheus-sd"
3
- version = "v2.0.0" # placeholder
3
+ version = "2.1.0" # placeholder
4
4
  description = "A Netbox plugin to provide Netbox entires to Prometheus HTTP service discovery"
5
5
  authors = ["Felix Peters <felix.peters@breuninger.de>"]
6
6
  license = "MIT"
@@ -1,158 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: netbox-plugin-prometheus-sd
3
- Version: 2.0.0
4
- Summary: A Netbox plugin to provide Netbox entires to Prometheus HTTP service discovery
5
- License: MIT
6
- Author: Felix Peters
7
- Author-email: felix.peters@breuninger.de
8
- Requires-Python: >=3.10,<4.0
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: 3.10
12
- Classifier: Programming Language :: Python :: 3.11
13
- Classifier: Programming Language :: Python :: 3.12
14
- Classifier: Programming Language :: Python :: 3.13
15
- Description-Content-Type: text/markdown
16
-
17
- # netbox-plugin-prometheus-sd
18
-
19
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
20
- [![CI](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/workflows/CI/badge.svg?event=push)](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/actions?query=workflow%3ACI)
21
- [![PyPI](https://img.shields.io/pypi/v/netbox-plugin-prometheus-sd)](https://pypi.org/project/netbox-plugin-prometheus-sd/)
22
-
23
- [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/flxpeters)
24
-
25
- Provide Prometheus `http_sd` compatible API Endpoint with data from Netbox.
26
-
27
- HTTP SD is a feature since Prometheus 2.28.0 that allows hosts to be found via a URL instead of just files.
28
- This plugin implements API endpoints in Netbox to make devices, services, IPs and virtual machines available to Prometheus.
29
-
30
- ## Compatibility
31
-
32
- We aim to support the latest major versions of Netbox.
33
- For now we support Netbox `>= 4.0` including bugfix versions. Older versions may work, but without any guarantee.
34
-
35
- Check the `.github/workflows/ci.yml` pipeline for the current tested builds.
36
- Other versions may work, but we do not test them explicitly. All relevant target versions are tested in CI.
37
-
38
- ## Installation
39
-
40
- The plugin is available as a Python package in pypi and can be installed with pip
41
-
42
- ```bash
43
- pip install netbox-plugin-prometheus-sd
44
- ```
45
-
46
- Enable the plugin in /opt/netbox/netbox/netbox/configuration.py:
47
-
48
- ```python
49
- PLUGINS = ['netbox_prometheus_sd']
50
- ```
51
-
52
- The plugin has not further plugin configuration.
53
-
54
- ## Usage
55
-
56
- The plugin only provides a new API endpoint on the Netbox API. There is no further action required after installation.
57
-
58
- ### API
59
-
60
- The plugin reuses Netbox API view sets with new serializers for Prometheus.
61
- This means that all filters that can be used on the Netbox API can also be used to filter Prometheus targets.
62
- Paging is disabled because Prometheus does not support paged results.
63
-
64
- The plugin also reuses the Netbox authentication and permission model.
65
- Depending on the Netbox configuration, a token with valid object permissions must be passed to Netbox.
66
-
67
- ```
68
- GET /api/plugins/prometheus-sd/devices/ Get a list of devices in a prometheus compatible format
69
- GET /api/plugins/prometheus-sd/virtual-machines/ Get a list of vms in a prometheus compatible format
70
- GET /api/plugins/prometheus-sd/services/ Get a list of services in a prometheus compatible format
71
- GET /api/plugins/prometheus-sd/ip-addresses/ Get a list of ip in a prometheus compatible format
72
- ```
73
-
74
- #### Extended services filters
75
-
76
- Apart from standard Netbox filters, services endpoint also supports `tenant=<slug>` or `tenant_id=<id>` parameters.
77
- The lookup is only executed against the `tenant` attribute of the object associated with the service.
78
-
79
- ### Config context
80
-
81
- The plugin can also discover extra config to inject in the HTTP SD JSON from the config context of the devices/virtual machines.
82
- If you have a `prometheus-plugin-prometheus-sd` entry in your config context with the following schema it will be automatically picked up:
83
-
84
- ```yaml
85
- prometheus-plugin-prometheus-sd:
86
- - metrics_path: /not/metrics
87
- port: 4242
88
- scheme: https
89
- - port: 4243
90
- ```
91
-
92
- This allow you to configure those values directly into netbox instead of doing that inside the Prometheus
93
- config and filtering each scenario by a specific tag for instance.
94
-
95
- If there is only one entry you can also use this form:
96
-
97
- ```yaml
98
- prometheus-plugin-prometheus-sd:
99
- metrics_path: /not/metrics
100
- port: 4242
101
- scheme: https
102
- ```
103
-
104
- ### Example
105
-
106
- A working example on how to use this plugin with Prometheus is located at the `example` folder.
107
- Netbox content is created by using Netbox docker initializers.
108
-
109
- The demo data doesn't make sense, but they are good enough for demonstrating how to configure Prometheus
110
- and get demo data to Prometheus service discovery.
111
-
112
- Go to the `example` folder and run `docker-compose up --build`. Prometheus should get available on `http://localhost:9090`.
113
-
114
- Push some example devices and objects to Netbox using the initializers:
115
-
116
- ```
117
- docker-compose exec netbox /opt/netbox/netbox/manage.py load_initializer_data --path /opt/netbox/initializers
118
- ```
119
-
120
- Netbox content should then be available in the service discovery tab.
121
-
122
- ## Development
123
-
124
- We use [Poetry](https://python-poetry.org/) for dependency management and [invoke](https://www.pyinvoke.org/) as task runner.
125
- To test the plugin in an isolated environment, we use [testcontainers](https://testcontainers.com/?language=python)
126
- which creates "throwaway, lightweight" Netbox Docker containers.
127
-
128
- All code to run in docker is located under `develop`.
129
- To start a virtual env managed by poetry run `poetry shell`.
130
- All following commands are started inside this environment.
131
-
132
- In order to run tests invoke the tests:
133
-
134
- ```bash
135
- # Build the containers and execute all tests
136
- invoke test
137
- ```
138
-
139
- Features should be covered by a unit test, but some times it's easier to develop on an running system.
140
-
141
- ```bash
142
- # Start a development environment
143
- invoke build_dev
144
- ```
145
-
146
- Visit http://localhost:8000 and log in with the default admin credentials.
147
- You can now define Netbox entities and test around.
148
-
149
- API endpoints for testing can be found at http://localhost:8000/api/plugins/prometheus-sd/
150
-
151
- ## Conventional Commits
152
-
153
- This repository follows the Conventional Commits specification for versioning and changelog generation.
154
- Conventional Commits provide a standardized way of writing commit messages to convey semantic meaning
155
- about the changes made. Each commit message follows a defined format that includes a type,
156
- an optional scope, and a message. The types typically include features, fixes, documentation, and more.
157
- By adhering to this convention, we ensure clear and automated versioning, release notes, and changelog generation.
158
-
@@ -1,141 +0,0 @@
1
- # netbox-plugin-prometheus-sd
2
-
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
- [![CI](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/workflows/CI/badge.svg?event=push)](https://github.com/FlxPeters/netbox-plugin-prometheus-sd/actions?query=workflow%3ACI)
5
- [![PyPI](https://img.shields.io/pypi/v/netbox-plugin-prometheus-sd)](https://pypi.org/project/netbox-plugin-prometheus-sd/)
6
-
7
- [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/flxpeters)
8
-
9
- Provide Prometheus `http_sd` compatible API Endpoint with data from Netbox.
10
-
11
- HTTP SD is a feature since Prometheus 2.28.0 that allows hosts to be found via a URL instead of just files.
12
- This plugin implements API endpoints in Netbox to make devices, services, IPs and virtual machines available to Prometheus.
13
-
14
- ## Compatibility
15
-
16
- We aim to support the latest major versions of Netbox.
17
- For now we support Netbox `>= 4.0` including bugfix versions. Older versions may work, but without any guarantee.
18
-
19
- Check the `.github/workflows/ci.yml` pipeline for the current tested builds.
20
- Other versions may work, but we do not test them explicitly. All relevant target versions are tested in CI.
21
-
22
- ## Installation
23
-
24
- The plugin is available as a Python package in pypi and can be installed with pip
25
-
26
- ```bash
27
- pip install netbox-plugin-prometheus-sd
28
- ```
29
-
30
- Enable the plugin in /opt/netbox/netbox/netbox/configuration.py:
31
-
32
- ```python
33
- PLUGINS = ['netbox_prometheus_sd']
34
- ```
35
-
36
- The plugin has not further plugin configuration.
37
-
38
- ## Usage
39
-
40
- The plugin only provides a new API endpoint on the Netbox API. There is no further action required after installation.
41
-
42
- ### API
43
-
44
- The plugin reuses Netbox API view sets with new serializers for Prometheus.
45
- This means that all filters that can be used on the Netbox API can also be used to filter Prometheus targets.
46
- Paging is disabled because Prometheus does not support paged results.
47
-
48
- The plugin also reuses the Netbox authentication and permission model.
49
- Depending on the Netbox configuration, a token with valid object permissions must be passed to Netbox.
50
-
51
- ```
52
- GET /api/plugins/prometheus-sd/devices/ Get a list of devices in a prometheus compatible format
53
- GET /api/plugins/prometheus-sd/virtual-machines/ Get a list of vms in a prometheus compatible format
54
- GET /api/plugins/prometheus-sd/services/ Get a list of services in a prometheus compatible format
55
- GET /api/plugins/prometheus-sd/ip-addresses/ Get a list of ip in a prometheus compatible format
56
- ```
57
-
58
- #### Extended services filters
59
-
60
- Apart from standard Netbox filters, services endpoint also supports `tenant=<slug>` or `tenant_id=<id>` parameters.
61
- The lookup is only executed against the `tenant` attribute of the object associated with the service.
62
-
63
- ### Config context
64
-
65
- The plugin can also discover extra config to inject in the HTTP SD JSON from the config context of the devices/virtual machines.
66
- If you have a `prometheus-plugin-prometheus-sd` entry in your config context with the following schema it will be automatically picked up:
67
-
68
- ```yaml
69
- prometheus-plugin-prometheus-sd:
70
- - metrics_path: /not/metrics
71
- port: 4242
72
- scheme: https
73
- - port: 4243
74
- ```
75
-
76
- This allow you to configure those values directly into netbox instead of doing that inside the Prometheus
77
- config and filtering each scenario by a specific tag for instance.
78
-
79
- If there is only one entry you can also use this form:
80
-
81
- ```yaml
82
- prometheus-plugin-prometheus-sd:
83
- metrics_path: /not/metrics
84
- port: 4242
85
- scheme: https
86
- ```
87
-
88
- ### Example
89
-
90
- A working example on how to use this plugin with Prometheus is located at the `example` folder.
91
- Netbox content is created by using Netbox docker initializers.
92
-
93
- The demo data doesn't make sense, but they are good enough for demonstrating how to configure Prometheus
94
- and get demo data to Prometheus service discovery.
95
-
96
- Go to the `example` folder and run `docker-compose up --build`. Prometheus should get available on `http://localhost:9090`.
97
-
98
- Push some example devices and objects to Netbox using the initializers:
99
-
100
- ```
101
- docker-compose exec netbox /opt/netbox/netbox/manage.py load_initializer_data --path /opt/netbox/initializers
102
- ```
103
-
104
- Netbox content should then be available in the service discovery tab.
105
-
106
- ## Development
107
-
108
- We use [Poetry](https://python-poetry.org/) for dependency management and [invoke](https://www.pyinvoke.org/) as task runner.
109
- To test the plugin in an isolated environment, we use [testcontainers](https://testcontainers.com/?language=python)
110
- which creates "throwaway, lightweight" Netbox Docker containers.
111
-
112
- All code to run in docker is located under `develop`.
113
- To start a virtual env managed by poetry run `poetry shell`.
114
- All following commands are started inside this environment.
115
-
116
- In order to run tests invoke the tests:
117
-
118
- ```bash
119
- # Build the containers and execute all tests
120
- invoke test
121
- ```
122
-
123
- Features should be covered by a unit test, but some times it's easier to develop on an running system.
124
-
125
- ```bash
126
- # Start a development environment
127
- invoke build_dev
128
- ```
129
-
130
- Visit http://localhost:8000 and log in with the default admin credentials.
131
- You can now define Netbox entities and test around.
132
-
133
- API endpoints for testing can be found at http://localhost:8000/api/plugins/prometheus-sd/
134
-
135
- ## Conventional Commits
136
-
137
- This repository follows the Conventional Commits specification for versioning and changelog generation.
138
- Conventional Commits provide a standardized way of writing commit messages to convey semantic meaning
139
- about the changes made. Each commit message follows a defined format that includes a type,
140
- an optional scope, and a message. The types typically include features, fixes, documentation, and more.
141
- By adhering to this convention, we ensure clear and automated versioning, release notes, and changelog generation.