checkpoint
parent
2c57888bac
commit
cf98f61ad6
|
|
@ -116,6 +116,18 @@ func (s *Stack) Pop() (Component, bool) {
|
|||
return c, true
|
||||
}
|
||||
|
||||
// Peek returns stack state.
|
||||
func (s *Stack) Peek() []Component {
|
||||
return s.components
|
||||
}
|
||||
|
||||
// Reset clear out the stack.
|
||||
func (s *Stack) Reset() {
|
||||
for range s.components {
|
||||
s.Pop()
|
||||
}
|
||||
}
|
||||
|
||||
// Empty returns true if the stack is empty.
|
||||
func (s *Stack) Empty() bool {
|
||||
return len(s.components) == 0
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ type (
|
|||
func NewContainerList(c Connection, pod *v1.Pod) List {
|
||||
return NewList(
|
||||
"",
|
||||
"co",
|
||||
"coontainers",
|
||||
NewContainer(c, pod),
|
||||
0,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -289,8 +289,7 @@ func (l *list) Reconcile(informer *wa.Informer, path *string) error {
|
|||
ns = *path
|
||||
}
|
||||
|
||||
items, err := l.load(informer, ns)
|
||||
if err == nil {
|
||||
if items, err := l.load(informer, ns); err == nil {
|
||||
l.update(items)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -299,11 +298,11 @@ func (l *list) Reconcile(informer *wa.Informer, path *string) error {
|
|||
LabelSelector: l.labelSelector,
|
||||
FieldSelector: l.fieldSelector,
|
||||
}
|
||||
|
||||
if items, err = l.resource.List(l.namespace, opts); err != nil {
|
||||
if items, err := l.resource.List(l.namespace, opts); err == nil {
|
||||
l.update(items)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
l.update(items)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ type Node struct {
|
|||
func NewNodeList(c Connection, _ string) List {
|
||||
return NewList(
|
||||
NotNamespaced,
|
||||
"no",
|
||||
"nodes",
|
||||
NewNode(c),
|
||||
ViewAccess|DescribeAccess,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ func NewApp() *App {
|
|||
Main: NewPages(),
|
||||
cmdBuff: NewCmdBuff(':', CommandBuff),
|
||||
}
|
||||
|
||||
a.RefreshStyles()
|
||||
|
||||
a.views = map[string]tview.Primitive{
|
||||
|
|
|
|||
|
|
@ -41,8 +41,12 @@ func (v *Menu) StackPushed(c model.Component) {
|
|||
v.HydrateMenu(c.Hints())
|
||||
}
|
||||
|
||||
func (v *Menu) StackPopped(o, n model.Component) {
|
||||
v.HydrateMenu(n.Hints())
|
||||
func (v *Menu) StackPopped(o, top model.Component) {
|
||||
if top != nil {
|
||||
v.HydrateMenu(top.Hints())
|
||||
} else {
|
||||
v.Clear()
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Menu) StackTop(t model.Component) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/derailed/k9s/internal/model"
|
||||
"github.com/derailed/tview"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
|
@ -21,40 +23,39 @@ func NewPages() *Pages {
|
|||
return &p
|
||||
}
|
||||
|
||||
// Get fetch a page given its name.
|
||||
func (p *Pages) get(n string) model.Component {
|
||||
if comp, ok := p.GetPrimitive(n).(model.Component); ok {
|
||||
return comp
|
||||
func (p *Pages) Show(c model.Component) {
|
||||
p.SwitchToPage(componentID(c))
|
||||
}
|
||||
|
||||
func (p *Pages) Current() model.Component {
|
||||
c := p.CurrentPage()
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.Item.(model.Component)
|
||||
}
|
||||
|
||||
// AddAndShow adds a new page and bring it to front.
|
||||
func (p *Pages) addAndShow(c model.Component) {
|
||||
p.add(c)
|
||||
p.Show(c.Name())
|
||||
p.Show(c)
|
||||
}
|
||||
|
||||
// Add adds a new page.
|
||||
func (p *Pages) add(c model.Component) {
|
||||
p.AddPage(c.Name(), c, true, true)
|
||||
p.AddPage(componentID(c), c, true, true)
|
||||
}
|
||||
|
||||
// Delete removes a page.
|
||||
func (p *Pages) delete(c model.Component) {
|
||||
p.RemovePage(c.Name())
|
||||
}
|
||||
|
||||
// Show brings a named page forward.
|
||||
func (p *Pages) Show(n string) {
|
||||
p.SwitchToPage(n)
|
||||
p.RemovePage(componentID(c))
|
||||
}
|
||||
|
||||
func (p *Pages) DumpPages() {
|
||||
log.Debug().Msgf("Dumping Pages %p", p)
|
||||
for i, n := range p.Stack.Flatten() {
|
||||
log.Debug().Msgf("%d -- %s -- %#v", i, n, p.GetPrimitive(n))
|
||||
for i, c := range p.Stack.Peek() {
|
||||
log.Debug().Msgf("%d -- %s -- %#v", i, componentID(c), p.GetPrimitive(componentID(c)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,5 +73,11 @@ func (p *Pages) StackTop(top model.Component) {
|
|||
if top == nil {
|
||||
return
|
||||
}
|
||||
p.Show(top.Name())
|
||||
p.Show(top)
|
||||
}
|
||||
|
||||
// Helpers...
|
||||
|
||||
func componentID(c model.Component) string {
|
||||
return fmt.Sprintf("%s-%p", c.Name(), c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ func NewTable(title string) *Table {
|
|||
}
|
||||
|
||||
func (t *Table) Init(ctx context.Context) {
|
||||
log.Debug().Msgf("UI Table INIT %q", t.baseTitle)
|
||||
t.styles = ctx.Value(KeyStyles).(*config.Styles)
|
||||
|
||||
t.SetFixed(1, 0)
|
||||
|
|
|
|||
|
|
@ -83,6 +83,9 @@ func (a *App) ActiveView() model.Component {
|
|||
}
|
||||
|
||||
func (a *App) PrevCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
log.Debug().Msgf("------ CONTENT PREVIOUS")
|
||||
a.Content.DumpStack()
|
||||
a.Content.DumpPages()
|
||||
if !a.Content.IsLast() {
|
||||
a.Content.Pop()
|
||||
}
|
||||
|
|
@ -227,9 +230,9 @@ func (a *App) switchNS(ns string) bool {
|
|||
ns = resource.AllNamespaces
|
||||
}
|
||||
if ns == a.Config.ActiveNamespace() {
|
||||
log.Debug().Msgf("Namespace did not change %s", ns)
|
||||
return true
|
||||
}
|
||||
|
||||
if err := a.Config.SetActiveNamespace(ns); err != nil {
|
||||
log.Error().Err(err).Msg("Config Set NS failed!")
|
||||
}
|
||||
|
|
@ -248,6 +251,11 @@ func (a *App) switchCtx(ctx string, load bool) error {
|
|||
if err != nil {
|
||||
log.Info().Err(err).Msg("No namespace specified using all namespaces")
|
||||
}
|
||||
if a.stopCh != nil {
|
||||
close(a.stopCh)
|
||||
a.stopCh = nil
|
||||
}
|
||||
a.informer = nil
|
||||
a.startInformer(ns)
|
||||
a.Config.Reset()
|
||||
if err := a.Config.Save(); err != nil {
|
||||
|
|
@ -262,6 +270,12 @@ func (a *App) switchCtx(ctx string, load bool) error {
|
|||
}
|
||||
|
||||
func (a *App) startInformer(ns string) bool {
|
||||
// if informer watches all ns - don't start a new informer then.
|
||||
if a.informer != nil && a.informer.Namespace == resource.AllNamespaces {
|
||||
log.Debug().Msgf(">>>> Informer is already watching all namespaces. No restart needed ;)")
|
||||
return true
|
||||
}
|
||||
|
||||
if a.stopCh != nil {
|
||||
close(a.stopCh)
|
||||
a.stopCh = nil
|
||||
|
|
@ -381,6 +395,7 @@ func (a *App) toggleHeaderCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
|
||||
a.Content.Stack.Reset()
|
||||
a.gotoResource(a.GetCmd(), true)
|
||||
a.ResetCmd()
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ func (b *Bench) refresh() {
|
|||
|
||||
func (b *Bench) keyBindings() {
|
||||
aa := ui.KeyActions{
|
||||
tcell.KeyEsc: ui.NewKeyAction("Back", b.app.PrevCmd, false),
|
||||
tcell.KeyEnter: ui.NewKeyAction("Enter", b.enterCmd, false),
|
||||
tcell.KeyCtrlD: ui.NewKeyAction("Delete", b.deleteCmd, false),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
|
|
@ -14,14 +15,17 @@ type Context struct {
|
|||
|
||||
// NewContext return a new context viewer.
|
||||
func NewContext(title, gvr string, list resource.List) ResourceViewer {
|
||||
c := Context{
|
||||
return &Context{
|
||||
Resource: NewResource(title, gvr, list),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) Init(ctx context.Context) {
|
||||
c.extraActionsFn = c.extraActions
|
||||
c.enterFn = c.useCtx
|
||||
c.masterPage().SetSelectedFn(c.cleanser)
|
||||
c.Resource.Init(ctx)
|
||||
|
||||
return &c
|
||||
c.masterPage().SetSelectedFn(c.cleanser)
|
||||
}
|
||||
|
||||
func (c *Context) extraActions(aa ui.KeyActions) {
|
||||
|
|
@ -57,9 +61,7 @@ func (c *Context) useContext(name string) error {
|
|||
return err
|
||||
}
|
||||
c.refresh()
|
||||
if tv, ok := c.GetPrimitive("ctx").(*Table); ok {
|
||||
tv.Select(1, 0)
|
||||
}
|
||||
c.masterPage().Select(1, 0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestCleaner(t *testing.T) {
|
||||
uu := map[string]struct {
|
||||
s, e string
|
||||
}{
|
||||
"normal": {"fred", "fred"},
|
||||
"default": {"fred*", "fred"},
|
||||
"delta": {"fred(𝜟)", "fred"},
|
||||
}
|
||||
|
||||
v := Context{}
|
||||
for k, u := range uu {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
assert.Equal(t, u.e, v.cleanser(u.s))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,17 @@
|
|||
package view_test
|
||||
|
||||
// import (
|
||||
// "testing"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
// "github.com/derailed/k9s/internal/config"
|
||||
// "github.com/derailed/k9s/internal/resource"
|
||||
// "github.com/derailed/k9s/internal/view"
|
||||
// "github.com/stretchr/testify/assert"
|
||||
// )
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// func TestContext(t *testing.T) {
|
||||
// l := resource.NewContextList(nil, "fred")
|
||||
// v := view.NewContext("blee", "", NewApp(config.NewConfig(ks{})), l).(*contextView)
|
||||
func TestContext(t *testing.T) {
|
||||
ctx := view.NewContext("ctx", "", resource.NewContextList(nil, "fred"))
|
||||
ctx.Init(makeCtx())
|
||||
|
||||
// assert.Equal(t, 10, len(v.Hints()))
|
||||
// }
|
||||
|
||||
// func TestCleaner(t *testing.T) {
|
||||
// uu := map[string]struct {
|
||||
// s, e string
|
||||
// }{
|
||||
// "normal": {"fred", "fred"},
|
||||
// "default": {"fred*", "fred"},
|
||||
// "delta": {"fred(𝜟)", "fred"},
|
||||
// }
|
||||
|
||||
// v := contextView{}
|
||||
// for k, u := range uu {
|
||||
// t.Run(k, func(t *testing.T) {
|
||||
// assert.Equal(t, u.e, v.cleanser(u.s))
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
assert.Equal(t, "ctx", ctx.Name())
|
||||
assert.Equal(t, 13, len(ctx.Hints()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/derailed/k9s/internal/ui"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// MasterDetail presents a master-detail viewer.
|
||||
|
|
@ -16,6 +15,7 @@ type MasterDetail struct {
|
|||
|
||||
enterFn enterFn
|
||||
extraActionsFn func(ui.KeyActions)
|
||||
master *Table
|
||||
details *Details
|
||||
currentNS string
|
||||
title string
|
||||
|
|
@ -32,7 +32,6 @@ func NewMasterDetail(title, ns string) *MasterDetail {
|
|||
|
||||
// Init initializes the viewer.
|
||||
func (m *MasterDetail) Init(ctx context.Context) {
|
||||
log.Debug().Msgf("\t>>>MasterDetail init %q", m.title)
|
||||
app := ctx.Value(ui.KeyApp).(*App)
|
||||
if m.currentNS != resource.NotNamespaced {
|
||||
m.currentNS = app.Config.ActiveNamespace()
|
||||
|
|
@ -40,15 +39,14 @@ func (m *MasterDetail) Init(ctx context.Context) {
|
|||
m.PageStack.Init(ctx)
|
||||
m.AddListener(app.Menu())
|
||||
|
||||
t := NewTable(m.title)
|
||||
m.Push(t)
|
||||
m.master = NewTable(m.title)
|
||||
m.Push(m.master)
|
||||
|
||||
m.details = NewDetails(m.app, func(evt *tcell.EventKey) *tcell.EventKey {
|
||||
m.Pop()
|
||||
return nil
|
||||
})
|
||||
m.details.Init(ctx)
|
||||
log.Debug().Msgf("\t<<<<MasterDetail INIT DONE!!")
|
||||
}
|
||||
|
||||
// Hints returns the current viewer hints
|
||||
|
|
@ -71,11 +69,11 @@ func (m *MasterDetail) setEnterFn(f enterFn) {
|
|||
}
|
||||
|
||||
func (m *MasterDetail) showMaster() {
|
||||
m.Show("table")
|
||||
m.Show(m.master)
|
||||
}
|
||||
|
||||
func (m *MasterDetail) masterPage() *Table {
|
||||
return m.GetPrimitive(m.title).(*Table)
|
||||
return m.master
|
||||
}
|
||||
|
||||
func (m *MasterDetail) showDetails() {
|
||||
|
|
@ -87,13 +85,7 @@ func (m *MasterDetail) detailsPage() *Details {
|
|||
}
|
||||
|
||||
func (m *MasterDetail) isMaster() bool {
|
||||
p := m.CurrentPage()
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
log.Debug().Msgf("!!!!!Checking MASTER %q vs %q -- %t", p.Name, m.title, p.Name == m.title)
|
||||
return p.Name == m.title
|
||||
return m.Current() == m.master
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -109,6 +101,9 @@ func (m *MasterDetail) defaultActions(aa ui.KeyActions) {
|
|||
}
|
||||
|
||||
func (m *MasterDetail) backCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
m.DumpPages()
|
||||
m.DumpStack()
|
||||
|
||||
if !m.isMaster() {
|
||||
return m.app.PrevCmd(evt)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
package view
|
||||
|
||||
// import (
|
||||
// "testing"
|
||||
|
||||
// "github.com/stretchr/testify/assert"
|
||||
// )
|
||||
|
||||
// func TestNSCleanser(t *testing.T) {
|
||||
// var v namespaceView
|
||||
|
||||
// uu := []struct {
|
||||
// s, e string
|
||||
// }{
|
||||
// {"fred", "fred"},
|
||||
// {"fred+", "fred"},
|
||||
// {"fred(*)", "fred"},
|
||||
// {"fred+(*)", "fred"},
|
||||
// {"fred-blee+(*)", "fred-blee"},
|
||||
// {"fred1-blee2+(*)", "fred1-blee2"},
|
||||
// {"fred(𝜟)", "fred"},
|
||||
// }
|
||||
|
||||
// for _, u := range uu {
|
||||
// assert.Equal(t, u.e, v.cleanser(u.s))
|
||||
// }
|
||||
// }
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
|
||||
"github.com/derailed/k9s/internal/config"
|
||||
|
|
@ -24,15 +25,17 @@ type Namespace struct {
|
|||
|
||||
// NewNamespace returns a new viewer
|
||||
func NewNamespace(title, gvr string, list resource.List) ResourceViewer {
|
||||
n := Namespace{
|
||||
return &Namespace{
|
||||
Resource: NewResource(title, gvr, list),
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Namespace) Init(ctx context.Context) {
|
||||
n.extraActionsFn = n.extraActions
|
||||
n.masterPage().SetSelectedFn(n.cleanser)
|
||||
n.decorateFn = n.decorate
|
||||
n.enterFn = n.switchNs
|
||||
|
||||
return &n
|
||||
n.Resource.Init(ctx)
|
||||
n.masterPage().SetSelectedFn(n.cleanser)
|
||||
}
|
||||
|
||||
func (n *Namespace) extraActions(aa ui.KeyActions) {
|
||||
|
|
@ -62,7 +65,7 @@ func (n *Namespace) useNamespace(ns string) {
|
|||
if err := n.app.Config.Save(); err != nil {
|
||||
log.Error().Err(err).Msg("Config file save failed!")
|
||||
}
|
||||
n.app.startInformer(ns)
|
||||
n.app.switchNS(ns)
|
||||
}
|
||||
|
||||
func (*Namespace) cleanser(s string) string {
|
||||
|
|
@ -70,6 +73,10 @@ func (*Namespace) cleanser(s string) string {
|
|||
}
|
||||
|
||||
func (n *Namespace) decorate(data resource.TableData) resource.TableData {
|
||||
if n.app.Conn() == nil {
|
||||
return resource.TableData{}
|
||||
}
|
||||
|
||||
if _, ok := data.Rows[resource.AllNamespaces]; !ok {
|
||||
if err := n.app.Conn().CheckNSAccess(""); err == nil {
|
||||
data.Rows[resource.AllNamespace] = &resource.RowEvent{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
package view
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNSCleanser(t *testing.T) {
|
||||
var v Namespace
|
||||
|
||||
uu := []struct {
|
||||
s, e string
|
||||
}{
|
||||
{"fred", "fred"},
|
||||
{"fred+", "fred"},
|
||||
{"fred(*)", "fred"},
|
||||
{"fred+(*)", "fred"},
|
||||
{"fred-blee+(*)", "fred-blee"},
|
||||
{"fred1-blee2+(*)", "fred1-blee2"},
|
||||
{"fred(𝜟)", "fred"},
|
||||
}
|
||||
|
||||
for _, u := range uu {
|
||||
assert.Equal(t, u.e, v.cleanser(u.s))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package view_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNSCleanser(t *testing.T) {
|
||||
ns := view.NewNamespace("ns", "", resource.NewNamespaceList(nil, ""))
|
||||
ns.Init(makeCtx())
|
||||
|
||||
assert.Equal(t, "ns", ns.Name())
|
||||
assert.Equal(t, 20, len(ns.Hints()))
|
||||
}
|
||||
|
|
@ -47,6 +47,7 @@ func NewPolicy(app *App, subject, name string) *Policy {
|
|||
// Init the view.
|
||||
func (p *Policy) Init(ctx context.Context) {
|
||||
p.Table.Init(ctx)
|
||||
p.bindKeys()
|
||||
|
||||
p.SetSortCol(1, len(rbacHeader), false)
|
||||
p.Start()
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ func (r *Resource) Init(ctx context.Context) {
|
|||
table.Select(1, 0)
|
||||
}
|
||||
}
|
||||
log.Debug().Msgf("<<<< RESOURCE INIT")
|
||||
}
|
||||
|
||||
// Start initializes updates.
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ func (s *ScreenDump) Start() {
|
|||
var ctx context.Context
|
||||
ctx, s.cancelFn = context.WithCancel(context.Background())
|
||||
if err := s.watchDumpDir(ctx); err != nil {
|
||||
s.app.Flash().Errf("Unable to watch dumpmarks directory %s", err)
|
||||
s.app.Flash().Errf("Unable to watch screen dumps directory %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// StatefulSet represents a statefulset viewer.
|
||||
type StatefulSet struct {
|
||||
*LogResource
|
||||
scalableResource *ScalableResource
|
||||
restartableResource *RestartableResource
|
||||
}
|
||||
|
||||
// NewStatefulSet returns a new viewer.
|
||||
func NewStatefulSet(title, gvr string, list resource.List) ResourceViewer {
|
||||
l := NewLogResource(title, gvr, list)
|
||||
s := StatefulSet{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package view_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/resource"
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStatefulSetNew(t *testing.T) {
|
||||
s := view.NewStatefulSet("sts", "", resource.NewStatefulSetList(nil, ""))
|
||||
s.Init(makeCtx())
|
||||
|
||||
assert.Equal(t, "sts", s.Name())
|
||||
assert.Equal(t, 24, len(s.Hints()))
|
||||
}
|
||||
|
|
@ -35,25 +35,23 @@ type (
|
|||
|
||||
// NewSubject returns a new subject viewer.
|
||||
func NewSubject(title, gvr string, list resource.List) ResourceViewer {
|
||||
s := Subject{}
|
||||
s.Table = NewTable("Subject")
|
||||
s.SetActiveNS("*")
|
||||
s.SetColorerFn(rbacColorer)
|
||||
s.bindKeys()
|
||||
|
||||
return &s
|
||||
return &Subject{
|
||||
Table: NewTable("Subject"),
|
||||
}
|
||||
}
|
||||
|
||||
// Init initializes the view.
|
||||
func (s *Subject) Init(ctx context.Context) {
|
||||
s.SetActiveNS("*")
|
||||
s.SetColorerFn(rbacColorer)
|
||||
s.Table.Init(ctx)
|
||||
s.bindKeys()
|
||||
s.SetSortCol(1, len(rbacHeader), true)
|
||||
s.subjectKind = mapCmdSubject(s.app.Config.K9s.ActiveCluster().View.Active)
|
||||
s.SetBaseTitle(s.subjectKind)
|
||||
|
||||
s.Start()
|
||||
s.refresh()
|
||||
s.SelectRow(1, true)
|
||||
|
||||
s.refresh()
|
||||
}
|
||||
|
||||
func (s *Subject) Start() {
|
||||
|
|
@ -125,6 +123,7 @@ func (s *Subject) refresh() {
|
|||
}
|
||||
|
||||
func (s *Subject) policyCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||
log.Debug().Msg("YO!!")
|
||||
if !s.RowSelected() {
|
||||
return evt
|
||||
}
|
||||
|
|
@ -163,6 +162,9 @@ func (s *Subject) backCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
|
||||
func (s *Subject) reconcile() (resource.TableData, error) {
|
||||
var table resource.TableData
|
||||
if s.app.Conn() == nil {
|
||||
return table, nil
|
||||
}
|
||||
|
||||
evts, err := s.clusterSubjects()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package view_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/derailed/k9s/internal/view"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSubjectNew(t *testing.T) {
|
||||
s := view.NewSubject("subject", "", nil)
|
||||
s.Init(makeCtx())
|
||||
|
||||
assert.Equal(t, "subject", s.Name())
|
||||
assert.Equal(t, 11, len(s.Hints()))
|
||||
}
|
||||
|
|
@ -22,8 +22,6 @@ func NewTable(title string) *Table {
|
|||
}
|
||||
|
||||
func (t *Table) Init(ctx context.Context) {
|
||||
log.Debug().Msgf("VIEW Table INIT %q", t.GetBaseTitle())
|
||||
|
||||
t.app = ctx.Value(ui.KeyApp).(*App)
|
||||
|
||||
ctx = context.WithValue(ctx, ui.KeyStyles, t.app.Styles)
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ type StoreInformer interface {
|
|||
|
||||
// Informer represents a collection of cluster wide watchers.
|
||||
type Informer struct {
|
||||
Namespace string
|
||||
informers map[string]StoreInformer
|
||||
client k8s.Connection
|
||||
podInformer *Pod
|
||||
|
|
@ -65,6 +66,7 @@ type Informer struct {
|
|||
func NewInformer(client k8s.Connection, ns string) (*Informer, error) {
|
||||
i := Informer{
|
||||
client: client,
|
||||
Namespace: ns,
|
||||
informers: map[string]StoreInformer{},
|
||||
}
|
||||
if err := client.CheckNSAccess(ns); err != nil {
|
||||
|
|
@ -76,6 +78,13 @@ func NewInformer(client k8s.Connection, ns string) (*Informer, error) {
|
|||
return &i, nil
|
||||
}
|
||||
|
||||
func (i *Informer) Dump() {
|
||||
log.Debug().Msgf("Informer Dump")
|
||||
for k := range i.informers {
|
||||
log.Debug().Msgf("\t%s", k)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Informer) init(ns string) {
|
||||
log.Debug().Msgf(">>>>> Starting Informer in namespace %q", ns)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
const (
|
||||
// NodeIndex marker for stored nodes.
|
||||
NodeIndex string = "no"
|
||||
NodeIndex string = "nodes"
|
||||
nodeCols = 12
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
const (
|
||||
// PodIndex marker for stored pods.
|
||||
PodIndex string = "po"
|
||||
PodIndex string = "pods"
|
||||
podCols = 11
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue