Skip to content

Commit 6fa582d

Browse files
committed
Additional query filters, parallel queries and changelog query added
- region_name, tenant and tag properties added to the query filter - device_site, device_region and device_tags properties added to the version output - use_changelog option added - parallel_queries option added - golang version updated to 1.25.7
1 parent 3a0241e commit 6fa582d

File tree

15 files changed

+997
-261
lines changed

15 files changed

+997
-261
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
21
# Changelog
32

3+
## 0.2.0
4+
5+
* `region_name`, `tenant` and `tag` properties added to the query filter
6+
* `device_site`, `device_region` and `device_tags` properties added to the version output
7+
* `use_changelog` option added to use the NetBox changelog. See the documentation for details and performance considerations
8+
* `parallel_queries` option added to speed up the check process by running multiple queries in parallel
9+
* golang version updated to `1.25.7`
10+
11+
412
## 0.1.0
513

614
* official netbox library used

README.md

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ A concourse resource to trigger from netbox
66
This resource is built using a Dockerfile that uses a multi-stage build process. The first stage builds the Go application, and the second stage creates a minimal container image using distroless. The following optional build arguments are available:
77

88
- `BUILDER_NAME`: The name of the Go builder image (default: `golang`)
9-
- `BUILDER_VERSION`: The version of the Go builder image (default: `1.24.4-bookworm`)
10-
- `BASE_NAME`: The base image for the final container (default: `gcr.io/distroless/static-debian12`)
9+
- `BUILDER_VERSION`: The version of the Go builder image (default: `1.25.0-bookworm`)
10+
- `BASE_NAME`: The base image for the final container (default: `gcr.io/distroless/static-debian13`)
1111
- `BASE_VERSION`: The version of the base image (default: `latest`) (`nonroot` is not possible because Concourse [requires root permissions to run the resource](https://github.com/concourse/concourse/issues/403))
1212

1313
The following build arguments are mandatory:
@@ -32,7 +32,49 @@ This resource is designed to be used in a Concourse CI pipeline. It can be confi
3232

3333
### Configuration
3434

35-
The `source.url` parameter is mandatory. All fields in the `source.filter` section and the `source.token` are optional. Fields with brackets `[]` can contain multiple values. `source.filter.device_name` and `source.filter.interface_name` are using a `case-insensitive contains` filter. The `source.filter.get_config_context` parameter can be set to `true` to include the device's config context in the output. Because of the current limitation in the go-netbox library the config context is gathered with every query, but only included in the output if this parameter is set to `true`.
35+
#### Source Parameters
36+
37+
| Parameter | Default | Description |
38+
|-----------|---------|-------------|
39+
| `url` | *(none)* | The URL of the NetBox instance (mandatory) |
40+
| `token` | *(none)* | The API token for authentication |
41+
| `parallel_queries` | `1` | Number of parallel queries to NetBox. Can speed up the check process, but be careful not to overload your NetBox instance |
42+
| `use_changelog` | `false` | Use the NetBox changelog to determine which devices have interface changes. More efficient than querying all devices, but it may miss changes without a changelog entry |
43+
44+
> **Warning:** When `use_changelog` is enabled with filters like `tenant`, `site_name`, or `region_name`, performance may be significantly slower than the classic query. The changelog API fetches all change events globally and filters afterward, while the classic query applies filters directly at the API level. Use `use_changelog: false` (default) for better performance when filtering by tenant or other device attributes.
45+
46+
#### Filter Parameters
47+
48+
All filter parameters are optional and can be used in combination to narrow down the devices and interfaces that trigger the resource. If no filters are provided, all devices and their interfaces will be considered.
49+
50+
| Parameter | Default | Description |
51+
|-----------|---------|-------------|
52+
| `filter.site_name` | `[]` | Filter devices by site name(s) |
53+
| `filter.region_name` | `[]` | Filter devices by region name(s) |
54+
| `filter.tenant` | `[]` | Filter devices by tenant slug(s) (e.g., `my-tenant`) |
55+
| `filter.tag` | `[]` | Filter devices by tag slug(s) |
56+
| `filter.role` | `[]` | Filter devices by role slug(s) |
57+
| `filter.device_id` | `[]` | Filter devices by device ID(s) |
58+
| `filter.device_name` | `[]` | Filter devices by name (case-insensitive contains) |
59+
| `filter.device_type` | `[]` | Filter devices by device type(s) |
60+
| `filter.device_status` | `[]` | Filter devices by status (e.g., `active`, `planned`) |
61+
| `filter.get_config_context` | `false` | Include the device's config context in the output |
62+
63+
#### Server Interface Filter Parameters
64+
65+
Additional filters can be applied to the server interfaces of the devices. These filters will be applied after filtering the devices, so they will only affect the interfaces of the already filtered devices.
66+
67+
| Parameter | Default | Description |
68+
|-----------|---------|-------------|
69+
| `filter.server_interface.interface_id` | `[]` | Filter interfaces by interface ID(s) |
70+
| `filter.server_interface.interface_name` | `[]` | Filter interfaces by name (case-insensitive contains) |
71+
| `filter.server_interface.enabled` | *(none)* | Filter interfaces by enabled state |
72+
| `filter.server_interface.mgmt_only` | *(none)* | Filter interfaces by management-only flag |
73+
| `filter.server_interface.connected` | *(none)* | Filter interfaces by connected state |
74+
| `filter.server_interface.cabled` | *(none)* | Filter interfaces by cabled state |
75+
| `filter.server_interface.type` | `[]` | Filter interfaces by type(s) (e.g., `virtual`, `1000base-t`) |
76+
77+
#### Example Configuration
3678

3779
This is an example of how to configure the resource in a Concourse pipeline:
3880

@@ -52,9 +94,13 @@ resources:
5294
check_every: 15m
5395
source:
5496
url: "https://netbox.example.local"
55-
token: "your-api-token"
97+
token: "your-api-token",
98+
parallel_queries: 1,
99+
use_changelog: false,
56100
filter:
57101
site_name: ["site 1"]
102+
region_name: ["region 1"]
103+
tenant: ["my-tenant"]
58104
tag: ["tag1"]
59105
role: ["server"]
60106
device_id: [123]

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module github.com/sapcc/concourse-netbox-resource
22

3-
go 1.25.4
3+
go 1.25.7
44

55
require github.com/netbox-community/go-netbox/v4 v4.2.2-3

internal/app/check.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@ The output will be a JSON array of objects with their latest versions.
2121
{
2222
"source": {
2323
"url": "https://netbox.example.local",
24-
"token": "your-api-token"
24+
"token": "your-api-token",
25+
"parallel_queries": 4,
26+
"use_changelog": true,
2527
},
2628
"filter": {
2729
"site_name": ["My Site"],
30+
"region_name": ["My Region"],
31+
"tenant": ["My Tenant"],
2832
"tag": ["my-tag"],
2933
"role": ["server"],
3034
"device_id": [123],

internal/concourse/types.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ type Output struct {
1515
}
1616

1717
type Source struct {
18-
Url string `json:"url"`
19-
Token string `json:"token,omitempty"`
20-
Filter filter.NetboxObject `json:"filter,omitempty"`
18+
Url string `json:"url"`
19+
Token string `json:"token,omitempty"`
20+
ParallelQueries int `json:"parallel_queries,omitempty"`
21+
UseChangelog *bool `json:"use_changelog,omitempty"`
22+
Filter filter.NetboxObject `json:"filter,omitempty"`
2123
}
2224

2325
type Version struct {
@@ -27,6 +29,9 @@ type Version struct {
2729
DeviceId string `json:"device_id,omitempty"`
2830
DeviceName string `json:"device_name"`
2931
DeviceRole string `json:"device_role"`
32+
DeviceSite string `json:"device_site"`
33+
DeviceRegion string `json:"device_region,omitempty"`
34+
DeviceTags string `json:"device_tags,omitempty"`
3035
DeviceApiUrl string `json:"device_api_url,omitempty"`
3136
DeviceDisplayUrl string `json:"device_display_url,omitempty"`
3237
ConfigContext string `json:"config_context,omitempty"`

internal/filter/netbox.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package filter
22

33
type NetboxObject struct {
44
SiteName []string `json:"site_name,omitempty"`
5+
RegionName []string `json:"region_name,omitempty"`
6+
Tenant []string `json:"tenant,omitempty"`
57
Tag []string `json:"tag,omitempty"`
68
Role []string `json:"role,omitempty"`
79
DeviceId []int32 `json:"device_id,omitempty"`

internal/helper/tests.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ var (
9999
DeviceDisplayUrl string = "http://netbox.example.local/dcim/devices"
100100
DeviceRoleId int32 = 8
101101
DeviceRoleSlug string = "server"
102+
DeviceSiteId int32 = 1
103+
DeviceSiteSlug string = "test-site"
102104
)
103105

104106
func EnsureFolder(path string) error {

0 commit comments

Comments
 (0)