fix clusterinfo on ctx switch
parent
a9f8e2b2b6
commit
3c5a5e147c
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue