revert logview + add live filters

mine
derailed 2019-03-02 19:59:59 -07:00
parent 46ca8df1d9
commit ecc4e0e04e
12 changed files with 133 additions and 64 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/derailed/k9s
require ( require (
contrib.go.opencensus.io/exporter/ocagent v0.4.3 // indirect contrib.go.opencensus.io/exporter/ocagent v0.4.3 // indirect
github.com/Azure/go-autorest v11.4.0+incompatible // indirect github.com/Azure/go-autorest v11.4.0+incompatible // indirect
github.com/derailed/tview v0.1.2 github.com/derailed/tview v0.1.3
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/evanphx/json-patch v4.1.0+incompatible // indirect github.com/evanphx/json-patch v4.1.0+incompatible // indirect
github.com/fatih/camelcase v1.0.0 // indirect github.com/fatih/camelcase v1.0.0 // indirect

4
go.sum
View File

@ -13,8 +13,8 @@ github.com/census-instrumentation/opencensus-proto v0.1.0-0.20181214143942-ba49f
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/derailed/tview v0.1.2 h1:T/XDdjvWrSdhi68bKE0O87O7oHD/JxmfU4IQ13y4fmc= github.com/derailed/tview v0.1.3 h1:2/Rz0Sdfg3tepSKt4yCcY2g8IlRtPTrA4UYIQJZs6DI=
github.com/derailed/tview v0.1.2/go.mod h1:WRYVfgb2PBMLZ/muaSpOc/4H4fYsOPnHOaGnBoJ+hGE= github.com/derailed/tview v0.1.3/go.mod h1:WRYVfgb2PBMLZ/muaSpOc/4H4fYsOPnHOaGnBoJ+hGE=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc= github.com/evanphx/json-patch v4.1.0+incompatible h1:K1MDoo4AZ4wU0GIU/fPmtZg7VpzLjCxu+UwBD1FvwOc=

View File

@ -137,8 +137,7 @@ func run(cmd *cobra.Command, args []string) {
{ {
app.Init(version, refreshRate, k8sFlags) app.Init(version, refreshRate, k8sFlags)
defer func() { defer func() {
// Clear screen clearScreen()
print("\033[H\033[2J")
if err := recover(); err != nil { if err := recover(); err != nil {
app.Stop() app.Stop()
fmt.Println(err) fmt.Println(err)
@ -147,7 +146,10 @@ func run(cmd *cobra.Command, args []string) {
}() }()
app.Run() app.Run()
} }
}
func clearScreen() {
fmt.Print("\033[H\033[2J")
} }
func initK8sFlags() { func initK8sFlags() {

View File

@ -5,9 +5,11 @@ import (
"fmt" "fmt"
"sort" "sort"
"strings" "strings"
"time"
"github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/resource"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
log "github.com/sirupsen/logrus"
) )
const ( const (
@ -18,6 +20,7 @@ const (
type aliasView struct { type aliasView struct {
*tableView *tableView
current igniter current igniter
cancel context.CancelFunc
} }
func newAliasView(app *appView) *aliasView { func newAliasView(app *appView) *aliasView {
@ -27,10 +30,26 @@ func newAliasView(app *appView) *aliasView {
v.colorerFn = aliasColorer v.colorerFn = aliasColorer
v.current = app.content.GetPrimitive("main").(igniter) v.current = app.content.GetPrimitive("main").(igniter)
v.sortFn = v.sorterFn v.sortFn = v.sorterFn
v.currentNS = ""
} }
v.actions[tcell.KeyEnter] = newKeyAction("Search", v.aliasCmd) v.actions[tcell.KeyEnter] = newKeyAction("Search", v.gotoCmd)
v.actions[tcell.KeyEscape] = newKeyAction("Reset", v.resetCmd) v.actions[tcell.KeyEscape] = newKeyAction("Reset", v.resetCmd)
v.actions[KeySlash] = newKeyAction("Filter", v.activateCmd) v.actions[KeySlash] = newKeyAction("Filter", v.activateCmd)
ctx, cancel := context.WithCancel(context.TODO())
v.cancel = cancel
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
log.Debug("Alias GR bailing out!")
return
case <-time.After(1 * time.Second):
v.update(v.hydrate())
v.app.Draw()
}
}
}(ctx)
return &v return &v
} }
@ -52,21 +71,32 @@ func (v *aliasView) getTitle() string {
func (v *aliasView) resetCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *aliasView) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
if !v.cmdBuff.empty() { if !v.cmdBuff.empty() {
v.cmdBuff.reset() v.cmdBuff.reset()
v.refresh()
return nil return nil
} }
return v.backCmd(evt) return v.backCmd(evt)
} }
func (v *aliasView) aliasCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *aliasView) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
r, _ := v.GetSelection()
if r != 0 {
return v.runCmd(evt)
}
if v.cmdBuff.isActive() { if v.cmdBuff.isActive() {
return v.filterCmd(evt) return v.filterCmd(evt)
} }
return v.runCmd(evt) return evt
} }
func (v *aliasView) backCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *aliasView) backCmd(evt *tcell.EventKey) *tcell.EventKey {
if v.cancel != nil {
v.cancel()
}
if v.cmdBuff.isActive() {
v.cmdBuff.reset()
} else {
v.app.inject(v.current) v.app.inject(v.current)
}
return nil return nil
} }

