fix age sorting issue

mine
derailed 2019-03-31 19:05:06 -06:00
parent 6f1b3ad659
commit 6219a58cb9
10 changed files with 107 additions and 45 deletions

View File

@ -1,4 +1,5 @@
<img src="../assets/k9s_small.png" align="right" width="200" height="auto"/> <img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
# Release v0.4.1 # Release v0.4.1
@ -59,4 +60,5 @@ Thank you so much for your support and awesome suggestions to make K9s better!!
--- ---
<img src="../assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -1,4 +1,4 @@
<img src="../assets/k9s_small.png" align="right" width="200" height="auto"/> <img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
# Release v0.4.2 # Release v0.4.2
@ -38,4 +38,4 @@ Also if you dig this tool, please make some noise on social! [@kitesurfer](https
--- ---
<img src="../assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) <img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -0,0 +1,29 @@
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
# Release v0.4.3
## Notes
Thank you to all that contributed with flushing out issues with K9s! I'll try
to mark some of these issues as fixed. But if you don't mind grab the latest
rev and see if we're happier with some of the fixes!
If you've filed an issue please help me verify and close.
Thank you so much for your support and awesome suggestions to make K9s better!!
Also if you dig this tool, please make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
---
## Change Logs
---
## Resolved Bugs
+ Sort by age busted (with feeling edition!) [Issue #145](https://github.com/derailed/k9s/issues/145)
---
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -107,7 +107,7 @@ func (r *CronJob) Fields(ns string) Row {
lastScheduled := "<none>" lastScheduled := "<none>"
if i.Status.LastScheduleTime != nil { if i.Status.LastScheduleTime != nil {
lastScheduled = toAge(*i.Status.LastScheduleTime) lastScheduled = toAgeHuman(toAge(*i.Status.LastScheduleTime))
} }
return append(ff, return append(ff,

View File

@ -83,11 +83,16 @@ func boolToStr(b bool) string {
} }
func toAge(timestamp metav1.Time) string { func toAge(timestamp metav1.Time) string {
if timestamp.IsZero() { return time.Since(timestamp.Time).String()
}
func toAgeHuman(s string) string {
d, err := time.ParseDuration(s)
if err != nil {
return "<unknown>" return "<unknown>"
} }
return duration.HumanDuration(time.Since(timestamp.Time)) return duration.HumanDuration(d)
} }
// Truncate a string to the given l and suffix ellipsis if needed. // Truncate a string to the given l and suffix ellipsis if needed.

View File

@ -13,46 +13,46 @@ func toPerc(f float64) string {
func deltas(c, n string) string { func deltas(c, n string) string {
c, n = strings.TrimSpace(c), strings.TrimSpace(n) c, n = strings.TrimSpace(c), strings.TrimSpace(n)
if c == "n/a" { if c == "n/a" {
return n return ""
} }
if i, ok := numerical(c); ok { if i, ok := numerical(c); ok {
if j, ok := numerical(n); ok { if j, ok := numerical(n); ok {
switch { switch {
case i < j: case i < j:
return plus(n) return plus()
case i > j: case i > j:
return minus(n) return minus()
default: default:
return n return ""
} }
} }
return n return ""
} }
if isAlpha(c) { if isAlpha(c) {
if strings.Contains(c, "(") { if strings.Contains(c, "(") {
return n return ""
} }
switch strings.Compare(c, n) { switch strings.Compare(c, n) {
case -1: case -1:
return plus(n) return plus()
case 1: case 1:
return minus(n) return minus()
default: default:
return n return ""
} }
} }
if len(c) == 0 { if len(c) == 0 {
return n return ""
} }
switch strings.Compare(c, n) { switch strings.Compare(c, n) {
case 1, -1: case 1, -1:
return delta(n) return delta()
default: default:
return n return ""
} }
} }
@ -75,18 +75,14 @@ func numerical(s string) (int, bool) {
return n, true return n, true
} }
func delta(s string) string { func delta() string {
return suffix(s, "𝜟") return "𝜟"
} }
func plus(s string) string { func plus() string {
return suffix(s, "⬆") return "⬆"
} }
func minus(s string) string { func minus() string {
return suffix(s, "⬇︎") return "⬇︎"
}
func suffix(s, su string) string {
return s + su
} }

View File

@ -11,14 +11,14 @@ func TestDeltas(t *testing.T) {
uu := []struct { uu := []struct {
s1, s2, e string s1, s2, e string
}{ }{
{"fred", "fred", "fred"}, {"fred", "fred", ""},
{"fred", "blee", delta("blee")}, {"fred", "blee", delta()},
{"1", "2", plus("2")}, {"1", "2", plus()},
{"2", "1", minus("1")}, {"2", "1", minus()},
{"10Gi", "20Gi", plus("20Gi")}, {"10Gi", "20Gi", plus()},
{"15%(-)", "15%", "15%"}, {"15%(-)", "15%", ""},
{resource.MissingValue, "fred", delta("fred")}, {resource.MissingValue, "", delta()},
{resource.NAValue, "fred", delta("fred")}, {resource.NAValue, "", delta()},
} }
for _, u := range uu { for _, u := range uu {

View File

@ -118,6 +118,18 @@ func isMetric(s string) (string, bool) {
} }
func isDuration(s string) (time.Duration, bool) { func isDuration(s string) (time.Duration, bool) {
// rx := regexp.MustCompile(`(\d+)([h|d])`)
// mm := rx.FindStringSubmatch(s)
// if len(mm) == 3 {
// n, _ := strconv.Atoi(mm[1])
// switch mm[2] {
// case "d":
// s = fmt.Sprintf("%dh", n*24)
// case "y":
// s = fmt.Sprintf("%dh", n*365*24)
// }
// }
d, err := time.ParseDuration(s) d, err := time.ParseDuration(s)
if err != nil { if err != nil {
return d, false return d, false

View File

@ -24,6 +24,11 @@ func TestGroupSort(t *testing.T) {
{false, []string{"xyz", "abc"}, []string{"xyz", "abc"}}, {false, []string{"xyz", "abc"}, []string{"xyz", "abc"}},
{true, []string{"2m30s", "1m10s"}, []string{"1m10s", "2m30s"}}, {true, []string{"2m30s", "1m10s"}, []string{"1m10s", "2m30s"}},
{true, []string{"3d", "1d"}, []string{"1d", "3d"}}, {true, []string{"3d", "1d"}, []string{"1d", "3d"}},
{true, []string{"95h", "93h"}, []string{"93h", "95h"}},
{true, []string{"95d", "93d"}, []string{"93d", "95d"}},
{true, []string{"1h10m", "59m"}, []string{"59m", "1h10m"}},
{true, []string{"95m", "1h30m"}, []string{"1h30m", "95m"}},
} }
for _, u := range uu { for _, u := range uu {

View File

@ -6,11 +6,13 @@ import (
"sort" "sort"
"strings" "strings"
"sync" "sync"
"time"
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/derailed/tview" "github.com/derailed/tview"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/util/duration"
) )
const ( const (
@ -338,7 +340,11 @@ func (v *tableView) doUpdate(data resource.TableData) {
fgColor = v.colorerFn(data.Namespace, data.Rows[sk]) fgColor = v.colorerFn(data.Namespace, data.Rows[sk])
} }
for col, field := range data.Rows[sk].Fields { for col, field := range data.Rows[sk].Fields {
v.addBodyCell(row, col, field, data.Rows[sk].Deltas[col], fgColor, pads) var age bool
if data.Header[col] == "AGE" {
age = true
}
v.addBodyCell(age, row, col, field, data.Rows[sk].Deltas[col], fgColor, pads)
} }
row++ row++
} }
@ -375,15 +381,22 @@ func (v *tableView) addHeaderCell(col int, name string, pads maxyPad) {
v.SetCell(0, col, c) v.SetCell(0, col, c)
} }
func (v *tableView) addBodyCell(row, col int, field, delta string, color tcell.Color, pads maxyPad) { func (v *tableView) addBodyCell(age bool, row, col int, field, delta string, color tcell.Color, pads maxyPad) {
var pField string dField := field
if isASCII(field) { if age {
pField = pad(deltas(delta, field), pads[col]+5) dur, err := time.ParseDuration(field)
} else { if err == nil {
pField = deltas(delta, field) log.Debug().Msg("YO!")
dField = duration.HumanDuration(dur)
}
} }
c := tview.NewTableCell(pField) dField += deltas(delta, field)
if isASCII(field) {
dField = pad(dField, pads[col]+5)
}
c := tview.NewTableCell(dField)
{ {
c.SetExpansion(1) c.SetExpansion(1)
c.SetTextColor(color) c.SetTextColor(color)