From 05558c89faba7cd9a92d4748c850ddd868e3c6dd Mon Sep 17 00:00:00 2001 From: derailed Date: Wed, 13 Nov 2019 07:37:23 -0700 Subject: [PATCH] ckeckpoint --- internal/view/bench.go | 2 +- internal/view/container.go | 6 -- internal/view/dump.go | 4 +- internal/view/log_resource.go | 15 +++- internal/view/logs.go | 15 +++- internal/view/master_detail.go | 9 ++- internal/view/pod.go | 24 +++--- internal/view/resource.go | 12 +-- internal/view/rs.go | 3 +- internal/view/secret.go | 2 +- internal/view/select_list.go | 13 +++- internal/view/svc.go | 138 ++++++++++++++++----------------- internal/view/table.go | 2 +- internal/watch/informer.go | 5 +- 14 files changed, 135 insertions(+), 115 deletions(-) diff --git a/internal/view/bench.go b/internal/view/bench.go index fc1ddfe6..a339471c 100644 --- a/internal/view/bench.go +++ b/internal/view/bench.go @@ -44,7 +44,7 @@ type Bench struct { func NewBench(title, gvr string, _ resource.List) ResourceViewer { return &Bench{ - MasterDetail: NewMasterDetail(), + MasterDetail: NewMasterDetail(title), } } diff --git a/internal/view/container.go b/internal/view/container.go index 4f7f14ea..550fe281 100644 --- a/internal/view/container.go +++ b/internal/view/container.go @@ -1,7 +1,6 @@ package view import ( - "context" "errors" "fmt" "strings" @@ -35,11 +34,6 @@ func NewContainer(title string, list resource.List, path string) ResourceViewer return &c } -// Init initializes a container view. -func (c *Container) Init(ctx context.Context) { - c.Resource.Init(ctx) -} - // Start starts the component. func (c *Container) Start() {} diff --git a/internal/view/dump.go b/internal/view/dump.go index 09643f9f..d5c14403 100644 --- a/internal/view/dump.go +++ b/internal/view/dump.go @@ -35,9 +35,9 @@ type ScreenDump struct { app *App } -func NewScreenDump(_, _ string, _ resource.List) ResourceViewer { +func NewScreenDump(title, _ string, _ resource.List) ResourceViewer { return &ScreenDump{ - MasterDetail: NewMasterDetail(), + MasterDetail: NewMasterDetail(title), } } diff --git a/internal/view/log_resource.go b/internal/view/log_resource.go index 284498a4..8b764e6c 100644 --- a/internal/view/log_resource.go +++ b/internal/view/log_resource.go @@ -1,6 +1,8 @@ package view import ( + "context" + "github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/ui" "github.com/gdamore/tcell" @@ -14,17 +16,23 @@ type LogResource struct { *Resource containerFn containerFn + logs *Logs } func NewLogResource(title, gvr string, list resource.List) *LogResource { l := LogResource{ Resource: NewResource(title, gvr, list), } - l.AddPage("logs", NewLogs(list.GetName(), &l), true, false) + l.logs = NewLogs(list.GetName(), &l) return &l } +func (l *LogResource) Init(ctx context.Context) { + l.Resource.Init(ctx) + l.logs.Init(ctx) +} + func (l *LogResource) extraActions(aa ui.KeyActions) { aa[ui.KeyL] = ui.NewKeyAction("Logs", l.logsCmd, true) aa[ui.KeyShiftL] = ui.NewKeyAction("Logs Previous", l.prevLogsCmd, true) @@ -68,13 +76,12 @@ func (l *LogResource) showLogs(prev bool) { return } - logs := l.GetPrimitive("logs").(*Logs) co := "" if l.containerFn != nil { co = l.containerFn() } - logs.reload(co, l, prev) - l.switchPage("logs") + l.logs.reload(co, l, prev) + l.Push(l.logs) } func (l *LogResource) backCmd(evt *tcell.EventKey) *tcell.EventKey { diff --git a/internal/view/logs.go b/internal/view/logs.go index 7bed8d38..f041cc14 100644 --- a/internal/view/logs.go +++ b/internal/view/logs.go @@ -8,7 +8,6 @@ import ( "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/ui" - "github.com/derailed/tview" "github.com/gdamore/tcell" "github.com/rs/zerolog/log" ) @@ -29,7 +28,7 @@ type ( // Logs presents a collection of logs. Logs struct { - *tview.Pages + *ui.Pages app *App parent loggable @@ -41,11 +40,19 @@ type ( // NewLogs returns a new logs viewer. func NewLogs(title string, parent loggable) *Logs { return &Logs{ - Pages: tview.NewPages(), + Pages: ui.NewPages(), parent: parent, } } +func (l *Logs) Init(ctx context.Context) { + l.app = ctx.Value(ui.KeyApp).(*App) +} + +func (l *Logs) Start() {} +func (l *Logs) Stop() {} +func (l *Logs) Name() string { return "logs" } + // Protocol... func (l *Logs) reload(co string, parent loggable, prevLogs bool) { @@ -171,7 +178,7 @@ func updateLogs(ctx context.Context, c <-chan string, l *Log, buffSize int) { func (l *Logs) backCmd(evt *tcell.EventKey) *tcell.EventKey { l.stop() - l.parent.switchPage("master") + l.parent.Pop() return evt } diff --git a/internal/view/master_detail.go b/internal/view/master_detail.go index 184cb188..5db9ff24 100644 --- a/internal/view/master_detail.go +++ b/internal/view/master_detail.go @@ -13,12 +13,15 @@ type MasterDetail struct { enterFn enterFn extraActionsFn func(ui.KeyActions) details *Details + currentNS string + title string } // NewMasterDetail returns a new master-detail viewer. -func NewMasterDetail() *MasterDetail { +func NewMasterDetail(title string) *MasterDetail { return &MasterDetail{ PageStack: NewPageStack(), + title: title, } } @@ -26,7 +29,7 @@ func NewMasterDetail() *MasterDetail { func (m *MasterDetail) Init(ctx context.Context) { m.PageStack.Init(ctx) - t := NewTable("master") + t := NewTable(m.title) t.Init(ctx) m.Push(t) @@ -49,7 +52,7 @@ func (m *MasterDetail) showMaster() { } func (m *MasterDetail) masterPage() *Table { - return m.GetPrimitive("table").(*Table) + return m.GetPrimitive(m.title).(*Table) } func (m *MasterDetail) showDetails() { diff --git a/internal/view/pod.go b/internal/view/pod.go index 0b6eef9e..77e2420b 100644 --- a/internal/view/pod.go +++ b/internal/view/pod.go @@ -3,6 +3,7 @@ package view import ( "fmt" + "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/ui" "github.com/derailed/k9s/internal/watch" @@ -20,12 +21,15 @@ const ( type loggable interface { getSelection() string getList() resource.List - switchPage(n string) + Pop() (model.Component, bool) } // Pod represents a pod viewer. type Pod struct { *Resource + + logs *Logs + picker *selectList } // NewPod returns a new viewer. @@ -36,14 +40,12 @@ func NewPod(title, gvr string, list resource.List) ResourceViewer { p.extraActionsFn = p.extraActions p.enterFn = p.listContainers - picker := newSelectList(&p) - { - picker.setActions(ui.KeyActions{ - tcell.KeyEscape: {Description: "Back", Action: p.backCmd, Visible: true}, - }) - } - p.AddPage("picker", picker, true, false) - p.AddPage("logs", NewLogs(list.GetName(), &p), true, false) + p.picker = newSelectList(&p) + p.picker.setActions(ui.KeyActions{ + tcell.KeyEscape: {Description: "Back", Action: p.backCmd, Visible: true}, + }) + + p.logs = NewLogs(list.GetName(), &p) return &p } @@ -144,7 +146,7 @@ func (p *Pod) viewLogs(prev bool) bool { func (p *Pod) showLogs(path, co string, parent loggable, prev bool) { l := p.GetPrimitive("logs").(*Logs) l.reload(co, parent, prev) - p.switchPage("logs") + p.Push(p.logs) } func (p *Pod) shellCmd(evt *tcell.EventKey) *tcell.EventKey { @@ -167,7 +169,7 @@ func (p *Pod) shellCmd(evt *tcell.EventKey) *tcell.EventKey { picker.SetSelectedFunc(func(i int, t, d string, r rune) { p.shellIn(sel, t) }) - p.switchPage("picker") + p.Push(p.picker) return evt } diff --git a/internal/view/resource.go b/internal/view/resource.go index dd7fd36e..c37c63bc 100644 --- a/internal/view/resource.go +++ b/internal/view/resource.go @@ -32,13 +32,12 @@ type Resource struct { decorateFn decorateFn envFn envFn gvr string - currentNS string } // NewResource returns a new viewer. func NewResource(title, gvr string, list resource.List) *Resource { return &Resource{ - MasterDetail: NewMasterDetail(), + MasterDetail: NewMasterDetail(title), list: list, gvr: gvr, } @@ -127,11 +126,12 @@ func (r *Resource) update(ctx context.Context) { } func (r *Resource) backCmd(*tcell.EventKey) *tcell.EventKey { - r.switchPage("master") + r.Pop() + return nil } -func (r *Resource) switchPage(p string) { +func (r *Resource) switchPage1(p string) { log.Debug().Msgf("Switching page to %s", p) if _, ok := r.CurrentPage().Item.(*Table); ok { r.Stop() @@ -211,7 +211,7 @@ func (r *Resource) deleteCmd(evt *tcell.EventKey) *tcell.EventKey { } r.refresh() }, func() { - r.switchPage("master") + r.Pop() }) return nil } @@ -254,7 +254,7 @@ func (r *Resource) defaultEnter(app *App, ns, _, selection string) { details.SetTextColor(r.app.Styles.FgColor()) details.SetText(colorizeYAML(r.app.Styles.Views().Yaml, yaml)) details.ScrollToBeginning() - r.switchPage("details") + r.showDetails() } func (r *Resource) describeCmd(evt *tcell.EventKey) *tcell.EventKey { diff --git a/internal/view/rs.go b/internal/view/rs.go index 8ea2d00c..8e816dfe 100644 --- a/internal/view/rs.go +++ b/internal/view/rs.go @@ -97,8 +97,7 @@ func (r *ReplicaSet) rollbackCmd(evt *tcell.EventKey) *tcell.EventKey { } func (r *ReplicaSet) dismissModal() { - r.RemovePage("confirm") - r.switchPage("master") + r.Pop() } func (r *ReplicaSet) showModal(msg string, done func(int, string)) { diff --git a/internal/view/secret.go b/internal/view/secret.go index 004c1ca9..133ff406 100644 --- a/internal/view/secret.go +++ b/internal/view/secret.go @@ -57,7 +57,7 @@ func (s *Secret) decodeCmd(evt *tcell.EventKey) *tcell.EventKey { details.SetTextColor(s.app.Styles.FgColor()) details.SetText(colorizeYAML(s.app.Styles.Views().Yaml, string(raw))) details.ScrollToBeginning() - s.switchPage("details") + s.showDetails() return nil } diff --git a/internal/view/select_list.go b/internal/view/select_list.go index d524e554..e10af0aa 100644 --- a/internal/view/select_list.go +++ b/internal/view/select_list.go @@ -1,6 +1,8 @@ package view import ( + "context" + "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/resource" "github.com/derailed/k9s/internal/ui" @@ -37,16 +39,21 @@ func newSelectList(parent loggable) *selectList { return &v } +func (v *selectList) Init(context.Context) {} +func (v *selectList) Start() {} +func (v *selectList) Stop() {} +func (v *selectList) Name() string { return "picker" } + func (v *selectList) back(evt *tcell.EventKey) *tcell.EventKey { - v.parent.switchPage("master") + v.parent.Pop() return nil } // Protocol... -func (v *selectList) switchPage(p string) { - v.parent.switchPage(p) +func (v *selectList) Pop() { + v.parent.Pop() } func (v *selectList) getList() resource.List { diff --git a/internal/view/svc.go b/internal/view/svc.go index f7c4ae08..9012dfb9 100644 --- a/internal/view/svc.go +++ b/internal/view/svc.go @@ -20,6 +20,7 @@ type Service struct { *Resource bench *perf.Benchmark + logs *Logs } func NewService(title, gvr string, list resource.List) ResourceViewer { @@ -28,31 +29,31 @@ func NewService(title, gvr string, list resource.List) ResourceViewer { } s.extraActionsFn = s.extraActions s.enterFn = s.showPods - s.AddPage("logs", NewLogs(list.GetName(), &s), true, false) + s.logs = NewLogs(list.GetName(), &s) return &s } // Protocol... -func (v *Service) getList() resource.List { - return v.list +func (s *Service) getList() resource.List { + return s.list } -func (v *Service) getSelection() string { - return v.masterPage().GetSelectedItem() +func (s *Service) getSelection() string { + return s.masterPage().GetSelectedItem() } -func (v *Service) extraActions(aa ui.KeyActions) { - aa[ui.KeyL] = ui.NewKeyAction("Logs", v.logsCmd, true) - aa[tcell.KeyCtrlB] = ui.NewKeyAction("Bench", v.benchCmd, true) - aa[tcell.KeyCtrlK] = ui.NewKeyAction("Bench Stop", v.benchStopCmd, true) - aa[ui.KeyShiftT] = ui.NewKeyAction("Sort Type", v.sortColCmd(1, false), false) +func (s *Service) extraActions(aa ui.KeyActions) { + aa[ui.KeyL] = ui.NewKeyAction("Logs", s.logsCmd, true) + aa[tcell.KeyCtrlB] = ui.NewKeyAction("Bench", s.benchCmd, true) + aa[tcell.KeyCtrlK] = ui.NewKeyAction("Bench Stop", s.benchStopCmd, true) + aa[ui.KeyShiftT] = ui.NewKeyAction("Sort Type", s.sortColCmd(1, false), false) } -func (v *Service) sortColCmd(col int, asc bool) func(evt *tcell.EventKey) *tcell.EventKey { +func (s *Service) sortColCmd(col int, asc bool) func(evt *tcell.EventKey) *tcell.EventKey { return func(evt *tcell.EventKey) *tcell.EventKey { - t := v.masterPage() + t := s.masterPage() t.SetSortCol(t.NameColIndex()+col, 0, asc) t.Refresh() @@ -60,63 +61,62 @@ func (v *Service) sortColCmd(col int, asc bool) func(evt *tcell.EventKey) *tcell } } -func (v *Service) showPods(app *App, ns, res, sel string) { - s := k8s.NewService(app.Conn()) +func (s *Service) showPods(app *App, ns, res, sel string) { ns, n := namespaced(sel) - svc, err := s.Get(ns, n) + svc, err := k8s.NewService(app.Conn()).Get(ns, n) if err != nil { app.Flash().Err(err) return } - if s, ok := svc.(*v1.Service); ok { - v.showSvcPods(ns, s.Spec.Selector, v.backCmd) + if sv, ok := svc.(*v1.Service); ok { + s.showSvcPods(ns, sv.Spec.Selector, s.backCmd) } } -func (v *Service) logsCmd(evt *tcell.EventKey) *tcell.EventKey { - if !v.masterPage().RowSelected() { +func (s *Service) logsCmd(evt *tcell.EventKey) *tcell.EventKey { + if !s.masterPage().RowSelected() { return evt } - l := v.GetPrimitive("logs").(*Logs) - l.reload("", v, false) - v.switchPage("logs") + l := s.GetPrimitive("logs").(*Logs) + l.reload("", s, false) + s.Push(s.logs) return nil } -func (v *Service) backCmd(evt *tcell.EventKey) *tcell.EventKey { +func (s *Service) backCmd(evt *tcell.EventKey) *tcell.EventKey { // Reset namespace to what it was - if err := v.app.Config.SetActiveNamespace(v.list.GetNamespace()); err != nil { + if err := s.app.Config.SetActiveNamespace(s.list.GetNamespace()); err != nil { log.Error().Err(err).Msg("Unable to set active namespace") } - v.app.inject(v) + s.app.inject(s) return nil } -func (v *Service) benchStopCmd(evt *tcell.EventKey) *tcell.EventKey { - if v.bench != nil { +func (s *Service) benchStopCmd(evt *tcell.EventKey) *tcell.EventKey { + if s.bench != nil { log.Debug().Msg(">>> Benchmark canceled!!") - v.app.status(ui.FlashErr, "Benchmark Canceled!") - v.bench.Cancel() + s.app.status(ui.FlashErr, "Benchmark Canceled!") + s.bench.Cancel() } - v.app.StatusReset() + s.app.StatusReset() return nil } -func (v *Service) checkSvc(row int) error { - svcType := trimCellRelative(v.masterPage(), row, 1) +func (s *Service) checkSvc(row int) error { + svcType := trimCellRelative(s.masterPage(), row, 1) if svcType != "NodePort" && svcType != "LoadBalancer" { return errors.New("You must select a reachable service") } return nil } -func (v *Service) getExternalPort(row int) (string, error) { - ports := trimCellRelative(v.masterPage(), row, 5) +func (s *Service) getExternalPort(row int) (string, error) { + ports := trimCellRelative(s.masterPage(), row, 5) pp := strings.Split(ports, " ") if len(pp) == 0 { @@ -132,75 +132,75 @@ func (v *Service) getExternalPort(row int) (string, error) { return tokens[1], nil } -func (v *Service) reloadBenchCfg() error { +func (s *Service) reloadBenchCfg() error { // BOZO!! Poorman Reload bench to make sure we pick up updates if any. - path := ui.BenchConfig(v.app.Config.K9s.CurrentCluster) - return v.app.Bench.Reload(path) + path := ui.BenchConfig(s.app.Config.K9s.CurrentCluster) + return s.app.Bench.Reload(path) } -func (v *Service) benchCmd(evt *tcell.EventKey) *tcell.EventKey { - if !v.masterPage().RowSelected() || v.bench != nil { +func (s *Service) benchCmd(evt *tcell.EventKey) *tcell.EventKey { + if !s.masterPage().RowSelected() || s.bench != nil { return evt } - if err := v.reloadBenchCfg(); err != nil { - v.app.Flash().Err(err) + if err := s.reloadBenchCfg(); err != nil { + s.app.Flash().Err(err) return nil } - sel := v.getSelection() - cfg, ok := v.app.Bench.Benchmarks.Services[sel] + sel := s.getSelection() + cfg, ok := s.app.Bench.Benchmarks.Services[sel] if !ok { - v.app.Flash().Errf("No bench config found for service %s", sel) + s.app.Flash().Errf("No bench config found for service %s", sel) return nil } cfg.Name = sel log.Debug().Msgf("Benchmark config %#v", cfg) - row, _ := v.masterPage().GetSelection() - if err := v.checkSvc(row); err != nil { - v.app.Flash().Err(err) + row, _ := s.masterPage().GetSelection() + if err := s.checkSvc(row); err != nil { + s.app.Flash().Err(err) return nil } - port, err := v.getExternalPort(row) + port, err := s.getExternalPort(row) if err != nil { - v.app.Flash().Err(err) + s.app.Flash().Err(err) return nil } - if err := v.runBenchmark(port, cfg); err != nil { - v.app.Flash().Errf("Benchmark failed %v", err) - v.app.StatusReset() - v.bench = nil + if err := s.runBenchmark(port, cfg); err != nil { + s.app.Flash().Errf("Benchmark failed %v", err) + s.app.StatusReset() + s.bench = nil } return nil } -func (v *Service) runBenchmark(port string, cfg config.BenchConfig) error { +func (s *Service) runBenchmark(port string, cfg config.BenchConfig) error { var err error base := "http://" + cfg.HTTP.Host + ":" + port + cfg.HTTP.Path - if v.bench, err = perf.NewBenchmark(base, cfg); err != nil { + if s.bench, err = perf.NewBenchmark(base, cfg); err != nil { return err } - v.app.status(ui.FlashWarn, "Benchmark in progress...") + s.app.status(ui.FlashWarn, "Benchmark in progress...") log.Debug().Msg("Bench starting...") - go v.bench.Run(v.app.Config.K9s.CurrentCluster, v.benchDone) + go s.bench.Run(s.app.Config.K9s.CurrentCluster, s.benchDone) return nil } -func (v *Service) benchDone() { +func (s *Service) benchDone() { log.Debug().Msg("Bench Completed!") - v.app.QueueUpdate(func() { - if v.bench.Canceled() { - v.app.status(ui.FlashInfo, "Benchmark canceled") + s.app.QueueUpdate(func() { + if s.bench.Canceled() { + s.app.status(ui.FlashInfo, "Benchmark canceled") } else { - v.app.status(ui.FlashInfo, "Benchmark Completed!") - v.bench.Cancel() + s.app.status(ui.FlashInfo, "Benchmark Completed!") + s.bench.Cancel() } - v.bench = nil - go benchTimedOut(v.app) + s.bench = nil + go benchTimedOut(s.app) }) } @@ -211,10 +211,10 @@ func benchTimedOut(app *App) { }) } -func (v *Service) showSvcPods(ns string, sel map[string]string, a ui.ActionHandler) { - var s []string +func (s *Service) showSvcPods(ns string, sel map[string]string, a ui.ActionHandler) { + var labels []string for k, v := range sel { - s = append(s, fmt.Sprintf("%s=%s", k, v)) + labels = append(labels, fmt.Sprintf("%s=%s", k, v)) } - showPods(v.app, ns, strings.Join(s, ","), "", a) + showPods(s.app, ns, strings.Join(labels, ","), "", a) } diff --git a/internal/view/table.go b/internal/view/table.go index 321cc554..08a0b384 100644 --- a/internal/view/table.go +++ b/internal/view/table.go @@ -33,7 +33,7 @@ func (t *Table) Init(ctx context.Context) { func (t *Table) Start() {} func (t *Table) Stop() {} -func (t *Table) Name() string { return "table" } +func (t *Table) Name() string { return t.GetBaseTitle() } // BufferChanged indicates the buffer was changed. func (t *Table) BufferChanged(s string) {} diff --git a/internal/watch/informer.go b/internal/watch/informer.go index 8b64c6a7..d7f0f55a 100644 --- a/internal/watch/informer.go +++ b/internal/watch/informer.go @@ -118,7 +118,7 @@ func (i *Informer) init(ns string) { // List items from store. func (i *Informer) List(res, ns string, opts metav1.ListOptions) (k8s.Collection, error) { if i == nil { - return nil, errors.New("Invalid informer") + return nil, errors.New("Invalid List informer") } if i, ok := i.informers[res]; ok { @@ -131,7 +131,8 @@ func (i *Informer) List(res, ns string, opts metav1.ListOptions) (k8s.Collection // Get a resource by name. func (i *Informer) Get(res, fqn string, opts metav1.GetOptions) (interface{}, error) { if i == nil { - return nil, errors.New("Invalid informer") + panic("blee") + return nil, errors.New("Invalid Get informer") } if informer, ok := i.informers[res]; ok {