@@ -106,6 +106,16 @@ func checkForUnexpectedFieldChange(a, b operatorsv1alpha1.Operator) bool {
106106func (r * OperatorReconciler ) reconcile (ctx context.Context , op * operatorsv1alpha1.Operator ) (ctrl.Result , error ) {
107107 // validate spec
108108 if err := validators .ValidateOperatorSpec (op ); err != nil {
109+ // Set the TypeInstalled condition to Unknown to indicate that the resolution
110+ // hasn't been attempted yet, due to the spec being invalid.
111+ op .Status .InstalledBundleSource = ""
112+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
113+ Type : operatorsv1alpha1 .TypeInstalled ,
114+ Status : metav1 .ConditionUnknown ,
115+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
116+ Message : "installation has not been attempted as spec is invalid" ,
117+ ObservedGeneration : op .GetGeneration (),
118+ })
109119 // Set the TypeResolved condition to Unknown to indicate that the resolution
110120 // hasn't been attempted yet, due to the spec being invalid.
111121 op .Status .ResolvedBundleResource = ""
@@ -121,6 +131,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
121131 // run resolution
122132 solution , err := r .Resolver .Resolve (ctx )
123133 if err != nil {
134+ op .Status .InstalledBundleSource = ""
135+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
136+ Type : operatorsv1alpha1 .TypeInstalled ,
137+ Status : metav1 .ConditionUnknown ,
138+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
139+ Message : "installation has not been attempted as resolution failed" ,
140+ ObservedGeneration : op .GetGeneration (),
141+ })
124142 op .Status .ResolvedBundleResource = ""
125143 apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
126144 Type : operatorsv1alpha1 .TypeResolved ,
@@ -136,6 +154,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
136154 // Operator's desired package name.
137155 bundleEntity , err := r .getBundleEntityFromSolution (solution , op .Spec .PackageName )
138156 if err != nil {
157+ op .Status .InstalledBundleSource = ""
158+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
159+ Type : operatorsv1alpha1 .TypeInstalled ,
160+ Status : metav1 .ConditionUnknown ,
161+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
162+ Message : "installation has not been attempted as resolution failed" ,
163+ ObservedGeneration : op .GetGeneration (),
164+ })
139165 op .Status .ResolvedBundleResource = ""
140166 apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
141167 Type : operatorsv1alpha1 .TypeResolved ,
@@ -150,6 +176,14 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
150176 // Get the bundle image reference for the bundle
151177 bundleImage , err := bundleEntity .BundlePath ()
152178 if err != nil {
179+ op .Status .InstalledBundleSource = ""
180+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
181+ Type : operatorsv1alpha1 .TypeInstalled ,
182+ Status : metav1 .ConditionUnknown ,
183+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
184+ Message : "installation has not been attempted as resolution failed" ,
185+ ObservedGeneration : op .GetGeneration (),
186+ })
153187 op .Status .ResolvedBundleResource = ""
154188 apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
155189 Type : operatorsv1alpha1 .TypeResolved ,
@@ -176,20 +210,93 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha
176210 dep := r .generateExpectedBundleDeployment (* op , bundleImage )
177211 if err := r .ensureBundleDeployment (ctx , dep ); err != nil {
178212 // originally Reason: operatorsv1alpha1.ReasonInstallationFailed
213+ op .Status .InstalledBundleSource = ""
214+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
215+ Type : operatorsv1alpha1 .TypeInstalled ,
216+ Status : metav1 .ConditionFalse ,
217+ Reason : operatorsv1alpha1 .ReasonInstallationFailed ,
218+ Message : err .Error (),
219+ ObservedGeneration : op .GetGeneration (),
220+ })
179221 return ctrl.Result {}, err
180222 }
181223
182224 // convert existing unstructured object into bundleDeployment for easier mapping of status.
183225 existingTypedBundleDeployment := & rukpakv1alpha1.BundleDeployment {}
184226 if err := runtime .DefaultUnstructuredConverter .FromUnstructured (dep .UnstructuredContent (), existingTypedBundleDeployment ); err != nil {
185227 // originally Reason: operatorsv1alpha1.ReasonInstallationStatusUnknown
228+ op .Status .InstalledBundleSource = ""
229+ apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
230+ Type : operatorsv1alpha1 .TypeInstalled ,
231+ Status : metav1 .ConditionUnknown ,
232+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
233+ Message : err .Error (),
234+ ObservedGeneration : op .GetGeneration (),
235+ })
186236 return ctrl.Result {}, err
187237 }
188238
239+ // Let's set the proper Installed condition and installedBundleSource field based on the
240+ // existing BundleDeployment object status.
241+ installedCond , installedBundleSource := mapBDStatusToInstalledCondition (existingTypedBundleDeployment , op )
242+ apimeta .SetStatusCondition (& op .Status .Conditions , installedCond )
243+ op .Status .InstalledBundleSource = installedBundleSource
244+
189245 // set the status of the operator based on the respective bundle deployment status conditions.
190246 return ctrl.Result {}, nil
191247}
192248
249+ func mapBDStatusToInstalledCondition (existingTypedBundleDeployment * rukpakv1alpha1.BundleDeployment , op * operatorsv1alpha1.Operator ) (metav1.Condition , string ) {
250+ bundleDeploymentReady := apimeta .FindStatusCondition (existingTypedBundleDeployment .Status .Conditions , rukpakv1alpha1 .TypeInstalled )
251+ if bundleDeploymentReady == nil {
252+ return metav1.Condition {
253+ Type : operatorsv1alpha1 .TypeInstalled ,
254+ Status : metav1 .ConditionUnknown ,
255+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
256+ Message : "bundledeployment status is unknown" ,
257+ ObservedGeneration : op .GetGeneration (),
258+ }, ""
259+ }
260+
261+ if bundleDeploymentReady .Status != metav1 .ConditionTrue {
262+ return metav1.Condition {
263+ Type : operatorsv1alpha1 .TypeInstalled ,
264+ Status : metav1 .ConditionFalse ,
265+ Reason : operatorsv1alpha1 .ReasonInstallationFailed ,
266+ Message : fmt .Sprintf ("bundledeployment not ready: %s" , bundleDeploymentReady .Message ),
267+ ObservedGeneration : op .GetGeneration (),
268+ }, ""
269+ }
270+
271+ bundleDeploymentSource := existingTypedBundleDeployment .Spec .Template .Spec .Source
272+ switch bundleDeploymentSource .Type {
273+ case rukpakv1alpha1 .SourceTypeImage :
274+ return metav1.Condition {
275+ Type : operatorsv1alpha1 .TypeInstalled ,
276+ Status : metav1 .ConditionTrue ,
277+ Reason : operatorsv1alpha1 .ReasonSuccess ,
278+ Message : fmt .Sprintf ("installed from %q" , bundleDeploymentSource .Image .Ref ),
279+ ObservedGeneration : op .GetGeneration (),
280+ }, bundleDeploymentSource .Image .Ref
281+ case rukpakv1alpha1 .SourceTypeGit :
282+ return metav1.Condition {
283+ Type : operatorsv1alpha1 .TypeInstalled ,
284+ Status : metav1 .ConditionTrue ,
285+ Reason : operatorsv1alpha1 .ReasonSuccess ,
286+ Message : fmt .Sprintf ("installed from %q" , bundleDeploymentSource .Git .Repository + "@" + bundleDeploymentSource .Git .Ref .Commit ),
287+ ObservedGeneration : op .GetGeneration (),
288+ }, bundleDeploymentSource .Git .Repository + "@" + bundleDeploymentSource .Git .Ref .Commit
289+ default :
290+ return metav1.Condition {
291+ Type : operatorsv1alpha1 .TypeInstalled ,
292+ Status : metav1 .ConditionUnknown ,
293+ Reason : operatorsv1alpha1 .ReasonInstallationStatusUnknown ,
294+ Message : fmt .Sprintf ("unknown bundledeployment source type %q" , bundleDeploymentSource .Type ),
295+ ObservedGeneration : op .GetGeneration (),
296+ }, ""
297+ }
298+ }
299+
193300func (r * OperatorReconciler ) getBundleEntityFromSolution (solution * solver.Solution , packageName string ) (* entity.BundleEntity , error ) {
194301 for _ , variable := range solution .SelectedVariables () {
195302 switch v := variable .(type ) {
0 commit comments