@@ -162,14 +162,21 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
162162 return ctrl.Result {}, err
163163 }
164164
165- // update operator status
166- apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
167- Type : operatorsv1alpha1 .TypeReady ,
168- Status : metav1 .ConditionTrue ,
169- Reason : operatorsv1alpha1 .ReasonResolutionSucceeded ,
170- Message : "resolution was successful" ,
171- ObservedGeneration : op .GetGeneration (),
172- })
165+ // convert existing unstructured object into bundleDeployment for easier mapping of status.
166+ existingTypedBundleDeployment := & rukpakv1alpha1.BundleDeployment {}
167+ if err := runtime .DefaultUnstructuredConverter .FromUnstructured (dep .UnstructuredContent (), existingTypedBundleDeployment ); err != nil {
168+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
169+ Type : operatorsv1alpha1 .TypeReady ,
170+ Status : metav1 .ConditionUnknown ,
171+ Reason : operatorsv1alpha1 .ReasonInstallationSucceeded ,
172+ Message : err .Error (),
173+ ObservedGeneration : op .GetGeneration (),
174+ })
175+ return ctrl.Result {}, err
176+ }
177+
178+ // set the status of the operator based on the respective bundle deployment status conditions.
179+ apimeta .SetStatusCondition (& op .Status .Conditions , mapBDStatusToReadyCondition (existingTypedBundleDeployment , op .GetGeneration ()))
173180 return ctrl.Result {}, nil
174181}
175182
@@ -257,9 +264,12 @@ func (r *OperatorReconciler) ensureBundleDeployment(ctx context.Context, desired
257264 }
258265
259266 // If the existing BD already has everything that the desired BD has, no need to contact the API server.
267+ // Make sure the status of the existingBD from the server is as expected.
260268 if equality .Semantic .DeepDerivative (desiredBundleDeployment , existingBundleDeployment ) {
269+ * desiredBundleDeployment = * existingBundleDeployment
261270 return nil
262271 }
272+
263273 return r .Client .Patch (ctx , desiredBundleDeployment , client .Apply , client .ForceOwnership , client .FieldOwner ("operator-controller" ))
264274}
265275
@@ -277,3 +287,51 @@ func (r *OperatorReconciler) existingBundleDeploymentUnstructured(ctx context.Co
277287 }
278288 return & unstructured.Unstructured {Object : unstrExistingBundleDeploymentObj }, nil
279289}
290+
291+ // verifyBDStatus reads the various possibilities of status in bundle deployment and translates
292+ // into corresponding operator condition status and message.
293+ func verifyBDStatus (dep * rukpakv1alpha1.BundleDeployment ) (metav1.ConditionStatus , string ) {
294+ isValidBundleCond := apimeta .FindStatusCondition (dep .Status .Conditions , rukpakv1alpha1 .TypeHasValidBundle )
295+ isInstalledCond := apimeta .FindStatusCondition (dep .Status .Conditions , rukpakv1alpha1 .TypeInstalled )
296+
297+ if isValidBundleCond == nil && isInstalledCond == nil {
298+ return metav1 .ConditionUnknown , fmt .Sprintf ("waiting for bundleDeployment %q status to be updated" , dep .Name )
299+ }
300+
301+ if isValidBundleCond != nil && isValidBundleCond .Status == metav1 .ConditionFalse {
302+ return metav1 .ConditionFalse , isValidBundleCond .Message
303+ }
304+
305+ if isInstalledCond != nil && isInstalledCond .Status == metav1 .ConditionFalse {
306+ return metav1 .ConditionFalse , isInstalledCond .Message
307+ }
308+
309+ if isInstalledCond != nil && isInstalledCond .Status == metav1 .ConditionTrue {
310+ return metav1 .ConditionTrue , "install was successful"
311+ }
312+ return metav1 .ConditionUnknown , fmt .Sprintf ("could not determine the state of bundleDeployment %s" , dep .Name )
313+ }
314+
315+ // mapBDStatusToReadyCondition returns the operator object's "TypeReady" condition based on the bundle deployment statuses.
316+ func mapBDStatusToReadyCondition (existingBD * rukpakv1alpha1.BundleDeployment , observedGeneration int64 ) metav1.Condition {
317+ // update operator status:
318+ // 1. If the Operator "Ready" status is "Unknown": The status of successful bundleDeployment is unknown, wait till Rukpak updates the BD status.
319+ // 2. If the Operator "Ready" status is "True": Update the "successful resolution" status and return the result.
320+ // 3. If the Operator "Ready" status is "False": There is error observed from Rukpak. Update the status accordingly.
321+ status , message := verifyBDStatus (existingBD )
322+ var reason string
323+ // TODO: introduce a new reason for condition Unknown, instead of defaulting it to Installation Succeeded.
324+ if status == metav1 .ConditionTrue {
325+ reason = operatorsv1alpha1 .ReasonInstallationSucceeded
326+ } else {
327+ reason = operatorsv1alpha1 .ReasonBundleDeploymentFailed
328+ }
329+
330+ return metav1.Condition {
331+ Type : operatorsv1alpha1 .TypeReady ,
332+ Status : status ,
333+ Reason : reason ,
334+ Message : message ,
335+ ObservedGeneration : observedGeneration ,
336+ }
337+ }
0 commit comments