clean up + fix toast skinner

mine
derailed 2019-12-30 15:08:42 -07:00
parent b536767a1f
commit 60cb53b8c2
38 changed files with 104 additions and 46 deletions

View File

@ -7,6 +7,7 @@ import (
"k8s.io/kubectl/pkg/describe/versioned"
)
// Describe describes a resource.
func Describe(c client.Connection, gvr client.GVR, ns, n string) (string, error) {
mapper := RestMapper{Connection: c}
m, err := mapper.ToRESTMapper()

View File

@ -20,6 +20,7 @@ import (
"k8s.io/kubectl/pkg/polymorphichelpers"
)
// DaemonSet represents a K8s daemonset.
type DaemonSet struct {
Generic
}

View File

@ -14,8 +14,8 @@ type Generic struct {
}
// Init initializes the resource.
func (r *Generic) Init(f Factory, gvr client.GVR) {
r.Factory, r.gvr = f, gvr
func (g *Generic) Init(f Factory, gvr client.GVR) {
g.Factory, g.gvr = f, gvr
}
// Delete a Generic.

View File

@ -64,7 +64,7 @@ func (p *Pod) Containers(path string, includeInit bool) ([]string, error) {
return cc, nil
}
// Logs tails a given container logs
// TailLogs tails a given container logs
func (p *Pod) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error {
if !opts.HasContainer() {
return p.logs(ctx, c, opts)
@ -72,7 +72,6 @@ func (p *Pod) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) er
return tailLogs(ctx, p, c, opts)
}
// PodLogs tail logs for all containers in a running Pod.
func (p *Pod) logs(ctx context.Context, c chan<- string, opts LogOptions) error {
fac, ok := ctx.Value(internal.KeyFactory).(*watch.Factory)
if !ok {

View File

@ -12,7 +12,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)
// MetaViewers represents a collection of meta viewers.
// ResourceMetas represents a collection of resource metadata.
type ResourceMetas map[client.GVR]metav1.APIResource
// Accessors represents a collection of dao accessors.
@ -55,6 +55,7 @@ func RegisterMeta(gvr string, res metav1.APIResource) {
resMetas[client.GVR(gvr)] = res
}
// AllGVRs returns all cluster resources.
func AllGVRs() client.GVRs {
kk := make(client.GVRs, 0, len(resMetas))
for k := range resMetas {
@ -85,7 +86,7 @@ func IsK9sMeta(m metav1.APIResource) bool {
return false
}
// Load hydrates server preferred+CRDs resource metadata.
// LoadResources hydrates server preferred+CRDs resource metadata.
func LoadResources(f Factory) error {
resMetas = make(ResourceMetas, 100)
if err := loadPreferred(f, resMetas); err != nil {

View File

@ -4,6 +4,7 @@ import (
"os"
)
// ScreenDump represents a scraped resources.
type ScreenDump struct {
Generic
}

View File

@ -11,6 +11,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)
// Service represents a k8s service.
type Service struct {
Generic
}
@ -18,7 +19,7 @@ type Service struct {
var _ Accessor = &Service{}
var _ Loggable = &Service{}
// Logs tail logs for all pods represented by this Service.
// TailLogs tail logs for all pods represented by this Service.
func (s *Service) TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error {
o, err := s.Get(string(s.gvr), opts.Path, labels.Everything())
if err != nil {

View File

@ -12,6 +12,7 @@ import (
restclient "k8s.io/client-go/rest"
)
// Factory represents a resource factory.
type Factory interface {
// Client retrieves an api client.
Client() client.Connection
@ -49,7 +50,9 @@ type Loggable interface {
TailLogs(ctx context.Context, c chan<- string, opts LogOptions) error
}
// Scalable represents resources that can scale.
type Scalable interface {
// Scale scales a resource up or down.
Scale(path string, replicas int32) error
}
@ -79,5 +82,6 @@ type Runnable interface {
// Loggers represents a resource that exposes logs.
type Logger interface {
// Logs tails a resource logs.
Logs(path string, opts *v1.PodLogOptions) *restclient.Request
}

View File

@ -54,7 +54,7 @@ func (p *Pod) List(ctx context.Context) ([]runtime.Object, error) {
return res, nil
}
// Render returns pod resources as rows.
// Hydrate returns pod resources as rows.
func (p *Pod) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error {
mx := client.NewMetricsServer(p.factory.Client())
mmx, err := mx.FetchPodsMetrics(p.namespace)

View File

@ -13,10 +13,12 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)
// Policy represent rbac policy.
type Policy struct {
Resource
}
// List returns available policies.
func (p *Policy) List(ctx context.Context) ([]runtime.Object, error) {
gvr, ok := ctx.Value(internal.KeyGVR).(string)
if !ok {

View File

@ -4,6 +4,7 @@ import (
"github.com/derailed/k9s/internal/render"
)
// Registy tracks resources metadata.
// BOZO!! Break up deps and merge into single registrar
var Registry = map[string]ResourceMeta{
// Custom...

View File

@ -15,6 +15,7 @@ type Resource struct {
factory Factory
}
// Init initializes the model.
func (r *Resource) Init(ns, gvr string, f Factory) {
r.namespace, r.gvr, r.factory = ns, gvr, f
}
@ -29,7 +30,7 @@ func (r *Resource) List(ctx context.Context) ([]runtime.Object, error) {
return r.factory.List(r.gvr, r.namespace, lsel)
}
// Render returns a node as a row.
// Hydrate renders all rows.
func (r *Resource) Hydrate(oo []runtime.Object, rr render.Rows, re Renderer) error {
for i, o := range oo {
if err := re.Render(o, r.namespace, &rr[i]); err != nil {

View File

@ -80,7 +80,7 @@ func (s *Stack) AddListener(l StackListener) {
}
// Dump prints out the stack.
func (s *Stack) DumpStack() {
func (s *Stack) Dump() {
log.Debug().Msgf("--- Stack Dump %p---", s)
for i, c := range s.components {
log.Debug().Msgf("%d -- %s -- %#v", i, c.Name(), c)

View File

@ -14,6 +14,7 @@ type Generic struct {
table *metav1beta1.Table
}
// SetTable sets the tabular resource.
func (g *Generic) SetTable(t *metav1beta1.Table) {
g.table = t
}

View File

@ -41,16 +41,16 @@ func (p Pod) ColorerFunc() ColorerFunc {
switch status {
case ContainerCreating, PodInitializing:
return AddColor
c = AddColor
case Initialized:
return HighlightColor
c = HighlightColor
case Completed:
return CompletedColor
c = CompletedColor
case Running:
case Terminating:
return KillColor
c = KillColor
default:
return ErrColor
c = ErrColor
}
return c

View File

@ -62,6 +62,7 @@ func (rr Rows) Delete(id string) Rows {
return append(rr[:idx], rr[idx+1:]...)
}
// Upserts adds a new item.
func (rr Rows) Upsert(r Row) Rows {
idx, ok := rr.Find(r.ID)
if !ok {
@ -113,6 +114,7 @@ func (s RowSorter) Less(i, j int) bool {
// ----------------------------------------------------------------------------
// Helpers...
// Less return true if c1 < c2.
func Less(asc bool, c1, c2 string) bool {
if o, ok := isDurationSort(asc, c1, c2); ok {
return o

View File

@ -21,6 +21,7 @@ func (h Header) Clone() Header {
// HeaderRow represents a table header.
type HeaderRow []Header
// Clone duplicates a header.
func (hh HeaderRow) Clone() HeaderRow {
h := make(HeaderRow, len(hh))
for i, v := range hh {
@ -44,9 +45,9 @@ func (hh HeaderRow) Changed(h HeaderRow) bool {
}
// Columns return header as a collection of strings.
func (h HeaderRow) Columns() []string {
cc := make([]string, len(h))
for i, c := range h {
func (hh HeaderRow) Columns() []string {
cc := make([]string, len(hh))
for i, c := range hh {
cc[i] = c.Name
}
@ -54,8 +55,8 @@ func (h HeaderRow) Columns() []string {
}
// HasAge returns true if table has an age column.
func (h HeaderRow) HasAge() bool {
for _, r := range h {
func (hh HeaderRow) HasAge() bool {
for _, r := range hh {
if r.Name == ageCol {
return true
}
@ -65,9 +66,9 @@ func (h HeaderRow) HasAge() bool {
}
// AgeCol checks if given column index is the age column.
func (h HeaderRow) AgeCol(col int) bool {
if !h.HasAge() {
func (hh HeaderRow) AgeCol(col int) bool {
if !hh.HasAge() {
return false
}
return col == len(h)-1
return col == len(hh)-1
}

View File

@ -48,6 +48,7 @@ func (s Subject) Render(o interface{}, ns string, r *Row) error {
// ----------------------------------------------------------------------------
// Helpers...
// SubjectRef represents a subject rule.
type SubjectRef struct {
Name, Kind, FirstLocation string
}

View File

@ -29,6 +29,7 @@ func NewKeyAction(d string, a ActionHandler, display bool) KeyAction {
return KeyAction{Description: d, Action: a, Visible: display}
}
// NewSharedKeyAction returns a new shared keyboard action.
func NewSharedKeyAction(d string, a ActionHandler, display bool) KeyAction {
return KeyAction{Description: d, Action: a, Visible: display, Shared: true}
}
@ -40,14 +41,14 @@ func (a KeyActions) Add(aa KeyActions) {
}
}
// Clear
// Clear remove all actions.
func (a KeyActions) Clear() {
for k := range a {
delete(a, k)
}
}
// SetActions replace actions with new ones.
// Set replace actions with new ones.
func (a KeyActions) Set(aa KeyActions) {
for k, v := range aa {
a[k] = v

View File

@ -121,6 +121,7 @@ func (c *CmdBuff) AddListener(w ...BuffWatcher) {
c.listeners = append(c.listeners, w...)
}
// RemoveListener unregisters a listener.
func (c *CmdBuff) RemoveListener(l BuffWatcher) {
victim := -1
for i, lis := range c.listeners {

View File

@ -35,6 +35,7 @@ func NewCommand(styles *config.Styles) *Command {
return &c
}
// StylesChanged notifies skin changed.
func (c *Command) StylesChanged(s *config.Styles) {
c.styles = s
c.SetBackgroundColor(s.BgColor())

View File

@ -96,6 +96,7 @@ func (c *Configurator) RefreshStyles(cluster string) {
if err := c.Styles.Load(config.K9sStylesFile); err != nil {
log.Info().Msgf("No skin file found -- %s. Loading stock skins.", config.K9sStylesFile)
c.updateStyles("")
return
}
c.updateStyles(config.K9sStylesFile)

View File

@ -33,6 +33,7 @@ func NewCrumbs(styles *config.Styles) *Crumbs {
return &c
}
// StylesChanged notifies skin changed.
func (c *Crumbs) StylesChanged(s *config.Styles) {
c.styles = s
c.SetBackgroundColor(s.BgColor())

View File

@ -36,7 +36,7 @@ func NewStatusIndicator(app *App, styles *config.Styles) *StatusIndicator {
return &s
}
// StyleChanged notifies the skins changed.
// StylesChanged notifies the skins changed.
func (s *StatusIndicator) StylesChanged(styles *config.Styles) {
s.styles = styles
s.SetBackgroundColor(styles.BgColor())

View File

@ -32,14 +32,17 @@ func NewLogo(styles *config.Styles) *Logo {
return &l
}
// Logo returns the logo viewer.
func (l *Logo) Logo() *tview.TextView {
return l.logo
}
// Status returns the status viewer.
func (l *Logo) Status() *tview.TextView {
return l.status
}
// StylesChanged notifies the skin changed.
func (l *Logo) StylesChanged(s *config.Styles) {
l.styles = s
l.Reset()

View File

@ -41,15 +41,18 @@ func NewMenu(styles *config.Styles) *Menu {
return &m
}
// StylesChanged notifies skin changed.
func (m *Menu) StylesChanged(s *config.Styles) {
m.styles = s
m.SetBackgroundColor(s.BgColor())
}
// StackPushed notifies a component was added.
func (m *Menu) StackPushed(c model.Component) {
m.HydrateMenu(c.Hints())
}
// StackPopped notifies a component was removed.
func (m *Menu) StackPopped(o, top model.Component) {
if top != nil {
m.HydrateMenu(top.Hints())
@ -58,6 +61,7 @@ func (m *Menu) StackPopped(o, top model.Component) {
}
}
// StackTop notifies the top component.
func (m *Menu) StackTop(t model.Component) {
m.HydrateMenu(t.Hints())
}

View File

@ -8,11 +8,13 @@ import (
"github.com/rs/zerolog/log"
)
// Pages represents a stack of view pages.
type Pages struct {
*tview.Pages
*model.Stack
}
// NewPages return a new view.
func NewPages() *Pages {
p := Pages{
Pages: tview.NewPages(),
@ -23,10 +25,12 @@ func NewPages() *Pages {
return &p
}
// Show displays a given page.
func (p *Pages) Show(c model.Component) {
p.SwitchToPage(componentID(c))
}
// Current returns the current component.
func (p *Pages) Current() model.Component {
c := p.CurrentPage()
if c == nil {
@ -52,7 +56,8 @@ func (p *Pages) delete(c model.Component) {
p.RemovePage(componentID(c))
}
func (p *Pages) DumpPages() {
// Dump for debug.
func (p *Pages) Dump() {
log.Debug().Msgf("Dumping Pages %p", p)
for i, c := range p.Stack.Peek() {
log.Debug().Msgf("%d -- %s -- %#v", i, componentID(c), p.GetPrimitive(componentID(c)))
@ -61,14 +66,17 @@ func (p *Pages) DumpPages() {
// Stack Protocol...
// StackPushed notifies a new component was pushed.
func (p *Pages) StackPushed(c model.Component) {
p.addAndShow(c)
}
// StackPopped notifies a component was removed.
func (p *Pages) StackPopped(o, top model.Component) {
p.delete(o)
}
// StackTop notifies a new component is at the top of the stack.
func (p *Pages) StackTop(top model.Component) {
if top == nil {
return

View File

@ -52,8 +52,8 @@ func NewTable(gvr string) *Table {
}
}
// Init initializes the component.
func (t *Table) Init(ctx context.Context) {
t.SetFixed(1, 0)
t.SetBorder(true)
t.SetBorderAttributes(tcell.AttrBold)
@ -61,14 +61,16 @@ func (t *Table) Init(ctx context.Context) {
t.SetSelectable(true, false)
t.SetSelectionChangedFunc(t.selectionChanged)
t.SetInputCapture(t.keyboard)
t.StylesChanged(mustExtractSyles(ctx))
t.styles = mustExtractSyles(ctx)
t.StylesChanged(t.styles)
}
// StylesChanged notifies the skin changed.
func (t *Table) StylesChanged(s *config.Styles) {
t.styles = s
t.SetBackgroundColor(config.AsColor(t.styles.GetTable().BgColor))
t.SetBorderColor(config.AsColor(t.styles.GetTable().FgColor))
t.SetBorderFocusColor(config.AsColor(t.styles.Frame().Border.FocusColor))
t.SetBackgroundColor(config.AsColor(s.GetTable().BgColor))
t.SetBorderColor(config.AsColor(s.GetTable().FgColor))
t.SetBorderFocusColor(config.AsColor(s.Frame().Border.FocusColor))
t.SetSelectedStyle(
tcell.ColorBlack,
config.AsColor(t.styles.GetTable().CursorColor),
@ -118,6 +120,7 @@ func (t *Table) keyboard(evt *tcell.EventKey) *tcell.EventKey {
return evt
}
// Hints returns the view hints.
func (t *Table) Hints() model.MenuHints {
return t.actions.Hints()
}
@ -261,7 +264,6 @@ func (t *Table) buildRow(ns string, r int, re render.RowEvent, header render.Hea
c.SetAlign(header[col].Align)
c.SetTextColor(color(ns, re))
if marked {
log.Debug().Msgf("Marked!")
c.SetTextColor(config.AsColor(t.styles.GetTable().MarkColor))
}
if col == 0 {
@ -271,6 +273,7 @@ func (t *Table) buildRow(ns string, r int, re render.RowEvent, header render.Hea
}
}
// ClearMarks clear out marked items.
func (t *Table) ClearMarks() {
t.marks = map[string]bool{}
t.Refresh()
@ -281,6 +284,7 @@ func (t *Table) Refresh() {
t.Update(t.model.Peek())
}
// GetSelectedRow returns the entire selected row.
func (t *Table) GetSelectedRow() render.Row {
return t.model.Peek().RowEvents[t.GetSelectedRowIndex()].Row
}

View File

@ -75,6 +75,7 @@ func TrimLabelSelector(s string) string {
return strings.TrimSpace(s[2:])
}
// SkinTitle decorates a title.
func SkinTitle(fmat string, style config.Frame) string {
fmat = strings.Replace(fmat, "[fg:bg", "["+style.Title.FgColor+":"+style.Title.BgColor, -1)
fmat = strings.Replace(fmat, "[hilite", "["+style.Title.HighlightColor, 1)

View File

@ -9,6 +9,7 @@ import (
"github.com/rs/zerolog/log"
)
// Runner represents a runnable action handler.
type Runner interface {
App() *App
GetSelectedItem() string
@ -50,7 +51,6 @@ func inScope(scopes, aliases []string) bool {
func hotKeyActions(r Runner, aa ui.KeyActions) {
hh := config.NewHotKeys()
if err := hh.Load(); err != nil {
log.Warn().Msgf("No HotKey configuration found")
return
}

View File

@ -114,7 +114,7 @@ func (a *App) Init(version string, rate int) error {
return nil
}
// StylesChanges notifies the skin changed.
// StylesChanged notifies the skin changed.
func (a *App) StylesChanged(s *config.Styles) {
a.Main.SetBackgroundColor(s.BgColor())
if f, ok := a.Main.GetPrimitive("main").(*tview.Flex); ok {

View File

@ -20,7 +20,7 @@ type Benchmark struct {
ResourceViewer
}
// NewBench returns a new viewer.
// NewBenchmark returns a new viewer.
func NewBenchmark(gvr client.GVR) ResourceViewer {
b := Benchmark{
ResourceViewer: NewBrowser(gvr),

View File

@ -59,6 +59,7 @@ func (d *Details) Init(_ context.Context) error {
return nil
}
// StylesChanged notifies the skin changed.
func (d *Details) StylesChanged(s *config.Styles) {
d.SetBackgroundColor(d.app.Styles.BgColor())
d.SetTextColor(d.app.Styles.FgColor())
@ -67,6 +68,7 @@ func (d *Details) StylesChanged(s *config.Styles) {
d.Update(d.buff)
}
// Update updates the view content.
func (d *Details) Update(buff string) *Details {
d.buff = buff
d.SetText(colorizeYAML(d.app.Styles.Views().Yaml, buff))
@ -75,6 +77,12 @@ func (d *Details) Update(buff string) *Details {
return d
}
// SetSubjects updates the subject.
func (d *Details) SetSubject(s string) {
d.subject = s
}
// Actions returns menu actions
func (d *Details) Actions() ui.KeyActions {
return d.actions
}
@ -132,10 +140,6 @@ func (d *Details) cpCmd(evt *tcell.EventKey) *tcell.EventKey {
return nil
}
func (d *Details) SetSubject(s string) {
d.subject = s
}
func (d *Details) updateTitle() {
if d.title == "" {
return

View File

@ -21,7 +21,7 @@ func TestHelp(t *testing.T) {
assert.Nil(t, v.Init(ctx))
assert.Equal(t, 17, v.GetRowCount())
assert.Equal(t, 10, v.GetColumnCount())
assert.Equal(t, 8, v.GetColumnCount())
assert.Equal(t, "<ctrl-k>", v.GetCell(1, 0).Text)
assert.Equal(t, "Kill", v.GetCell(1, 1).Text)
}

View File

@ -210,7 +210,7 @@ func (l *Log) updateLogs(ctx context.Context, c <-chan string, buffSize int) {
}
}
// ScrollIndicator returns the scroll mode viewer.
// Indicator returns the scroll mode viewer.
func (l *Log) Indicator() *LogIndicator {
return l.indicator
}

View File

@ -7,18 +7,21 @@ import (
"github.com/derailed/k9s/internal/ui"
)
// PageStack represents a stack of pages.
type PageStack struct {
*ui.Pages
app *App
}
// NewPageStack returns a new page stack.
func NewPageStack() *PageStack {
return &PageStack{
Pages: ui.NewPages(),
}
}
// Init initializes the view.
func (p *PageStack) Init(ctx context.Context) (err error) {
if p.app, err = extractApp(ctx); err != nil {
return err
@ -28,16 +31,19 @@ func (p *PageStack) Init(ctx context.Context) (err error) {
return nil
}
// StackPushed notifies a new page was added.
func (p *PageStack) StackPushed(c model.Component) {
c.Start()
p.app.SetFocus(c)
}
// StackPopped notifies a page was removed.
func (p *PageStack) StackPopped(o, top model.Component) {
o.Stop()
p.StackTop(top)
}
// StackTop notifies for the top component.
func (p *PageStack) StackTop(top model.Component) {
if top == nil {
return

View File

@ -13,10 +13,12 @@ import (
"github.com/rs/zerolog/log"
)
// ScaleExtenders adds scaling extensions.
type ScaleExtender struct {
ResourceViewer
}
// NewScaleExtender returns a new extender.
func NewScaleExtender(r ResourceViewer) ResourceViewer {
s := ScaleExtender{ResourceViewer: r}
s.bindKeys(s.Actions())

View File

@ -71,7 +71,7 @@ func (f *Factory) Get(gvr, path string, sel labels.Selector) (runtime.Object, er
return inf.Lister().ByNamespace(ns).Get(n)
}
// WaitForCachesync waits for all factories to update their cache.
// WaitForCacheSync waits for all factories to update their cache.
func (f *Factory) WaitForCacheSync() {
for _, fac := range f.factories {
m := fac.WaitForCacheSync(f.stopChan)
@ -98,7 +98,7 @@ func (f *Factory) Terminate() {
f.forwarders.DeleteAll()
}
// RegisterForwarder registers a new portforward for a given container.
// AddForwarder registers a new portforward for a given container.
func (f *Factory) AddForwarder(pf Forwarder) {
f.forwarders[pf.Path()] = pf
}
@ -114,7 +114,7 @@ func (f *Factory) DeleteForwarder(path string) {
delete(f.forwarders, path)
}
// Forwards returns all portforwards.
// Forwarders returns all portforwards.
func (f *Factory) Forwarders() Forwarders {
return f.forwarders
}
@ -133,6 +133,7 @@ func (f *Factory) Start(stopChan chan struct{}) {
}
}
// SetActive sets the active namespace.
// BOZO!! Check ns access for resource??
func (f *Factory) SetActive(ns string) {
if !f.isClusterWide() {
@ -222,6 +223,7 @@ func (f *Factory) Client() client.Connection {
// ----------------------------------------------------------------------------
// Helpers...
// Dump for debug.
func (f *Factory) Dump() {
log.Debug().Msgf("----------- FACTORIES -------------")
for ns := range f.factories {
@ -230,6 +232,7 @@ func (f *Factory) Dump() {
log.Debug().Msgf("-----------------------------------")
}
// Debug for debug.
func (f *Factory) Debug(gvr string) {
log.Debug().Msgf("----------- DEBUG FACTORY (%s) -------------", gvr)
inf := f.factories[allNamespaces].ForResource(toGVR(gvr))
@ -238,6 +241,7 @@ func (f *Factory) Debug(gvr string) {
}
}
// Show for debug.
func (f *Factory) Show(ns, gvr string) {
log.Debug().Msgf("----------- SHOW FACTORIES %q -------------", ns)
inf := f.ForResource(ns, gvr)