fix(tiller): fix spurious "no release found" errors.

There are some places where releases are only located if they are in the
state DEPLOYED. That particular logic was incorrectly used for upgrades.
That caused . While fixing that issue, I found that this was also
the root cause of  (though because it was off by one). I added a
generic method to get the last release, regardless of its status.

This allows some behaviors that previously failed:

- 'helm upgrade' can now be performed on a DELETED release
- 'helm rollback' can now be performed on a DELETED release even if
  there is only one revision of that release history.

Closes 
Closes 
pull/1632/head
Matt Butcher 8 years ago
parent ec04da196d
commit a5d96c2704
No known key found for this signature in database
GPG Key ID: DCD5F5E5EF32C345

@ -139,6 +139,19 @@ func (s *Storage) History(name string) ([]*rspb.Release, error) {
return l, nil return l, nil
} }
func (s *Storage) Last(name string) (*rspb.Release, error) {
h, err := s.History(name)
if err != nil {
return nil, err
}
if len(h) == 0 {
return nil, fmt.Errorf("no revision for release %q", name)
}
relutil.Reverse(h, relutil.SortByRevision)
return h[0], nil
}
// makeKey concatenates a release name and version into // makeKey concatenates a release name and version into
// a string with format ```<release_name>#v<version>```. // a string with format ```<release_name>#v<version>```.
// This key is used to uniquely identify storage objects. // This key is used to uniquely identify storage objects.

@ -217,6 +217,38 @@ func TestStorageHistory(t *testing.T) {
} }
} }
func TestStorageLast(t *testing.T) {
storage := Init(driver.NewMemory())
const name = "angry-bird"
// setup storage with test releases
setup := func() {
// release records
rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease()
rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease()
rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease()
rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_FAILED}.ToRelease()
// create the release records in the storage
assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)")
assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)")
assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)")
assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)")
}
setup()
h, err := storage.Last(name)
if err != nil {
t.Fatalf("Failed to query for release history (%q): %s\n", name, err)
}
if h.Version != 4 {
t.Errorf("Expected revision 4, got %d", h.Version)
}
}
type ReleaseTestData struct { type ReleaseTestData struct {
Name string Name string
Version int32 Version int32

@ -229,17 +229,11 @@ func (s *ReleaseServer) GetReleaseStatus(c ctx.Context, req *services.GetRelease
var rel *release.Release var rel *release.Release
if req.Version <= 0 { if req.Version <= 0 {
h, err := s.env.Releases.History(req.Name) var err error
rel, err = s.env.Releases.Last(req.Name)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting deployed release '%s': %s", req.Name, err) return nil, fmt.Errorf("getting deployed release %q: %s", req.Name, err)
}
if len(h) < 1 {
return nil, errMissingRelease
} }
relutil.Reverse(h, relutil.SortByRevision)
rel = h[0]
} else { } else {
var err error var err error
if rel, err = s.env.Releases.Get(req.Name, req.Version); err != nil { if rel, err = s.env.Releases.Get(req.Name, req.Version); err != nil {
@ -376,7 +370,7 @@ func (s *ReleaseServer) prepareUpdate(req *services.UpdateReleaseRequest) (*rele
} }
// finds the non-deleted release with the given name // finds the non-deleted release with the given name
currentRelease, err := s.env.Releases.Deployed(req.Name) currentRelease, err := s.env.Releases.Last(req.Name)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -504,17 +498,10 @@ func (s *ReleaseServer) prepareRollback(req *services.RollbackReleaseRequest) (*
return nil, nil, errInvalidRevision return nil, nil, errInvalidRevision
} }
// finds the non-deleted release with the given name crls, err := s.env.Releases.Last(req.Name)
h, err := s.env.Releases.History(req.Name)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if len(h) <= 1 {
return nil, nil, errors.New("no revision to rollback")
}
relutil.SortByRevision(h)
crls := h[len(h)-1]
rbv := req.Version rbv := req.Version
if req.Version == 0 { if req.Version == 0 {

Loading…
Cancel
Save