diff --git a/change_logs/release_v0.13.7.md b/change_logs/release_v0.13.7.md
new file mode 100644
index 00000000..1fdb5717
--- /dev/null
+++ b/change_logs/release_v0.13.7.md
@@ -0,0 +1,32 @@
+
+
+# Release v0.13.7
+
+## 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)
+
+On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM)
+
+---
+
+### GH Sponsorships
+
+WOOT!! Big Thank you in this release to [Matthew Davis](https://github.com/mateothegreat) for your contributions and support for K9s!
+Duly noted and so much appreciated!!
+
+---
+
+## Resolved Bugs/Features/PRs
+
+* [Issue #520](https://github.com/derailed/k9s/issues/520)
+* [Issue #518](https://github.com/derailed/k9s/issues/518)
+* [Issue #517](https://github.com/derailed/k9s/issues/517)
+* [Issue #516](https://github.com/derailed/k9s/issues/516)
+* [Issue #506](https://github.com/derailed/k9s/issues/506)
+
+---
+
+
© 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
diff --git a/internal/client/client.go b/internal/client/client.go
index 7669a86e..7c287284 100644
--- a/internal/client/client.go
+++ b/internal/client/client.go
@@ -22,23 +22,25 @@ import (
)
const (
- cacheSize = 100
- cacheExpiry = 5 * time.Minute
- cacheMXKey = "metrics"
+ cacheSize = 100
+ cacheExpiry = 5 * time.Minute
+ cacheMXKey = "metrics"
+ checkConnTimeout = 10 * time.Second
)
var supportedMetricsAPIVersions = []string{"v1beta1"}
// APIClient represents a Kubernetes api client.
type APIClient struct {
- client kubernetes.Interface
- dClient dynamic.Interface
- nsClient dynamic.NamespaceableResourceInterface
- mxsClient *versioned.Clientset
- cachedClient *disk.CachedDiscoveryClient
- config *Config
- mx sync.Mutex
- cache *cache.LRUExpireCache
+ checkClientSet *kubernetes.Clientset
+ client kubernetes.Interface
+ dClient dynamic.Interface
+ nsClient dynamic.NamespaceableResourceInterface
+ mxsClient *versioned.Clientset
+ cachedClient *disk.CachedDiscoveryClient
+ config *Config
+ mx sync.Mutex
+ cache *cache.LRUExpireCache
}
// InitConnectionOrDie initialize connection from command line args.
@@ -134,17 +136,26 @@ func (a *APIClient) CheckConnectivity() (status bool) {
}
}()
- client, ok := a.DialOrDie().(*kubernetes.Clientset)
- if !ok {
- return status
+ if a.checkClientSet == nil {
+ cfg, err := a.config.flags.ToRESTConfig()
+ if err != nil {
+ return
+ }
+ cfg.Timeout = checkConnTimeout
+
+ if a.checkClientSet, err = kubernetes.NewForConfig(cfg); err != nil {
+ log.Error().Err(err).Msgf("Unable to connect to api server")
+ return
+ }
}
- if _, err := client.ServerVersion(); err != nil {
+
+ if _, err := a.checkClientSet.ServerVersion(); err != nil {
log.Error().Err(err).Msgf("K9s can't connect to cluster")
} else {
status = true
}
- return status
+ return
}
// Config return a kubernetes configuration.
diff --git a/internal/client/config.go b/internal/client/config.go
index 1ba0f5f8..bcfec129 100644
--- a/internal/client/config.go
+++ b/internal/client/config.go
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"sync"
- "time"
"github.com/rs/zerolog/log"
v1 "k8s.io/api/core/v1"
@@ -15,9 +14,8 @@ import (
)
const (
- defaultQPS = 100
- defaultBurst = 50
- defaultTimeout = 10 * time.Second
+ defaultQPS = 50
+ defaultBurst = 50
)
// Config tracks a kubernetes configuration.
@@ -289,7 +287,6 @@ func (c *Config) RESTConfig() (*restclient.Config, error) {
}
c.restConfig.QPS = defaultQPS
c.restConfig.Burst = defaultBurst
- c.restConfig.Timeout = defaultTimeout
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
return c.restConfig, nil
diff --git a/internal/dao/pod.go b/internal/dao/pod.go
index cff6cbf3..1258af29 100644
--- a/internal/dao/pod.go
+++ b/internal/dao/pod.go
@@ -249,6 +249,7 @@ func readLogs(ctx context.Context, stream io.ReadCloser, c chan<- string, opts L
c <- opts.DecorateLog(scanner.Text())
}
}
+ log.Error().Msgf("SCAN_ERR %#v", scanner.Err())
}
// ----------------------------------------------------------------------------
diff --git a/internal/model/log.go b/internal/model/log.go
index 7930e083..a632903e 100644
--- a/internal/model/log.go
+++ b/internal/model/log.go
@@ -137,7 +137,9 @@ func (l *Log) load() error {
}
if err := logger.TailLogs(ctx, c, l.logOptions); err != nil {
- l.cancelFn()
+ if l.cancelFn != nil {
+ l.cancelFn()
+ }
close(c)
return err
}
@@ -155,7 +157,7 @@ func (l *Log) Append(line string) {
defer l.mx.Unlock()
if l.initialized {
- l.lines = []string{}
+ l.lines, l.lastSent = []string{}, 0
l.initialized = false
l.fireLogCleared()
}
@@ -175,7 +177,7 @@ func (l *Log) Notify(timedOut bool) {
l.mx.Lock()
defer l.mx.Unlock()
- if timedOut || l.lastSent < len(l.lines) {
+ if timedOut && l.lastSent < len(l.lines) {
l.fireLogBuffChanged(l.lines[l.lastSent:])
l.lastSent = len(l.lines)
}
@@ -224,6 +226,9 @@ func (l *Log) RemoveListener(listener LogsListener) {
}
func applyFilter(q string, lines []string) ([]string, error) {
+ if q == "" {
+ return lines, nil
+ }
indexes, err := filter(q, lines)
if err != nil {
return nil, err
diff --git a/internal/model/log_test.go b/internal/model/log_test.go
index bb3fd6cc..ddb3efcb 100644
--- a/internal/model/log_test.go
+++ b/internal/model/log_test.go
@@ -29,7 +29,7 @@ func TestLogFullBuffer(t *testing.T) {
data = append(data, "line"+strconv.Itoa(i))
m.Append(data[i])
}
- m.Notify(false)
+ m.Notify(true)
assert.Equal(t, 1, v.dataCalled)
assert.Equal(t, 1, v.clearCalled)
diff --git a/internal/view/log.go b/internal/view/log.go
index db1c7c60..fdca9fc1 100644
--- a/internal/view/log.go
+++ b/internal/view/log.go
@@ -57,7 +57,6 @@ func NewLog(gvr client.GVR, path, co string, prev bool) *Log {
// Init initialiazes the viewer.
func (l *Log) Init(ctx context.Context) (err error) {
- log.Debug().Msgf(">>> Logs INIT")
if l.app, err = extractApp(ctx); err != nil {
return err
}
@@ -235,9 +234,6 @@ func (l *Log) write(lines string) {
// Flush write logs to viewer.
func (l *Log) Flush(lines []string) {
- if !l.indicator.AutoScroll() {
- return
- }
l.write(strings.Join(lines, "\n"))
l.indicator.Refresh()
l.logs.ScrollToEnd()
@@ -356,6 +352,11 @@ func (l *Log) textWrapCmd(*tcell.EventKey) *tcell.EventKey {
// ToggleAutoScrollCmd toggles autoscroll status.
func (l *Log) ToggleAutoScrollCmd(evt *tcell.EventKey) *tcell.EventKey {
l.indicator.ToggleAutoScroll()
+ if l.indicator.AutoScroll() {
+ l.model.Start()
+ } else {
+ l.model.Stop()
+ }
return nil
}
diff --git a/internal/view/log_test.go b/internal/view/log_test.go
index 5e4fb84a..bb13df3b 100644
--- a/internal/view/log_test.go
+++ b/internal/view/log_test.go
@@ -34,11 +34,10 @@ func TestLogAutoScroll(t *testing.T) {
v.GetModel().Set([]string{"blee", "bozo"})
v.GetModel().Notify(true)
+ assert.Equal(t, 6, len(v.Hints()))
+
v.ToggleAutoScrollCmd(nil)
assert.Equal(t, " Autoscroll: Off FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
- v.ToggleAutoScrollCmd(nil)
- assert.Equal(t, " Autoscroll: On FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
- assert.Equal(t, 6, len(v.Hints()))
}
func TestLogViewSave(t *testing.T) {