parent
5ebf196fc3
commit
9f36d29dc7
|
|
@ -0,0 +1,32 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<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)
|
||||||
|
|
@ -25,12 +25,14 @@ const (
|
||||||
cacheSize = 100
|
cacheSize = 100
|
||||||
cacheExpiry = 5 * time.Minute
|
cacheExpiry = 5 * time.Minute
|
||||||
cacheMXKey = "metrics"
|
cacheMXKey = "metrics"
|
||||||
|
checkConnTimeout = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
var supportedMetricsAPIVersions = []string{"v1beta1"}
|
var supportedMetricsAPIVersions = []string{"v1beta1"}
|
||||||
|
|
||||||
// APIClient represents a Kubernetes api client.
|
// APIClient represents a Kubernetes api client.
|
||||||
type APIClient struct {
|
type APIClient struct {
|
||||||
|
checkClientSet *kubernetes.Clientset
|
||||||
client kubernetes.Interface
|
client kubernetes.Interface
|
||||||
dClient dynamic.Interface
|
dClient dynamic.Interface
|
||||||
nsClient dynamic.NamespaceableResourceInterface
|
nsClient dynamic.NamespaceableResourceInterface
|
||||||
|
|
@ -134,17 +136,26 @@ func (a *APIClient) CheckConnectivity() (status bool) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
client, ok := a.DialOrDie().(*kubernetes.Clientset)
|
if a.checkClientSet == nil {
|
||||||
if !ok {
|
cfg, err := a.config.flags.ToRESTConfig()
|
||||||
return status
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if _, err := client.ServerVersion(); err != nil {
|
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 := a.checkClientSet.ServerVersion(); err != nil {
|
||||||
log.Error().Err(err).Msgf("K9s can't connect to cluster")
|
log.Error().Err(err).Msgf("K9s can't connect to cluster")
|
||||||
} else {
|
} else {
|
||||||
status = true
|
status = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return status
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config return a kubernetes configuration.
|
// Config return a kubernetes configuration.
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
|
@ -15,9 +14,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultQPS = 100
|
defaultQPS = 50
|
||||||
defaultBurst = 50
|
defaultBurst = 50
|
||||||
defaultTimeout = 10 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config tracks a kubernetes configuration.
|
// Config tracks a kubernetes configuration.
|
||||||
|
|
@ -289,7 +287,6 @@ func (c *Config) RESTConfig() (*restclient.Config, error) {
|
||||||
}
|
}
|
||||||
c.restConfig.QPS = defaultQPS
|
c.restConfig.QPS = defaultQPS
|
||||||
c.restConfig.Burst = defaultBurst
|
c.restConfig.Burst = defaultBurst
|
||||||
c.restConfig.Timeout = defaultTimeout
|
|
||||||
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
|
log.Debug().Msgf("Connecting to API Server %s", c.restConfig.Host)
|
||||||
|
|
||||||
return c.restConfig, nil
|
return c.restConfig, nil
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,7 @@ func readLogs(ctx context.Context, stream io.ReadCloser, c chan<- string, opts L
|
||||||
c <- opts.DecorateLog(scanner.Text())
|
c <- opts.DecorateLog(scanner.Text())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Error().Msgf("SCAN_ERR %#v", scanner.Err())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,9 @@ func (l *Log) load() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := logger.TailLogs(ctx, c, l.logOptions); err != nil {
|
if err := logger.TailLogs(ctx, c, l.logOptions); err != nil {
|
||||||
|
if l.cancelFn != nil {
|
||||||
l.cancelFn()
|
l.cancelFn()
|
||||||
|
}
|
||||||
close(c)
|
close(c)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +157,7 @@ func (l *Log) Append(line string) {
|
||||||
defer l.mx.Unlock()
|
defer l.mx.Unlock()
|
||||||
|
|
||||||
if l.initialized {
|
if l.initialized {
|
||||||
l.lines = []string{}
|
l.lines, l.lastSent = []string{}, 0
|
||||||
l.initialized = false
|
l.initialized = false
|
||||||
l.fireLogCleared()
|
l.fireLogCleared()
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +177,7 @@ func (l *Log) Notify(timedOut bool) {
|
||||||
l.mx.Lock()
|
l.mx.Lock()
|
||||||
defer l.mx.Unlock()
|
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.fireLogBuffChanged(l.lines[l.lastSent:])
|
||||||
l.lastSent = len(l.lines)
|
l.lastSent = len(l.lines)
|
||||||
}
|
}
|
||||||
|
|
@ -224,6 +226,9 @@ func (l *Log) RemoveListener(listener LogsListener) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyFilter(q string, lines []string) ([]string, error) {
|
func applyFilter(q string, lines []string) ([]string, error) {
|
||||||
|
if q == "" {
|
||||||
|
return lines, nil
|
||||||
|
}
|
||||||
indexes, err := filter(q, lines)
|
indexes, err := filter(q, lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ func TestLogFullBuffer(t *testing.T) {
|
||||||
data = append(data, "line"+strconv.Itoa(i))
|
data = append(data, "line"+strconv.Itoa(i))
|
||||||
m.Append(data[i])
|
m.Append(data[i])
|
||||||
}
|
}
|
||||||
m.Notify(false)
|
m.Notify(true)
|
||||||
|
|
||||||
assert.Equal(t, 1, v.dataCalled)
|
assert.Equal(t, 1, v.dataCalled)
|
||||||
assert.Equal(t, 1, v.clearCalled)
|
assert.Equal(t, 1, v.clearCalled)
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ func NewLog(gvr client.GVR, path, co string, prev bool) *Log {
|
||||||
|
|
||||||
// Init initialiazes the viewer.
|
// Init initialiazes the viewer.
|
||||||
func (l *Log) Init(ctx context.Context) (err error) {
|
func (l *Log) Init(ctx context.Context) (err error) {
|
||||||
log.Debug().Msgf(">>> Logs INIT")
|
|
||||||
if l.app, err = extractApp(ctx); err != nil {
|
if l.app, err = extractApp(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -235,9 +234,6 @@ func (l *Log) write(lines string) {
|
||||||
|
|
||||||
// Flush write logs to viewer.
|
// Flush write logs to viewer.
|
||||||
func (l *Log) Flush(lines []string) {
|
func (l *Log) Flush(lines []string) {
|
||||||
if !l.indicator.AutoScroll() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
l.write(strings.Join(lines, "\n"))
|
l.write(strings.Join(lines, "\n"))
|
||||||
l.indicator.Refresh()
|
l.indicator.Refresh()
|
||||||
l.logs.ScrollToEnd()
|
l.logs.ScrollToEnd()
|
||||||
|
|
@ -356,6 +352,11 @@ func (l *Log) textWrapCmd(*tcell.EventKey) *tcell.EventKey {
|
||||||
// ToggleAutoScrollCmd toggles autoscroll status.
|
// ToggleAutoScrollCmd toggles autoscroll status.
|
||||||
func (l *Log) ToggleAutoScrollCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (l *Log) ToggleAutoScrollCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
l.indicator.ToggleAutoScroll()
|
l.indicator.ToggleAutoScroll()
|
||||||
|
if l.indicator.AutoScroll() {
|
||||||
|
l.model.Start()
|
||||||
|
} else {
|
||||||
|
l.model.Stop()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,10 @@ func TestLogAutoScroll(t *testing.T) {
|
||||||
v.GetModel().Set([]string{"blee", "bozo"})
|
v.GetModel().Set([]string{"blee", "bozo"})
|
||||||
v.GetModel().Notify(true)
|
v.GetModel().Notify(true)
|
||||||
|
|
||||||
|
assert.Equal(t, 6, len(v.Hints()))
|
||||||
|
|
||||||
v.ToggleAutoScrollCmd(nil)
|
v.ToggleAutoScrollCmd(nil)
|
||||||
assert.Equal(t, " Autoscroll: Off FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
|
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) {
|
func TestLogViewSave(t *testing.T) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue