Skip to content

Commit ff7f155

Browse files
committed
use availabe ips in range to create list for status
1 parent a3b932d commit ff7f155

File tree

11 files changed

+130
-100
lines changed

11 files changed

+130
-100
lines changed

api/v1/iprangeclaim_types.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ type IpRangeClaimSpec struct {
5151
type IpRangeClaimStatus struct {
5252
IpRange string `json:"ipRange,omitempty"`
5353

54+
IpRangeDotDecimal string `json:"ipRangeDotDecimal,omitempty"`
55+
56+
IpAddresses []string `json:"ipAddresses,omitempty"`
57+
58+
IpAddressesDotDecimal []string `json:"ipAddressesDotDecimal,omitempty"`
59+
60+
StartAddress string `json:"startAddress,omitempty"`
61+
62+
StartAddressDotDecimal string `json:"startAddressDotDecimal,omitempty"`
63+
64+
EndAddress string `json:"endAddress,omitempty"`
65+
66+
EndAddressDotDecimal string `json:"endAddressDotDecimal,omitempty"`
67+
5468
IpRangeName string `json:"ipAddressName,omitempty"`
5569

5670
Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
@@ -60,7 +74,7 @@ type IpRangeClaimStatus struct {
6074
//+kubebuilder:subresource:status
6175
//+kubebuilder:storageversion
6276
//+kubebuilder:printcolumn:name="IpRange",type=string,JSONPath=`.status.ipRange`
63-
//+kubebuilder:printcolumn:name="IpRangeAssigned",type=string,JSONPath=`.status.conditions[?(@.type=="IPAssigned")].status`
77+
//+kubebuilder:printcolumn:name="IpRangeAssigned",type=string,JSONPath=`.status.conditions[?(@.type=="IpRangeAssigned")].status`
6478
//+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
6579
//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
6680
// +kubebuilder:resource:shortName=irc
@@ -115,9 +129,9 @@ var ConditionIpRangeAssignedFalse = metav1.Condition{
115129
Message: "Failed to fetch new Ip Range from NetBox",
116130
}
117131

118-
var ConditionIpAssignedFalseSizeMissmatch = metav1.Condition{
132+
var ConditionIpRangeAssignedFalseSizeMissmatch = metav1.Condition{
119133
Type: "IpRangeAssigned",
120134
Status: "False",
121135
Reason: "IpRangeCRNotCreated",
122-
Message: "Size of restored IpRange does not match the requested size",
136+
Message: "Assigned/Resored ip range has less available ip addresses than requested",
123137
}

api/v1/zz_generated.deepcopy.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/netbox.dev_iprangeclaims.yaml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ spec:
2020
- jsonPath: .status.ipRange
2121
name: IpRange
2222
type: string
23-
- jsonPath: .status.conditions[?(@.type=="IPAssigned")].status
23+
- jsonPath: .status.conditions[?(@.type=="IpRangeAssigned")].status
2424
name: IpRangeAssigned
2525
type: string
2626
- jsonPath: .status.conditions[?(@.type=="Ready")].status
@@ -155,10 +155,28 @@ spec:
155155
- type
156156
type: object
157157
type: array
158+
endAddress:
159+
type: string
160+
endAddressDotDecimal:
161+
type: string
158162
ipAddressName:
159163
type: string
164+
ipAddresses:
165+
items:
166+
type: string
167+
type: array
168+
ipAddressesDotDecimal:
169+
items:
170+
type: string
171+
type: array
160172
ipRange:
161173
type: string
174+
ipRangeDotDecimal:
175+
type: string
176+
startAddress:
177+
type: string
178+
startAddressDotDecimal:
179+
type: string
162180
type: object
163181
type: object
164182
served: true

gen/mock_interfaces/netbox_mocks.go

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/controller/iprangeclaim_controller.go

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"time"
2424

2525
netboxv1 "github.com/netbox-community/netbox-operator/api/v1"
26-
"github.com/netbox-community/netbox-operator/pkg/config"
2726
"github.com/netbox-community/netbox-operator/pkg/netbox/api"
2827
"github.com/netbox-community/netbox-operator/pkg/netbox/models"
2928
"github.com/swisscom/leaselocker"
@@ -102,9 +101,9 @@ func (r *IpRangeClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
102101

103102
// 4. try to reclaim ip range
104103
h := generateIpRangeRestorationHash(o)
105-
ipRangeModel, err := r.NetboxClient.RestoreExistingIpRangeByHash(config.GetOperatorConfig().NetboxRestorationHashFieldName, h)
104+
ipRangeModel, err := r.NetboxClient.RestoreExistingIpRangeByHash(h)
106105
if err != nil {
107-
if err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpAssignedFalse, corev1.EventTypeWarning, "", err); err != nil {
106+
if err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeAssignedFalse, corev1.EventTypeWarning, "", err); err != nil {
108107
return ctrl.Result{}, err
109108
}
110109
return ctrl.Result{Requeue: true}, nil
@@ -123,7 +122,7 @@ func (r *IpRangeClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
123122
},
124123
)
125124
if err != nil {
126-
if err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpAssignedFalse, corev1.EventTypeWarning, "", err); err != nil {
125+
if err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeAssignedFalse, corev1.EventTypeWarning, "", err); err != nil {
127126
return ctrl.Result{}, err
128127
}
129128
return ctrl.Result{Requeue: true}, nil
@@ -133,10 +132,10 @@ func (r *IpRangeClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
133132
// 5.b reassign reserved ip range from netbox
134133

135134
// check if the restored ip range has the size requested by the claim
136-
err = correctSizeOrErr(*ipRangeModel, o.Spec.Size)
137-
if err != nil {
135+
availableIps, err := r.NetboxClient.GetAvailableIpAddressesByIpRange(ipRangeModel.Id)
136+
if len(availableIps.Payload) != o.Spec.Size {
138137
ll.Unlock()
139-
err = r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpAssignedFalseSizeMissmatch, corev1.EventTypeWarning, "", err)
138+
err = r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeAssignedFalseSizeMissmatch, corev1.EventTypeWarning, "", err)
140139
if err != nil {
141140
return ctrl.Result{}, err
142141
}
@@ -173,7 +172,7 @@ func (r *IpRangeClaimReconciler) Reconcile(ctx context.Context, req ctrl.Request
173172
}
174173
}
175174

176-
err = r.updateIpRangeClaimReadyStatus(ctx, o, ipRange)
175+
err = r.updateIpRangeClaimStatus(ctx, o, ipRange)
177176
if err != nil {
178177
return ctrl.Result{}, err
179178
}
@@ -256,21 +255,46 @@ func (r *IpRangeClaimReconciler) tryLockOnParentPrefix(ctx context.Context, o *n
256255
return ll, ctrl.Result{}, nil
257256
}
258257

259-
func (r *IpRangeClaimReconciler) updateIpRangeClaimReadyStatus(ctx context.Context, o *netboxv1.IpRangeClaim, ipRange *netboxv1.IpRange) error {
258+
func (r *IpRangeClaimReconciler) updateIpRangeClaimStatus(ctx context.Context, o *netboxv1.IpRangeClaim, ipRange *netboxv1.IpRange) error {
260259
debugLogger := log.FromContext(ctx).V(4)
261260

262261
if apismeta.IsStatusConditionTrue(ipRange.Status.Conditions, "Ready") {
263262
debugLogger.Info("iprange status ready true")
264-
o.Status.IpRange = fmt.Sprintf("%s-%s", strings.Split(ipRange.Spec.StartAddress, "/")[0],
265-
strings.Split(ipRange.Spec.EndAddress, "/")[0])
263+
264+
startAddressDotDecimal := strings.Split(ipRange.Spec.StartAddress, "/")[0]
265+
endAddressDotDecimal := strings.Split(ipRange.Spec.EndAddress, "/")[0]
266+
267+
o.Status.IpRange = fmt.Sprintf("%s-%s", ipRange.Spec.StartAddress, ipRange.Spec.EndAddress)
268+
269+
o.Status.IpRangeDotDecimal = fmt.Sprintf("%s-%s", startAddressDotDecimal, endAddressDotDecimal)
270+
271+
availableIps, err := r.NetboxClient.GetAvailableIpAddressesByIpRange(ipRange.Status.IpRangeId)
272+
if err != nil {
273+
return err
274+
}
275+
276+
o.Status.IpAddresses = []string{}
277+
o.Status.IpAddressesDotDecimal = []string{}
278+
for _, ip := range availableIps.Payload {
279+
o.Status.IpAddresses = append(o.Status.IpAddresses, ip.Address)
280+
o.Status.IpAddressesDotDecimal = append(o.Status.IpAddressesDotDecimal, strings.Split(ip.Address, "/")[0])
281+
}
282+
283+
o.Status.StartAddress = ipRange.Spec.StartAddress
284+
o.Status.StartAddressDotDecimal = startAddressDotDecimal
285+
286+
o.Status.EndAddress = ipRange.Spec.EndAddress
287+
o.Status.EndAddressDotDecimal = endAddressDotDecimal
288+
266289
o.Status.IpRangeName = ipRange.Name
267-
err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpClaimReadyTrue, corev1.EventTypeNormal, "", nil)
290+
291+
err = r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeReadyTrue, corev1.EventTypeNormal, "", nil)
268292
if err != nil {
269293
return err
270294
}
271295
} else {
272296
debugLogger.Info("iprange status ready false")
273-
err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpClaimReadyFalse, corev1.EventTypeWarning, "", nil)
297+
err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeReadyFalse, corev1.EventTypeWarning, "", nil)
274298
if err != nil {
275299
return err
276300
}
@@ -288,14 +312,14 @@ func (r *IpRangeClaimReconciler) createIpRangeCR(ctx context.Context, o *netboxv
288312

289313
err = r.Client.Create(ctx, ipRangeResource)
290314
if err != nil {
291-
err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpAssignedFalse, corev1.EventTypeWarning, "", err)
315+
err := r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeAssignedFalse, corev1.EventTypeWarning, "", err)
292316
if err != nil {
293317
return err
294318
}
295319
return err
296320
}
297321

298-
err = r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpAssignedTrue, corev1.EventTypeNormal, "", nil)
322+
err = r.SetConditionAndCreateEvent(ctx, o, netboxv1.ConditionIpRangeAssignedTrue, corev1.EventTypeNormal, "", nil)
299323
if err != nil {
300324
return err
301325
}

internal/controller/iprangeclaim_controller_test.go

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,45 +23,10 @@ import (
2323
. "github.com/onsi/gomega"
2424

2525
netboxv1 "github.com/netbox-community/netbox-operator/api/v1"
26-
"github.com/netbox-community/netbox-operator/pkg/netbox/models"
2726
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2827
)
2928

3029
var _ = Describe("IpRangeClaim Controller", func() {
31-
Context("When checking the ip range size", func() {
32-
It("should succeed if correct size", func() {
33-
ipRange := &models.IpRange{
34-
StartAddress: "1.0.0.1/32",
35-
EndAddress: "1.0.0.3/32",
36-
}
37-
Expect(correctSizeOrErr(*ipRange, 3)).To(Succeed())
38-
})
39-
40-
It("should succeed if correct size IPv6", func() {
41-
ipRange := &models.IpRange{
42-
StartAddress: "2001:db8:85a3:8d3::1/128",
43-
EndAddress: "2001:db8:85a3:8d3::3/128",
44-
}
45-
Expect(correctSizeOrErr(*ipRange, 3)).To(Succeed())
46-
})
47-
48-
It("should fail if wrong size", func() {
49-
ipRange := &models.IpRange{
50-
StartAddress: "1.0.0.1/32",
51-
EndAddress: "1.0.0.2/32",
52-
}
53-
Expect(correctSizeOrErr(*ipRange, 3)).To(HaveOccurred())
54-
})
55-
56-
It("should fail if ip adresses are invalid", func() {
57-
ipRange := &models.IpRange{
58-
StartAddress: "",
59-
EndAddress: "",
60-
}
61-
Expect(correctSizeOrErr(*ipRange, 3)).To(HaveOccurred())
62-
})
63-
})
64-
6530
Context("When generating the ip range spec", func() {
6631
It("should create the correct spec", func() {
6732
ctx := context.TODO()

internal/controller/iprangeclaim_helpers.go

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@ import (
2020
"context"
2121
"crypto/sha1"
2222
"fmt"
23-
"net"
2423

2524
"github.com/go-logr/logr"
2625
netboxv1 "github.com/netbox-community/netbox-operator/api/v1"
2726
"github.com/netbox-community/netbox-operator/pkg/config"
28-
"github.com/netbox-community/netbox-operator/pkg/netbox/models"
2927
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3028
"sigs.k8s.io/controller-runtime/pkg/log"
3129
)
@@ -79,43 +77,6 @@ func generateIpRangeRestorationHash(claim *netboxv1.IpRangeClaim) string {
7977
return fmt.Sprintf("%x", sha1.Sum([]byte(rd.Namespace+rd.Name+rd.ParentPrefix+rd.Tenant+rd.Size)))
8078
}
8179

82-
func correctSizeOrErr(ipRange models.IpRange, size int) error {
83-
// check if the restored ip range has the size that was requested in the claim
84-
// to detect if the ip range was restored correctly and was not edited in NetBox
85-
startIP, _, err := net.ParseCIDR(ipRange.StartAddress)
86-
if err != nil {
87-
return fmt.Errorf("invalid IP address in IP range")
88-
}
89-
90-
endIP, _, err := net.ParseCIDR(ipRange.EndAddress)
91-
if err != nil {
92-
return fmt.Errorf("invalid IP address in IP range")
93-
}
94-
95-
if startIP == nil || endIP == nil {
96-
return fmt.Errorf("invalid IP address in IP range")
97-
}
98-
99-
if startIP.To4() != nil && endIP.To4() != nil {
100-
ipRangeSize := int(endIP.To4()[3]-startIP.To4()[3]) + 1
101-
if ipRangeSize != size {
102-
return fmt.Errorf("IP range size mismatch: requested size by claim %d, size of restored ip range %d",
103-
size, ipRangeSize)
104-
}
105-
}
106-
if startIP.To16() != nil && endIP.To16() != nil {
107-
ipRangeSize := int(endIP.To16()[15]-startIP.To16()[15]) + 1
108-
if ipRangeSize != size {
109-
return fmt.Errorf("IP range size mismatch: requested size by claim %d, size of restored ip range %d",
110-
size, ipRangeSize)
111-
}
112-
}
113-
114-
// Calculate the size of the IP range
115-
116-
return nil
117-
}
118-
11980
type IpRangeClaimRestorationData struct {
12081
// only use immutable fields
12182
Namespace string

pkg/netbox/api/ip_range_claim.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,19 @@ import (
2323
"net"
2424

2525
"github.com/netbox-community/go-netbox/v3/netbox/client/ipam"
26+
"github.com/netbox-community/netbox-operator/pkg/config"
2627
"github.com/netbox-community/netbox-operator/pkg/netbox/models"
2728
"github.com/netbox-community/netbox-operator/pkg/netbox/utils"
2829
)
2930

30-
func (r *NetboxClient) RestoreExistingIpRangeByHash(customFieldName string, hash string) (*models.IpRange, error) {
31-
customIpSearch := newCustomFieldStringFilterOperation(customFieldName, hash)
32-
list, err := r.Ipam.IpamIPRangesList(ipam.NewIpamIPRangesListParams(), nil, customIpSearch)
31+
func (r *NetboxClient) RestoreExistingIpRangeByHash(hash string) (*models.IpRange, error) {
32+
customIpRangeSearch := newQueryFilterOperation(nil, []CustomFieldEntry{
33+
{
34+
key: config.GetOperatorConfig().NetboxRestorationHashFieldName,
35+
value: hash,
36+
},
37+
})
38+
list, err := r.Ipam.IpamIPRangesList(ipam.NewIpamIPRangesListParams(), nil, customIpRangeSearch)
3339
if err != nil {
3440
return nil, err
3541
}
@@ -51,6 +57,7 @@ func (r *NetboxClient) RestoreExistingIpRangeByHash(customFieldName string, hash
5157
return &models.IpRange{
5258
StartAddress: *res.StartAddress,
5359
EndAddress: *res.EndAddress,
60+
Id: res.ID,
5461
}, nil
5562
}
5663

@@ -99,6 +106,16 @@ func (r *NetboxClient) GetAvailableIpRangeByClaim(ipRangeClaim *models.IpRangeCl
99106
}, nil
100107
}
101108

109+
// GetAvailableIpsByIpRange returns all available Ips in Netbox matching IpRangeClaim requirements
110+
func (r *NetboxClient) GetAvailableIpAddressesByIpRange(ipRangeId int64) (*ipam.IpamIPRangesAvailableIpsListOK, error) {
111+
requestAvailableIPs := ipam.NewIpamIPRangesAvailableIpsListParams().WithID(ipRangeId)
112+
responseAvailableIPs, err := r.Ipam.IpamIPRangesAvailableIpsList(requestAvailableIPs, nil)
113+
if err != nil {
114+
return nil, err
115+
}
116+
return responseAvailableIPs, nil
117+
}
118+
102119
func searchAvailableIpRange(availableIps *ipam.IpamPrefixesAvailableIpsListOK, requiredSize int) (string, string, error) {
103120
// this function receives a list of available IPs it chan have IPv4 or IPv6 IPs
104121
// it will search for the first available range of IPs with the required size

0 commit comments

Comments
 (0)