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 #1566. While fixing that issue, I found that this was also
the root cause of #1587 (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 #1566
Closes #1587
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
}
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
// a string with format ```<release_name>#v<version>```.
// 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 {
Name string
Version int32

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

Loading…
Cancel
Save