View File

@ -205,6 +205,10 @@ func (a *appView) noopCmd(*tcell.EventKey) *tcell.EventKey {
return nil return nil
} }
func (a *appView) puntCmd(evt *tcell.EventKey) *tcell.EventKey {
return evt
}
func (a *appView) showPage(p string) { func (a *appView) showPage(p string) {
a.pages.SwitchToPage(p) a.pages.SwitchToPage(p)
} }

View File

@ -66,7 +66,6 @@ func (v *cmdView) active(f bool) {
v.SetBackgroundColor(tcell.ColorDodgerBlue) v.SetBackgroundColor(tcell.ColorDodgerBlue)
v.activate() v.activate()
} else { } else {
log.Debug("CmdView was deactivated!")
v.SetBackgroundColor(tcell.ColorDefault) v.SetBackgroundColor(tcell.ColorDefault)
v.Clear() v.Clear()
} }

View File

@ -3,9 +3,11 @@ package views
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"os" "os"
"os/exec" "os/exec"
"os/signal" "os/signal"
"strings"
"syscall" "syscall"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -18,11 +20,19 @@ func runK(app *appView, args ...string) bool {
return false return false
} }
log.Debugf("Running command > %s %s", bin, args)
return app.Suspend(func() { return app.Suspend(func() {
last := len(args) - 1
if args[last] == "sh" {
args[last] = "bash"
if err := execute(bin, args...); err != nil {
args[last] = "sh"
} else {
return
}
}
if err := execute(bin, args...); err != nil { if err := execute(bin, args...); err != nil {
log.Errorf("Command exited: %T %v %v", err, err, args) log.Errorf("Command exited: %T %v %v", err, err, args)
app.flash(flashErr, err.Error()) app.flash(flashErr, "Command exited:", err.Error())
} }
}) })
} }
@ -37,6 +47,8 @@ func run1(app *appView, bin string, args ...string) bool {
} }
func execute(bin string, args ...string) error { func execute(bin string, args ...string) error {
clearScreen()
log.Debugf("Running command > %s %s", bin, strings.Join(args, " "))
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
@ -59,3 +71,7 @@ func execute(bin string, args ...string) error {
return err return err
} }
} }
func clearScreen() {
fmt.Print("\033[H\033[2J")
}

View File

