Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider units when sorting capacity of pv and pvc #2252

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions internal/render/header.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type HeaderColumn struct {
Wide bool
MX bool
Time bool
Capacity bool
}

// Clone copies a header.
Expand Down Expand Up @@ -163,6 +164,15 @@ func (h Header) IsTimeCol(col int) bool {
return h[col].Time
}

// IsCapacityCol checks if given column index represents a capacity.
func (h Header) IsCapacityCol(col int) bool {
if col < 0 || col >= len(h) {
return false
}

return h[col].Capacity
}

// ValidColIndex returns the valid col index or -1 if none.
func (h Header) ValidColIndex() int {
return h.IndexOf("VALID", true)
Expand Down
6 changes: 6 additions & 0 deletions internal/render/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/rs/zerolog/log"
"golang.org/x/text/language"
"golang.org/x/text/message"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/duration"
)
Expand Down Expand Up @@ -57,6 +58,11 @@ func durationToSeconds(duration string) int64 {
return n
}

func capacityToNumber(capacity string) int64 {
quantity := resource.MustParse(capacity)
return quantity.Value()
}

// AsThousands prints a number with thousand separator.
func AsThousands(n int64) string {
p := message.NewPrinter(language.English)
Expand Down
2 changes: 1 addition & 1 deletion internal/render/pv.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (p PersistentVolume) ColorerFunc() ColorerFunc {
func (PersistentVolume) Header(string) Header {
return Header{
HeaderColumn{Name: "NAME"},
HeaderColumn{Name: "CAPACITY"},
HeaderColumn{Name: "CAPACITY", Capacity: true},
HeaderColumn{Name: "ACCESS MODES"},
HeaderColumn{Name: "RECLAIM POLICY"},
HeaderColumn{Name: "STATUS"},
Expand Down
2 changes: 1 addition & 1 deletion internal/render/pvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func (PersistentVolumeClaim) Header(ns string) Header {
HeaderColumn{Name: "NAME"},
HeaderColumn{Name: "STATUS"},
HeaderColumn{Name: "VOLUME"},
HeaderColumn{Name: "CAPACITY"},
HeaderColumn{Name: "CAPACITY", Capacity: true},
HeaderColumn{Name: "ACCESS MODES"},
HeaderColumn{Name: "STORAGECLASS"},
HeaderColumn{Name: "LABELS", Wide: true},
Expand Down
20 changes: 13 additions & 7 deletions internal/render/row.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,13 @@ func (rr Rows) Find(id string) (int, bool) {
}

// Sort rows based on column index and order.
func (rr Rows) Sort(col int, asc, isNum, isDur bool) {
func (rr Rows) Sort(col int, asc, isNum, isDur, isCapacity bool) {
t := RowSorter{
Rows: rr,
Index: col,
IsNumber: isNum,
IsDuration: isDur,
IsCapacity: isCapacity,
Asc: asc,
}
sort.Sort(t)
Expand All @@ -160,10 +161,12 @@ func (rr Rows) Sort(col int, asc, isNum, isDur bool) {

// RowSorter sorts rows.
type RowSorter struct {
Rows Rows
Index int
IsNumber, IsDuration bool
Asc bool
Rows Rows
Index int
IsNumber bool
IsDuration bool
IsCapacity bool
Asc bool
}

func (s RowSorter) Len() int {
Expand All @@ -177,7 +180,7 @@ func (s RowSorter) Swap(i, j int) {
func (s RowSorter) Less(i, j int) bool {
v1, v2 := s.Rows[i].Fields[s.Index], s.Rows[j].Fields[s.Index]
id1, id2 := s.Rows[i].ID, s.Rows[j].ID
less := Less(s.IsNumber, s.IsDuration, id1, id2, v1, v2)
less := Less(s.IsNumber, s.IsDuration, s.IsCapacity, id1, id2, v1, v2)
if s.Asc {
return less
}
Expand All @@ -188,7 +191,7 @@ func (s RowSorter) Less(i, j int) bool {
// Helpers...

// Less return true if c1 < c2.
func Less(isNumber, isDuration bool, id1, id2, v1, v2 string) bool {
func Less(isNumber, isDuration, isCapacity bool, id1, id2, v1, v2 string) bool {
var less bool
switch {
case isNumber:
Expand All @@ -197,6 +200,9 @@ func Less(isNumber, isDuration bool, id1, id2, v1, v2 string) bool {
case isDuration:
d1, d2 := durationToSeconds(v1), durationToSeconds(v2)
less = d1 <= d2
case isCapacity:
c1, c2 := capacityToNumber(v1), capacityToNumber(v2)
less = c1 <= c2
default:
less = sortorder.NaturalLess(v1, v2)
}
Expand Down
6 changes: 4 additions & 2 deletions internal/render/row_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ func (r RowEvents) FindIndex(id string) (int, bool) {
}

// Sort rows based on column index and order.
func (r RowEvents) Sort(ns string, sortCol int, isDuration, numCol, asc bool) {
func (r RowEvents) Sort(ns string, sortCol int, isDuration, numCol, isCapacity, asc bool) {
if sortCol == -1 {
return
}
Expand All @@ -205,6 +205,7 @@ func (r RowEvents) Sort(ns string, sortCol int, isDuration, numCol, asc bool) {
Asc: asc,
IsNumber: numCol,
IsDuration: isDuration,
IsCapacity: isCapacity,
}
sort.Sort(t)
}
Expand All @@ -218,6 +219,7 @@ type RowEventSorter struct {
NS string
IsNumber bool
IsDuration bool
IsCapacity bool
Asc bool
}

Expand All @@ -232,7 +234,7 @@ func (r RowEventSorter) Swap(i, j int) {
func (r RowEventSorter) Less(i, j int) bool {
f1, f2 := r.Events[i].Row.Fields, r.Events[j].Row.Fields
id1, id2 := r.Events[i].Row.ID, r.Events[j].Row.ID
less := Less(r.IsNumber, r.IsDuration, id1, id2, f1[r.Index], f2[r.Index])
less := Less(r.IsNumber, r.IsDuration, r.IsCapacity, id1, id2, f1[r.Index], f2[r.Index])
if r.Asc {
return less
}
Expand Down
24 changes: 23 additions & 1 deletion internal/render/row_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ func TestRowEventsSort(t *testing.T) {
re render.RowEvents
col int
duration, num, asc bool
capacity bool
e render.RowEvents
}{
"age_time": {
Expand Down Expand Up @@ -464,12 +465,33 @@ func TestRowEventsSort(t *testing.T) {
{Row: render.Row{ID: "ns2/C", Fields: render.Fields{"C", "2", "3"}}},
},
},
"capacity": {
re: render.RowEvents{
{Row: render.Row{ID: "ns1/B", Fields: render.Fields{"B", "2", "3", "1Gi"}}},
{Row: render.Row{ID: "ns1/A", Fields: render.Fields{"A", "2", "3", "1.1G"}}},
{Row: render.Row{ID: "ns1/C", Fields: render.Fields{"C", "2", "3", "0.5Ti"}}},
{Row: render.Row{ID: "ns2/B", Fields: render.Fields{"B", "2", "3", "12e6"}}},
{Row: render.Row{ID: "ns2/A", Fields: render.Fields{"A", "2", "3", "1234"}}},
{Row: render.Row{ID: "ns2/C", Fields: render.Fields{"C", "2", "3", "0.1Ei"}}},
},
col: 3,
asc: true,
capacity: true,
e: render.RowEvents{
{Row: render.Row{ID: "ns2/A", Fields: render.Fields{"A", "2", "3", "1234"}}},
{Row: render.Row{ID: "ns2/B", Fields: render.Fields{"B", "2", "3", "12e6"}}},
{Row: render.Row{ID: "ns1/B", Fields: render.Fields{"B", "2", "3", "1Gi"}}},
{Row: render.Row{ID: "ns1/A", Fields: render.Fields{"A", "2", "3", "1.1G"}}},
{Row: render.Row{ID: "ns1/C", Fields: render.Fields{"C", "2", "3", "0.5Ti"}}},
{Row: render.Row{ID: "ns2/C", Fields: render.Fields{"C", "2", "3", "0.1Ei"}}},
},
},
}

for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.re.Sort("", u.col, u.duration, u.num, u.asc)
u.re.Sort("", u.col, u.duration, u.num, u.capacity, u.asc)
assert.Equal(t, u.e, u.re)
})
}
Expand Down
82 changes: 74 additions & 8 deletions internal/render/row_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ func TestRowsSortText(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.rows.Sort(u.col, u.asc, u.num, false)
u.rows.Sort(u.col, u.asc, u.num, false, false)
assert.Equal(t, u.e, u.rows)
})
}
Expand Down Expand Up @@ -369,7 +369,7 @@ func TestRowsSortDuration(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.rows.Sort(u.col, u.asc, false, true)
u.rows.Sort(u.col, u.asc, false, true, false)
assert.Equal(t, u.e, u.rows)
})
}
Expand Down Expand Up @@ -411,22 +411,67 @@ func TestRowsSortMetrics(t *testing.T) {
for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.rows.Sort(u.col, u.asc, true, false)
u.rows.Sort(u.col, u.asc, true, false, false)
assert.Equal(t, u.e, u.rows)
})
}
}

func TestRowsSortCapacity(t *testing.T) {
uu := map[string]struct {
rows render.Rows
col int
asc bool
e render.Rows
}{
"capacityAsc": {
rows: render.Rows{
{Fields: []string{"10Gi", "duh"}},
{Fields: []string{"10G", "blee"}},
},
col: 0,
asc: true,
e: render.Rows{
{Fields: []string{"10G", "blee"}},
{Fields: []string{"10Gi", "duh"}},
},
},
"capacityDesc": {
rows: render.Rows{
{Fields: []string{"10000m", "1000Mi"}},
{Fields: []string{"1m", "50Mi"}},
},
col: 1,
asc: false,
e: render.Rows{
{Fields: []string{"10000m", "1000Mi"}},
{Fields: []string{"1m", "50Mi"}},
},
},
}

for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
u.rows.Sort(u.col, u.asc, false, false, true)
assert.Equal(t, u.e, u.rows)
})
}
}

func TestLess(t *testing.T) {
uu := map[string]struct {
isNumber, isDuration bool
id1, id2 string
v1, v2 string
e bool
isNumber bool
isDuration bool
isCapacity bool
id1, id2 string
v1, v2 string
e bool
}{
"years": {
isNumber: false,
isDuration: true,
isCapacity: false,
id1: "id1",
id2: "id2",
v1: "2y263d",
Expand All @@ -435,17 +480,38 @@ func TestLess(t *testing.T) {
"hours": {
isNumber: false,
isDuration: true,
isCapacity: false,
id1: "id1",
id2: "id2",
v1: "2y263d",
v2: "19h",
},
"capacity1": {
isNumber: false,
isDuration: false,
isCapacity: true,
id1: "id1",
id2: "id2",
v1: "1Gi",
v2: "1G",
e: false,
},
"capacity2": {
isNumber: false,
isDuration: false,
isCapacity: true,
id1: "id1",
id2: "id2",
v1: "1Gi",
v2: "1Ti",
e: true,
},
}

for k := range uu {
u := uu[k]
t.Run(k, func(t *testing.T) {
assert.Equal(t, u.e, render.Less(u.isNumber, u.isDuration, u.id1, u.id2, u.v1, u.v2))
assert.Equal(t, u.e, render.Less(u.isNumber, u.isDuration, u.isCapacity, u.id1, u.id2, u.v1, u.v2))
})
}
}
1 change: 1 addition & 0 deletions internal/ui/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ func (t *Table) doUpdate(data *render.TableData) {
colIndex,
custData.Header.IsTimeCol(colIndex),
custData.Header.IsMetricsCol(colIndex),
custData.Header.IsCapacityCol(colIndex),
t.sortCol.asc,
)

Expand Down