@@ -22,7 +22,6 @@ import (
2222 "fmt"
2323
2424 corev1 "k8s.io/api/core/v1"
25- k8serrors "k8s.io/apimachinery/pkg/api/errors"
2625 "k8s.io/apimachinery/pkg/api/meta"
2726 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2827 "k8s.io/apimachinery/pkg/labels"
@@ -61,7 +60,6 @@ type HypervisorController struct {
6160// +kubebuilder:rbac:groups=kvm.cloud.sap,resources=hypervisors/status,verbs=get;list;watch;create;update;patch;delete
6261
6362func (hv * HypervisorController ) Reconcile (ctx context.Context , req ctrl.Request ) (ctrl.Result , error ) {
64- var lifecycleEnabled , skipTest bool
6563 log := logger .FromContext (ctx ).WithName (req .Name )
6664
6765 node := & corev1.Node {}
@@ -71,71 +69,58 @@ func (hv *HypervisorController) Reconcile(ctx context.Context, req ctrl.Request)
7169 }
7270
7371 nodeLabels := labels .Set (node .Labels )
74- if nodeLabels .Has (labelLifecycleMode ) {
75- lifecycleEnabled = true
76- skipTest = nodeLabels .Get (labelLifecycleMode ) == "skip-test"
77- }
78-
7972 hypervisor := & kvmv1.Hypervisor {
8073 ObjectMeta : metav1.ObjectMeta {
8174 Name : node .Name ,
8275 Labels : map [string ]string {},
8376 },
8477 Spec : kvmv1.HypervisorSpec {
85- LifecycleEnabled : lifecycleEnabled ,
86- SkipTests : skipTest ,
8778 HighAvailability : true ,
8879 InstallCertificate : true ,
8980 },
9081 }
9182
92- // Transfer Labels
93- for _ , label := range transferLabels {
94- if nodeLabels .Has (label ) {
95- hypervisor .Labels [label ] = nodeLabels .Get (label )
96- }
97- }
98-
99- // Ensure corresponding hypervisor exists
100- if err := hv .Get (ctx , k8sclient .ObjectKeyFromObject (hypervisor ), hypervisor ); err != nil {
101- if k8serrors .IsNotFound (err ) {
102- // attach ownerReference for cascading deletion
103- if err = controllerutil .SetControllerReference (node , hypervisor , hv .Scheme ); err != nil {
104- return ctrl.Result {}, fmt .Errorf ("failed setting controller reference: %w" , err )
105- }
106-
107- log .Info ("Setup hypervisor" , "name" , node .Name )
108- if err = hv .Create (ctx , hypervisor ); err != nil {
109- return ctrl.Result {}, err
83+ // Ensure corresponding hypervisor exists or update it
84+ op , err := controllerutil .CreateOrPatch (ctx , hv .Client , hypervisor , func () error {
85+ // Transfer Labels
86+ for _ , label := range transferLabels {
87+ if nodeLabels .Has (label ) {
88+ hypervisor .Labels [label ] = nodeLabels .Get (label )
11089 }
90+ }
11191
112- // Requeue to update status
113- return ctrl.Result {RequeueAfter : 0 }, nil
92+ if nodeLabels .Has (labelLifecycleMode ) {
93+ hypervisor .Spec .LifecycleEnabled = true
94+ hypervisor .Spec .SkipTests = nodeLabels .Get (labelLifecycleMode ) == "skip-tests"
11495 }
11596
116- return ctrl.Result {}, err
117- }
97+ if err := controllerutil .SetControllerReference (node , hypervisor , hv .Scheme ); err != nil {
98+ return fmt .Errorf ("failed setting controller reference: %w" , err )
99+ }
118100
119- nodeTerminationCondition := FindNodeStatusCondition (node .Status .Conditions , "Terminating" )
120- if nodeTerminationCondition != nil && nodeTerminationCondition .Status == corev1 .ConditionTrue {
121- // Node might be terminating, propagate condition to hypervisor
122- meta .SetStatusCondition (& hypervisor .Status .Conditions , metav1.Condition {
123- Type : kvmv1 .ConditionTypeReady ,
124- Status : metav1 .ConditionFalse ,
125- Reason : nodeTerminationCondition .Reason ,
126- Message : nodeTerminationCondition .Message ,
127- })
128- meta .SetStatusCondition (& hypervisor .Status .Conditions , metav1.Condition {
129- Type : kvmv1 .ConditionTypeTerminating ,
130- Status : metav1 .ConditionStatus (nodeTerminationCondition .Status ),
131- Reason : nodeTerminationCondition .Reason ,
132- Message : nodeTerminationCondition .Message ,
133- })
134-
135- // update status
136- if err := hv .Status ().Update (ctx , hypervisor ); err != nil {
137- return ctrl.Result {}, fmt .Errorf ("failed to update hypervisor status: %w" , err )
101+ nodeTerminationCondition := FindNodeStatusCondition (node .Status .Conditions , "Terminating" )
102+ if nodeTerminationCondition != nil && nodeTerminationCondition .Status == corev1 .ConditionTrue {
103+ // Node might be terminating, propagate condition to hypervisor
104+ meta .SetStatusCondition (& hypervisor .Status .Conditions , metav1.Condition {
105+ Type : kvmv1 .ConditionTypeReady ,
106+ Status : metav1 .ConditionFalse ,
107+ Reason : nodeTerminationCondition .Reason ,
108+ Message : nodeTerminationCondition .Message ,
109+ })
110+ meta .SetStatusCondition (& hypervisor .Status .Conditions , metav1.Condition {
111+ Type : kvmv1 .ConditionTypeTerminating ,
112+ Status : metav1 .ConditionStatus (nodeTerminationCondition .Status ),
113+ Reason : nodeTerminationCondition .Reason ,
114+ Message : nodeTerminationCondition .Message ,
115+ })
138116 }
117+
118+ return nil
119+ })
120+ if err != nil {
121+ log .Error (err , "Hypervisor reconcile failed" )
122+ } else if op != controllerutil .OperationResultNone {
123+ log .Info ("Hypervisor successfully reconciled" , "operation" , op )
139124 }
140125
141126 return ctrl.Result {}, nil
0 commit comments