@ -2,8 +2,6 @@ package views
import ( import (
"fmt" "fmt"
log "github.com/sirupsen/logrus"
) )
type logView struct { type logView struct {
@ -11,7 +9,6 @@ type logView struct {
} }
func newLogView(title string, parent loggable) *logView { func newLogView(title string, parent loggable) *logView {
log.Debug("LogsView init...")
v := logView{detailsView: newDetailsView(parent.appView(), parent.backFn())} v := logView{detailsView: newDetailsView(parent.appView(), parent.backFn())}
{ {
v.SetBorderPadding(0, 0, 1, 1) v.SetBorderPadding(0, 0, 1, 1)

View File

@ -40,8 +40,8 @@ func newLogsView(parent loggable) *logsView {
v.setActions(keyActions{ v.setActions(keyActions{
tcell.KeyEscape: {description: "Back", action: v.back}, tcell.KeyEscape: {description: "Back", action: v.back},
KeyC: {description: "Clear", action: v.clearLogs}, KeyC: {description: "Clear", action: v.clearLogs},
KeyU: {description: "Top", action: v.top}, KeyG: {description: "Top", action: v.top},
KeyD: {description: "Bottom", action: v.bottom}, KeyShiftG: {description: "Bottom", action: v.bottom},
KeyF: {description: "Up", action: v.pageUp}, KeyF: {description: "Up", action: v.pageUp},
KeyB: {description: "Down", action: v.pageDown}, KeyB: {description: "Down", action: v.pageDown},
}) })
@ -206,7 +206,7 @@ func (v *logsView) back(evt *tcell.EventKey) *tcell.EventKey {
func (v *logsView) top(evt *tcell.EventKey) *tcell.EventKey { func (v *logsView) top(evt *tcell.EventKey) *tcell.EventKey {
if p := v.CurrentPage(); p != nil { if p := v.CurrentPage(); p != nil {
v.parent.appView().flash(flashInfo, "Top logs...") v.parent.appView().flash(flashInfo, "Top of logs...")
p.Item.(*logView).ScrollToBeginning() p.Item.(*logView).ScrollToBeginning()
} }
return nil return nil
@ -214,7 +214,7 @@ func (v *logsView) top(evt *tcell.EventKey) *tcell.EventKey {
func (v *logsView) bottom(*tcell.EventKey) *tcell.EventKey { func (v *logsView) bottom(*tcell.EventKey) *tcell.EventKey {
if p := v.CurrentPage(); p != nil { if p := v.CurrentPage(); p != nil {
v.parent.appView().flash(flashInfo, "Bottom logs...") v.parent.appView().flash(flashInfo, "Bottom of logs...")
p.Item.(*logView).ScrollToEnd() p.Item.(*logView).ScrollToEnd()
} }
return nil return nil
@ -222,7 +222,6 @@ func (v *logsView) bottom(*tcell.EventKey) *tcell.EventKey {
func (v *logsView) pageUp(*tcell.EventKey) *tcell.EventKey { func (v *logsView) pageUp(*tcell.EventKey) *tcell.EventKey {
if p := v.CurrentPage(); p != nil { if p := v.CurrentPage(); p != nil {
v.parent.appView().flash(flashInfo, "Page Up logs...")
p.Item.(*logView).PageUp() p.Item.(*logView).PageUp()
} }
return nil return nil
@ -230,7 +229,6 @@ func (v *logsView) pageUp(*tcell.EventKey) *tcell.EventKey {
func (v *logsView) pageDown(*tcell.EventKey) *tcell.EventKey { func (v *logsView) pageDown(*tcell.EventKey) *tcell.EventKey {
if p := v.CurrentPage(); p != nil { if p := v.CurrentPage(); p != nil {
v.parent.appView().flash(flashInfo, "Page Down logs...")
p.Item.(*logView).PageDown() p.Item.(*logView).PageDown()
} }
return nil return nil

View File

@ -59,56 +59,57 @@ func (v *podView) getSelection() string {
// Handlers... // Handlers...
func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey {
log.Println("Selected", v.rowSelected())
if !v.rowSelected() {
return evt
}
cc, err := fetchContainers(v.list, v.selectedItem, true)
if err != nil {
v.app.flash(flashErr, err.Error())
log.Error(err)
return evt
}
l := v.GetPrimitive("logs").(*logsView)
l.deleteAllPages()
for _, c := range cc {
l.addContainer(c)
}
v.switchPage("logs")
l.init()
return nil
}
// func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey { // func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey {
// if !v.rowSelected() { // if !v.rowSelected() {
// return evt // return evt
// } // }
// previous := false
// if evt.Rune() == 'p' {
// log.Debug("Previous logs detected")
// previous = true
// }
// cc, err := fetchContainers(v.list, v.selectedItem, true) // cc, err := fetchContainers(v.list, v.selectedItem, true)
// if err != nil { // if err != nil {
// v.app.flash(flashErr, err.Error()) // v.app.flash(flashErr, err.Error())
// log.Error(err) // log.Error("Error fetching containers", err)
// return evt // return evt
// } // }
// l := v.GetPrimitive("logs").(*logsView) // if len(cc) == 1 {
// l.deleteAllPages() // v.showLogs(v.selectedItem, "", previous)
// for _, c := range cc { // } else {
// l.addContainer(c) // p := v.GetPrimitive("choose").(*selectList)
// p.populate(cc)
// p.SetSelectedFunc(func(i int, t, d string, r rune) {
// v.showLogs(v.selectedItem, t, previous)
// })
// v.switchPage("choose")
// } // }
// v.switchPage("logs") // return evt
// l.init()
// return nil
// } // }
func (v *podView) logsCmd(evt *tcell.EventKey) *tcell.EventKey {
if !v.rowSelected() {
return evt
}
previous := false
if evt.Rune() == 'p' {
log.Debug("Previous logs detected")
previous = true
}
cc, err := fetchContainers(v.list, v.selectedItem, true)
if err != nil {
v.app.flash(flashErr, err.Error())
log.Error("Error fetching containers", err)
return evt
}
if len(cc) == 1 {
v.showLogs(v.selectedItem, "", previous)
} else {
p := v.GetPrimitive("choose").(*selectList)
p.populate(cc)
p.SetSelectedFunc(func(i int, t, d string, r rune) {
v.showLogs(v.selectedItem, t, previous)
})
v.switchPage("choose")
}
return evt
}
func (v *podView) shellCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *podView) shellCmd(evt *tcell.EventKey) *tcell.EventKey {
if !v.rowSelected() { if !v.rowSelected() {
return evt return evt

View File

@ -94,6 +94,7 @@ func (v *resourceView) getTitle() string {
func (v *resourceView) selChanged(r, c int) { func (v *resourceView) selChanged(r, c int) {
v.selectItem(r, c) v.selectItem(r, c)
v.getTV().cmdBuff.setActive(false)
} }
func (v *resourceView) colorFn(f colorerFn) { func (v *resourceView) colorFn(f colorerFn) {
@ -289,8 +290,7 @@ func (v *resourceView) switchPage(p string) {
} }
func (v *resourceView) rowSelected() bool { func (v *resourceView) rowSelected() bool {
item := v.selectedItem return v.selectedItem != noSelection
return item != noSelection
} }
func namespaced(n string) (string, string) { func namespaced(n string) (string, string) {

View File

@ -57,15 +57,26 @@ func newTableView(app *appView, title string, sortFn resource.SortFn) *tableView
v.actions[tcell.KeyEnter] = newKeyAction("Search", v.filterCmd) v.actions[tcell.KeyEnter] = newKeyAction("Search", v.filterCmd)
v.actions[tcell.KeyEscape] = newKeyAction("Reset", v.resetCmd) v.actions[tcell.KeyEscape] = newKeyAction("Reset", v.resetCmd)
v.actions[tcell.KeyBackspace2] = newKeyAction("Erase", v.eraseCmd) v.actions[tcell.KeyBackspace2] = newKeyAction("Erase", v.eraseCmd)
v.actions[KeyG] = newKeyAction("Top", app.puntCmd)
v.actions[KeyShiftG] = newKeyAction("Bottom", app.puntCmd)
v.actions[KeyB] = newKeyAction("Down", v.pageDownCmd)
v.actions[KeyF] = newKeyAction("Up", v.pageUpCmd)
return &v return &v
} }
func (v *tableView) clearSelection() {
v.Select(0, 0)
v.ScrollToBeginning()
}
func (v *tableView) keyboard(evt *tcell.EventKey) *tcell.EventKey { func (v *tableView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
key := evt.Key() key := evt.Key()
if key == tcell.KeyRune { if key == tcell.KeyRune {
if v.cmdBuff.isActive() { if v.cmdBuff.isActive() {
v.cmdBuff.add(evt.Rune()) v.cmdBuff.add(evt.Rune())
v.clearSelection()
v.doUpdate(v.filtered())
return nil return nil
} }
key = tcell.Key(evt.Rune()) key = tcell.Key(evt.Rune())
@ -78,6 +89,16 @@ func (v *tableView) keyboard(evt *tcell.EventKey) *tcell.EventKey {
return evt return evt
} }
func (v *tableView) pageUpCmd(evt *tcell.EventKey) *tcell.EventKey {
v.PageUp()
return nil
}
func (v *tableView) pageDownCmd(evt *tcell.EventKey) *tcell.EventKey {
v.PageDown()
return nil
}
func (v *tableView) filterCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *tableView) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
v.cmdBuff.setActive(false) v.cmdBuff.setActive(false)
v.refresh() v.refresh()
@ -92,6 +113,7 @@ func (v *tableView) eraseCmd(evt *tcell.EventKey) *tcell.EventKey {
} }
func (v *tableView) resetCmd(evt *tcell.EventKey) *tcell.EventKey { func (v *tableView) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
v.app.flash(flashInfo, "Filtering off...")
v.cmdBuff.reset() v.cmdBuff.reset()
v.refresh() v.refresh()
return nil return nil
@ -102,7 +124,7 @@ func (v *tableView) activateCmd(evt *tcell.EventKey) *tcell.EventKey {
return evt return evt
} }
v.app.flash(flashInfo, "Entering filtering mode...") v.app.flash(flashInfo, "Filtering...")
log.Info("Entering filtering mode...") log.Info("Entering filtering mode...")
v.cmdBuff.reset() v.cmdBuff.reset()
v.cmdBuff.setActive(true) v.cmdBuff.setActive(true)
@ -150,7 +172,7 @@ func (v *tableView) update(data resource.TableData) {
v.refreshMX.Lock() v.refreshMX.Lock()
{ {
v.data = data v.data = data
if !v.cmdBuff.isActive() && !v.cmdBuff.empty() { if !v.cmdBuff.empty() {
v.doUpdate(v.filtered()) v.doUpdate(v.filtered())
} else { } else {
v.doUpdate(data) v.doUpdate(data)