@@ -176,18 +176,55 @@ func (m manager) InstallRelease(ctx context.Context) (*rpb.Release, error) {
176
176
install := action .NewInstall (m .actionConfig )
177
177
install .ReleaseName = m .releaseName
178
178
install .Namespace = m .namespace
179
- install .Atomic = true
180
- return install .Run (m .chart , m .values )
179
+
180
+ installedRelease , err := install .Run (m .chart , m .values )
181
+ if err != nil {
182
+ // Workaround for helm/helm#3338
183
+ if installedRelease != nil {
184
+ uninstall := action .NewUninstall (m .actionConfig )
185
+ _ , uninstallErr := uninstall .Run (m .releaseName )
186
+
187
+ // In certain cases, InstallRelease will return a partial release in
188
+ // the response even when it doesn't record the release in its release
189
+ // store (e.g. when there is an error rendering the release manifest).
190
+ // In that case the rollback will fail with a not found error because
191
+ // there was nothing to rollback.
192
+ //
193
+ // Only log a message about a rollback failure if the failure was caused
194
+ // by something other than the release not being found.
195
+ if uninstallErr != nil && ! notFoundErr (uninstallErr ) {
196
+ return nil , fmt .Errorf ("failed installation (%s) and failed rollback (%s)" , err , uninstallErr )
197
+ }
198
+ }
199
+ return nil , fmt .Errorf ("failed to install release: %s" , err )
200
+ }
201
+ return installedRelease , nil
181
202
}
182
203
183
204
// UpdateRelease performs a Helm release update.
184
205
func (m manager ) UpdateRelease (ctx context.Context ) (* rpb.Release , * rpb.Release , error ) {
185
206
upgrade := action .NewUpgrade (m .actionConfig )
186
207
upgrade .Namespace = m .namespace
187
- upgrade .Atomic = true
188
- upgrade .CleanupOnFail = true
189
- updatedRelease , err := upgrade .Run (m .releaseName , m .chart , m .values )
190
208
209
+ updatedRelease , err := upgrade .Run (m .releaseName , m .chart , m .values )
210
+ if err != nil {
211
+ // Workaround for helm/helm#3338
212
+ if updatedRelease != nil {
213
+ rollback := action .NewRollback (m .actionConfig )
214
+ rollback .Force = true
215
+
216
+ // As of Helm 2.13, if UpdateRelease returns a non-nil release, that
217
+ // means the release was also recorded in the release store.
218
+ // Therefore, we should perform the rollback when we have a non-nil
219
+ // release. Any rollback error here would be unexpected, so always
220
+ // log both the update and rollback errors.
221
+ rollbackErr := rollback .Run (m .releaseName )
222
+ if rollbackErr != nil {
223
+ return nil , nil , fmt .Errorf ("failed update (%s) and failed rollback (%s)" , err , rollbackErr )
224
+ }
225
+ }
226
+ return nil , nil , fmt .Errorf ("failed to update release: %s" , err )
227
+ }
191
228
return m .deployedRelease , updatedRelease , err
192
229
}
193
230
0 commit comments