diff --git a/changelog/fragments/helm_operator_uninstall_error_handling_change.yaml b/changelog/fragments/helm_operator_uninstall_error_handling_change.yaml new file mode 100644 index 0000000000..9d98462ad5 --- /dev/null +++ b/changelog/fragments/helm_operator_uninstall_error_handling_change.yaml @@ -0,0 +1,14 @@ +entries: + - description: > + For Helm-based operators delete resource, if the Helm uninstall completed with error, then keep trying to uninstall until there is no error on the Helm uninstall. + + kind: "change" + + breaking: true + + migration: + header: For Helm-based operators delete resource, the finalizer will not be removed until the Helm uninstall is completed without error. + body: > + In the prior releases, Helm-based operators delete resource will remove it's finalizer even if the Helm uninstallation completed with error. + With this change, Helm-based operators will keep attempting to perform Helm uninstall until it completes without error. + Only then, will the finalizer be removed. diff --git a/internal/helm/release/manager.go b/internal/helm/release/manager.go index 2d494f42c2..daff407a12 100644 --- a/internal/helm/release/manager.go +++ b/internal/helm/release/manager.go @@ -361,7 +361,34 @@ func (m manager) UninstallRelease(ctx context.Context, opts ...UninstallOption) return nil, fmt.Errorf("failed to apply uninstall option: %w", err) } } + + // Get history of this release + h, err := m.storageBackend.History(m.releaseName) + if err != nil { + return nil, fmt.Errorf("failed to get release history: %w", err) + } + releaseutil.SortByRevision(h) + lastRelease := h[len(h)-1] + + // Helm uninstall on a "uninstalled" status doesn't actually perform any resource deletes. + // See: https://github.com/helm/helm/blob/v3.4.2/pkg/action/uninstall.go#L83-L91 + // Set the release to "uninstalling" status and trigger the uninstall again. + if lastRelease.Info != nil && lastRelease.Info.Status == rpb.StatusUninstalled { + lastRelease.Info.Status = rpb.StatusUninstalling + if err := m.storageBackend.Update(lastRelease); err != nil { + return nil, err + } + } + + // Always keep the release record in case the uninstall errors. + uninstall.KeepHistory = true + uninstallResponse, err := uninstall.Run(m.releaseName) + if err == nil { + // Uninstall was successful so purge the release by running the uninstall again. + uninstall.KeepHistory = false + uninstallResponse, err = uninstall.Run(m.releaseName) + } if uninstallResponse == nil { return nil, err }