parent
c9783fac61
commit
a631712c05
|
|
@ -28,25 +28,27 @@ type LogsListener interface {
|
|||
|
||||
// Log represents a resource logger.
|
||||
type Log struct {
|
||||
factory dao.Factory
|
||||
lines dao.LogItems
|
||||
listeners []LogsListener
|
||||
gvr client.GVR
|
||||
logOptions dao.LogOptions
|
||||
cancelFn context.CancelFunc
|
||||
mx sync.RWMutex
|
||||
filter string
|
||||
lastSent int
|
||||
flushTimeout time.Duration
|
||||
factory dao.Factory
|
||||
lines dao.LogItems
|
||||
listeners []LogsListener
|
||||
gvr client.GVR
|
||||
logOptions dao.LogOptions
|
||||
cancelFn context.CancelFunc
|
||||
mx sync.RWMutex
|
||||
filter string
|
||||
lastSent int
|
||||
flushTimeout time.Duration
|
||||
originalContainer string
|
||||
}
|
||||
|
||||
// NewLog returns a new model.
|
||||
func NewLog(gvr client.GVR, opts dao.LogOptions, flushTimeout time.Duration) *Log {
|
||||
return &Log{
|
||||
gvr: gvr,
|
||||
logOptions: opts,
|
||||
lines: nil,
|
||||
flushTimeout: flushTimeout,
|
||||
gvr: gvr,
|
||||
logOptions: opts,
|
||||
lines: nil,
|
||||
flushTimeout: flushTimeout,
|
||||
originalContainer: opts.Container,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +252,16 @@ func (l *Log) Notify() {
|
|||
}
|
||||
}
|
||||
|
||||
// ToggleShowTimestamp toggles to show all containers logs.
|
||||
func (l *Log) ToggleAllContainers() {
|
||||
if l.logOptions.Container != "" {
|
||||
l.logOptions.Container = ""
|
||||
} else {
|
||||
l.logOptions.Container = l.originalContainer
|
||||
}
|
||||
l.Restart()
|
||||
}
|
||||
|
||||
func (l *Log) updateLogs(ctx context.Context, c dao.LogChan) {
|
||||
defer func() {
|
||||
log.Debug().Msgf("updateLogs view bailing out!")
|
||||
|
|
|
|||
|
|
@ -205,6 +205,16 @@ func TestLogTimedout(t *testing.T) {
|
|||
assert.Equal(t, e, string(v.data[0]))
|
||||
}
|
||||
|
||||
func TestToggleAllContainers(t *testing.T) {
|
||||
m := model.NewLog(client.NewGVR(""), makeLogOpts(1), 10*time.Millisecond)
|
||||
m.Init(makeFactory())
|
||||
assert.Equal(t, m.GetContainer(), "blee")
|
||||
m.ToggleAllContainers()
|
||||
assert.Equal(t, m.GetContainer(), "")
|
||||
m.ToggleAllContainers()
|
||||
assert.Equal(t, m.GetContainer(), "blee")
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func (l *Log) Init(ctx context.Context) (err error) {
|
|||
l.SetBorder(true)
|
||||
l.SetDirection(tview.FlexRow)
|
||||
|
||||
l.indicator = NewLogIndicator(l.app.Config, l.app.Styles)
|
||||
l.indicator = NewLogIndicator(l.app.Config, l.app.Styles, l.isContainerLogView())
|
||||
l.AddItem(l.indicator, 1, 1, false)
|
||||
l.indicator.Refresh()
|
||||
|
||||
|
|
@ -198,6 +198,11 @@ func (l *Log) bindKeys() {
|
|||
tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true),
|
||||
ui.KeyC: ui.NewKeyAction("Copy", l.cpCmd, true),
|
||||
})
|
||||
if l.isContainerLogView() {
|
||||
l.logs.Actions().Set(ui.KeyActions{
|
||||
ui.KeyA: ui.NewKeyAction("Toggle AllContainers", l.showAllContainers, true),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Log) resetCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
|
|
@ -287,6 +292,15 @@ func (l *Log) sinceCmd(a int) func(evt *tcell.EventKey) *tcell.EventKey {
|
|||
}
|
||||
}
|
||||
|
||||
func (l *Log) showAllContainers(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if l.app.InCmdMode() {
|
||||
return evt
|
||||
}
|
||||
l.indicator.ToggleAllContainers()
|
||||
l.model.ToggleAllContainers()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Log) filterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if !l.logs.cmdBuff.IsActive() {
|
||||
return evt
|
||||
|
|
@ -416,6 +430,10 @@ func (l *Log) goFullScreen() {
|
|||
}
|
||||
}
|
||||
|
||||
func (l *Log) isContainerLogView() bool {
|
||||
return l.model.GetContainer() != ""
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
|
|
|
|||
|
|
@ -8,36 +8,40 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
autoscroll = "Autoscroll"
|
||||
fullscreen = "FullScreen"
|
||||
timestamp = "Timestamps"
|
||||
wrap = "Wrap"
|
||||
on = "On"
|
||||
off = "Off"
|
||||
spacer = " "
|
||||
bold = "[::b]"
|
||||
autoscroll = "Autoscroll"
|
||||
fullscreen = "FullScreen"
|
||||
timestamp = "Timestamps"
|
||||
wrap = "Wrap"
|
||||
allContainers = "AllContainers"
|
||||
on = "On"
|
||||
off = "Off"
|
||||
spacer = " "
|
||||
bold = "[::b]"
|
||||
)
|
||||
|
||||
// LogIndicator represents a log view indicator.
|
||||
type LogIndicator struct {
|
||||
*tview.TextView
|
||||
|
||||
styles *config.Styles
|
||||
scrollStatus int32
|
||||
fullScreen bool
|
||||
textWrap bool
|
||||
showTime bool
|
||||
styles *config.Styles
|
||||
scrollStatus int32
|
||||
fullScreen bool
|
||||
textWrap bool
|
||||
showTime bool
|
||||
allContainers bool
|
||||
shouldDisplayAllContainers bool
|
||||
}
|
||||
|
||||
// NewLogIndicator returns a new indicator.
|
||||
func NewLogIndicator(cfg *config.Config, styles *config.Styles) *LogIndicator {
|
||||
func NewLogIndicator(cfg *config.Config, styles *config.Styles, isContainerLogView bool) *LogIndicator {
|
||||
l := LogIndicator{
|
||||
styles: styles,
|
||||
TextView: tview.NewTextView(),
|
||||
scrollStatus: 1,
|
||||
fullScreen: cfg.K9s.Logger.FullScreenLogs,
|
||||
textWrap: cfg.K9s.Logger.TextWrap,
|
||||
showTime: cfg.K9s.Logger.ShowTime,
|
||||
styles: styles,
|
||||
TextView: tview.NewTextView(),
|
||||
scrollStatus: 1,
|
||||
fullScreen: cfg.K9s.Logger.FullScreenLogs,
|
||||
textWrap: cfg.K9s.Logger.TextWrap,
|
||||
showTime: cfg.K9s.Logger.ShowTime,
|
||||
shouldDisplayAllContainers: isContainerLogView,
|
||||
}
|
||||
l.StylesChanged(styles)
|
||||
styles.AddListener(&l)
|
||||
|
|
@ -100,9 +104,18 @@ func (l *LogIndicator) ToggleAutoScroll() {
|
|||
l.Refresh()
|
||||
}
|
||||
|
||||
// ToggleTextWrap toggles the wrap mode.
|
||||
func (l *LogIndicator) ToggleAllContainers() {
|
||||
l.allContainers = !l.allContainers
|
||||
l.Refresh()
|
||||
}
|
||||
|
||||
// Refresh updates the view.
|
||||
func (l *LogIndicator) Refresh() {
|
||||
l.Clear()
|
||||
if l.shouldDisplayAllContainers {
|
||||
l.update(allContainers, l.allContainers, spacer)
|
||||
}
|
||||
l.update(autoscroll, l.AutoScroll(), spacer)
|
||||
l.update(fullscreen, l.fullScreen, spacer)
|
||||
l.update(timestamp, l.showTime, spacer)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,19 @@ import (
|
|||
|
||||
func TestLogIndicatorRefresh(t *testing.T) {
|
||||
defaults := config.NewStyles()
|
||||
v := view.NewLogIndicator(config.NewConfig(nil), defaults)
|
||||
v.Refresh()
|
||||
uu := map[string]struct {
|
||||
li *view.LogIndicator
|
||||
e string
|
||||
}{
|
||||
"all containers": {view.NewLogIndicator(config.NewConfig(nil), defaults, true), "[::b]AllContainers:Off [::b]Autoscroll:On [::b]FullScreen:Off [::b]Timestamps:Off [::b]Wrap:Off\n"},
|
||||
"no all containers": {view.NewLogIndicator(config.NewConfig(nil), defaults, false), "[::b]Autoscroll:On [::b]FullScreen:Off [::b]Timestamps:Off [::b]Wrap:Off\n"},
|
||||
}
|
||||
|
||||
assert.Equal(t, "[::b]Autoscroll:On [::b]FullScreen:Off [::b]Timestamps:Off [::b]Wrap:Off\n", v.GetText(false))
|
||||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
u.li.Refresh()
|
||||
assert.Equal(t, u.li.GetText(false), u.e)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@ func TestLogAutoScroll(t *testing.T) {
|
|||
v.GetModel().Set(dao.LogItems{dao.NewLogItemFromString("blee"), dao.NewLogItemFromString("bozo")})
|
||||
v.GetModel().Notify()
|
||||
|
||||
assert.Equal(t, 15, len(v.Hints()))
|
||||
assert.Equal(t, 16, len(v.Hints()))
|
||||
|
||||
v.toggleAutoScrollCmd(nil)
|
||||
assert.Equal(t, "Autoscroll:Off FullScreen:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true))
|
||||
assert.Equal(t, "AllContainers:Off Autoscroll:Off FullScreen:Off Timestamps:Off Wrap:Off", v.Indicator().GetText(true))
|
||||
}
|
||||
|
||||
func TestLogViewNav(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/derailed/k9s/internal/client"
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
"github.com/derailed/k9s/internal/dao"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/derailed/tview"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -73,6 +74,24 @@ func TestLogViewSave(t *testing.T) {
|
|||
assert.Equal(t, len(c2), len(c1)+1)
|
||||
}
|
||||
|
||||
func TestAllContainerKeyBinding(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
l *view.Log
|
||||
e bool
|
||||
}{
|
||||
"all containers": {view.NewLog(client.NewGVR("v1/pods"), "", "container", false), true},
|
||||
"no all containers": {view.NewLog(client.NewGVR("v1/pods"), "", "", false), false},
|
||||
}
|
||||
for k := range uu {
|
||||
u := uu[k]
|
||||
t.Run(k, func(t *testing.T) {
|
||||
u.l.Init(makeContext())
|
||||
_, got := u.l.Logs().Actions()[ui.KeyA]
|
||||
assert.Equal(t, u.e, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue