Skip to content

Commit de8786e

Browse files
Add support for filtering netbox_prefix by custom fields (#819)
* Filter prefix by custom fields Signed-off-by: Christopher Svensson <christopher.svensson@stegra.com> * Support custom field query params Signed-off-by: Christopher Svensson <christopher.svensson@stegra.com> * Doc fix Signed-off-by: Christopher Svensson <christopher.svensson@stegra.com> * Added test to cover custom field filter Signed-off-by: Christopher Svensson <christopher.svensson@stegra.com> --------- Signed-off-by: Christopher Svensson <christopher.svensson@stegra.com>
1 parent 9321047 commit de8786e

File tree

4 files changed

+96
-28
lines changed

4 files changed

+96
-28
lines changed

docs/data-sources/prefix.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,22 @@ description: |-
1717

1818
### Optional
1919

20-
- `cidr` (String, Deprecated) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given. Conflicts with `prefix`.
21-
- `custom_fields` (Map of String)
22-
- `description` (String) Description to include in the data source filter. At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
23-
- `family` (Number) The IP family of the prefix. One of 4 or 6. At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
24-
- `prefix` (String) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given. Conflicts with `cidr`.
25-
- `role_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
26-
- `site_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
27-
- `status` (String) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
28-
- `tag` (String) Tag to include in the data source filter (must match the tag's slug). At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
20+
- `cidr` (String, Deprecated) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given. Conflicts with `prefix`.
21+
- `custom_fields` (Map of String) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
22+
- `description` (String) Description to include in the data source filter. At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
23+
- `family` (Number) The IP family of the prefix. One of 4 or 6. At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
24+
- `prefix` (String) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given. Conflicts with `cidr`.
25+
- `role_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
26+
- `site_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
27+
- `status` (String) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
28+
- `tag` (String) Tag to include in the data source filter (must match the tag's slug). At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
2929
- `tag__n` (String) Tag to exclude from the data source filter (must match the tag's slug).
3030
Refer to [Netbox's documentation](https://demo.netbox.dev/static/docs/rest-api/filtering/#lookup-expressions)
3131
for more information on available lookup expressions.
32-
- `tenant_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
33-
- `vlan_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
34-
- `vlan_vid` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
35-
- `vrf_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `tag` or `status` must be given.
32+
- `tenant_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
33+
- `vlan_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
34+
- `vlan_vid` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
35+
- `vrf_id` (Number) At least one of `description`, `family`, `prefix`, `vlan_vid`, `vrf_id`, `vlan_id`, `tenant_id`, `site_id`, `role_id`, `cidr`, `custom_fields`, `tag` or `status` must be given.
3636

3737
### Read-Only
3838

netbox/custom_fields.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ package netbox
33
import (
44
"encoding/json"
55
"fmt"
6+
"net/url"
67

8+
"github.com/go-openapi/runtime"
9+
"github.com/go-openapi/strfmt"
710
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
811
)
912

@@ -61,3 +64,37 @@ func flattenCustomFields(cf interface{}) map[string]interface{} {
6164

6265
return result
6366
}
67+
68+
type CustomFieldParams struct {
69+
params runtime.ClientRequestWriter
70+
cfm map[string]interface{}
71+
}
72+
73+
func (o *CustomFieldParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
74+
if err := o.params.WriteToRequest(r, reg); err != nil {
75+
return err
76+
}
77+
78+
for k, v := range o.cfm {
79+
if vs, ok := v.(string); ok {
80+
if err := r.SetQueryParam(fmt.Sprintf("cf_%s", url.QueryEscape(k)), vs); err != nil {
81+
return err
82+
}
83+
}
84+
}
85+
86+
return nil
87+
}
88+
89+
func WithCustomFieldParamsOption(cfm map[string]interface{}) func(*runtime.ClientOperation) {
90+
if cfm == nil {
91+
cfm = make(map[string]interface{})
92+
}
93+
94+
return func(co *runtime.ClientOperation) {
95+
co.Params = &CustomFieldParams{
96+
params: co.Params,
97+
cfm: cfm,
98+
}
99+
}
100+
}

netbox/data_source_netbox_prefix.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ import (
1010
)
1111

1212
func dataSourceNetboxPrefix() *schema.Resource {
13+
filterAtLeastOneOf := []string{
14+
"description",
15+
"family",
16+
"prefix",
17+
"vlan_vid",
18+
"vrf_id",
19+
"vlan_id",
20+
"tenant_id",
21+
"site_id",
22+
"role_id",
23+
"cidr",
24+
"custom_fields",
25+
"tag",
26+
"status",
27+
}
28+
customFieldsFilterSchema := *customFieldsSchema
29+
customFieldsFilterSchema.AtLeastOneOf = filterAtLeastOneOf
1330
return &schema.Resource{
1431
Read: dataSourceNetboxPrefixRead,
1532
Description: `:meta:subcategory:IP Address Management (IPAM):`,
@@ -24,62 +41,62 @@ func dataSourceNetboxPrefix() *schema.Resource {
2441
Deprecated: "The `cidr` parameter is deprecated in favor of the canonical `prefix` attribute.",
2542
ConflictsWith: []string{"prefix"},
2643
ValidateFunc: validation.IsCIDR,
27-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
44+
AtLeastOneOf: filterAtLeastOneOf,
2845
},
29-
customFieldsKey: customFieldsSchema,
46+
customFieldsKey: &customFieldsFilterSchema,
3047
"description": {
3148
Type: schema.TypeString,
3249
Optional: true,
3350
Computed: true,
34-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
51+
AtLeastOneOf: filterAtLeastOneOf,
3552
Description: "Description to include in the data source filter.",
3653
},
3754
"family": {
3855
Type: schema.TypeInt,
3956
Optional: true,
4057
Computed: true,
41-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
58+
AtLeastOneOf: filterAtLeastOneOf,
4259
ValidateFunc: validation.IntInSlice([]int{4, 6}),
4360
Description: "The IP family of the prefix. One of 4 or 6",
4461
},
4562
"role_id": {
4663
Type: schema.TypeInt,
4764
Optional: true,
4865
Computed: true,
49-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
66+
AtLeastOneOf: filterAtLeastOneOf,
5067
},
5168
"prefix": {
5269
Type: schema.TypeString,
5370
Optional: true,
5471
ValidateFunc: validation.IsCIDR,
5572
ConflictsWith: []string{"cidr"},
56-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
73+
AtLeastOneOf: filterAtLeastOneOf,
5774
},
5875
"vlan_vid": {
5976
Type: schema.TypeFloat,
6077
Optional: true,
61-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
78+
AtLeastOneOf: filterAtLeastOneOf,
6279
ValidateFunc: validation.FloatBetween(1, 4094),
6380
},
6481
"vrf_id": {
6582
Type: schema.TypeInt,
6683
Optional: true,
67-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
84+
AtLeastOneOf: filterAtLeastOneOf,
6885
},
6986
"vlan_id": {
7087
Type: schema.TypeInt,
7188
Optional: true,
72-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
89+
AtLeastOneOf: filterAtLeastOneOf,
7390
},
7491
"tenant_id": {
7592
Type: schema.TypeInt,
7693
Optional: true,
77-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
94+
AtLeastOneOf: filterAtLeastOneOf,
7895
},
7996
"site_id": {
8097
Type: schema.TypeInt,
8198
Optional: true,
82-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
99+
AtLeastOneOf: filterAtLeastOneOf,
83100
},
84101
"site_group_id": {
85102
Type: schema.TypeInt,
@@ -96,7 +113,7 @@ func dataSourceNetboxPrefix() *schema.Resource {
96113
"tag": {
97114
Type: schema.TypeString,
98115
Optional: true,
99-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
116+
AtLeastOneOf: filterAtLeastOneOf,
100117
Description: "Tag to include in the data source filter (must match the tag's slug).",
101118
},
102119
"tag__n": {
@@ -109,7 +126,7 @@ for more information on available lookup expressions.`,
109126
"status": {
110127
Type: schema.TypeString,
111128
Optional: true,
112-
AtLeastOneOf: []string{"description", "family", "prefix", "vlan_vid", "vrf_id", "vlan_id", "tenant_id", "site_id", "role_id", "cidr", "tag", "status"},
129+
AtLeastOneOf: filterAtLeastOneOf,
113130
},
114131
"tags": tagsSchemaRead,
115132
},
@@ -120,6 +137,7 @@ func dataSourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error {
120137
api := m.(*providerState)
121138

122139
params := ipam.NewIpamPrefixesListParams()
140+
var opts []ipam.ClientOption
123141

124142
limit := int64(2) // Limit of 2 is enough
125143
params.Limit = &limit
@@ -181,7 +199,11 @@ func dataSourceNetboxPrefixRead(d *schema.ResourceData, m interface{}) error {
181199
params.Status = &status
182200
}
183201

184-
res, err := api.Ipam.IpamPrefixesList(params, nil)
202+
if cfm, ok := d.Get(customFieldsKey).(map[string]interface{}); ok {
203+
opts = append(opts, WithCustomFieldParamsOption(cfm))
204+
}
205+
206+
res, err := api.Ipam.IpamPrefixesList(params, nil, opts...)
185207
if err != nil {
186208
return err
187209
}

netbox/data_source_netbox_prefix_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,20 @@ resource "netbox_prefix" "test" {
165165
data "netbox_prefix" "test_output" {
166166
depends_on = [netbox_prefix.test]
167167
prefix = "%[2]s"
168-
}`, testField, testPrefix),
168+
}
169+
170+
data "netbox_prefix" "by_custom_fields" {
171+
depends_on = [netbox_prefix.test]
172+
custom_fields = {
173+
"${netbox_custom_field.test.name}" = "test value"
174+
}
175+
}
176+
`, testField, testPrefix),
169177
Check: resource.ComposeTestCheckFunc(
170178
resource.TestCheckResourceAttr("data.netbox_prefix.test_output", "status", "active"),
171179
resource.TestCheckResourceAttr("data.netbox_prefix.test_output", "prefix", testPrefix),
172180
resource.TestCheckResourceAttr("data.netbox_prefix.test_output", "custom_fields."+testField, "test value"),
181+
resource.TestCheckResourceAttrPair("data.netbox_prefix.by_custom_fields", "id", "netbox_prefix.test", "id"),
173182
),
174183
},
175184
},

0 commit comments

Comments
 (0)