fix: allow upgrading when history has nothing but failures

Signed-off-by: Matt Butcher <matt.butcher@microsoft.com>
pull/7913/head
Matt Butcher 6 years ago
parent 0c87ca544f
commit 9a1a2202ca
No known key found for this signature in database
GPG Key ID: DCD5F5E5EF32C345

@ -33,6 +33,7 @@ import (
"helm.sh/helm/v3/pkg/postrender"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/storage"
)
// Upgrade is the action for upgrading releases.
@ -132,8 +133,24 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
// finds the deployed release with the given name
currentRelease, err := u.cfg.Releases.Deployed(name)
if err != nil {
switch err.(type) {
case storage.NoDeployedReleases:
// Try lookup again. Note that what we are doing here is attempting to get the
// _last release_, which might have been a failure. Our assumption is that this
// release best represents the current state of a rendered Helm chart. We are then
// relying upon the 3-way diff to help us repair the current in-cluster version.
u.cfg.Log("Could not find a deployed release for %q. Trying to get an older (possibly failed) release", name)
currentRelease, err = u.cfg.Releases.Last(name)
if err != nil {
// Regardless of what the error is here, it is likely that we cannot proceed
// any more with the upgrade. So we bail.
return nil, nil, errors.Wrapf(err, "there are no recorded releases for %q", name)
}
u.cfg.Log("loaded release %s.%d", currentRelease.Name, currentRelease.Version)
default:
return nil, nil, err
}
}
// determine if values will be reused
vals, err = u.reuseValues(chart, currentRelease, vals)
@ -196,6 +213,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
if len(notesTxt) > 0 {
upgradedRelease.Info.Notes = notesTxt
}
u.cfg.Log("Manifest: %s", manifestDoc)
err = validateManifest(u.cfg.KubeClient, manifestDoc.Bytes(), !u.DisableOpenAPIValidation)
return currentRelease, upgradedRelease, err
}

@ -107,6 +107,14 @@ func (s *Storage) ListDeployed() ([]*rspb.Release, error) {
})
}
// NoDeployedReleases describes the situation where none of the releases in the history are deployed.
//
// Aggressive pruning can mask the fact that there is a deployed release, but that it
// was cleaned up by the history pruner.
type NoDeployedReleases string
func (e NoDeployedReleases) Error() string { return string(e) }
// Deployed returns the last deployed release with the provided release name, or
// returns ErrReleaseNotFound if not found.
func (s *Storage) Deployed(name string) (*rspb.Release, error) {
@ -116,7 +124,7 @@ func (s *Storage) Deployed(name string) (*rspb.Release, error) {
}
if len(ls) == 0 {
return nil, errors.Errorf("%q has no deployed releases", name)
return nil, NoDeployedReleases(fmt.Sprintf("%q has no deployed releases", name))
}
// If executed concurrently, Helm's database gets corrupted
@ -140,7 +148,7 @@ func (s *Storage) DeployedAll(name string) ([]*rspb.Release, error) {
return ls, nil
}
if strings.Contains(err.Error(), "not found") {
return nil, errors.Errorf("%q has no deployed releases", name)
return nil, NoDeployedReleases(fmt.Sprintf("%q has no deployed releases", name))
}
return nil, err
}

Loading…
Cancel
Save