@@ -38,14 +38,12 @@ import (
3838 "helm.sh/helm/v3/pkg/storage/driver"
3939 corev1 "k8s.io/api/core/v1"
4040 "k8s.io/apimachinery/pkg/api/equality"
41- apierrors "k8s.io/apimachinery/pkg/api/errors"
4241 apimeta "k8s.io/apimachinery/pkg/api/meta"
4342 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4443 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
4544 "k8s.io/apimachinery/pkg/runtime"
4645 "k8s.io/apimachinery/pkg/runtime/schema"
4746 "k8s.io/apimachinery/pkg/types"
48- utilerrors "k8s.io/apimachinery/pkg/util/errors"
4947 "k8s.io/apimachinery/pkg/util/sets"
5048 apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
5149 ctrl "sigs.k8s.io/controller-runtime"
@@ -120,40 +118,35 @@ func (r *ClusterExtensionReconciler) Reconcile(ctx context.Context, req ctrl.Req
120118
121119 var existingExt = & ocv1alpha1.ClusterExtension {}
122120 if err := r .Client .Get (ctx , req .NamespacedName , existingExt ); err != nil {
123- return ctrl.Result {}, utilerrors . NewAggregate ([] error { client .IgnoreNotFound (err ), nil } )
121+ return ctrl.Result {}, client .IgnoreNotFound (err )
124122 }
125123
126- reconciledExt := existingExt .DeepCopy ()
127- res , reconcileErr := r .reconcile (ctx , reconciledExt )
124+ var updateError error
128125
129- var updateErrors []error
126+ reconciledExt := existingExt .DeepCopy ()
127+ res , err := r .reconcile (ctx , reconciledExt )
128+ updateError = errors .Join (updateError , err )
130129
131130 // Do checks before any Update()s, as Update() may modify the resource structure!
132131 updateStatus := ! equality .Semantic .DeepEqual (existingExt .Status , reconciledExt .Status )
133132 updateFinalizers := ! equality .Semantic .DeepEqual (existingExt .Finalizers , reconciledExt .Finalizers )
134133 unexpectedFieldsChanged := checkForUnexpectedFieldChange (* existingExt , * reconciledExt )
135134
136135 if updateStatus {
137- if updateErr := r .Client .Status ().Update (ctx , reconciledExt ); updateErr != nil {
138- updateErrors = append (updateErrors , updateErr )
139- }
136+ err = r .Client .Status ().Update (ctx , reconciledExt )
137+ updateError = errors .Join (updateError , err )
140138 }
141139
142140 if unexpectedFieldsChanged {
143141 panic ("spec or metadata changed by reconciler" )
144142 }
145143
146144 if updateFinalizers {
147- if updateErr := r .Client .Update (ctx , reconciledExt ); updateErr != nil {
148- updateErrors = append (updateErrors , updateErr )
149- }
150- }
151-
152- if reconcileErr != nil {
153- updateErrors = append (updateErrors , reconcileErr )
145+ err = r .Client .Update (ctx , reconciledExt )
146+ updateError = errors .Join (updateError , err )
154147 }
155148
156- return res , utilerrors . NewAggregate ( updateErrors )
149+ return res , updateError
157150}
158151
159152// ensureAllConditionsWithReason checks that all defined condition types exist in the given ClusterExtension,
@@ -183,35 +176,6 @@ func checkForUnexpectedFieldChange(a, b ocv1alpha1.ClusterExtension) bool {
183176 return ! equality .Semantic .DeepEqual (a , b )
184177}
185178
186- func (r * ClusterExtensionReconciler ) handleResolutionErrors (ext * ocv1alpha1.ClusterExtension , err error ) (ctrl.Result , error ) {
187- var aggErrs utilerrors.Aggregate
188- if errors .As (err , & aggErrs ) {
189- for _ , err := range aggErrs .Errors () {
190- errorMessage := err .Error ()
191- if strings .Contains (errorMessage , "no package" ) {
192- // Handle no package found errors, potentially setting status conditions
193- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
194- ensureAllConditionsWithReason (ext , "ResolutionFailed" , errorMessage )
195- } else if strings .Contains (errorMessage , "invalid version range" ) {
196- // Handle invalid version range errors, potentially setting status conditions
197- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
198- ensureAllConditionsWithReason (ext , "ResolutionFailed" , errorMessage )
199- } else {
200- // General error handling
201- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
202- ensureAllConditionsWithReason (ext , "InstallationStatusUnknown" , "" )
203- }
204- }
205- } else {
206- // If the error is not an aggregate, handle it as a general error
207- errorMessage := err .Error ()
208- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
209- ensureAllConditionsWithReason (ext , "InstallationStatusUnknown" , "" )
210- }
211- ext .Status .ResolvedBundle = nil
212- return ctrl.Result {}, err
213- }
214-
215179// Helper function to do the actual reconcile
216180//
217181// Today we always return ctrl.Result{} and an error.
@@ -232,10 +196,18 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
232196 // run resolution
233197 bundle , err := r .resolve (ctx , * ext )
234198 if err != nil {
235- return r .handleResolutionErrors (ext , err )
199+ // Note: We don't distinguish between resolution-specific errors and generic errors
200+ ext .Status .ResolvedBundle = nil
201+ ext .Status .InstalledBundle = nil
202+ setResolvedStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
203+ ensureAllConditionsWithReason (ext , ocv1alpha1 .ReasonResolutionFailed , err .Error ())
204+ return ctrl.Result {}, err
236205 }
237206
238207 if err := r .validateBundle (bundle ); err != nil {
208+ ext .Status .ResolvedBundle = nil
209+ ext .Status .InstalledBundle = nil
210+ setResolvedStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
239211 setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
240212 setDeprecationStatusesUnknown (& ext .Status .Conditions , "deprecation checks have not been attempted as installation has failed" , ext .GetGeneration ())
241213 return ctrl.Result {}, err
@@ -291,23 +263,13 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
291263
292264 bundleFS , err := r .Storage .Load (ctx , ext )
293265 if err != nil {
294- apimeta .SetStatusCondition (& ext .Status .Conditions , metav1.Condition {
295- Type : ocv1alpha1 .TypeHasValidBundle ,
296- Status : metav1 .ConditionFalse ,
297- Reason : ocv1alpha1 .ReasonBundleLoadFailed ,
298- Message : err .Error (),
299- })
266+ setHasValidBundleFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
300267 return ctrl.Result {}, err
301268 }
302269
303270 chrt , values , err := r .Handler .Handle (ctx , bundleFS , ext )
304271 if err != nil {
305- apimeta .SetStatusCondition (& ext .Status .Conditions , metav1.Condition {
306- Type : ocv1alpha1 .TypeInstalled ,
307- Status : metav1 .ConditionFalse ,
308- Reason : ocv1alpha1 .ReasonInstallationFailed ,
309- Message : err .Error (),
310- })
272+ setInstalledStatusConditionFailed (& ext .Status .Conditions , err .Error (), ext .GetGeneration ())
311273 return ctrl.Result {}, err
312274 }
313275
@@ -342,26 +304,17 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
342304 return nil
343305 }, helmclient .AppendInstallPostRenderer (post ))
344306 if err != nil {
345- if isResourceNotFoundErr (err ) {
346- err = errRequiredResourceNotFound {err }
347- }
348307 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonInstallationFailed , err ), ext .Generation )
349308 return ctrl.Result {}, err
350309 }
351310 case stateNeedsUpgrade :
352311 rel , err = ac .Upgrade (ext .GetName (), r .ReleaseNamespace , chrt , values , helmclient .AppendUpgradePostRenderer (post ))
353312 if err != nil {
354- if isResourceNotFoundErr (err ) {
355- err = errRequiredResourceNotFound {err }
356- }
357313 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonUpgradeFailed , err ), ext .Generation )
358314 return ctrl.Result {}, err
359315 }
360316 case stateUnchanged :
361317 if err := ac .Reconcile (rel ); err != nil {
362- if isResourceNotFoundErr (err ) {
363- err = errRequiredResourceNotFound {err }
364- }
365318 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonResolutionFailed , err ), ext .Generation )
366319 return ctrl.Result {}, err
367320 }
@@ -414,7 +367,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
414367func (r * ClusterExtensionReconciler ) resolve (ctx context.Context , ext ocv1alpha1.ClusterExtension ) (* catalogmetadata.Bundle , error ) {
415368 allBundles , err := r .BundleProvider .Bundles (ctx )
416369 if err != nil {
417- return nil , utilerrors . NewAggregate ([] error { fmt .Errorf ("error fetching bundles: %w" , err )} )
370+ return nil , fmt .Errorf ("error fetching bundles: %w" , err )
418371 }
419372
420373 packageName := ext .Spec .PackageName
@@ -437,7 +390,7 @@ func (r *ClusterExtensionReconciler) resolve(ctx context.Context, ext ocv1alpha1
437390 if versionRange != "" {
438391 vr , err := mmsemver .NewConstraint (versionRange )
439392 if err != nil {
440- return nil , utilerrors . NewAggregate ([] error { fmt .Errorf ("invalid version range '%s' : %w" , versionRange , err )} )
393+ return nil , fmt .Errorf ("invalid version range %q : %w" , versionRange , err )
441394 }
442395 predicates = append (predicates , catalogfilter .InMastermindsSemverRange (vr ))
443396 }
@@ -753,37 +706,6 @@ func (d *DefaultInstalledBundleGetter) GetInstalledBundle(ctx context.Context, a
753706 return resultSet [0 ], nil
754707}
755708
756- type errRequiredResourceNotFound struct {
757- error
758- }
759-
760- func (err errRequiredResourceNotFound ) Error () string {
761- return fmt .Sprintf ("required resource not found: %v" , err .error )
762- }
763-
764- func isResourceNotFoundErr (err error ) bool {
765- var agg utilerrors.Aggregate
766- if errors .As (err , & agg ) {
767- for _ , err := range agg .Errors () {
768- return isResourceNotFoundErr (err )
769- }
770- }
771-
772- nkme := & apimeta.NoKindMatchError {}
773- if errors .As (err , & nkme ) {
774- return true
775- }
776- if apierrors .IsNotFound (err ) {
777- return true
778- }
779-
780- // TODO: improve NoKindMatchError matching
781- // An error that is bubbled up from the k8s.io/cli-runtime library
782- // does not wrap meta.NoKindMatchError, so we need to fallback to
783- // the use of string comparisons for now.
784- return strings .Contains (err .Error (), "no matches for kind" )
785- }
786-
787709type postrenderer struct {
788710 labels map [string ]string
789711 cascade postrender.PostRenderer
0 commit comments