@@ -39,6 +39,11 @@ const (
39
39
maxHelmReleaseHistory = 10
40
40
)
41
41
42
+ var (
43
+ errPendingRelease = errors .New ("release is in a pending state" )
44
+ errBundleToHelmChartConverterNil = errors .New ("BundleToHelmChartConverter is nil" )
45
+ )
46
+
42
47
// Preflight is a check that should be run before making any changes to the cluster
43
48
type Preflight interface {
44
49
// Install runs checks that should be successful prior
@@ -144,6 +149,23 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExte
144
149
}
145
150
146
151
rel , desiredRel , state , err := h .getReleaseState (ctx , ac , ext , chrt , values , post )
152
+ // if a release is pending, that means that a helm action
153
+ // (installation/upgrade) we were attempting was likely interrupted in-flight.
154
+ // Pending release would leave us in reconciliation error loop because helm
155
+ // wouldn't be able to progress automatically from it.
156
+ //
157
+ // one of the workarounds is to try and remove helm metadata relating to
158
+ // that pending release which should 'reset' its state communicated to helm
159
+ // and the next reconciliation should be able to successfully pick up from here
160
+ // for context see: https://github.com/helm/helm/issues/5595 and https://github.com/helm/helm/issues/7476
161
+ // and the discussion in https://github.com/operator-framework/operator-controller/pull/1776
162
+ if errors .Is (err , errPendingRelease ) {
163
+ if _ , err := ac .Config ().Releases .Delete (rel .Name , rel .Version ); err != nil {
164
+ return nil , "" , fmt .Errorf ("failed removing pending release %q version %d metadata: %w" , rel .Name , rel .Version , err )
165
+ }
166
+ // return an error to try to detect proper state (installation/upgrade) at next reconciliation
167
+ return nil , "" , fmt .Errorf ("removed pending release %q version %d metadata" , rel .Name , rel .Version )
168
+ }
147
169
if err != nil {
148
170
return nil , "" , fmt .Errorf ("failed to get release state using server-side dry-run: %w" , err )
149
171
}
@@ -203,7 +225,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExte
203
225
204
226
func (h * Helm ) buildHelmChart (bundleFS fs.FS , ext * ocv1.ClusterExtension ) (* chart.Chart , error ) {
205
227
if h .BundleToHelmChartConverter == nil {
206
- return nil , errors . New ( "BundleToHelmChartConverter is nil" )
228
+ return nil , errBundleToHelmChartConverterNil
207
229
}
208
230
watchNamespace , err := GetWatchNamespace (ext )
209
231
if err != nil {
@@ -244,24 +266,6 @@ func (h *Helm) getReleaseState(ctx context.Context, cl helmclient.ActionInterfac
244
266
logger := log .FromContext (ctx )
245
267
currentRelease , err := cl .Get (ext .GetName ())
246
268
247
- // if a release is pending at this point, that means that a helm action
248
- // (installation/upgrade) we were attempting was likely interrupted in-flight.
249
- // Pending release would leave us in reconciliation error loop because helm
250
- // wouldn't be able to progress automatically from it.
251
- //
252
- // one of the workarounds is to try and remove helm metadata relating to
253
- // that pending release which should 'reset' its state communicated to helm
254
- // and the next reconciliation should be able to successfully pick up from here
255
- // for context see: https://github.com/helm/helm/issues/5595 and https://github.com/helm/helm/issues/7476
256
- // and the discussion in https://github.com/operator-framework/operator-controller/pull/1776
257
- if err == nil && currentRelease .Info .Status .IsPending () {
258
- if _ , err = cl .Config ().Releases .Delete (currentRelease .Name , currentRelease .Version ); err != nil {
259
- return nil , nil , StateError , fmt .Errorf ("failed removing interrupted release %q version %d metadata: %w" , currentRelease .Name , currentRelease .Version , err )
260
- }
261
- // return error to try to detect proper state (installation/upgrade) at next reconciliation
262
- return nil , nil , StateError , fmt .Errorf ("removed interrupted release %q version %d metadata" , currentRelease .Name , currentRelease .Version )
263
- }
264
-
265
269
if errors .Is (err , driver .ErrReleaseNotFound ) {
266
270
logger .V (4 ).Info ("ClusterExtension dry-run install" , "extension" , ext .GetName ())
267
271
desiredRelease , err := cl .Install (ext .GetName (), ext .Spec .Namespace , chrt , values , func (i * action.Install ) error {
@@ -277,6 +281,9 @@ func (h *Helm) getReleaseState(ctx context.Context, cl helmclient.ActionInterfac
277
281
if err != nil {
278
282
return nil , nil , StateError , err
279
283
}
284
+ if currentRelease .Info .Status .IsPending () {
285
+ return currentRelease , nil , StateError , errPendingRelease
286
+ }
280
287
281
288
desiredRelease , err := cl .Upgrade (ext .GetName (), ext .Spec .Namespace , chrt , values , func (upgrade * action.Upgrade ) error {
282
289
logger .V (4 ).Info ("ClusterExtension dry-run upgrade" , "extension" , ext .GetName ())
0 commit comments