diff --git a/go.sum b/go.sum index 66ba659f..d0ce2c03 100644 --- a/go.sum +++ b/go.sum @@ -21,24 +21,37 @@ github.com/Azure/go-autorest v10.8.1+incompatible h1:u0jVQf+a6k6x8A+sT60l6EY9XZu github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.0.0+incompatible h1:r/ug62X9o8vikt53/nkAPmFmzfSrCCAplPH7wa+mK0U= github.com/Azure/go-autorest v14.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.10.0 h1:mvdtztBqcL8se7MdrUweNieTNi4kfNG6GOJuurQJpuY= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.11.10 h1:j5sGbX7uj1ieYYkQ3Mpvewd4DCsEQ+ZeJpqnSM9pjnM= +github.com/Azure/go-autorest/autorest v0.11.10/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -89,6 +102,8 @@ github.com/atotto/clipboard v0.1.2/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.29.32 h1:o4I8Qc+h9ht8NXvTHeXZH3EmtSUZ/PC0bg9Wawr+aTA= github.com/aws/aws-sdk-go v1.29.32/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= +github.com/aws/aws-sdk-go v1.35.21 h1:6cMeHzcca+0uweOpUonDYv4DsPp9Qa9PTMYxH+VqDkY= +github.com/aws/aws-sdk-go v1.35.21/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -223,6 +238,8 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= @@ -420,6 +437,9 @@ github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= @@ -745,6 +765,8 @@ golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEB golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= diff --git a/internal/client/client.go b/internal/client/client.go index da7b35cf..df2d2666 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -26,7 +26,6 @@ import ( const ( cacheSize = 100 cacheExpiry = 5 * time.Minute - cacheMXKey = "metrics" cacheMXAPIKey = "metricsAPI" ) @@ -46,7 +45,7 @@ type APIClient struct { } // NewTestClient for testing ONLY!! -func NewTestClient() *APIClient { +func NewTestAPIClient() *APIClient { return &APIClient{ config: NewConfig(nil), cache: cache.NewLRUExpireCache(cacheSize), @@ -61,12 +60,12 @@ func InitConnection(config *Config) (*APIClient, error) { cache: cache.NewLRUExpireCache(cacheSize), } a.connOK = true - _, err := a.supportsMetricsResources() - if err != nil { + if err := a.supportsMetricsResources(); err != nil { a.connOK = false + return nil, err } - return &a, err + return &a, nil } // ConnectionOK returns connection status. @@ -272,35 +271,12 @@ func (a *APIClient) Config() *Config { return a.config } -// HasMetrics returns true if the cluster supports metrics. +// HasMetrics checks if the cluster supports metrics. func (a *APIClient) HasMetrics() bool { - ok, err := a.supportsMetricsResources() - if !ok || err != nil { + if err := a.supportsMetricsResources(); err != nil { return false } - if v, ok := a.cache.Get(cacheMXKey); ok { - flag, k := v.(bool) - return k && flag - } - - var metricsOK bool - defer func() { - a.cache.Add(cacheMXKey, metricsOK, cacheExpiry) - }() - dial, err := a.MXDial() - if err != nil { - return metricsOK - } - - ctx, cancel := context.WithTimeout(context.Background(), a.config.CallTimeout()) - defer cancel() - if _, err := dial.MetricsV1beta1().NodeMetricses().List(ctx, metav1.ListOptions{Limit: 1}); err == nil { - metricsOK = true - } else { - log.Error().Err(err).Msgf("List metrics failed") - } - - return metricsOK + return true } // Dial returns a handle to api server or die. @@ -425,27 +401,37 @@ func (a *APIClient) reset() { a.connOK = true } -func (a *APIClient) supportsMetricsResources() (supported bool, err error) { - if v, ok := a.cache.Get(cacheMXAPIKey); ok { - flag, k := v.(bool) - supported = k && flag +func (a *APIClient) checkCacheBool(key string) (state bool, ok bool) { + v, found := a.cache.Get(key) + if !found { return } - if a.config == nil || a.config.flags == nil { - return + state, ok = v.(bool) + return +} + +func (a *APIClient) supportsMetricsResources() error { + supported, ok := a.checkCacheBool(cacheMXAPIKey) + if ok { + if supported { + return nil + } + return errors.New("No metrics-server detected") } + defer func() { a.cache.Add(cacheMXAPIKey, supported, cacheExpiry) }() dial, err := a.CachedDiscovery() if err != nil { - return false, err + log.Warn().Err(err).Msgf("Unable to dial discovery API") + return err } apiGroups, err := dial.ServerGroups() if err != nil { - log.Debug().Msgf("Unable to access servergroups %#v", err) - return + log.Warn().Err(err).Msgf("Unable to retrieve server groups") + return err } for _, grp := range apiGroups.Groups { if grp.Name != metricsapi.GroupName { @@ -453,11 +439,11 @@ func (a *APIClient) supportsMetricsResources() (supported bool, err error) { } if checkMetricsVersion(grp) { supported = true - return + return nil } } - return + return errors.New("No metrics-server detected") } func checkMetricsVersion(grp metav1.APIGroup) bool { diff --git a/internal/client/client_test.go b/internal/client/client_test.go new file mode 100644 index 00000000..a489f467 --- /dev/null +++ b/internal/client/client_test.go @@ -0,0 +1,54 @@ +package client + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestCheckCacheBool(t *testing.T) { + c := NewTestAPIClient() + + const key = "fred" + uu := map[string]struct { + key string + val interface{} + found, actual, sleep bool + }{ + "setTrue": { + key: key, + val: true, + found: true, + actual: true, + }, + "setFalse": { + key: key, + val: false, + found: true, + }, + "missing": { + key: "blah", + val: false, + }, + "expired": { + key: key, + val: true, + sleep: true, + }, + } + + expiry := 1 * time.Millisecond + for k := range uu { + u := uu[k] + c.cache.Add(key, u.val, expiry) + if u.sleep { + time.Sleep(expiry) + } + t.Run(k, func(t *testing.T) { + val, ok := c.checkCacheBool(u.key) + assert.Equal(t, u.found, ok) + assert.Equal(t, u.actual, val) + }) + } +} diff --git a/internal/client/metrics.go b/internal/client/metrics.go index ad979500..af8e37f0 100644 --- a/internal/client/metrics.go +++ b/internal/client/metrics.go @@ -2,6 +2,7 @@ package client import ( "context" + "errors" "fmt" "math" "strconv" @@ -90,7 +91,7 @@ func (m *MetricsServer) ClusterLoad(nos *v1.NodeList, nmx *mv1beta1.NodeMetricsL func (m *MetricsServer) checkAccess(ns, gvr, msg string) error { if !m.HasMetrics() { - return fmt.Errorf("No metrics-server detected on cluster") + return errors.New("No metrics-server detected on cluster") } auth, err := m.CanI(ns, gvr, ListAccess) diff --git a/internal/dao/node.go b/internal/dao/node.go index b0dfcf21..0985089d 100644 --- a/internal/dao/node.go +++ b/internal/dao/node.go @@ -115,9 +115,7 @@ func (n *Node) Get(ctx context.Context, path string) (runtime.Object, error) { err error ) if withMx, ok := ctx.Value(internal.KeyWithMetrics).(bool); withMx || !ok { - if nmx, err = client.DialMetrics(n.Client()).FetchNodesMetrics(ctx); err != nil { - log.Debug().Err(err).Msgf("No node metrics") - } + nmx, _ = client.DialMetrics(n.Client()).FetchNodesMetrics(ctx) } no, err := FetchNode(ctx, n.Factory, path) @@ -142,9 +140,7 @@ func (n *Node) List(ctx context.Context, ns string) ([]runtime.Object, error) { err error ) if withMx, ok := ctx.Value(internal.KeyWithMetrics).(bool); withMx || !ok { - if nmx, err = client.DialMetrics(n.Client()).FetchNodesMetrics(ctx); err != nil { - log.Warn().Err(err).Msgf("No node metrics") - } + nmx, _ = client.DialMetrics(n.Client()).FetchNodesMetrics(ctx) } labels, _ := ctx.Value(internal.KeyLabels).(string) diff --git a/internal/dao/pod.go b/internal/dao/pod.go index cd789f31..b408222c 100644 --- a/internal/dao/pod.go +++ b/internal/dao/pod.go @@ -65,9 +65,7 @@ func (p *Pod) Get(ctx context.Context, path string) (runtime.Object, error) { var pmx *mv1beta1.PodMetrics if withMx, ok := ctx.Value(internal.KeyWithMetrics).(bool); withMx || !ok { - if pmx, err = client.DialMetrics(p.Client()).FetchPodMetrics(ctx, path); err != nil { - log.Debug().Err(err).Msgf("No pod metrics") - } + pmx, _ = client.DialMetrics(p.Client()).FetchPodMetrics(ctx, path) } return &render.PodWithMetrics{Raw: u, MX: pmx}, nil diff --git a/internal/dao/popeye.go b/internal/dao/popeye.go index 0fd8130b..7e8a4552 100644 --- a/internal/dao/popeye.go +++ b/internal/dao/popeye.go @@ -77,7 +77,7 @@ func (p *Popeye) List(ctx context.Context, ns string) ([]runtime.Object, error) if err != nil { return nil, err } - popeye.SetFactory(newPopFactory(p.Factory)) + popeye.SetFactory(newPopeyeFactory(p.Factory)) if err = popeye.Init(); err != nil { return nil, err } @@ -120,19 +120,19 @@ type popFactory struct { var _ types.Factory = (*popFactory)(nil) -func newPopFactory(f Factory) *popFactory { +func newPopeyeFactory(f Factory) *popFactory { return &popFactory{Factory: f} } func (p *popFactory) Client() types.Connection { - return &popConnection{Connection: p.Factory.Client()} + return &popeyeConnection{Connection: p.Factory.Client()} } -type popConnection struct { +type popeyeConnection struct { client.Connection } -var _ types.Connection = (*popConnection)(nil) +var _ types.Connection = (*popeyeConnection)(nil) -func (c *popConnection) Config() types.Config { +func (c *popeyeConnection) Config() types.Config { return c.Connection.Config() } diff --git a/internal/model/fish_buff.go b/internal/model/fish_buff.go index 4a1c2223..8566a8f3 100644 --- a/internal/model/fish_buff.go +++ b/internal/model/fish_buff.go @@ -105,11 +105,6 @@ func (f *FishBuff) Notify(delete bool) { if f.suggestionFn == nil { return } - ss := f.suggestionFn(string(f.buff)) - if len(ss) == 1 && !delete { - f.SetText(string(string(f.buff) + ss[0])) - return - } f.fireSuggestionChanged(f.suggestionFn(string(f.buff))) } diff --git a/internal/model/fish_buff_test.go b/internal/model/fish_buff_test.go index f57327f4..227c6d60 100644 --- a/internal/model/fish_buff_test.go +++ b/internal/model/fish_buff_test.go @@ -8,23 +8,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestFishExact(t *testing.T) { - m := mockSuggestionListener{} - - f := model.NewFishBuff(' ', model.FilterBuffer) - f.AddListener(&m) - f.SetSuggestionFn(func(text string) sort.StringSlice { - return sort.StringSlice{"lee"} - }) - f.Add('b') - f.SetActive(true) - - assert.True(t, m.active) - assert.Equal(t, 1, m.buff) - assert.Equal(t, 0, m.sugg) - assert.Equal(t, "blee", m.text) -} - func TestFishAdd(t *testing.T) { m := mockSuggestionListener{} @@ -37,8 +20,8 @@ func TestFishAdd(t *testing.T) { f.SetActive(true) assert.True(t, m.active) - assert.Equal(t, 1, m.buff) - assert.Equal(t, 1, m.sugg) + assert.Equal(t, 1, m.changeCount) + assert.Equal(t, 1, m.suggCount) assert.Equal(t, "blee", m.suggestion) c, ok := f.CurrentSuggestion() @@ -66,8 +49,8 @@ func TestFishDelete(t *testing.T) { f.Delete() f.SetActive(true) - assert.Equal(t, 2, m.buff) - assert.Equal(t, 2, m.sugg) + assert.Equal(t, 2, m.changeCount) + assert.Equal(t, 2, m.suggCount) assert.True(t, m.active) assert.Equal(t, "blee", m.suggestion) @@ -87,13 +70,13 @@ func TestFishDelete(t *testing.T) { // Helpers... type mockSuggestionListener struct { - buff, sugg int - suggestion, text string - active bool + changeCount, suggCount int + suggestion, text string + active bool } func (m *mockSuggestionListener) BufferChanged(s string) { - m.buff++ + m.changeCount++ } func (m *mockSuggestionListener) BufferCompleted(s string) { @@ -106,5 +89,5 @@ func (m *mockSuggestionListener) BufferActive(state bool, kind model.BufferKind) func (m *mockSuggestionListener) SuggestionChanged(text, sugg string) { m.suggestion = sugg - m.sugg++ + m.suggCount++ } diff --git a/internal/model/table_int_test.go b/internal/model/table_int_test.go index 2923bbd8..af891d88 100644 --- a/internal/model/table_int_test.go +++ b/internal/model/table_int_test.go @@ -179,7 +179,7 @@ type testFactory struct { var _ dao.Factory = testFactory{} func (f testFactory) Client() client.Connection { - return client.NewTestClient() + return client.NewTestAPIClient() } func (f testFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runtime.Object, error) { if len(f.rows) > 0 { diff --git a/internal/model/table_test.go b/internal/model/table_test.go index fd1111e4..a6074ff4 100644 --- a/internal/model/table_test.go +++ b/internal/model/table_test.go @@ -86,7 +86,7 @@ type tableFactory struct { var _ dao.Factory = tableFactory{} func (f tableFactory) Client() client.Connection { - return client.NewTestClient() + return client.NewTestAPIClient() } func (f tableFactory) Get(gvr, path string, wait bool, sel labels.Selector) (runtime.Object, error) { if len(f.rows) > 0 { diff --git a/internal/render/container.go b/internal/render/container.go index ba7f47c5..a254bb2f 100644 --- a/internal/render/container.go +++ b/internal/render/container.go @@ -219,8 +219,8 @@ func ToContainerState(s v1.ContainerState) string { } const ( - on string = "on" - off = "off" + on = "on" + off = "off" ) func probe(p *v1.Probe) string { diff --git a/internal/render/helpers.go b/internal/render/helpers.go index 41204afb..f84fdb58 100644 --- a/internal/render/helpers.go +++ b/internal/render/helpers.go @@ -248,14 +248,6 @@ func mapToIfc(m interface{}) (s string) { return } -func toMcPerc(v1, v2 int64) string { - return toMc(v1) + " (" + strconv.Itoa(client.ToPercentage(v1, v2)) + "%)" -} - -func toMiPerc(v1, v2 int64) string { - return toMi(v1) + " (" + strconv.Itoa(client.ToPercentage(v1, v2)) + "%)" -} - func toMc(v int64) string { if v == 0 { return ZeroValue diff --git a/internal/render/node.go b/internal/render/node.go index 4c1d5419..af59dbb5 100644 --- a/internal/render/node.go +++ b/internal/render/node.go @@ -10,7 +10,6 @@ import ( "github.com/derailed/k9s/internal/client" "github.com/derailed/tview" v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -45,10 +44,6 @@ func (Node) Header(_ string) Header { HeaderColumn{Name: "MEM", Align: tview.AlignRight, MX: true}, HeaderColumn{Name: "%CPU", Align: tview.AlignRight, MX: true}, HeaderColumn{Name: "%MEM", Align: tview.AlignRight, MX: true}, - HeaderColumn{Name: "CPU/R", Align: tview.AlignRight, MX: true}, - HeaderColumn{Name: "CPU/L", Align: tview.AlignRight, MX: true}, - HeaderColumn{Name: "MEM/R", Align: tview.AlignRight, MX: true}, - HeaderColumn{Name: "MEM/L", Align: tview.AlignRight, MX: true}, HeaderColumn{Name: "CPU/A", Align: tview.AlignRight, MX: true}, HeaderColumn{Name: "MEM/A", Align: tview.AlignRight, MX: true}, HeaderColumn{Name: "LABELS", Wide: true}, @@ -78,16 +73,6 @@ func (n Node) Render(o interface{}, ns string, r *Row) error { iIP, eIP = missing(iIP), missing(eIP) c, p, a := gatherNodeMX(&no, oo.MX) - trc, trm, tlc, tlm := new(resource.Quantity), new(resource.Quantity), new(resource.Quantity), new(resource.Quantity) - for _, p := range oo.Pods { - rcpu, rmem := podRequests(p.Spec) - trc.Add(rcpu) - trm.Add(rmem) - - lcpu, lmem := podLimits(p.Spec) - tlc.Add(lcpu) - tlm.Add(lmem) - } statuses := make(sort.StringSlice, 10) status(no.Status.Conditions, no.Spec.Unschedulable, statuses) sort.Sort(statuses) @@ -109,10 +94,6 @@ func (n Node) Render(o interface{}, ns string, r *Row) error { toMi(c.mem), strconv.Itoa(p.rCPU()), strconv.Itoa(p.rMEM()), - toMcPerc(trc.MilliValue(), a.cpu), - toMcPerc(tlc.MilliValue(), a.cpu), - toMiPerc(trm.Value(), a.mem), - toMiPerc(tlm.Value(), a.mem), toMc(a.cpu), toMi(a.mem), mapToStr(no.Labels), diff --git a/internal/render/node_test.go b/internal/render/node_test.go index 163963c2..90986827 100644 --- a/internal/render/node_test.go +++ b/internal/render/node_test.go @@ -21,8 +21,8 @@ func TestNodeRender(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "minikube", r.ID) - e := render.Fields{"minikube", "Ready", "master", "v1.15.2", "4.15.0", "192.168.64.107", "", "0", "10", "20", "0", "0", "0 (0%)", "0 (0%)", "0 (0%)", "0 (0%)", "4000", "7874"} - assert.Equal(t, e, r.Fields[:18]) + e := render.Fields{"minikube", "Ready", "master", "v1.15.2", "4.15.0", "192.168.64.107", "", "0", "10", "20", "0", "0", "4000", "7874"} + assert.Equal(t, e, r.Fields[:14]) } func BenchmarkNodeRender(b *testing.B) { diff --git a/internal/view/cluster_info.go b/internal/view/cluster_info.go index 2cf17122..53f44039 100644 --- a/internal/view/cluster_info.go +++ b/internal/view/cluster_info.go @@ -4,12 +4,14 @@ import ( "fmt" "os" + "github.com/derailed/k9s/internal/client" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/model" "github.com/derailed/k9s/internal/render" "github.com/derailed/k9s/internal/ui" "github.com/derailed/tview" "github.com/gdamore/tcell" + "github.com/rs/zerolog/log" ) var _ model.ClusterInfoListener = (*ClusterInfo)(nil) @@ -46,9 +48,22 @@ func (c *ClusterInfo) StylesChanged(s *config.Styles) { c.updateStyle() } +func (c *ClusterInfo) hasMetrics() bool { + mx := c.app.Conn().HasMetrics() + if mx { + auth, err := c.app.Conn().CanI("", "metrics.k8s.io/v1beta1/nodes", client.ListAccess) + if err != nil { + log.Warn().Err(err).Msgf("No nodes metrics access") + } + mx = auth + } + + return mx +} + func (c *ClusterInfo) layout() { for row, section := range []string{"Context", "Cluster", "User", "K9s Rev", "K8s Rev", "CPU", "MEM"} { - if (section == "CPU" || section == "MEM") && !c.app.Conn().HasMetrics() { + if (section == "CPU" || section == "MEM") && !c.hasMetrics() { continue } c.SetCell(row, 0, c.sectionCell(section)) @@ -96,7 +111,7 @@ func (c *ClusterInfo) ClusterInfoChanged(prev, curr model.ClusterMeta) { row = c.setCell(row, curr.User) row = c.setCell(row, fmt.Sprintf("%s [%d]", curr.K9sVer, os.Getpid())) row = c.setCell(row, curr.K8sVer) - if c.app.Conn().HasMetrics() { + if c.hasMetrics() { row = c.setCell(row, ui.AsPercDelta(prev.Cpu, curr.Cpu)) _ = c.setCell(row, ui.AsPercDelta(prev.Mem, curr.Mem)) c.setDefCon(curr.Cpu, curr.Mem)