added screen dumps
parent
d369c0694a
commit
6aa9e18e12
|
|
@ -3,7 +3,10 @@ package views
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/tview"
|
||||
|
|
@ -21,6 +24,7 @@ type logView struct {
|
|||
ansiWriter io.Writer
|
||||
autoScroll bool
|
||||
actions keyActions
|
||||
path string
|
||||
}
|
||||
|
||||
func newLogView(title string, parent masterView) *logView {
|
||||
|
|
@ -47,13 +51,14 @@ func newLogView(title string, parent masterView) *logView {
|
|||
v.AddItem(v.logs, 0, 1, true)
|
||||
|
||||
v.actions = keyActions{
|
||||
tcell.KeyEscape: {description: "Back", action: v.backCmd, visible: true},
|
||||
KeyC: {description: "Clear", action: v.clearCmd, visible: true},
|
||||
KeyS: {description: "Toggle AutoScroll", action: v.toggleScrollCmd, visible: true},
|
||||
KeyG: {description: "Top", action: v.topCmd, visible: false},
|
||||
KeyShiftG: {description: "Bottom", action: v.bottomCmd, visible: false},
|
||||
KeyF: {description: "Up", action: v.pageUpCmd, visible: false},
|
||||
KeyB: {description: "Down", action: v.pageDownCmd, visible: false},
|
||||
tcell.KeyEscape: newKeyAction("Back", v.backCmd, true),
|
||||
KeyC: newKeyAction("Clear", v.clearCmd, true),
|
||||
KeyS: newKeyAction("Toggle AutoScroll", v.toggleScrollCmd, true),
|
||||
KeyG: newKeyAction("Top", v.topCmd, false),
|
||||
KeyShiftG: newKeyAction("Bottom", v.bottomCmd, false),
|
||||
KeyF: newKeyAction("Up", v.pageUpCmd, false),
|
||||
KeyB: newKeyAction("Down", v.pageDownCmd, false),
|
||||
tcell.KeyCtrlS: newKeyAction("Save", v.saveCmd, true),
|
||||
}
|
||||
v.logs.SetInputCapture(v.keyboard)
|
||||
|
||||
|
|
@ -111,6 +116,37 @@ func (v *logView) update() {
|
|||
// ----------------------------------------------------------------------------
|
||||
// Actions...
|
||||
|
||||
func (v *logView) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if err := os.MkdirAll(K9sDump, 0744); err != nil {
|
||||
log.Error().Err(err).Msgf("Mkdir K9s dump")
|
||||
return nil
|
||||
}
|
||||
|
||||
now := time.Now().UnixNano()
|
||||
fName := fmt.Sprintf("%s-%d.log", strings.Replace(v.path, "/", "-", -1), now)
|
||||
|
||||
path := filepath.Join(K9sDump, fName)
|
||||
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
||||
file, err := os.OpenFile(path, mod, 0644)
|
||||
defer func() {
|
||||
if file != nil {
|
||||
file.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("LogFile create %s", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err := fmt.Fprintf(file, v.logs.GetText(true)); err != nil {
|
||||
log.Error().Err(err).Msgf("Log dump %s", v.path)
|
||||
}
|
||||
v.app.flash().infof("Log %s saved successfully!", path)
|
||||
log.Debug().Msgf("Log %s saved successfully!", path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *logView) toggleScrollCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
v.autoScroll = !v.autoScroll
|
||||
if v.autoScroll {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ func (v *logsView) doLoad(path, co string) error {
|
|||
l.logs.Clear()
|
||||
fmat := skinTitle(fmt.Sprintf(logFmt, path, co), v.parent.appView().styles.Style)
|
||||
l.SetTitle(fmat)
|
||||
l.path = path
|
||||
|
||||
c := make(chan string, 10)
|
||||
go func(l *logView) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
|
|
@ -86,8 +90,7 @@ func newTableView(app *appView, title string) *tableView {
|
|||
|
||||
func (v *tableView) bindKeys() {
|
||||
v.actions[KeyShiftI] = newKeyAction("Invert", v.sortInvertCmd, false)
|
||||
v.actions[KeyShiftN] = newKeyAction("Sort Name", v.sortColCmd(0), true)
|
||||
v.actions[KeyShiftA] = newKeyAction("Sort Age", v.sortColCmd(-1), true)
|
||||
v.actions[tcell.KeyCtrlS] = newKeyAction("Save", v.saveCmd, true)
|
||||
|
||||
v.actions[KeySlash] = newKeyAction("Filter Mode", v.activateCmd, false)
|
||||
v.actions[tcell.KeyEscape] = newKeyAction("Filter Reset", v.resetCmd, false)
|
||||
|
|
@ -96,6 +99,9 @@ func (v *tableView) bindKeys() {
|
|||
v.actions[tcell.KeyBackspace2] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
v.actions[tcell.KeyBackspace] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
v.actions[tcell.KeyDelete] = newKeyAction("Erase", v.eraseCmd, false)
|
||||
|
||||
v.actions[KeyShiftN] = newKeyAction("Sort Name", v.sortColCmd(0), true)
|
||||
v.actions[KeyShiftA] = newKeyAction("Sort Age", v.sortColCmd(-1), true)
|
||||
}
|
||||
|
||||
func (v *tableView) clearSelection() {
|
||||
|
|
@ -133,6 +139,57 @@ func (v *tableView) setSelection() {
|
|||
}
|
||||
}
|
||||
|
||||
// K9sDump represents a directory where K9s artifacts will be persisted.
|
||||
var K9sDump = filepath.Join(os.TempDir(), fmt.Sprintf("k9s-screens-%s", config.MustK9sUser()))
|
||||
|
||||
const (
|
||||
fullFmat = "%s-%s-%d.csv"
|
||||
noNSFmat = "%s-%d.csv"
|
||||
)
|
||||
|
||||
func (v *tableView) saveCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if err := os.MkdirAll(K9sDump, 0744); err != nil {
|
||||
log.Error().Err(err).Msgf("Mkdir K9s dump")
|
||||
return nil
|
||||
}
|
||||
|
||||
ns, now := v.data.Namespace, time.Now().UnixNano()
|
||||
if ns == resource.AllNamespaces {
|
||||
ns = resource.AllNamespace
|
||||
}
|
||||
fName := fmt.Sprintf(fullFmat, v.baseTitle, ns, now)
|
||||
if ns == resource.NotNamespaced {
|
||||
fName = fmt.Sprintf(noNSFmat, v.baseTitle, now)
|
||||
}
|
||||
|
||||
path := filepath.Join(K9sDump, fName)
|
||||
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
||||
file, err := os.OpenFile(path, mod, 0644)
|
||||
defer func() {
|
||||
if file != nil {
|
||||
file.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("CSV create %s", path)
|
||||
return nil
|
||||
}
|
||||
|
||||
w := csv.NewWriter(file)
|
||||
w.Write(v.data.Header)
|
||||
for _, r := range v.data.Rows {
|
||||
w.Write(r.Fields)
|
||||
}
|
||||
w.Flush()
|
||||
if err := w.Error(); err != nil {
|
||||
log.Error().Err(err).Msgf("Screen dump %s", v.baseTitle)
|
||||
}
|
||||
v.app.flash().infof("File %s saved successfully!", path)
|
||||
log.Debug().Msgf("File %s saved successfully!", path)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *tableView) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if v.cmdBuff.isActive() {
|
||||
v.cmdBuff.setActive(false)
|
||||
|
|
|
|||
20
main.go
20
main.go
|
|
@ -12,15 +12,21 @@ import (
|
|||
|
||||
func init() {
|
||||
config.EnsurePath(config.K9sLogs, config.DefaultDirMod)
|
||||
|
||||
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
||||
if file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod); err == nil {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: file})
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
||||
file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod)
|
||||
defer func() {
|
||||
if file != nil {
|
||||
file.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: file})
|
||||
|
||||
cmd.Execute()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue