Skip to content

Commit 71c7422

Browse files
committed
using defer for status and logging improvements in ipaddressclaim_controller
1 parent 44e2aaf commit 71c7422

File tree

1 file changed

+60
-43
lines changed

1 file changed

+60
-43
lines changed

internal/controller/ipaddressclaim_controller.go

Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"strings"
2323
"time"
2424

25+
"github.com/go-logr/logr"
2526
netboxv1 "github.com/netbox-community/netbox-operator/api/v1"
2627
"github.com/netbox-community/netbox-operator/pkg/netbox/api"
2728
"github.com/netbox-community/netbox-operator/pkg/netbox/models"
@@ -74,11 +75,18 @@ func (r *IpAddressClaimReconciler) Reconcile(ctx context.Context, req ctrl.Reque
7475
return ctrl.Result{}, nil
7576
}
7677

78+
// Defer status update to ensure it happens regardless of how we exit
79+
// This follows Kubernetes controller best practices
80+
defer func() {
81+
if err := r.updateStatus(ctx, o, req.NamespacedName, debugLogger); err != nil {
82+
logger.Error(err, "failed to update IpAddressClaim status in deferred call")
83+
}
84+
}()
85+
7786
// Set ready to false initially
7887
if apismeta.FindStatusCondition(o.Status.Conditions, netboxv1.ConditionReadyFalseNewResource.Type) == nil {
79-
err := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionReadyFalseNewResource, corev1.EventTypeNormal, nil)
80-
if err != nil {
81-
return ctrl.Result{}, fmt.Errorf("failed to initialise Ready condition: %w, ", err)
88+
if err := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionReadyFalseNewResource, corev1.EventTypeNormal, nil); err != nil {
89+
return ctrl.Result{}, fmt.Errorf("failed to initialise Ready condition: %w", err)
8290
}
8391
}
8492

