@@ -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"
@@ -80,6 +78,17 @@ import (
8078 "github.com/operator-framework/operator-controller/internal/labels"
8179)
8280
81+ // ResolutionError type
82+ // If a more specific error type needs to be distinguished,
83+ // add another type here
84+ type ResolutionError struct {
85+ message string
86+ }
87+
88+ func (e ResolutionError ) Error () string {
89+ return e .message
90+ }
91+
8392// ClusterExtensionReconciler reconciles a ClusterExtension object
8493type ClusterExtensionReconciler struct {
8594 client.Client
@@ -115,40 +124,35 @@ func (r *ClusterExtensionReconciler) Reconcile(ctx context.Context, req ctrl.Req
115124
116125 var existingExt = & ocv1alpha1.ClusterExtension {}
117126 if err := r .Client .Get (ctx , req .NamespacedName , existingExt ); err != nil {
118- return ctrl.Result {}, utilerrors . NewAggregate ([] error { client .IgnoreNotFound (err ), nil } )
127+ return ctrl.Result {}, client .IgnoreNotFound (err )
119128 }
120129
121- reconciledExt := existingExt .DeepCopy ()
122- res , reconcileErr := r .reconcile (ctx , reconciledExt )
130+ var updateError error
123131
124- var updateErrors []error
132+ reconciledExt := existingExt .DeepCopy ()
133+ res , err := r .reconcile (ctx , reconciledExt )
134+ updateError = errors .Join (updateError , err )
125135
126136 // Do checks before any Update()s, as Update() may modify the resource structure!
127137 updateStatus := ! equality .Semantic .DeepEqual (existingExt .Status , reconciledExt .Status )
128138 updateFinalizers := ! equality .Semantic .DeepEqual (existingExt .Finalizers , reconciledExt .Finalizers )
129139 unexpectedFieldsChanged := checkForUnexpectedFieldChange (* existingExt , * reconciledExt )
130140
131141 if updateStatus {
132- if updateErr := r .Client .Status ().Update (ctx , reconciledExt ); updateErr != nil {
133- updateErrors = append (updateErrors , updateErr )
134- }
142+ err = r .Client .Status ().Update (ctx , reconciledExt )
143+ updateError = errors .Join (updateError , err )
135144 }
136145
137146 if unexpectedFieldsChanged {
138147 panic ("spec or metadata changed by reconciler" )
139148 }
140149
141150 if updateFinalizers {
142- if updateErr := r .Client .Update (ctx , reconciledExt ); updateErr != nil {
143- updateErrors = append (updateErrors , updateErr )
144- }
145- }
146-
147- if reconcileErr != nil {
148- updateErrors = append (updateErrors , reconcileErr )
151+ err = r .Client .Update (ctx , reconciledExt )
152+ updateError = errors .Join (updateError , err )
149153 }
150154
151- return res , utilerrors . NewAggregate ( updateErrors )
155+ return res , updateError
152156}
153157
154158// ensureAllConditionsWithReason checks that all defined condition types exist in the given ClusterExtension,
@@ -179,29 +183,15 @@ func checkForUnexpectedFieldChange(a, b ocv1alpha1.ClusterExtension) bool {
179183}
180184
181185func (r * ClusterExtensionReconciler ) handleResolutionErrors (ext * ocv1alpha1.ClusterExtension , err error ) (ctrl.Result , error ) {
182- var aggErrs utilerrors.Aggregate
183- if errors .As (err , & aggErrs ) {
184- for _ , err := range aggErrs .Errors () {
185- errorMessage := err .Error ()
186- if strings .Contains (errorMessage , "no package" ) {
187- // Handle no package found errors, potentially setting status conditions
188- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
189- ensureAllConditionsWithReason (ext , "ResolutionFailed" , errorMessage )
190- } else if strings .Contains (errorMessage , "invalid version range" ) {
191- // Handle invalid version range errors, potentially setting status conditions
192- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
193- ensureAllConditionsWithReason (ext , "ResolutionFailed" , errorMessage )
194- } else {
195- // General error handling
196- setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
197- ensureAllConditionsWithReason (ext , "InstallationStatusUnknown" , "" )
198- }
199- }
186+ errorMessage := err .Error ()
187+ if errors .As (err , & ResolutionError {}) {
188+ // Handle resolution errors
189+ setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
190+ ensureAllConditionsWithReason (ext , ocv1alpha1 .ReasonResolutionFailed , errorMessage )
200191 } else {
201- // If the error is not an aggregate, handle it as a general error
202- errorMessage := err .Error ()
192+ // General error handling
203193 setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
204- ensureAllConditionsWithReason (ext , "InstallationStatusUnknown" , "" )
194+ ensureAllConditionsWithReason (ext , ocv1alpha1 . ReasonInstallationStatusUnknown , errorMessage )
205195 }
206196 ext .Status .ResolvedBundle = nil
207197 return ctrl.Result {}, err
@@ -337,26 +327,17 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
337327 return nil
338328 }, helmclient .AppendInstallPostRenderer (post ))
339329 if err != nil {
340- if isResourceNotFoundErr (err ) {
341- err = errRequiredResourceNotFound {err }
342- }
343330 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonInstallationFailed , err ), ext .Generation )
344331 return ctrl.Result {}, err
345332 }
346333 case stateNeedsUpgrade :
347334 rel , err = ac .Upgrade (ext .GetName (), r .ReleaseNamespace , chrt , values , helmclient .AppendUpgradePostRenderer (post ))
348335 if err != nil {
349- if isResourceNotFoundErr (err ) {
350- err = errRequiredResourceNotFound {err }
351- }
352336 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonUpgradeFailed , err ), ext .Generation )
353337 return ctrl.Result {}, err
354338 }
355339 case stateUnchanged :
356340 if err := ac .Reconcile (rel ); err != nil {
357- if isResourceNotFoundErr (err ) {
358- err = errRequiredResourceNotFound {err }
359- }
360341 setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonResolutionFailed , err ), ext .Generation )
361342 return ctrl.Result {}, err
362343 }
@@ -409,7 +390,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
409390func (r * ClusterExtensionReconciler ) resolve (ctx context.Context , ext ocv1alpha1.ClusterExtension ) (* catalogmetadata.Bundle , error ) {
410391 allBundles , err := r .BundleProvider .Bundles (ctx )
411392 if err != nil {
412- return nil , utilerrors . NewAggregate ([] error { fmt .Errorf ("error fetching bundles: %w" , err )} )
393+ return nil , fmt .Errorf ("error fetching bundles: %w" , err )
413394 }
414395
415396 packageName := ext .Spec .PackageName
@@ -432,7 +413,7 @@ func (r *ClusterExtensionReconciler) resolve(ctx context.Context, ext ocv1alpha1
432413 if versionRange != "" {
433414 vr , err := mmsemver .NewConstraint (versionRange )
434415 if err != nil {
435- return nil , utilerrors . NewAggregate ([] error {fmt .Errorf ("invalid version range '%s' : %w " , versionRange , err )})
416+ return nil , ResolutionError {fmt .Sprintf ("invalid version range %q : %v " , versionRange , err )}
436417 }
437418 predicates = append (predicates , catalogfilter .InMastermindsSemverRange (vr ))
438419 }
@@ -459,13 +440,13 @@ func (r *ClusterExtensionReconciler) resolve(ctx context.Context, ext ocv1alpha1
459440 if len (resultSet ) == 0 {
460441 switch {
461442 case versionRange != "" && channelName != "" :
462- return nil , fmt .Errorf ("%sno package %q matching version %q in channel %q found" , upgradeErrorPrefix , packageName , versionRange , channelName )
443+ return nil , ResolutionError { fmt .Sprintf ("%sno package %q matching version %q in channel %q found" , upgradeErrorPrefix , packageName , versionRange , channelName )}
463444 case versionRange != "" :
464- return nil , fmt .Errorf ("%sno package %q matching version %q found" , upgradeErrorPrefix , packageName , versionRange )
445+ return nil , ResolutionError { fmt .Sprintf ("%sno package %q matching version %q found" , upgradeErrorPrefix , packageName , versionRange )}
465446 case channelName != "" :
466- return nil , fmt .Errorf ("%sno package %q in channel %q found" , upgradeErrorPrefix , packageName , channelName )
447+ return nil , ResolutionError { fmt .Sprintf ("%sno package %q in channel %q found" , upgradeErrorPrefix , packageName , channelName )}
467448 default :
468- return nil , fmt .Errorf ("%sno package %q found" , upgradeErrorPrefix , packageName )
449+ return nil , ResolutionError { fmt .Sprintf ("%sno package %q found" , upgradeErrorPrefix , packageName )}
469450 }
470451 }
471452
@@ -754,29 +735,6 @@ func (err errRequiredResourceNotFound) Error() string {
754735 return fmt .Sprintf ("required resource not found: %v" , err .error )
755736}
756737
757- func isResourceNotFoundErr (err error ) bool {
758- var agg utilerrors.Aggregate
759- if errors .As (err , & agg ) {
760- for _ , err := range agg .Errors () {
761- return isResourceNotFoundErr (err )
762- }
763- }
764-
765- nkme := & apimeta.NoKindMatchError {}
766- if errors .As (err , & nkme ) {
767- return true
768- }
769- if apierrors .IsNotFound (err ) {
770- return true
771- }
772-
773- // TODO: improve NoKindMatchError matching
774- // An error that is bubbled up from the k8s.io/cli-runtime library
775- // does not wrap meta.NoKindMatchError, so we need to fallback to
776- // the use of string comparisons for now.
777- return strings .Contains (err .Error (), "no matches for kind" )
778- }
779-
780738type postrenderer struct {
781739 labels map [string ]string
782740 cascade postrender.PostRenderer
0 commit comments