@@ -18,7 +18,9 @@ package controllers
1818
1919import  (
2020	"context" 
21+ 	"fmt" 
2122
23+ 	"github.com/operator-framework/deppy/pkg/deppy/solver" 
2224	rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" 
2325	"k8s.io/apimachinery/pkg/api/equality" 
2426	apimeta "k8s.io/apimachinery/pkg/api/meta" 
@@ -35,6 +37,7 @@ import (
3537	operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" 
3638	"github.com/operator-framework/operator-controller/internal/resolution" 
3739	"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/bundles_and_dependencies" 
40+ 	"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity" 
3841)
3942
4043// OperatorReconciler reconciles a Operator object 
@@ -105,54 +108,87 @@ func checkForUnexpectedFieldChange(a, b operatorsv1alpha1.Operator) bool {
105108
106109// Helper function to do the actual reconcile 
107110func  (r  * OperatorReconciler ) reconcile (ctx  context.Context , op  * operatorsv1alpha1.Operator ) (ctrl.Result , error ) {
108- 	// define condition parameters 
109- 	var  status  =  metav1 .ConditionTrue 
110- 	var  reason  =  operatorsv1alpha1 .ReasonResolutionSucceeded 
111- 	var  message  =  "resolution was successful" 
112- 
113111	// run resolution 
114112	solution , err  :=  r .Resolver .Resolve (ctx )
115113	if  err  !=  nil  {
116- 		status  =  metav1 .ConditionFalse 
117- 		reason  =  operatorsv1alpha1 .ReasonResolutionFailed 
118- 		message  =  err .Error ()
119- 	} else  {
120- 		// extract package bundle path from resolved variable 
121- 		for  _ , variable  :=  range  solution .SelectedVariables () {
122- 			switch  v  :=  variable .(type ) {
123- 			case  * bundles_and_dependencies.BundleVariable :
124- 				packageName , err  :=  v .BundleEntity ().PackageName ()
125- 				if  err  !=  nil  {
126- 					return  ctrl.Result {}, err 
127- 				}
128- 				if  packageName  ==  op .Spec .PackageName  {
129- 					bundlePath , err  :=  v .BundleEntity ().BundlePath ()
130- 					if  err  !=  nil  {
131- 						return  ctrl.Result {}, err 
132- 					}
133- 					// Create bundleDeployment if not found or Update if needed 
134- 					dep  :=  r .generateExpectedBundleDeployment (* op , bundlePath )
135- 					if  err  :=  r .ensureBundleDeployment (ctx , dep ); err  !=  nil  {
136- 						return  ctrl.Result {}, err 
137- 					}
138- 					break 
139- 				}
140- 			}
141- 		}
114+ 		apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
115+ 			Type :               operatorsv1alpha1 .TypeReady ,
116+ 			Status :             metav1 .ConditionFalse ,
117+ 			Reason :             operatorsv1alpha1 .ReasonResolutionFailed ,
118+ 			Message :            err .Error (),
119+ 			ObservedGeneration : op .GetGeneration (),
120+ 		})
121+ 		return  ctrl.Result {}, err 
122+ 	}
123+ 
124+ 	// lookup the bundle entity in the solution that corresponds to the 
125+ 	// Operator's desired package name. 
126+ 	bundleEntity , err  :=  r .getBundleEntityFromSolution (solution , op .Spec .PackageName )
127+ 	if  err  !=  nil  {
128+ 		apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
129+ 			Type :               operatorsv1alpha1 .TypeReady ,
130+ 			Status :             metav1 .ConditionFalse ,
131+ 			Reason :             operatorsv1alpha1 .ReasonBundleLookupFailed ,
132+ 			Message :            err .Error (),
133+ 			ObservedGeneration : op .GetGeneration (),
134+ 		})
135+ 		return  ctrl.Result {}, err 
136+ 	}
137+ 
138+ 	// Get the bundle image reference for the bundle 
139+ 	bundleImage , err  :=  bundleEntity .BundlePath ()
140+ 	if  err  !=  nil  {
141+ 		apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
142+ 			Type :               operatorsv1alpha1 .TypeReady ,
143+ 			Status :             metav1 .ConditionFalse ,
144+ 			Reason :             operatorsv1alpha1 .ReasonBundleLookupFailed ,
145+ 			Message :            err .Error (),
146+ 			ObservedGeneration : op .GetGeneration (),
147+ 		})
148+ 		return  ctrl.Result {}, err 
149+ 	}
150+ 
151+ 	// Ensure a BundleDeployment exists with its bundle source from the bundle 
152+ 	// image we just looked up in the solution. 
153+ 	dep  :=  r .generateExpectedBundleDeployment (* op , bundleImage )
154+ 	if  err  :=  r .ensureBundleDeployment (ctx , dep ); err  !=  nil  {
155+ 		apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
156+ 			Type :               operatorsv1alpha1 .TypeReady ,
157+ 			Status :             metav1 .ConditionFalse ,
158+ 			Reason :             operatorsv1alpha1 .ReasonBundleDeploymentFailed ,
159+ 			Message :            err .Error (),
160+ 			ObservedGeneration : op .GetGeneration (),
161+ 		})
162+ 		return  ctrl.Result {}, err 
142163	}
143164
144165	// update operator status 
145166	apimeta .SetStatusCondition (& op .Status .Conditions , metav1.Condition {
146167		Type :               operatorsv1alpha1 .TypeReady ,
147- 		Status :             status ,
148- 		Reason :             reason ,
149- 		Message :            message ,
168+ 		Status :             metav1 . ConditionTrue ,
169+ 		Reason :             operatorsv1alpha1 . ReasonResolutionSucceeded ,
170+ 		Message :            "resolution was successful" ,
150171		ObservedGeneration : op .GetGeneration (),
151172	})
152- 
153173	return  ctrl.Result {}, nil 
154174}
155175
176+ func  (r  * OperatorReconciler ) getBundleEntityFromSolution (solution  * solver.Solution , packageName  string ) (* entity.BundleEntity , error ) {
177+ 	for  _ , variable  :=  range  solution .SelectedVariables () {
178+ 		switch  v  :=  variable .(type ) {
179+ 		case  * bundles_and_dependencies.BundleVariable :
180+ 			entityPkgName , err  :=  v .BundleEntity ().PackageName ()
181+ 			if  err  !=  nil  {
182+ 				return  nil , err 
183+ 			}
184+ 			if  packageName  ==  entityPkgName  {
185+ 				return  v .BundleEntity (), nil 
186+ 			}
187+ 		}
188+ 	}
189+ 	return  nil , fmt .Errorf ("entity for package %q not found in solution" , packageName )
190+ }
191+ 
156192func  (r  * OperatorReconciler ) generateExpectedBundleDeployment (o  operatorsv1alpha1.Operator , bundlePath  string ) * unstructured.Unstructured  {
157193	// We use unstructured here to avoid problems of serializing default values when sending patches to the apiserver. 
158194	// If you use a typed object, any default values from that struct get serialized into the JSON patch, which could 
0 commit comments