derailed 2020-01-06 15:05:07 -07:00
parent 6b5da1091e
commit a8771b8c67
15 changed files with 66 additions and 31 deletions

1
.gitignore vendored
View File

@ -16,3 +16,4 @@ cluster_info_test.go
*.test *.test
*.log *.log
*~ *~
pod1.go

View File

@ -576,4 +576,4 @@ to make this project a reality!
--- ---
<img src="assets/imhotep_logo.png" width="32" height="auto"/> © 2019 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0) <img src="assets/imhotep_logo.png" width="32" height="auto"/> © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -0,0 +1,26 @@
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
# Release v0.11.2
## Notes
Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better is as ever very much noticed and appreciated!
Also if you dig this tool, please make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
---
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_helm.png" align="center" width="300" height="auto"/>
Maintenance Release!
---
## Resolved Bugs/Features
* [Issue #469](https://github.com/derailed/k9s/issues/469)
* [Issue #468](https://github.com/derailed/k9s/issues/468)
---
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)

View File

@ -39,19 +39,14 @@ type Pod struct {
// List returns a collection of nodes. // List returns a collection of nodes.
func (p *Pod) List(ctx context.Context, ns string) ([]runtime.Object, error) { func (p *Pod) List(ctx context.Context, ns string) ([]runtime.Object, error) {
oo, err := p.Resource.List(ctx, ns)
if err != nil {
return oo, err
}
pmx, ok := ctx.Value(internal.KeyMetrics).(*mv1beta1.PodMetricsList) pmx, ok := ctx.Value(internal.KeyMetrics).(*mv1beta1.PodMetricsList)
if !ok { if !ok {
log.Warn().Msgf("expecting context PodMetricsList") log.Warn().Msgf("no metrics available for %q", p.gvr)
} }
sel, ok := ctx.Value(internal.KeyFields).(string) sel, ok := ctx.Value(internal.KeyFields).(string)
if !ok { if !ok {
return oo, nil return nil, fmt.Errorf("expecting a fieldSelector in context")
} }
fsel, err := labels.ConvertSelectorToLabelsMap(sel) fsel, err := labels.ConvertSelectorToLabelsMap(sel)
if err != nil { if err != nil {
@ -59,6 +54,11 @@ func (p *Pod) List(ctx context.Context, ns string) ([]runtime.Object, error) {
} }
nodeName := fsel["spec.nodeName"] nodeName := fsel["spec.nodeName"]
oo, err := p.Resource.List(ctx, ns)
if err != nil {
return oo, err
}
var res []runtime.Object var res []runtime.Object
for _, o := range oo { for _, o := range oo {
u, ok := o.(*unstructured.Unstructured) u, ok := o.(*unstructured.Unstructured)

View File

@ -47,5 +47,5 @@ func (r *Resource) List(ctx context.Context, ns string) ([]runtime.Object, error
lsel = sel.AsSelector() lsel = sel.AsSelector()
} }
return r.Factory.List(r.gvr.String(), ns, true, lsel) return r.Factory.List(r.gvr.String(), ns, false, lsel)
} }

View File

@ -49,7 +49,7 @@ func (t *Table) getClient() (*rest.RESTClient, error) {
gv := t.gvr.AsGV() gv := t.gvr.AsGV()
crConfig.GroupVersion = &gv crConfig.GroupVersion = &gv
crConfig.APIPath = "/apis" crConfig.APIPath = "/apis"
if len(t.gvr.ToG()) == 0 { if t.gvr.ToG() == "" {
crConfig.APIPath = "/api" crConfig.APIPath = "/api"
} }
codec, _ := t.codec() codec, _ := t.codec()

View File

@ -193,6 +193,10 @@ func (t *Table) refresh(ctx context.Context) {
} }
func (t *Table) list(ctx context.Context, a dao.Accessor) ([]runtime.Object, error) { func (t *Table) list(ctx context.Context, a dao.Accessor) ([]runtime.Object, error) {
defer func(t time.Time) {
log.Debug().Msgf(" LIST elapsed %v", time.Since(t))
}(time.Now())
factory, ok := ctx.Value(internal.KeyFactory).(dao.Factory) factory, ok := ctx.Value(internal.KeyFactory).(dao.Factory)
if !ok { if !ok {
return nil, fmt.Errorf("expected Factory in context but got %T", ctx.Value(internal.KeyFactory)) return nil, fmt.Errorf("expected Factory in context but got %T", ctx.Value(internal.KeyFactory))
@ -212,7 +216,7 @@ func (t *Table) reconcile(ctx context.Context) error {
if err != nil { if err != nil {
return err return err
} }
log.Debug().Msgf("LIST returned %d rows", len(oo)) log.Debug().Msgf(" LIST returned %d rows", len(oo))
var rows render.Rows var rows render.Rows
if _, ok := meta.Renderer.(*render.Generic); ok { if _, ok := meta.Renderer.(*render.Generic); ok {
@ -221,7 +225,7 @@ func (t *Table) reconcile(ctx context.Context) error {
return fmt.Errorf("expecting a meta table but got %T", oo[0]) return fmt.Errorf("expecting a meta table but got %T", oo[0])
} }
rows = make(render.Rows, len(table.Rows)) rows = make(render.Rows, len(table.Rows))
if err := tableHydrate(t.namespace, table, rows, meta.Renderer); err != nil { if err := genericHydrate(t.namespace, table, rows, meta.Renderer); err != nil {
return err return err
} }
} else { } else {
@ -287,6 +291,10 @@ func (t *Table) fireTableLoadFailed(err error) {
// Helpers... // Helpers...
func hydrate(ns string, oo []runtime.Object, rr render.Rows, re Renderer) error { func hydrate(ns string, oo []runtime.Object, rr render.Rows, re Renderer) error {
defer func(t time.Time) {
log.Debug().Msgf(" HYDRATE elapsed %v", time.Since(t))
}(time.Now())
for i, o := range oo { for i, o := range oo {
if err := re.Render(o, ns, &rr[i]); err != nil { if err := re.Render(o, ns, &rr[i]); err != nil {
return err return err
@ -296,7 +304,7 @@ func hydrate(ns string, oo []runtime.Object, rr render.Rows, re Renderer) error
return nil return nil
} }
func tableHydrate(ns string, table *metav1beta1.Table, rr render.Rows, re Renderer) error { func genericHydrate(ns string, table *metav1beta1.Table, rr render.Rows, re Renderer) error {
gr, ok := re.(*render.Generic) gr, ok := re.(*render.Generic)
if !ok { if !ok {
return fmt.Errorf("expecting generic renderer but got %T", re) return fmt.Errorf("expecting generic renderer but got %T", re)

View File

@ -24,11 +24,11 @@ func (Deployment) ColorerFunc() ColorerFunc {
return c return c
} }
markCol := 2 readyCol := 2
if !client.IsAllNamespaces(ns) { if !client.IsAllNamespaces(ns) {
markCol = 1 readyCol--
} }
tokens := strings.Split(r.Row.Fields[markCol], "/") tokens := strings.Split(r.Row.Fields[readyCol], "/")
if tokens[0] != tokens[1] { if tokens[0] != tokens[1] {
return ErrColor return ErrColor
} }

View File

@ -24,11 +24,11 @@ func (DaemonSet) ColorerFunc() ColorerFunc {
return c return c
} }
markCol := 2 desiredCol := 2
if !client.IsAllNamespaces(ns) { if !client.IsAllNamespaces(ns) {
markCol = 1 desiredCol = 1
} }
if strings.TrimSpace(r.Row.Fields[markCol]) != strings.TrimSpace(r.Row.Fields[markCol+2]) { if strings.TrimSpace(r.Row.Fields[desiredCol]) != strings.TrimSpace(r.Row.Fields[desiredCol+2]) {
return ErrColor return ErrColor
} }

View File

@ -26,8 +26,8 @@ func (PodDisruptionBudget) ColorerFunc() ColorerFunc {
} }
markCol := 5 markCol := 5
if client.IsNamespaced(ns) { if !client.IsAllNamespaces(ns) {
markCol = 4 markCol--
} }
if strings.TrimSpace(r.Row.Fields[markCol]) != strings.TrimSpace(r.Row.Fields[markCol+1]) { if strings.TrimSpace(r.Row.Fields[markCol]) != strings.TrimSpace(r.Row.Fields[markCol+1]) {
return ErrColor return ErrColor

View File

@ -26,8 +26,8 @@ func (p Pod) ColorerFunc() ColorerFunc {
c := DefaultColorer(ns, re) c := DefaultColorer(ns, re)
readyCol := 2 readyCol := 2
if len(ns) != 0 { if !client.IsAllNamespaces(ns) {
readyCol = 1 readyCol--
} }
statusCol := readyCol + 1 statusCol := readyCol + 1
@ -75,7 +75,7 @@ func (Pod) Header(ns string) HeaderRow {
Header{Name: "NAME"}, Header{Name: "NAME"},
Header{Name: "READY"}, Header{Name: "READY"},
Header{Name: "STATUS"}, Header{Name: "STATUS"},
Header{Name: "RS", Align: tview.AlignRight}, Header{Name: "RESTART", Align: tview.AlignRight},
Header{Name: "CPU", Align: tview.AlignRight}, Header{Name: "CPU", Align: tview.AlignRight},
Header{Name: "MEM", Align: tview.AlignRight}, Header{Name: "MEM", Align: tview.AlignRight},
Header{Name: "%CPU", Align: tview.AlignRight}, Header{Name: "%CPU", Align: tview.AlignRight},

View File

@ -23,10 +23,9 @@ func (PersistentVolumeClaim) ColorerFunc() ColorerFunc {
} }
markCol := 2 markCol := 2
if client.IsNamespaced(ns) { if !client.IsAllNamespaces(ns) {
markCol = 1 markCol--
} }
if strings.TrimSpace(r.Row.Fields[markCol]) != "Bound" { if strings.TrimSpace(r.Row.Fields[markCol]) != "Bound" {
c = ErrColor c = ErrColor
} }

View File

@ -25,8 +25,8 @@ func (ReplicaSet) ColorerFunc() ColorerFunc {
} }
markCol := 2 markCol := 2
if client.IsNamespaced(ns) { if !client.IsAllNamespaces(ns) {
markCol = 1 markCol--
} }
if strings.TrimSpace(r.Row.Fields[markCol]) != strings.TrimSpace(r.Row.Fields[markCol+1]) { if strings.TrimSpace(r.Row.Fields[markCol]) != strings.TrimSpace(r.Row.Fields[markCol+1]) {
return ErrColor return ErrColor

View File

@ -24,7 +24,7 @@ func (StatefulSet) ColorerFunc() ColorerFunc {
} }
readyCol := 2 readyCol := 2
if client.IsNamespaced(ns) { if !client.IsAllNamespaces(ns) {
readyCol-- readyCol--
} }
tokens := strings.Split(strings.TrimSpace(r.Row.Fields[readyCol]), "/") tokens := strings.Split(strings.TrimSpace(r.Row.Fields[readyCol]), "/")

View File

@ -55,7 +55,8 @@ func (n *Namespace) useNsCmd(evt *tcell.EventKey) *tcell.EventKey {
return nil return nil
} }
func (n *Namespace) useNamespace(ns string) { func (n *Namespace) useNamespace(fqn string) {
_, ns := client.Namespaced(fqn)
log.Debug().Msgf("SWITCHING NS %q", ns) log.Debug().Msgf("SWITCHING NS %q", ns)
n.App().switchNS(ns) n.App().switchNS(ns)
if err := n.App().Config.SetActiveNamespace(ns); err != nil { if err := n.App().Config.SetActiveNamespace(ns); err != nil {