@@ -38,14 +38,12 @@ import (
38
38
"helm.sh/helm/v3/pkg/storage/driver"
39
39
corev1 "k8s.io/api/core/v1"
40
40
"k8s.io/apimachinery/pkg/api/equality"
41
- apierrors "k8s.io/apimachinery/pkg/api/errors"
42
41
apimeta "k8s.io/apimachinery/pkg/api/meta"
43
42
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
44
43
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
45
44
"k8s.io/apimachinery/pkg/runtime"
46
45
"k8s.io/apimachinery/pkg/runtime/schema"
47
46
"k8s.io/apimachinery/pkg/types"
48
- utilerrors "k8s.io/apimachinery/pkg/util/errors"
49
47
"k8s.io/apimachinery/pkg/util/sets"
50
48
apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
51
49
ctrl "sigs.k8s.io/controller-runtime"
@@ -80,6 +78,17 @@ import (
80
78
"github.com/operator-framework/operator-controller/internal/labels"
81
79
)
82
80
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
+
83
92
// ClusterExtensionReconciler reconciles a ClusterExtension object
84
93
type ClusterExtensionReconciler struct {
85
94
client.Client
@@ -115,40 +124,35 @@ func (r *ClusterExtensionReconciler) Reconcile(ctx context.Context, req ctrl.Req
115
124
116
125
var existingExt = & ocv1alpha1.ClusterExtension {}
117
126
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 )
119
128
}
120
129
121
- reconciledExt := existingExt .DeepCopy ()
122
- res , reconcileErr := r .reconcile (ctx , reconciledExt )
130
+ var updateError error
123
131
124
- var updateErrors []error
132
+ reconciledExt := existingExt .DeepCopy ()
133
+ res , err := r .reconcile (ctx , reconciledExt )
134
+ updateError = errors .Join (updateError , err )
125
135
126
136
// Do checks before any Update()s, as Update() may modify the resource structure!
127
137
updateStatus := ! equality .Semantic .DeepEqual (existingExt .Status , reconciledExt .Status )
128
138
updateFinalizers := ! equality .Semantic .DeepEqual (existingExt .Finalizers , reconciledExt .Finalizers )
129
139
unexpectedFieldsChanged := checkForUnexpectedFieldChange (* existingExt , * reconciledExt )
130
140
131
141
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 )
135
144
}
136
145
137
146
if unexpectedFieldsChanged {
138
147
panic ("spec or metadata changed by reconciler" )
139
148
}
140
149
141
150
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 )
149
153
}
150
154
151
- return res , utilerrors . NewAggregate ( updateErrors )
155
+ return res , updateError
152
156
}
153
157
154
158
// ensureAllConditionsWithReason checks that all defined condition types exist in the given ClusterExtension,
@@ -179,29 +183,15 @@ func checkForUnexpectedFieldChange(a, b ocv1alpha1.ClusterExtension) bool {
179
183
}
180
184
181
185
func (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 )
200
191
} else {
201
- // If the error is not an aggregate, handle it as a general error
202
- errorMessage := err .Error ()
192
+ // General error handling
203
193
setResolvedStatusConditionFailed (& ext .Status .Conditions , errorMessage , ext .Generation )
204
- ensureAllConditionsWithReason (ext , "InstallationStatusUnknown" , "" )
194
+ ensureAllConditionsWithReason (ext , ocv1alpha1 . ReasonInstallationStatusUnknown , errorMessage )
205
195
}
206
196
ext .Status .ResolvedBundle = nil
207
197
return ctrl.Result {}, err
@@ -337,26 +327,17 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
337
327
return nil
338
328
}, helmclient .AppendInstallPostRenderer (post ))
339
329
if err != nil {
340
- if isResourceNotFoundErr (err ) {
341
- err = errRequiredResourceNotFound {err }
342
- }
343
330
setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonInstallationFailed , err ), ext .Generation )
344
331
return ctrl.Result {}, err
345
332
}
346
333
case stateNeedsUpgrade :
347
334
rel , err = ac .Upgrade (ext .GetName (), r .ReleaseNamespace , chrt , values , helmclient .AppendUpgradePostRenderer (post ))
348
335
if err != nil {
349
- if isResourceNotFoundErr (err ) {
350
- err = errRequiredResourceNotFound {err }
351
- }
352
336
setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonUpgradeFailed , err ), ext .Generation )
353
337
return ctrl.Result {}, err
354
338
}
355
339
case stateUnchanged :
356
340
if err := ac .Reconcile (rel ); err != nil {
357
- if isResourceNotFoundErr (err ) {
358
- err = errRequiredResourceNotFound {err }
359
- }
360
341
setInstalledStatusConditionFailed (& ext .Status .Conditions , fmt .Sprintf ("%s:%v" , ocv1alpha1 .ReasonResolutionFailed , err ), ext .Generation )
361
342
return ctrl.Result {}, err
362
343
}
@@ -409,7 +390,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1alp
409
390
func (r * ClusterExtensionReconciler ) resolve (ctx context.Context , ext ocv1alpha1.ClusterExtension ) (* catalogmetadata.Bundle , error ) {
410
391
allBundles , err := r .BundleProvider .Bundles (ctx )
411
392
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 )
413
394
}
414
395
415
396
packageName := ext .Spec .PackageName
@@ -432,7 +413,7 @@ func (r *ClusterExtensionReconciler) resolve(ctx context.Context, ext ocv1alpha1
432
413
if versionRange != "" {
433
414
vr , err := mmsemver .NewConstraint (versionRange )
434
415
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 )}
436
417
}
437
418
predicates = append (predicates , catalogfilter .InMastermindsSemverRange (vr ))
438
419
}
@@ -459,13 +440,13 @@ func (r *ClusterExtensionReconciler) resolve(ctx context.Context, ext ocv1alpha1
459
440
if len (resultSet ) == 0 {
460
441
switch {
461
442
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 )}
463
444
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 )}
465
446
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 )}
467
448
default :
468
- return nil , fmt .Errorf ("%sno package %q found" , upgradeErrorPrefix , packageName )
449
+ return nil , ResolutionError { fmt .Sprintf ("%sno package %q found" , upgradeErrorPrefix , packageName )}
469
450
}
470
451
}
471
452
@@ -754,29 +735,6 @@ func (err errRequiredResourceNotFound) Error() string {
754
735
return fmt .Sprintf ("required resource not found: %v" , err .error )
755
736
}
756
737
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
-
780
738
type postrenderer struct {
781
739
labels map [string ]string
782
740
cascade postrender.PostRenderer
0 commit comments