fix(uninstall): supersede deployed releases

This ensures that when `helm uninstall` is run with `--keep-history`,
any release in a `deployed` state other than the last release (e.g.
due to a failed upgrade) is being marked as `superseded`.

As a by-effect, running `helm upgrade` on a release which has been
uninstalled after an upgrade failure now no longer works. But instead
fails with a `"<name>" has no deployed releases` error. Which is the
(likely) intended behavior, and prevents other side-effects like
rolling back to a release version which happened before the uninstall
if `--atomic` was provided.

Signed-off-by: Hidde Beydals <hidde@hhh.computer>
pull/12564/head
Hidde Beydals 2 years ago
parent 0592b3800a
commit 96c43a07da
No known key found for this signature in database
GPG Key ID: 979F380FC2341744

@ -57,6 +57,15 @@ func TestUninstall(t *testing.T) {
golden: "output/uninstall-keep-history.txt", golden: "output/uninstall-keep-history.txt",
rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "aeneas"})}, rels: []*release.Release{release.Mock(&release.MockReleaseOptions{Name: "aeneas"})},
}, },
{
name: "keep history with earlier deployed release",
cmd: "uninstall aeneas --keep-history",
golden: "output/uninstall-keep-history-earlier-deployed.txt",
rels: []*release.Release{
release.Mock(&release.MockReleaseOptions{Name: "aeneas", Version: 1, Status: release.StatusDeployed}),
release.Mock(&release.MockReleaseOptions{Name: "aeneas", Version: 2, Status: release.StatusFailed}),
},
},
{ {
name: "wait", name: "wait",
cmd: "uninstall aeneas --wait", cmd: "uninstall aeneas --wait",

@ -28,6 +28,7 @@ import (
"helm.sh/helm/v3/pkg/kube" "helm.sh/helm/v3/pkg/kube"
"helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil" "helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/storage/driver"
helmtime "helm.sh/helm/v3/pkg/time" helmtime "helm.sh/helm/v3/pkg/time"
) )
@ -166,6 +167,18 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
return res, nil return res, nil
} }
deployed, err := u.cfg.Releases.DeployedAll(rel.Name)
if err != nil && !errors.Is(err, driver.ErrNoDeployedReleases) {
return nil, err
}
// Supersede all previous deployments, see issue #12556 (which is a
// variation on #2941).
for _, rel := range deployed {
u.cfg.Log("superseding previous deployment %d", rel.Version)
rel.Info.Status = release.StatusSuperseded
u.cfg.recordRelease(rel)
}
if err := u.cfg.Releases.Update(rel); err != nil { if err := u.cfg.Releases.Update(rel); err != nil {
u.cfg.Log("uninstall: Failed to store updated release: %s", err) u.cfg.Log("uninstall: Failed to store updated release: %s", err)
} }

Loading…
Cancel
Save