@@ -23,7 +23,6 @@ import (
2323 "fmt"
2424
2525 corev1 "k8s.io/api/core/v1"
26- "k8s.io/apimachinery/pkg/api/equality"
2726 "k8s.io/apimachinery/pkg/api/meta"
2827 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2928 "k8s.io/apimachinery/pkg/runtime"
@@ -64,7 +63,6 @@ func (ac *AggregatesController) Reconcile(ctx context.Context, req ctrl.Request)
6463 return ctrl.Result {}, nil
6564 }
6665
67- base := hv .DeepCopy ()
6866 desiredAggregateNames , desiredCondition := ac .determineDesiredState (hv )
6967
7068 // Extract current aggregate names for comparison
@@ -73,39 +71,51 @@ func (ac *AggregatesController) Reconcile(ctx context.Context, req ctrl.Request)
7371 currentAggregateNames [i ] = agg .Name
7472 }
7573
74+ var newAggregates []kvmv1.Aggregate
75+ aggregatesChanged := false
7676 if ! slicesEqualUnordered (desiredAggregateNames , currentAggregateNames ) {
7777 // Apply aggregates to OpenStack and update status
7878 aggregates , err := openstack .ApplyAggregates (ctx , ac .computeClient , hv .Name , desiredAggregateNames )
7979 if err != nil {
80- // Set error condition
80+ // Set error condition with retry on conflict
8181 condition := metav1.Condition {
8282 Type : kvmv1 .ConditionTypeAggregatesUpdated ,
8383 Status : metav1 .ConditionFalse ,
8484 Reason : kvmv1 .ConditionReasonFailed ,
8585 Message : fmt .Errorf ("failed to apply aggregates: %w" , err ).Error (),
8686 }
8787
88- if meta .SetStatusCondition (& hv .Status .Conditions , condition ) {
89- if err2 := ac .Status ().Patch (ctx , hv , k8sclient .MergeFromWithOptions (base ,
90- k8sclient.MergeFromWithOptimisticLock {}), k8sclient .FieldOwner (AggregatesControllerName )); err2 != nil {
91- return ctrl.Result {}, errors .Join (err , err2 )
92- }
88+ if err2 := utils .PatchHypervisorStatusWithRetry (ctx , ac .Client , hv .Name , AggregatesControllerName , func (h * kvmv1.Hypervisor ) {
89+ meta .SetStatusCondition (& h .Status .Conditions , condition )
90+ }); err2 != nil {
91+ return ctrl.Result {}, errors .Join (err , err2 )
9392 }
9493 return ctrl.Result {}, err
9594 }
9695
97- hv .Status .Aggregates = aggregates
96+ newAggregates = aggregates
97+ aggregatesChanged = true
9898 }
9999
100- // Set the condition based on the determined desired state
101- meta .SetStatusCondition (& hv .Status .Conditions , desiredCondition )
102-
103- if equality .Semantic .DeepEqual (base , hv ) {
100+ // Skip the round-trip when nothing would change
101+ existing := meta .FindStatusCondition (hv .Status .Conditions , desiredCondition .Type )
102+ conditionUnchanged := existing != nil &&
103+ existing .Status == desiredCondition .Status &&
104+ existing .Reason == desiredCondition .Reason &&
105+ existing .Message == desiredCondition .Message
106+ if ! aggregatesChanged && conditionUnchanged {
104107 return ctrl.Result {}, nil
105108 }
106109
107- return ctrl.Result {}, ac .Status ().Patch (ctx , hv , k8sclient .MergeFromWithOptions (base ,
108- k8sclient.MergeFromWithOptimisticLock {}), k8sclient .FieldOwner (AggregatesControllerName ))
110+ // Patch status with retry on conflict
111+ err := utils .PatchHypervisorStatusWithRetry (ctx , ac .Client , hv .Name , AggregatesControllerName , func (h * kvmv1.Hypervisor ) {
112+ if aggregatesChanged {
113+ h .Status .Aggregates = newAggregates
114+ }
115+ meta .SetStatusCondition (& h .Status .Conditions , desiredCondition )
116+ })
117+
118+ return ctrl.Result {}, err
109119}
110120
111121// determineDesiredState returns the desired aggregates and the corresponding condition
0 commit comments