@@ -148,81 +148,89 @@ func ResolveBundle(r resolve.Resolver, c client.Client) ReconcileStepFunc {
148148func handleResolutionError (ctx context.Context , c client.Client , state * reconcileState , ext * ocv1.ClusterExtension , err error ) (* ctrl.Result , error ) {
149149 l := log .FromContext (ctx )
150150
151- // If we have an installed bundle, check if we can fall back to it
152- if state .revisionStates .Installed != nil {
153- // Check if the spec is requesting a specific version that differs from installed
154- specVersion := ""
155- if ext .Spec .Source .Catalog != nil {
156- specVersion = ext .Spec .Source .Catalog .Version
157- }
158- installedVersion := state .revisionStates .Installed .Version
159-
160- // If spec requests a different version, we cannot fall back - must fail and retry
161- if specVersion != "" && specVersion != installedVersion {
162- msg := fmt .Sprintf ("unable to upgrade to version %s: %v (currently installed: %s)" , specVersion , err , installedVersion )
163- l .Error (err , "resolution failed and spec requests version change - cannot fall back" ,
164- "requestedVersion" , specVersion ,
165- "installedVersion" , installedVersion )
166- setStatusProgressing (ext , err )
167- setInstalledStatusFromRevisionStates (ext , state .revisionStates )
168- ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
169- return nil , err
170- }
151+ // No installed bundle and resolution failed - cannot proceed
152+ if state .revisionStates .Installed == nil {
153+ msg := fmt .Sprintf ("failed to resolve bundle: %v" , err )
154+ setStatusProgressing (ext , err )
155+ setInstalledStatusFromRevisionStates (ext , state .revisionStates )
156+ ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
157+ return nil , err
158+ }
171159
172- // No version change requested - check if ClusterCatalogs exist
173- // Only fall back if ClusterCatalogs have been deleted
174- catalogsExist , catalogCheckErr := CheckCatalogsExist (ctx , c , ext )
175- if catalogCheckErr != nil {
176- msg := fmt .Sprintf ("failed to resolve bundle: %v" , err )
177- catalogName := getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
178- l .Error (catalogCheckErr , "error checking if ClusterCatalogs exist, will retry resolution" ,
179- "resolutionError" , err ,
180- "packageName" , getPackageName (ext ),
181- "catalogName" , catalogName )
182- setStatusProgressing (ext , err )
183- setInstalledStatusFromRevisionStates (ext , state .revisionStates )
184- ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
185- return nil , err
186- }
160+ // Check if the spec is requesting a specific version that differs from installed
161+ specVersion := ""
162+ if ext .Spec .Source .Catalog != nil {
163+ specVersion = ext .Spec .Source .Catalog .Version
164+ }
165+ installedVersion := state .revisionStates .Installed .Version
166+
167+ // If spec requests a different version, we cannot fall back - must fail and retry
168+ if specVersion != "" && specVersion != installedVersion {
169+ msg := fmt .Sprintf ("unable to upgrade to version %s: %v (currently installed: %s)" , specVersion , err , installedVersion )
170+ l .Error (err , "resolution failed and spec requests version change - cannot fall back" ,
171+ "requestedVersion" , specVersion ,
172+ "installedVersion" , installedVersion )
173+ setStatusProgressing (ext , err )
174+ setInstalledStatusFromRevisionStates (ext , state .revisionStates )
175+ ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
176+ return nil , err
177+ }
187178
188- if catalogsExist {
189- // ClusterCatalogs exist but resolution failed - likely a transient issue (ClusterCatalog updating, cache stale, etc.)
190- // Retry resolution instead of falling back
191- msg := fmt .Sprintf ("failed to resolve bundle, retrying: %v" , err )
192- catalogName := getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
193- l .Error (err , "resolution failed but matching ClusterCatalogs exist - retrying instead of falling back" ,
194- "packageName" , getPackageName (ext ),
195- "catalogName" , catalogName )
196- setStatusProgressing (ext , err )
197- setInstalledStatusFromRevisionStates (ext , state .revisionStates )
198- ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
199- return nil , err
179+ // No version change requested - check if ClusterCatalogs exist
180+ // Only fall back if ClusterCatalogs have been deleted
181+ catalogsExist , catalogCheckErr := CheckCatalogsExist (ctx , c , ext )
182+ if catalogCheckErr != nil {
183+ msg := fmt .Sprintf ("failed to resolve bundle: %v" , err )
184+ var catalogName string
185+ if ext .Spec .Source .Catalog != nil {
186+ catalogName = getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
200187 }
188+ l .Error (catalogCheckErr , "error checking if ClusterCatalogs exist, will retry resolution" ,
189+ "resolutionError" , err ,
190+ "packageName" , getPackageName (ext ),
191+ "catalogName" , catalogName )
192+ setStatusProgressing (ext , err )
193+ setInstalledStatusFromRevisionStates (ext , state .revisionStates )
194+ ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
195+ return nil , err
196+ }
201197
202- // ClusterCatalogs don't exist (deleted) - fall back to installed bundle to maintain current state.
203- // The controller watches ClusterCatalog resources, so when ClusterCatalogs become available again,
204- // a reconcile will be triggered automatically, allowing the extension to upgrade.
205- msg := fmt .Sprintf ("continuing to maintain current installation at version %s due to catalog unavailability" , state .revisionStates .Installed .Version )
206- catalogName := getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
207- l .Error (err , "matching ClusterCatalogs unavailable or deleted - falling back to installed bundle to maintain workload" ,
198+ if catalogsExist {
199+ // ClusterCatalogs exist but resolution failed - likely a transient issue (ClusterCatalog updating, cache stale, etc.)
200+ // Retry resolution instead of falling back
201+ msg := fmt .Sprintf ("failed to resolve bundle, retrying: %v" , err )
202+ var catalogName string
203+ if ext .Spec .Source .Catalog != nil {
204+ catalogName = getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
205+ }
206+ l .Error (err , "resolution failed but matching ClusterCatalogs exist - retrying instead of falling back" ,
208207 "packageName" , getPackageName (ext ),
209- "catalogName" , catalogName ,
210- "installedBundle" , state .revisionStates .Installed .Name ,
211- "installedVersion" , state .revisionStates .Installed .Version )
208+ "catalogName" , catalogName )
212209 setStatusProgressing (ext , err )
213210 setInstalledStatusFromRevisionStates (ext , state .revisionStates )
214211 ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
215- state .resolvedRevisionMetadata = state .revisionStates .Installed
216- // Return no error to allow Apply step to run and maintain resources.
217- return nil , nil
212+ return nil , err
218213 }
219214
220- // No installed bundle and resolution failed - cannot proceed
221- msg := fmt .Sprintf ("failed to resolve bundle: %v" , err )
215+ // ClusterCatalogs don't exist (deleted) - fall back to installed bundle to maintain current state.
216+ // The controller watches ClusterCatalog resources, so when ClusterCatalogs become available again,
217+ // a reconcile will be triggered automatically, allowing the extension to upgrade.
218+ msg := fmt .Sprintf ("continuing to maintain current installation at version %s due to catalog unavailability" , state .revisionStates .Installed .Version )
219+ var catalogName string
220+ if ext .Spec .Source .Catalog != nil {
221+ catalogName = getCatalogNameFromSelector (ext .Spec .Source .Catalog .Selector )
222+ }
223+ l .Error (err , "matching ClusterCatalogs unavailable or deleted - falling back to installed bundle to maintain workload" ,
224+ "packageName" , getPackageName (ext ),
225+ "catalogName" , catalogName ,
226+ "installedBundle" , state .revisionStates .Installed .Name ,
227+ "installedVersion" , state .revisionStates .Installed .Version )
222228 setStatusProgressing (ext , err )
223229 setInstalledStatusFromRevisionStates (ext , state .revisionStates )
224230 ensureAllConditionsWithReason (ext , ocv1 .ReasonRetrying , msg )
225- return nil , err
231+ state .resolvedRevisionMetadata = state .revisionStates .Installed
232+ // Return no error to allow Apply step to run and maintain resources.
233+ return nil , nil
226234}
227235
228236// getCatalogNameFromSelector extracts the catalog name from the selector if available.
0 commit comments