@@ -27,13 +27,15 @@ import (
2727 "k8s.io/apimachinery/pkg/api/meta"
2828 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2929 "k8s.io/apimachinery/pkg/runtime"
30+ k8sacmetav1 "k8s.io/client-go/applyconfigurations/meta/v1"
3031 ctrl "sigs.k8s.io/controller-runtime"
3132 k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
3233
3334 "github.com/gophercloud/gophercloud/v2"
3435 "github.com/gophercloud/gophercloud/v2/openstack/placement/v1/resourceproviders"
3536
3637 kvmv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/api/v1"
38+ apiv1 "github.com/cobaltcore-dev/openstack-hypervisor-operator/applyconfigurations/api/v1"
3739 "github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/openstack"
3840 "github.com/cobaltcore-dev/openstack-hypervisor-operator/internal/utils"
3941)
@@ -103,11 +105,8 @@ func (tc *TraitsController) Reconcile(ctx context.Context, req ctrl.Request) (ct
103105 // fetch current traits, to ensure we don't add duplicates
104106 current , err := resourceproviders .GetTraits (ctx , tc .serviceClient , hv .Status .HypervisorID ).Extract ()
105107 if err != nil {
106- condition := getTraitCondition (err , "Failed to get current traits from placement" )
107- patchErr := utils .PatchHypervisorStatusWithRetry (ctx , tc .Client , hv .Name , TraitsControllerName , func (h * kvmv1.Hypervisor ) {
108- meta .SetStatusCondition (& h .Status .Conditions , condition )
109- })
110- return ctrl.Result {}, errors .Join (err , patchErr )
108+ return ctrl.Result {}, errors .Join (err ,
109+ tc .applyTraitsStatus (ctx , hv , hv .Status .Traits , getTraitCondition (err , "Failed to get current traits from placement" )))
111110 }
112111
113112 var targetTraits []string
@@ -131,22 +130,31 @@ func (tc *TraitsController) Reconcile(ctx context.Context, req ctrl.Request) (ct
131130 ResourceProviderGeneration : current .ResourceProviderGeneration ,
132131 Traits : targetTraits ,
133132 })
134- err = result .Err
135- if err != nil {
136- condition := getTraitCondition (err , "Failed to update traits in placement" )
137- patchErr := utils .PatchHypervisorStatusWithRetry (ctx , tc .Client , hv .Name , TraitsControllerName , func (h * kvmv1.Hypervisor ) {
138- meta .SetStatusCondition (& h .Status .Conditions , condition )
139- })
140- return ctrl.Result {}, errors .Join (err , patchErr )
133+ if result .Err != nil {
134+ return ctrl.Result {}, errors .Join (result .Err ,
135+ tc .applyTraitsStatus (ctx , hv , hv .Status .Traits , getTraitCondition (result .Err , "Failed to update traits in placement" )))
141136 }
142137 }
143138
144139 // update status unconditionally, since we want always to propagate the current traits
145- err = utils .PatchHypervisorStatusWithRetry (ctx , tc .Client , hv .Name , TraitsControllerName , func (h * kvmv1.Hypervisor ) {
146- h .Status .Traits = targetTraits
147- meta .SetStatusCondition (& h .Status .Conditions , getTraitCondition (nil , "Traits successfully updated" ))
148- })
149- return ctrl.Result {}, err
140+ return ctrl.Result {}, tc .applyTraitsStatus (ctx , hv , targetTraits , getTraitCondition (nil , "Traits successfully updated" ))
141+ }
142+
143+ func (tc * TraitsController ) applyTraitsStatus (ctx context.Context , hv * kvmv1.Hypervisor , traits []string , cond metav1.Condition ) error {
144+ statusCfg := apiv1 .HypervisorStatus ()
145+ statusCfg .Conditions = utils .ConditionsFromStatus (hv .Status .Conditions )
146+ utils .SetApplyConfigurationStatusCondition (& statusCfg .Conditions ,
147+ * k8sacmetav1 .Condition ().
148+ WithType (cond .Type ).
149+ WithStatus (cond .Status ).
150+ WithReason (cond .Reason ).
151+ WithMessage (cond .Message ))
152+ if traits != nil {
153+ statusCfg .WithTraits (traits ... )
154+ }
155+ return tc .Status ().Apply (ctx ,
156+ apiv1 .Hypervisor (hv .Name , "" ).WithStatus (statusCfg ),
157+ k8sclient .ForceOwnership , k8sclient .FieldOwner (TraitsControllerName ))
150158}
151159
152160// getTraitCondition creates a Condition object for trait updates
0 commit comments