@@ -94,7 +102,7 @@ func (r *IpAddressClaimReconciler) Reconcile(ctx context.Context, req ctrl.Reque
94102
if err != nil {
95103
// return error if not a notfound error
96104
if !apierrors.IsNotFound(err) {
97-
return ctrl.Result{}, err
105+
return ctrl.Result{}, fmt.Errorf("failed to get IpAddress: %w", err)
98106
}
99107

100108
debugLogger.Info("ipaddress object matching ipaddress claim was not found, creating new ipaddress object")
@@ -106,7 +114,7 @@ func (r *IpAddressClaimReconciler) Reconcile(ctx context.Context, req ctrl.Reque
106114
}
107115
ll, err := leaselocker.NewLeaseLocker(r.RestConfig, leaseLockerNSN, req.Namespace+"/"+ipAddressName)
108116
if err != nil {
109-
return ctrl.Result{}, err
117+
return ctrl.Result{}, fmt.Errorf("failed to create lease locker: %w", err)
110118
}
111119

112120
lockCtx, cancel := context.WithCancel(ctx)
@@ -159,71 +167,45 @@ func (r *IpAddressClaimReconciler) Reconcile(ctx context.Context, req ctrl.Reque
159167

160168
// 6.a create the IPAddress object
161169
ipAddressResource := generateIpAddressFromIpAddressClaim(o, ipAddressModel.IpAddress, logger)
162-
err = controllerutil.SetControllerReference(o, ipAddressResource, r.Scheme)
163-
if err != nil {
164-
return ctrl.Result{}, err
170+
if err := controllerutil.SetControllerReference(o, ipAddressResource, r.Scheme); err != nil {
171+
return ctrl.Result{}, fmt.Errorf("failed to set controller reference: %w", err)
165172
}
166173

167-
err = r.Client.Create(ctx, ipAddressResource)
168-
if err != nil {
174+
if err := r.Client.Create(ctx, ipAddressResource); err != nil {
169175
if errReport := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionIpAssignedFalse, corev1.EventTypeWarning, err); errReport != nil {
170176
return ctrl.Result{}, errReport
171177
}
172-
return ctrl.Result{}, err
178+
return ctrl.Result{}, fmt.Errorf("failed to create IpAddress: %w", err)
173179
}
174180

175-
err = r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionIpAssignedTrue, corev1.EventTypeNormal, nil)
176-
if err != nil {
177-
return ctrl.Result{}, err
181+
if err := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionIpAssignedTrue, corev1.EventTypeNormal, nil); err != nil {
182+
return ctrl.Result{}, fmt.Errorf("failed to report IpAssigned condition: %w", err)
178183
}
179184

180185
} else {
181186
// 6.b update fields of IPAddress object
182187
debugLogger.Info("update ipaddress resource")
183-
err := r.Client.Get(ctx, ipAddressLookupKey, ipAddress)
184-
if err != nil {
185-
return ctrl.Result{}, err
188+
if err := r.Client.Get(ctx, ipAddressLookupKey, ipAddress); err != nil {
189+
return ctrl.Result{}, fmt.Errorf("failed to get IpAddress for update: %w", err)
186190
}
187191

188192
updatedIpAddressSpec := generateIpAddressSpec(o, ipAddress.Spec.IpAddress, logger)
189-
_, err = ctrl.CreateOrUpdate(ctx, r.Client, ipAddress, func() error {
193+
_, err := ctrl.CreateOrUpdate(ctx, r.Client, ipAddress, func() error {
190194
// only add the mutable fields here
191195
ipAddress.Spec.CustomFields = updatedIpAddressSpec.CustomFields
192196
ipAddress.Spec.Comments = updatedIpAddressSpec.Comments
193197
ipAddress.Spec.Description = updatedIpAddressSpec.Description
194198
ipAddress.Spec.PreserveInNetbox = updatedIpAddressSpec.PreserveInNetbox
195-
err = controllerutil.SetControllerReference(o, ipAddress, r.Scheme)
196-
if err != nil {
197-
return err
199+
if err := controllerutil.SetControllerReference(o, ipAddress, r.Scheme); err != nil {
200+
return fmt.Errorf("failed to set controller reference: %w", err)
198201
}
199202
return nil
200203
})
201204
if err != nil {
202-
return ctrl.Result{}, err
205+
return ctrl.Result{}, fmt.Errorf("failed to update IpAddress: %w", err)
203206
}
204207
}
205208

206-
// 7. update IPAddressClaim Ready status
207-
debugLogger.Info("update ipaddressclaim status")
208-
209-
if apismeta.IsStatusConditionTrue(ipAddress.Status.Conditions, "Ready") {
210-
debugLogger.Info("ipaddress status ready true")
211-
o.Status.IpAddress = ipAddress.Spec.IpAddress
212-
o.Status.IpAddressDotDecimal = strings.Split(ipAddress.Spec.IpAddress, "/")[0]
213-
o.Status.IpAddressName = ipAddress.Name
214-
err := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionIpClaimReadyTrue, corev1.EventTypeNormal, nil)
215-
if err != nil {
216-
return ctrl.Result{}, err
217-
}
218-
} else {
219-
debugLogger.Info("ipaddress status ready false")
220-
err := r.EventStatusRecorder.Report(ctx, o, netboxv1.ConditionIpClaimReadyFalse, corev1.EventTypeWarning, nil)
221-
if err != nil {
222-
return ctrl.Result{}, err
223-
}
224-
return ctrl.Result{Requeue: true}, nil
225-
}
226-
227209
logger.Info("reconcile loop finished")
228210
return ctrl.Result{}, nil
229211
}
@@ -235,3 +217,38 @@ func (r *IpAddressClaimReconciler) SetupWithManager(mgr ctrl.Manager) error {
235217
Owns(&netboxv1.IpAddress{}).
236218
Complete(r)
237219
}
220+
221+
// updateStatus updates the IpAddressClaim status based on the current state of the owned IpAddress.
222+
// This function is called as a deferred function in Reconcile to ensure status is always updated.
223+
func (r *IpAddressClaimReconciler) updateStatus(ctx context.Context, claim *netboxv1.IpAddressClaim, lookupKey types.NamespacedName, debugLogger logr.Logger) error {
224+
debugLogger.Info("updating ipaddressclaim status")
225+
226+
// Fetch the latest IpAddress object
227+
ipAddress := &netboxv1.IpAddress{}
228+
if err := r.Client.Get(ctx, lookupKey, ipAddress); err != nil {
229+
if apierrors.IsNotFound(err) {
230+
// IpAddress doesn't exist yet, this is expected during creation
231+
debugLogger.Info("ipaddress not found, skipping status update")
232+
return nil
233+
}
234+
return fmt.Errorf("failed to get IpAddress for status update: %w", err)
235+
}
236+
237+
// Update status based on IpAddress readiness
238+
if apismeta.IsStatusConditionTrue(ipAddress.Status.Conditions, "Ready") {
239+
debugLogger.Info("ipaddress status ready true")
240+
claim.Status.IpAddress = ipAddress.Spec.IpAddress
241+
claim.Status.IpAddressDotDecimal = strings.Split(ipAddress.Spec.IpAddress, "/")[0]
242+
claim.Status.IpAddressName = ipAddress.Name
243+
if err := r.EventStatusRecorder.Report(ctx, claim, netboxv1.ConditionIpClaimReadyTrue, corev1.EventTypeNormal, nil); err != nil {
244+
return fmt.Errorf("failed to report IpClaimReady true condition: %w", err)
245+
}
246+
} else {
247+
debugLogger.Info("ipaddress status ready false")
248+
if err := r.EventStatusRecorder.Report(ctx, claim, netboxv1.ConditionIpClaimReadyFalse, corev1.EventTypeWarning, nil); err != nil {
249+
return fmt.Errorf("failed to report IpClaimReady false condition: %w", err)
250+
}
251+
}
252+
253+
return nil
254+
}

0 commit comments

Comments
 (0)