@@ -36,6 +36,11 @@ const (
36
36
maxHelmReleaseHistory = 10
37
37
)
38
38
39
+ var (
40
+ errPendingRelease = errors .New ("release is in a pending state" )
41
+ errBuildHelmChartFuncNil = errors .New ("BundleToHelmChartFn is nil" )
42
+ )
43
+
39
44
// Preflight is a check that should be run before making any changes to the cluster
40
45
type Preflight interface {
41
46
// Install runs checks that should be successful prior
@@ -96,6 +101,23 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExte
96
101
}
97
102
98
103
rel , desiredRel , state , err := h .getReleaseState (ctx , ac , ext , chrt , values , post )
104
+ // if a release is pending, that means that a helm action
105
+ // (installation/upgrade) we were attempting was likely interrupted in-flight.
106
+ // Pending release would leave us in reconciliation error loop because helm
107
+ // wouldn't be able to progress automatically from it.
108
+ //
109
+ // one of the workarounds is to try and remove helm metadata relating to
110
+ // that pending release which should 'reset' its state communicated to helm
111
+ // and the next reconciliation should be able to successfully pick up from here
112
+ // for context see: https://github.com/helm/helm/issues/5595 and https://github.com/helm/helm/issues/7476
113
+ // and the discussion in https://github.com/operator-framework/operator-controller/pull/1776
114
+ if errors .Is (err , errPendingRelease ) {
115
+ if _ , err := ac .Config ().Releases .Delete (rel .Name , rel .Version ); err != nil {
116
+ return nil , "" , fmt .Errorf ("failed removing pending release %q version %d metadata: %w" , rel .Name , rel .Version , err )
117
+ }
118
+ // return an error to try to detect proper state (installation/upgrade) at next reconciliation
119
+ return nil , "" , fmt .Errorf ("removed pending release %q version %d metadata" , rel .Name , rel .Version )
120
+ }
99
121
if err != nil {
100
122
return nil , "" , err
101
123
}
@@ -155,7 +177,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExte
155
177
156
178
func (h * Helm ) buildHelmChart (bundleFS fs.FS , ext * ocv1.ClusterExtension ) (* chart.Chart , error ) {
157
179
if h .BundleToHelmChartFn == nil {
158
- return nil , errors . New ( "BundleToHelmChartFn is nil" )
180
+ return nil , errBuildHelmChartFuncNil
159
181
}
160
182
watchNamespace , err := GetWatchNamespace (ext )
161
183
if err != nil {
@@ -168,24 +190,6 @@ func (h *Helm) getReleaseState(ctx context.Context, cl helmclient.ActionInterfac
168
190
logger := log .FromContext (ctx )
169
191
currentRelease , err := cl .Get (ext .GetName ())
170
192
171
- // if a release is pending at this point, that means that a helm action
172
- // (installation/upgrade) we were attempting was likely interrupted in-flight.
173
- // Pending release would leave us in reconciliation error loop because helm
174
- // wouldn't be able to progress automatically from it.
175
- //
176
- // one of the workarounds is to try and remove helm metadata relating to
177
- // that pending release which should 'reset' its state communicated to helm
178
- // and the next reconciliation should be able to successfully pick up from here
179
- // for context see: https://github.com/helm/helm/issues/5595 and https://github.com/helm/helm/issues/7476
180
- // and the discussion in https://github.com/operator-framework/operator-controller/pull/1776
181
- if err == nil && currentRelease .Info .Status .IsPending () {
182
- if _ , err = cl .Config ().Releases .Delete (currentRelease .Name , currentRelease .Version ); err != nil {
183
- return nil , nil , StateError , fmt .Errorf ("failed removing interrupted release %q version %d metadata: %w" , currentRelease .Name , currentRelease .Version , err )
184
- }
185
- // return error to try to detect proper state (installation/upgrade) at next reconciliation
186
- return nil , nil , StateError , fmt .Errorf ("removed interrupted release %q version %d metadata" , currentRelease .Name , currentRelease .Version )
187
- }
188
-
189
193
if errors .Is (err , driver .ErrReleaseNotFound ) {
190
194
logger .V (4 ).Info ("ClusterExtension dry-run install" , "extension" , ext .GetName ())
191
195
desiredRelease , err := cl .Install (ext .GetName (), ext .Spec .Namespace , chrt , values , func (i * action.Install ) error {
@@ -205,6 +209,9 @@ func (h *Helm) getReleaseState(ctx context.Context, cl helmclient.ActionInterfac
205
209
if err != nil {
206
210
return nil , nil , StateError , err
207
211
}
212
+ if currentRelease .Info .Status .IsPending () {
213
+ return currentRelease , nil , StateError , errPendingRelease
214
+ }
208
215
209
216
desiredRelease , err := cl .Upgrade (ext .GetName (), ext .Spec .Namespace , chrt , values , func (upgrade * action.Upgrade ) error {
210
217
logger .V (4 ).Info ("ClusterExtension dry-run upgrade" , "extension" , ext .GetName ())
0 commit comments