fix clusterinfo on ctx switch

mine
derailed 2019-05-04 08:03:15 -06:00
parent a9f8e2b2b6
commit 3c5a5e147c
8 changed files with 73 additions and 19 deletions

View File

@ -1,6 +1,9 @@
package k8s package k8s
import ( import (
"time"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1" mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
@ -49,6 +52,10 @@ func NewMetricsServer(c Connection) *MetricsServer {
// NodesMetrics retrieves metrics for a given set of nodes. // NodesMetrics retrieves metrics for a given set of nodes.
func (m *MetricsServer) NodesMetrics(nodes Collection, metrics *mv1beta1.NodeMetricsList, mmx NodesMetrics) { func (m *MetricsServer) NodesMetrics(nodes Collection, metrics *mv1beta1.NodeMetricsList, mmx NodesMetrics) {
defer func(t time.Time) {
log.Debug().Msgf("Node MX %v", time.Since(t))
}(time.Now())
for _, n := range nodes { for _, n := range nodes {
no := n.(v1.Node) no := n.(v1.Node)
mmx[no.Name] = NodeMetrics{ mmx[no.Name] = NodeMetrics{
@ -70,6 +77,10 @@ func (m *MetricsServer) NodesMetrics(nodes Collection, metrics *mv1beta1.NodeMet
// ClusterLoad retrieves all cluster nodes metrics. // ClusterLoad retrieves all cluster nodes metrics.
func (m *MetricsServer) ClusterLoad(nodes *v1.NodeList, metrics *mv1beta1.NodeMetricsList, mx *ClusterMetrics) { func (m *MetricsServer) ClusterLoad(nodes *v1.NodeList, metrics *mv1beta1.NodeMetricsList, mx *ClusterMetrics) {
defer func(t time.Time) {
log.Debug().Msgf("Cluster Load %v", time.Since(t))
}(time.Now())
nodeMetrics := make(NodesMetrics, len(nodes.Items)) nodeMetrics := make(NodesMetrics, len(nodes.Items))
for _, n := range nodes.Items { for _, n := range nodes.Items {
@ -100,6 +111,10 @@ func (m *MetricsServer) ClusterLoad(nodes *v1.NodeList, metrics *mv1beta1.NodeMe
// FetchNodesMetrics return all metrics for pods in a given namespace. // FetchNodesMetrics return all metrics for pods in a given namespace.
func (m *MetricsServer) FetchNodesMetrics() (*mv1beta1.NodeMetricsList, error) { func (m *MetricsServer) FetchNodesMetrics() (*mv1beta1.NodeMetricsList, error) {
defer func(t time.Time) {
log.Debug().Msgf("Node metrics %v", time.Since(t))
}(time.Now())
client, err := m.MXDial() client, err := m.MXDial()
if err != nil { if err != nil {
return nil, err return nil, err
@ -110,6 +125,10 @@ func (m *MetricsServer) FetchNodesMetrics() (*mv1beta1.NodeMetricsList, error) {
// FetchPodsMetrics return all metrics for pods in a given namespace. // FetchPodsMetrics return all metrics for pods in a given namespace.
func (m *MetricsServer) FetchPodsMetrics(ns string) (*mv1beta1.PodMetricsList, error) { func (m *MetricsServer) FetchPodsMetrics(ns string) (*mv1beta1.PodMetricsList, error) {
defer func(t time.Time) {
log.Debug().Msgf("Pod Metrics %v", time.Since(t))
}(time.Now())
client, err := m.MXDial() client, err := m.MXDial()
if err != nil { if err != nil {
return nil, err return nil, err
@ -120,6 +139,10 @@ func (m *MetricsServer) FetchPodsMetrics(ns string) (*mv1beta1.PodMetricsList, e
// PodsMetrics retrieves metrics for all pods in a given namespace. // PodsMetrics retrieves metrics for all pods in a given namespace.
func (m *MetricsServer) PodsMetrics(pods *mv1beta1.PodMetricsList, mmx PodsMetrics) { func (m *MetricsServer) PodsMetrics(pods *mv1beta1.PodMetricsList, mmx PodsMetrics) {
defer func(t time.Time) {
log.Debug().Msgf("Pod MX %v", time.Since(t))
}(time.Now())
// Compute all pod's containers metrics. // Compute all pod's containers metrics.
for _, p := range pods.Items { for _, p := range pods.Items {
var mx PodMetrics var mx PodMetrics

View File

@ -1,6 +1,9 @@
package k8s package k8s
import ( import (
"time"
"github.com/rs/zerolog/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
@ -22,6 +25,10 @@ func (n *Node) Get(_, name string) (interface{}, error) {
// List all nodes on the cluster. // List all nodes on the cluster.
func (n *Node) List(_ string) (Collection, error) { func (n *Node) List(_ string) (Collection, error) {
defer func(t time.Time) {
log.Debug().Msgf("List Node %v", time.Since(t))
}(time.Now())
opts := metav1.ListOptions{ opts := metav1.ListOptions{
LabelSelector: n.labelSelector, LabelSelector: n.labelSelector,
FieldSelector: n.fieldSelector, FieldSelector: n.fieldSelector,

View File

@ -2,7 +2,9 @@ package resource
import ( import (
"reflect" "reflect"
"time"
"github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/cli-runtime/pkg/genericclioptions"
) )
@ -217,6 +219,10 @@ func (l *list) Data() TableData {
// Reconcile previous vs current state and emits delta events. // Reconcile previous vs current state and emits delta events.
func (l *list) Reconcile() error { func (l *list) Reconcile() error {
defer func(t time.Time) {
log.Debug().Msgf("Reconcile %v", time.Since(t))
}(time.Now())
items, err := l.resource.List(l.namespace) items, err := l.resource.List(l.namespace)
if err != nil { if err != nil {
return err return err

View File

@ -179,6 +179,10 @@ func (r *Pod) Logs(c chan<- string, ns, n, co string, lines int64, prev bool) (c
// List resources for a given namespace. // List resources for a given namespace.
func (r *Pod) List(ns string) (Columnars, error) { func (r *Pod) List(ns string) (Columnars, error) {
defer func(t time.Time) {
log.Debug().Msgf("List Pod %v", time.Since(t))
}(time.Now())
pods, err := r.Resource.List(ns) pods, err := r.Resource.List(ns)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -148,8 +148,8 @@ func (a *appView) stylesUpdater() (*fsnotify.Watcher, error) {
a.QueueUpdateDraw(func() { a.QueueUpdateDraw(func() {
a.refreshStyles() a.refreshStyles()
}) })
// case err := <-w.Errors: case err := <-w.Errors:
// log.Info().Err(err).Msg("Skin watcher failed") log.Info().Err(err).Msg("Skin watcher failed")
} }
} }
}() }()

View File

@ -14,8 +14,8 @@ import (
type clusterInfoView struct { type clusterInfoView struct {
*tview.Table *tview.Table
app *appView app *appView
cluster *resource.Cluster mxs resource.MetricsServer
} }
// ClusterInfo tracks Kubernetes cluster and K9s information. // ClusterInfo tracks Kubernetes cluster and K9s information.
@ -31,31 +31,33 @@ type ClusterInfo interface {
func newClusterInfoView(app *appView, mx resource.MetricsServer) *clusterInfoView { func newClusterInfoView(app *appView, mx resource.MetricsServer) *clusterInfoView {
return &clusterInfoView{ return &clusterInfoView{
app: app, app: app,
Table: tview.NewTable(), Table: tview.NewTable(),
cluster: resource.NewCluster(app.conn(), &log.Logger, mx), mxs: mx,
} }
} }
func (v *clusterInfoView) init() { func (v *clusterInfoView) init() {
cluster := resource.NewCluster(v.app.conn(), &log.Logger, v.mxs)
var row int var row int
v.SetCell(row, 0, v.sectionCell("Context")) v.SetCell(row, 0, v.sectionCell("Context"))
v.SetCell(row, 1, v.infoCell(v.cluster.ContextName())) v.SetCell(row, 1, v.infoCell(cluster.ContextName()))
row++ row++
v.SetCell(row, 0, v.sectionCell("Cluster")) v.SetCell(row, 0, v.sectionCell("Cluster"))
v.SetCell(row, 1, v.infoCell(v.cluster.ClusterName())) v.SetCell(row, 1, v.infoCell(cluster.ClusterName()))
row++ row++
v.SetCell(row, 0, v.sectionCell("User")) v.SetCell(row, 0, v.sectionCell("User"))
v.SetCell(row, 1, v.infoCell(v.cluster.UserName())) v.SetCell(row, 1, v.infoCell(cluster.UserName()))
row++ row++
v.SetCell(row, 0, v.sectionCell("K9s Rev")) v.SetCell(row, 0, v.sectionCell("K9s Rev"))
v.SetCell(row, 1, v.infoCell(v.app.version)) v.SetCell(row, 1, v.infoCell(v.app.version))
row++ row++
rev := v.cluster.Version() rev := cluster.Version()
v.SetCell(row, 0, v.sectionCell("K8s Rev")) v.SetCell(row, 0, v.sectionCell("K8s Rev"))
v.SetCell(row, 1, v.infoCell(rev)) v.SetCell(row, 1, v.infoCell(rev))
row++ row++
@ -88,29 +90,31 @@ func (v *clusterInfoView) infoCell(t string) *tview.TableCell {
} }
func (v *clusterInfoView) refresh() { func (v *clusterInfoView) refresh() {
cluster := resource.NewCluster(v.app.conn(), &log.Logger, v.mxs)
var row int var row int
v.GetCell(row, 1).SetText(v.cluster.ContextName()) v.GetCell(row, 1).SetText(cluster.ContextName())
row++ row++
v.GetCell(row, 1).SetText(v.cluster.ClusterName()) v.GetCell(row, 1).SetText(cluster.ClusterName())
row++ row++
v.GetCell(row, 1).SetText(v.cluster.UserName()) v.GetCell(row, 1).SetText(cluster.UserName())
row += 2 row += 2
v.GetCell(row, 1).SetText(v.cluster.Version()) v.GetCell(row, 1).SetText(cluster.Version())
row++ row++
nodes, err := v.cluster.GetNodes() nodes, err := cluster.GetNodes()
if err != nil { if err != nil {
log.Warn().Err(err).Msg("List nodes") log.Warn().Err(err).Msg("List nodes")
return return
} }
mxNodes, err := v.cluster.FetchNodesMetrics() mxNodes, err := cluster.FetchNodesMetrics()
if err != nil { if err != nil {
log.Warn().Err(err).Msg("List node metrics") log.Warn().Err(err).Msg("List node metrics")
return return
} }
var mx k8s.ClusterMetrics var mx k8s.ClusterMetrics
v.cluster.Metrics(nodes, mxNodes, &mx) cluster.Metrics(nodes, mxNodes, &mx)
c := v.GetCell(row, 1) c := v.GetCell(row, 1)
cpu := resource.AsPerc(mx.PercCPU) cpu := resource.AsPerc(mx.PercCPU)
c.SetText(cpu + deltas(strip(c.Text), cpu)) c.SetText(cpu + deltas(strip(c.Text), cpu))

View File

@ -34,6 +34,11 @@ func (v *contextView) useCmd(evt *tcell.EventKey) *tcell.EventKey {
return evt return evt
} }
// Update cluster info on context switch.
v.app.QueueUpdateDraw(func() {
v.app.clusterInfoView.refresh()
})
v.app.gotoResource("po", true) v.app.gotoResource("po", true)
return nil return nil

View File

@ -116,7 +116,7 @@ func (v *resourceView) updater(ctx context.Context) {
if v.isSuspended() { if v.isSuspended() {
continue continue
} }
v.app.QueueUpdate(func() { v.app.QueueUpdateDraw(func() {
v.app.clusterInfoView.refresh() v.app.clusterInfoView.refresh()
}) })
} }
@ -375,6 +375,11 @@ func (v *resourceView) doSwitchNamespace(ns string) {
} }
func (v *resourceView) refresh() { func (v *resourceView) refresh() {
log.Debug().Msgf("%s", strings.Repeat("-", 80))
defer func(t time.Time) {
log.Debug().Msgf("Refresh %v", time.Since(t))
}(time.Now())
if _, ok := v.CurrentPage().Item.(*tableView); !ok { if _, ok := v.CurrentPage().Item.(*tableView); !ok {
return return
} }