From f3fdfbabd023f6a8364fd5b85ec4ceb9f6f38179 Mon Sep 17 00:00:00 2001 From: Chun-Hung Tseng Date: Wed, 20 Nov 2024 10:32:25 +0100 Subject: [PATCH] Add support for built-in field `family` --- ParentPrefixSelectorGuide.md | 9 +++++---- api/v1/prefixclaim_types.go | 3 ++- config/crd/bases/netbox.dev_prefixclaims.yaml | 4 +++- .../netbox_v1_prefixclaim_parentprefixselector.yaml | 1 + pkg/netbox/api/errors.go | 1 + pkg/netbox/api/prefix_claim.go | 11 +++++++++++ 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/ParentPrefixSelectorGuide.md b/ParentPrefixSelectorGuide.md index daeda957..3cfd4c45 100644 --- a/ParentPrefixSelectorGuide.md +++ b/ParentPrefixSelectorGuide.md @@ -28,6 +28,7 @@ spec: parentPrefixSelector: tenant: "MY_TENANT" site: "DM-Buffalo" + family: "IPv4" environment: "Production" poolName: "Pool 1" ``` @@ -47,10 +48,10 @@ The map contains a set of query conditions for selecting a set of prefixes that The query conditions will be chained by the AND operator, and exact match of the keys and values will be performed. The fields that can be used as query conditions in the `parentPrefixSelector` are: -- `tenant` and `site` (in lowercase characters) - - these 2 fields are built-in fields from NetBox, so you do *not* need to create custom fields for them - - please provide the *name*, not the *slug* value - - if the entry for tenant or site is missing, it will *not* inherit from the tenant and site from the Spec +- `tenant`, `site`, and `family` (in lowercase characters) + - these fields are built-in fields from NetBox, so you do *not* need to create custom fields for them + - please provide the *name*, not the *slug* value for `tenant` and `site` + - if the entry for `tenant` and `site` fields is missing, it will *not* inherit from the Spec - custom fields - the data types tested and supported so far are `string`, `integer`, and `boolean` - for `boolean` type, please use `true` and `false` as the value diff --git a/api/v1/prefixclaim_types.go b/api/v1/prefixclaim_types.go index 826a9909..54cdfcc0 100644 --- a/api/v1/prefixclaim_types.go +++ b/api/v1/prefixclaim_types.go @@ -39,9 +39,10 @@ type PrefixClaimSpec struct { // The `parentPrefixSelector` is a key-value map, where all the entries are of data type `` // The map contains a set of query conditions for selecting a set of prefixes that can be used as the parent prefix // The query conditions will be chained by the AND operator, and exact match of the keys and values will be performed - // 2 built-in fields, namely `tenant` and `site`, along with custom fields, can be used + // The built-in fields `tenant`, `site`, and `family`, along with custom fields, can be used // For more information, please see ParentPrefixSelectorGuide.md //+kubebuilder:validation:XValidation:rule="self == oldSelf",message="Field 'parentPrefixSelector' is immutable" + //+kubebuilder:validation:XValidation:rule="!has(self.family) || (self.family == 'IPv4' || self.family == 'IPv6')" ParentPrefixSelector map[string]string `json:"parentPrefixSelector,omitempty"` //+kubebuilder:validation:Required diff --git a/config/crd/bases/netbox.dev_prefixclaims.yaml b/config/crd/bases/netbox.dev_prefixclaims.yaml index 5cfc979d..31459bac 100644 --- a/config/crd/bases/netbox.dev_prefixclaims.yaml +++ b/config/crd/bases/netbox.dev_prefixclaims.yaml @@ -77,12 +77,14 @@ spec: The `parentPrefixSelector` is a key-value map, where all the entries are of data type `` The map contains a set of query conditions for selecting a set of prefixes that can be used as the parent prefix The query conditions will be chained by the AND operator, and exact match of the keys and values will be performed - 2 built-in fields, namely `tenant` and `site`, along with custom fields, can be used + The built-in fields `tenant`, `site`, and `family`, along with custom fields, can be used For more information, please see ParentPrefixSelectorGuide.md type: object x-kubernetes-validations: - message: Field 'parentPrefixSelector' is immutable rule: self == oldSelf + - rule: '!has(self.family) || (self.family == ''IPv4'' || self.family + == ''IPv6'')' prefixLength: pattern: ^\/[0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]$ type: string diff --git a/config/samples/netbox_v1_prefixclaim_parentprefixselector.yaml b/config/samples/netbox_v1_prefixclaim_parentprefixselector.yaml index d51083fb..1db9785a 100644 --- a/config/samples/netbox_v1_prefixclaim_parentprefixselector.yaml +++ b/config/samples/netbox_v1_prefixclaim_parentprefixselector.yaml @@ -16,6 +16,7 @@ spec: # if the entry for tenant or site is missing, it will *not* inherit from the tenant and site from the Spec tenant: "MY_TENANT" # Use the `name` value instead of the `slug` value site: "DM-Buffalo" # Use the `name` value instead of the `slug` value + family: "IPv4" # Can only be either IPv4 or IPv6" # custom fields of your interest environment: "Production" diff --git a/pkg/netbox/api/errors.go b/pkg/netbox/api/errors.go index fe7100c5..302c8fbc 100644 --- a/pkg/netbox/api/errors.go +++ b/pkg/netbox/api/errors.go @@ -22,4 +22,5 @@ var ( ErrParentPrefixExhausted = errors.New("parent prefix exhausted") ErrParentPrefixNotFound = errors.New("parent prefix not found") ErrWrongMatchingPrefixSubnetFormat = errors.New("wrong matchingPrefix subnet format") + ErrInvalidIpFamily = errors.New("invalid IP Family") ) diff --git a/pkg/netbox/api/prefix_claim.go b/pkg/netbox/api/prefix_claim.go index 99a0e265..621eaee6 100644 --- a/pkg/netbox/api/prefix_claim.go +++ b/pkg/netbox/api/prefix_claim.go @@ -114,6 +114,17 @@ func (r *NetboxClient) GetAvailablePrefixByParentPrefixSelector(prefixClaimSpec fieldEntries["site_id"] = strconv.Itoa(int(details.Id)) } + if family, ok := prefixClaimSpec.ParentPrefixSelector["family"]; ok { + if family == "IPv4" { + family = "4" + } else if family == "IPv6" { + family = "6" + } else { + return nil, ErrInvalidIpFamily + } + fieldEntries["family"] = family + } + var conditions func(co *runtime.ClientOperation) parentPrefixSelectorEntries := make([]CustomFieldEntry, 0, len(prefixClaimSpec.ParentPrefixSelector)) for k, v := range prefixClaimSpec.ParentPrefixSelector {