Merge pull request #5539 from jan25/fix-list-sorting-5499

fix(helm): sort release list with flags --reverse and --date
pull/5848/head
Matthew Fisher 6 years ago committed by GitHub
commit da83115510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -66,7 +66,6 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
if client.AllNamespaces { if client.AllNamespaces {
client.SetConfiguration(newActionConfig(true)) client.SetConfiguration(newActionConfig(true))
} }
client.All = client.Limit == -1
client.SetStateMask() client.SetStateMask()
results, err := client.Run() results, err := client.Run()
@ -86,8 +85,8 @@ func newListCmd(cfg *action.Configuration, out io.Writer) *cobra.Command {
f := cmd.Flags() f := cmd.Flags()
f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format") f.BoolVarP(&client.Short, "short", "q", false, "output short (quiet) listing format")
f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date") f.BoolVarP(&client.ByDate, "date", "d", false, "sort by release date")
f.BoolVarP(&client.SortDesc, "reverse", "r", false, "reverse the sort order") f.BoolVarP(&client.SortReverse, "reverse", "r", false, "reverse the sort order")
f.BoolVarP(&client.All, "all", "a", false, "show all releases, not just the ones marked deployed") f.BoolVarP(&client.All, "all", "a", false, "show all releases, not just the ones marked deployed or failed")
f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases") f.BoolVar(&client.Uninstalled, "uninstalled", false, "show uninstalled releases")
f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases") f.BoolVar(&client.Superseded, "superseded", false, "show superseded releases")
f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled") f.BoolVar(&client.Uninstalling, "uninstalling", false, "show releases that are currently being uninstalled")

@ -26,14 +26,19 @@ import (
func TestListCmd(t *testing.T) { func TestListCmd(t *testing.T) {
defaultNamespace := "default" defaultNamespace := "default"
timestamp1 := time.Unix(1452902400, 0).UTC()
timestamp2 := time.Unix(1452902401, 0).UTC() sampleTimeSeconds := int64(1452902400)
timestamp1 := time.Unix(sampleTimeSeconds+1, 0).UTC()
timestamp2 := time.Unix(sampleTimeSeconds+2, 0).UTC()
timestamp3 := time.Unix(sampleTimeSeconds+3, 0).UTC()
timestamp4 := time.Unix(sampleTimeSeconds+4, 0).UTC()
chartInfo := &chart.Chart{ chartInfo := &chart.Chart{
Metadata: &chart.Metadata{ Metadata: &chart.Metadata{
Name: "chickadee", Name: "chickadee",
Version: "1.0.0", Version: "1.0.0",
}, },
} }
releaseFixture := []*release.Release{ releaseFixture := []*release.Release{
{ {
Name: "starlord", Name: "starlord",
@ -60,7 +65,7 @@ func TestListCmd(t *testing.T) {
Version: 1, Version: 1,
Namespace: defaultNamespace, Namespace: defaultNamespace,
Info: &release.Info{ Info: &release.Info{
LastDeployed: timestamp2, LastDeployed: timestamp1,
Status: release.StatusUninstalled, Status: release.StatusUninstalled,
}, },
Chart: chartInfo, Chart: chartInfo,
@ -105,6 +110,26 @@ func TestListCmd(t *testing.T) {
}, },
Chart: chartInfo, Chart: chartInfo,
}, },
{
Name: "hummingbird",
Version: 1,
Namespace: defaultNamespace,
Info: &release.Info{
LastDeployed: timestamp3,
Status: release.StatusDeployed,
},
Chart: chartInfo,
},
{
Name: "iguana",
Version: 2,
Namespace: defaultNamespace,
Info: &release.Info{
LastDeployed: timestamp4,
Status: release.StatusDeployed,
},
Chart: chartInfo,
},
} }
tests := []cmdTestCase{{ tests := []cmdTestCase{{
@ -152,6 +177,11 @@ func TestListCmd(t *testing.T) {
cmd: "list --reverse", cmd: "list --reverse",
golden: "output/list-reverse.txt", golden: "output/list-reverse.txt",
rels: releaseFixture, rels: releaseFixture,
}, {
name: "list releases sorted by reversed release date",
cmd: "list --date --reverse",
golden: "output/list-date-reversed.txt",
rels: releaseFixture,
}, { }, {
name: "list releases in short output format", name: "list releases in short output format",
cmd: "list --short", cmd: "list --short",

@ -1,3 +1,10 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 drax default 1 2016-01-16 00:00:01 +0000 UTC uninstalling chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 gamora default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0
groot default 1 2016-01-16 00:00:01 +0000 UTC uninstalled chickadee-1.0.0
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
starlord default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0
thanos default 1 2016-01-16 00:00:01 +0000 UTC pending-install chickadee-1.0.0

@ -0,0 +1,5 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0

@ -1,3 +1,5 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0

@ -1,2 +1,2 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0

@ -1,3 +1,5 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0

@ -1,2 +1,2 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0

@ -1,2 +1,4 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0

@ -1,2 +1,2 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
thanos default 1 2016-01-16 00:00:00 +0000 UTC pending-install chickadee-1.0.0 thanos default 1 2016-01-16 00:00:01 +0000 UTC pending-install chickadee-1.0.0

@ -1,3 +1,5 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0

@ -1,2 +1,4 @@
starlord hummingbird
iguana
rocket rocket
starlord

@ -1,3 +1,3 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 gamora default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 starlord default 1 2016-01-16 00:00:01 +0000 UTC superseded chickadee-1.0.0

@ -1,2 +1,2 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
drax default 1 2016-01-16 00:00:00 +0000 UTC uninstalling chickadee-1.0.0 drax default 1 2016-01-16 00:00:01 +0000 UTC uninstalling chickadee-1.0.0

@ -1,3 +1,5 @@
NAME NAMESPACE REVISION UPDATED STATUS CHART NAME NAMESPACE REVISION UPDATED STATUS CHART
starlord default 2 2016-01-16 00:00:00 +0000 UTC deployed chickadee-1.0.0 hummingbird default 1 2016-01-16 00:00:03 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:01 +0000 UTC failed chickadee-1.0.0 iguana default 2 2016-01-16 00:00:04 +0000 UTC deployed chickadee-1.0.0
rocket default 1 2016-01-16 00:00:02 +0000 UTC failed chickadee-1.0.0
starlord default 2 2016-01-16 00:00:01 +0000 UTC deployed chickadee-1.0.0

@ -87,12 +87,12 @@ const ListAll = ListDeployed | ListUninstalled | ListUninstalling | ListPendingI
type Sorter uint type Sorter uint
const ( const (
// ByDate sorts by date
ByDate Sorter = iota
// ByNameAsc sorts by ascending lexicographic order
ByNameAsc
// ByNameDesc sorts by descending lexicographic order // ByNameDesc sorts by descending lexicographic order
ByNameDesc ByNameDesc Sorter = iota + 1
// ByDateAsc sorts by ascending dates (oldest updated release first)
ByDateAsc
// ByDateDesc sorts by descending dates (latest updated release first)
ByDateDesc
) )
// List is the action for listing releases. // List is the action for listing releases.
@ -109,6 +109,9 @@ type List struct {
// //
// see pkg/releaseutil for several useful sorters // see pkg/releaseutil for several useful sorters
Sort Sorter Sort Sorter
// Overrides the default lexicographic sorting
ByDate bool
SortReverse bool
// StateMask accepts a bitmask of states for items to show. // StateMask accepts a bitmask of states for items to show.
// The default is ListDeployed // The default is ListDeployed
StateMask ListStates StateMask ListStates
@ -119,8 +122,6 @@ type List struct {
// Filter is a filter that is applied to the results // Filter is a filter that is applied to the results
Filter string Filter string
Short bool Short bool
ByDate bool
SortDesc bool
Uninstalled bool Uninstalled bool
Superseded bool Superseded bool
Uninstalling bool Uninstalling bool
@ -194,9 +195,22 @@ func (l *List) Run() ([]*release.Release, error) {
// sort is an in-place sort where order is based on the value of a.Sort // sort is an in-place sort where order is based on the value of a.Sort
func (l *List) sort(rels []*release.Release) { func (l *List) sort(rels []*release.Release) {
if l.SortReverse {
l.Sort = ByNameDesc
}
if l.ByDate {
l.Sort = ByDateDesc
if l.SortReverse {
l.Sort = ByDateAsc
}
}
switch l.Sort { switch l.Sort {
case ByDate: case ByDateDesc:
releaseutil.SortByDate(rels) releaseutil.SortByDate(rels)
case ByDateAsc:
releaseutil.Reverse(rels, releaseutil.SortByDate)
case ByNameDesc: case ByNameDesc:
releaseutil.Reverse(rels, releaseutil.SortByName) releaseutil.Reverse(rels, releaseutil.SortByName)
default: default:
@ -227,6 +241,9 @@ func (l *List) SetStateMask() {
if l.Failed { if l.Failed {
state |= ListFailed state |= ListFailed
} }
if l.Superseded {
state |= ListSuperseded
}
// Apply a default // Apply a default
if state == 0 { if state == 0 {

@ -81,6 +81,7 @@ func TestList_AllNamespaces(t *testing.T) {
lister := newListFixture(t) lister := newListFixture(t)
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
lister.AllNamespaces = true lister.AllNamespaces = true
lister.SetStateMask()
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) is.NoError(err)
is.Len(list, 3) is.Len(list, 3)
@ -103,13 +104,10 @@ func TestList_Limit(t *testing.T) {
is := assert.New(t) is := assert.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
// Sort because otherwise there is no guaranteed order
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) is.NoError(err)
is.Len(list, 2) is.Len(list, 2)
// Lex order means one, three, two // Lex order means one, three, two
is.Equal("one", list[0].Name) is.Equal("one", list[0].Name)
is.Equal("three", list[1].Name) is.Equal("three", list[1].Name)
@ -119,8 +117,6 @@ func TestList_BigLimit(t *testing.T) {
is := assert.New(t) is := assert.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 20 lister.Limit = 20
// Sort because otherwise there is no guaranteed order
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) is.NoError(err)
@ -137,8 +133,6 @@ func TestList_LimitOffset(t *testing.T) {
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
lister.Offset = 1 lister.Offset = 1
// Sort because otherwise there is no guaranteed order
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) is.NoError(err)
@ -154,8 +148,6 @@ func TestList_LimitOffsetOutOfBounds(t *testing.T) {
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
lister.Offset = 3 // Last item is index 2 lister.Offset = 3 // Last item is index 2
// Sort because otherwise there is no guaranteed order
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) is.NoError(err)
@ -170,8 +162,6 @@ func TestList_LimitOffsetOutOfBounds(t *testing.T) {
func TestList_StateMask(t *testing.T) { func TestList_StateMask(t *testing.T) {
is := assert.New(t) is := assert.New(t)
lister := newListFixture(t) lister := newListFixture(t)
// Sort because otherwise there is no guaranteed order
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
one, err := lister.cfg.Releases.Get("one", 1) one, err := lister.cfg.Releases.Get("one", 1)
is.NoError(err) is.NoError(err)
@ -200,7 +190,6 @@ func TestList_Filter(t *testing.T) {
is := assert.New(t) is := assert.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Filter = "th." lister.Filter = "th."
lister.Sort = ByNameAsc
makeMeSomeReleases(lister.cfg.Releases, t) makeMeSomeReleases(lister.cfg.Releases, t)
res, err := lister.Run() res, err := lister.Run()
@ -233,6 +222,11 @@ func makeMeSomeReleases(store *storage.Storage, t *testing.T) {
three.Name = "three" three.Name = "three"
three.Namespace = "default" three.Namespace = "default"
three.Version = 3 three.Version = 3
four := releaseStub()
four.Name = "four"
four.Namespace = "default"
four.Version = 4
four.Info.Status = release.StatusSuperseded
for _, rel := range []*release.Release{one, two, three} { for _, rel := range []*release.Release{one, two, three} {
if err := store.Create(rel); err != nil { if err := store.Create(rel); err != nil {

@ -38,8 +38,8 @@ type ByDate struct{ list }
// Less compares to releases // Less compares to releases
func (s ByDate) Less(i, j int) bool { func (s ByDate) Less(i, j int) bool {
ti := s.list[i].Info.LastDeployed.Second() ti := s.list[i].Info.LastDeployed.Unix()
tj := s.list[j].Info.LastDeployed.Second() tj := s.list[j].Info.LastDeployed.Unix()
return ti < tj return ti < tj
} }

Loading…
Cancel
Save