clean up and bugs fix
parent
372b4d8e09
commit
c4fcecf7e7
|
|
@ -10,6 +10,7 @@ dist
|
||||||
notes
|
notes
|
||||||
vendor
|
vendor
|
||||||
go.mod1
|
go.mod1
|
||||||
|
go.mod2
|
||||||
gen.sh
|
gen.sh
|
||||||
*.test
|
*.test
|
||||||
*.log
|
*.log
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,14 @@ On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_inv
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ♫ Sound Behind The Release ♭
|
## ♫ Sounds Behind The Release ♭
|
||||||
|
|
||||||
I figured why not share one of the tunes I was spinning when powering thru teh bugs? Might as well share the pain/pleasure while viewing this release notes!
|
I figured why not share one of the tunes I was spinning when powering thru teh bugs? Might as well share the pain/pleasure while viewing these release notes!
|
||||||
|
|
||||||
[On An Island - David Gilmour With Crosby&Nash](https://www.youtube.com/watch?v=kEa__0wtIRo)
|
* [On An Island - David Gilmour With Crosby&Nash](https://www.youtube.com/watch?v=kEa__0wtIRo)
|
||||||
|
* [Cause We've Ended As Lovers - Jeff Beck](https://www.youtube.com/watch?v=VC02wGj5gPw)
|
||||||
|
* [La Maitresse D'Ecole - Maxime Le Forestier](https://www.youtube.com/watch?v=eE2-cv7taPo)
|
||||||
|
* [Three Wishes - Roger Waters](https://www.youtube.com/watch?v=fVw1N6wyo4c)
|
||||||
|
|
||||||
## Our Release Heroes...
|
## Our Release Heroes...
|
||||||
|
|
||||||
|
|
@ -24,11 +27,11 @@ Please join me in recognizing and applauding this drop contributors that went th
|
||||||
|
|
||||||
Big ATTA BOY/GIRL! in full effect this week to the good folks below for their efforts and contributions to K9s!!
|
Big ATTA BOY/GIRL! in full effect this week to the good folks below for their efforts and contributions to K9s!!
|
||||||
|
|
||||||
* [Antoine Méausoone](https://github.com/Ameausoone)
|
|
||||||
* [Michael Albers](https://github.com/michaeljohnalbers)
|
* [Michael Albers](https://github.com/michaeljohnalbers)
|
||||||
* [Wi1dcard](https://github.com/wi1dcard)
|
* [Wi1dcard](https://github.com/wi1dcard)
|
||||||
* [Saskia Keil](https://github.com/SaskiaKeil)
|
* [Saskia Keil](https://github.com/SaskiaKeil)
|
||||||
* [Tomasz Lipinski](https://github.com/tlipinski)
|
* [Tomasz Lipinski](https://github.com/tlipinski)
|
||||||
|
* [Antoine Méausoone](https://github.com/Ameausoone)
|
||||||
* [Emeric Martineau](https://github.com/emeric-martineau)
|
* [Emeric Martineau](https://github.com/emeric-martineau)
|
||||||
* [Eldad Assis](https://github.com/eldada)
|
* [Eldad Assis](https://github.com/eldada)
|
||||||
* [David Arnold](https://github.com/blaggacao)
|
* [David Arnold](https://github.com/blaggacao)
|
||||||
|
|
@ -45,29 +48,29 @@ First off I would like to send a `Big Thank You` to the following generous K9s f
|
||||||
* [Matt Welke](https://github.com/mattwelke)
|
* [Matt Welke](https://github.com/mattwelke)
|
||||||
* [Stefan Mikolajczyk](https://github.com/stefanmiko)
|
* [Stefan Mikolajczyk](https://github.com/stefanmiko)
|
||||||
|
|
||||||
Contrarily to popular belief, OSS is not free! We've now reached ~9k stars and 300k downloads! As you all know, this project is not pimped out by a big company with deep pockets. K9s is complex and does demand lots of my time. So if this tool is useful to you and benefits you and your organization in your Kubernetes journey, please contribute! Your contribution whether financial, PRs, issues or shout-outs on social/blogs are crucial to keep K9s growing and powerful for all of us. Don't let OSS by individual contributors become an oxymoron!
|
Contrarily to popular belief, OSS is not free! We've now reached ~9k stars and 300k downloads! As you all know, this project is not pimped out by a big company with deep pockets and a big dev team. K9s is complex and does demand lots of my time. So if this tool is useful to you and your organization and part of your daily Kubernetes flow, please contribute! Your contribution whether financial, PRs, issues or shout-outs on social/blogs are crucial to keep K9s growing and powerful for all of us. Don't let OSS by individual contributors become an oxymoron!
|
||||||
|
|
||||||
## Describe/YAML views goes FullMonty
|
## Describe/YAML goes FullMonty!!
|
||||||
|
|
||||||
We've added a new option to enable full screen while describing or viewing a resource YAML. Similarly to the full screen toggle option in the log view, pressing `f` will now toggle fullscreen for both YAML and Describe views.
|
We've added a new option to enable full screen while describing or viewing a resource YAML. Similarly to the full screen toggle option in the log view, pressing `f` will now toggle full-screen for both YAML and Describe views.
|
||||||
|
|
||||||
Additionally, the YAML and Describe view are now reactive! YAML/Describe views will now watch for changes to the underlying resource manifests. How cool is that?
|
Additionally, the YAML and Describe view are now reactive! YAML/Describe views will now watch for changes to the underlying resource manifests. I'll admit this was a feature I was missing, but decided to punt as it required a bit of re-org to make it happen correctly. So BIG thanks to [Fabian-K](https://github.com/Fabian-K) for entering this issue and for the boost!!
|
||||||
|
|
||||||
Not cool enough for Ya? the YAML view also affords for getting ride of those pesky `managedFields` while viewing a resource. Pressing `m` will toggle visibility on these fields.
|
Not cool enough for Ya? the YAML view now also affords for getting ride of those pesky `managedFields` while viewing a resource. Use the `m` key to toggle visibility on the managedFields.
|
||||||
|
|
||||||
## Best Effort... Not!
|
## Best Effort... Not!
|
||||||
|
|
||||||
In this drop, we've added 2 new columns to the Pod/Container views namely `CPU(R:L)` and `MEM(R:L)`. These represents the current request:limit resources specified at either the pod or container level. While in Pod view, you will need to use the `Go Wide` option `Ctrl-W` to see the resources set at the pod level. You can also leverage K9s [Custom Column](https://github.com/derailed/k9s#resource-custom-columns) feature to volunteer them while in Pod view. In the Container view these columns will be available by default.
|
In this drop, we've added 2 new columns namely `CPU/R:L` and `MEM/R:L`. These represents the current request:limit specified on containers. They are available in node, pod and container views. While in Pod view, you will need to volunteer them and use the `Go Wide` option `Ctrl-W` to see the columns. These columns will be display by default for Node/Container views. In the node view, they tally the total amount of resources for all pods hosted a given node. If that's inadequate, you can also leverage K9s [Custom Column](https://github.com/derailed/k9s#resource-custom-columns) feature to volunteer them or not.
|
||||||
|
|
||||||
## Set Container Images
|
## Set Container Images
|
||||||
|
|
||||||
You have now the ability to tweak your container images for experimentation, using the new SetImage binding aka `i`. This feature is available for unmanaged pods, deployments, sts and ds. With a resource selected, pressing `i` will provision an edit dialog listing all init/container images.
|
You will have the ability to tweak your container images for experimentation, using the new SetImage binding aka `i`. This feature is available for un-managed pods, deployments, statefulsets and daemonsets. With a resource selected, pressing `i` will provision an edit dialog listing all init/container images. So you will have to ability to tweak the images and update your containers. Big Thanks to [Antoine Méausoone](https://github.com/Ameausoone) for making this feature available to all of us!!
|
||||||
|
|
||||||
NOTE! This is a one shot commands applied directly against your cluster and won't survive a new resource deployment.
|
NOTE! This is a one shot commands applied directly against your cluster and won't survive a new resource deployment.
|
||||||
|
|
||||||
## Crumbs On, Crumbs Off, Caterpillar
|
## Crumbs On...Crumbs Off, Caterpillar
|
||||||
|
|
||||||
We've added a new configuration to turn off the crumbs via `crumbsLess` configuration option. You can also toggle the crumbs via the new key option `C`. You can enable/disable this option in your ~/.k9s/config.yml or via command line using `--crumbsless` CLI option.
|
We've added a new configuCCration to turn off the crumbs via `crumbsLess` configuration option. You can also toggle the crumbs via the new key option `Ctrl-g`. You can enable/disable this option in your ~/.k9s/config.yml or via command line using `--crumbsless` CLI option.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
k9s:
|
k9s:
|
||||||
|
|
@ -80,7 +83,30 @@ k9s:
|
||||||
|
|
||||||
## BANG FILTERS!
|
## BANG FILTERS!
|
||||||
|
|
||||||
Some folks have voiced the desire to use inverse filters to refine content while in resource table views. Prepending a `!` to your filter will now enable an inverse filtering operation For example, in order to see all pods that do not contain `fred` in their name, you can now use `/!fred` as your filtering command.
|
Some folks have voiced the desire to use inverse filters to refine content while in resource table views. Appending a `!` to your filter will now enable an inverse filtering operation For example, in order to see all pods that do not contain `fred` in their name, you can now use `/!fred` as your filtering command. If you dig this implementation, please make sure to give a big thank you to [Michael Albers](https://github.com/michaeljohnalbers) for the swift implementation!
|
||||||
|
|
||||||
|
## New Conf On the Block...
|
||||||
|
|
||||||
|
In this release, we've made some changes to the retry policies when things fail on your cluster and the api-server is suffering from an hearing impediment. The current policy was to check for connection issues every 15secs and retry 15 times before exiting K9s. This rules were not configurable and could yield for overtaxing the api-server. So we've implemented exponential back-off so that K9s can attempt to remediate or bail out of the session if not.
|
||||||
|
To this end, there is a new config option namely `maxConnRetry` to will be added to your K9s config to set the retry policy. The default is currently set to 5 retries.
|
||||||
|
|
||||||
|
NOTE: This is likely an ongoing story and more will come based on your feedback!
|
||||||
|
|
||||||
|
Sample K9s configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
k9s:
|
||||||
|
refreshRate: 2
|
||||||
|
# Set the maximum attempt to reconnect with the api-server in case of failures.
|
||||||
|
maxConnRetry: 5
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## And That's A Wrap!
|
||||||
|
|
||||||
|
As you can see, this is a pretty big drop and likely we've created some new issues in the process. Please make sure to file issues/PRs if things are not working as expected so we can improve on these features.
|
||||||
|
|
||||||
|
Thank you all for your continued excitement and support for K9s!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
24
cmd/root.go
24
cmd/root.go
|
|
@ -3,7 +3,6 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
|
|
@ -45,17 +44,22 @@ func init() {
|
||||||
initK9sFlags()
|
initK9sFlags()
|
||||||
initK8sFlags()
|
initK8sFlags()
|
||||||
|
|
||||||
// Klogs (of course) want to print stuff to the screen ;(
|
var flags flag.FlagSet
|
||||||
klog.InitFlags(nil)
|
klog.InitFlags(&flags)
|
||||||
klog.SetOutput(ioutil.Discard)
|
if err := flags.Set("logtostderr", "false"); err != nil {
|
||||||
if err := flag.Set("stderrthreshold", "fatal"); err != nil {
|
panic(err)
|
||||||
log.Error().Err(err)
|
|
||||||
}
|
}
|
||||||
if err := flag.Set("alsologtostderr", "false"); err != nil {
|
if err := flags.Set("alsologtostderr", "false"); err != nil {
|
||||||
log.Error().Err(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if err := flag.Set("logtostderr", "false"); err != nil {
|
if err := flags.Set("stderrthreshold", "fatal"); err != nil {
|
||||||
log.Error().Err(err)
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := flags.Set("v", "0"); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := flags.Set("log_file", config.K9sLogs); err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
6
go.mod
6
go.mod
|
|
@ -10,9 +10,9 @@ require (
|
||||||
github.com/derailed/tview v0.4.6
|
github.com/derailed/tview v0.4.6
|
||||||
github.com/drone/envsubst v1.0.2 // indirect
|
github.com/drone/envsubst v1.0.2 // indirect
|
||||||
github.com/fatih/color v1.9.0
|
github.com/fatih/color v1.9.0
|
||||||
github.com/fsnotify/fsnotify v1.4.7
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/fvbommel/sortorder v1.0.1
|
github.com/fvbommel/sortorder v1.0.2
|
||||||
github.com/gdamore/tcell v1.3.0
|
github.com/gdamore/tcell v1.4.0
|
||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/golang/protobuf v1.4.2 // indirect
|
github.com/golang/protobuf v1.4.2 // indirect
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
|
|
|
||||||
7
go.sum
7
go.sum
|
|
@ -229,6 +229,8 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
|
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
|
||||||
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
|
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||||
|
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko=
|
||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
|
|
@ -236,6 +238,8 @@ github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo
|
||||||
github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8uzurE=
|
github.com/gdamore/tcell v1.1.2/go.mod h1:h3kq4HO9l2On+V9ed8w8ewqQEmGCSSHOgQ+2h8uzurE=
|
||||||
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
|
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
|
||||||
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
|
||||||
|
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
|
||||||
|
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
|
@ -463,6 +467,8 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
|
||||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
|
||||||
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
|
@ -485,6 +491,7 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA
|
||||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/mattn/go-runewidth v0.0.5/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.5/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
|
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||||
|
|
|
||||||
|
|
@ -179,13 +179,27 @@ func (a *APIClient) CurrentNamespaceName() (string, error) {
|
||||||
return a.config.CurrentNamespaceName()
|
return a.config.CurrentNamespaceName()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const serverVersion = "serverVersion"
|
||||||
|
|
||||||
// ServerVersion returns the current server version info.
|
// ServerVersion returns the current server version info.
|
||||||
func (a *APIClient) ServerVersion() (*version.Info, error) {
|
func (a *APIClient) ServerVersion() (*version.Info, error) {
|
||||||
|
if v, ok := a.cache.Get(serverVersion); ok {
|
||||||
|
if version, ok := v.(*version.Info); ok {
|
||||||
|
return version, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
dial, err := a.CachedDiscovery()
|
dial, err := a.CachedDiscovery()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return dial.ServerVersion()
|
|
||||||
|
info, err := dial.ServerVersion()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
a.cache.Add(serverVersion, info, cacheExpiry)
|
||||||
|
|
||||||
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidNamespaces returns all available namespaces.
|
// ValidNamespaces returns all available namespaces.
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ func AccessorFor(f Factory, gvr client.GVR) (Accessor, error) {
|
||||||
r, ok := m[gvr]
|
r, ok := m[gvr]
|
||||||
if !ok {
|
if !ok {
|
||||||
r = &Generic{}
|
r = &Generic{}
|
||||||
log.Debug().Msgf("No DAO registry entry for %q. Using factory!", gvr)
|
log.Debug().Msgf("No DAO registry entry for %q. Using generics!", gvr)
|
||||||
}
|
}
|
||||||
r.Init(f, gvr)
|
r.Init(f, gvr)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BOZO!! Figure out how to convert to table def and use factory.
|
||||||
|
|
||||||
// Table retrieves K8s resources as tabular data.
|
// Table retrieves K8s resources as tabular data.
|
||||||
type Table struct {
|
type Table struct {
|
||||||
Generic
|
Generic
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,21 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
"github.com/derailed/k9s/internal/dao"
|
"github.com/derailed/k9s/internal/dao"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/cache"
|
||||||
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
clusterCacheSize = 100
|
||||||
|
clusterCacheExpiry = 1 * time.Minute
|
||||||
|
clusterNodesKey = "nodes"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
// MetricsServer gather metrics information from pods and nodes.
|
// MetricsServer gather metrics information from pods and nodes.
|
||||||
MetricsServer interface {
|
MetricsServer interface {
|
||||||
|
|
@ -30,6 +38,7 @@ type (
|
||||||
Cluster struct {
|
Cluster struct {
|
||||||
factory dao.Factory
|
factory dao.Factory
|
||||||
mx MetricsServer
|
mx MetricsServer
|
||||||
|
cache *cache.LRUExpireCache
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -38,6 +47,7 @@ func NewCluster(f dao.Factory) *Cluster {
|
||||||
return &Cluster{
|
return &Cluster{
|
||||||
factory: f,
|
factory: f,
|
||||||
mx: client.DialMetrics(f.Client()),
|
mx: client.DialMetrics(f.Client()),
|
||||||
|
cache: cache.NewLRUExpireCache(clusterCacheSize),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,11 +90,21 @@ func (c *Cluster) UserName() string {
|
||||||
|
|
||||||
// Metrics gathers node level metrics and compute utilization percentages.
|
// Metrics gathers node level metrics and compute utilization percentages.
|
||||||
func (c *Cluster) Metrics(ctx context.Context, mx *client.ClusterMetrics) error {
|
func (c *Cluster) Metrics(ctx context.Context, mx *client.ClusterMetrics) error {
|
||||||
nn, err := dao.FetchNodes(ctx, c.factory, "")
|
var nn *v1.NodeList
|
||||||
|
if n, ok := c.cache.Get(clusterNodesKey); ok {
|
||||||
|
if nodes, ok := n.(*v1.NodeList); ok {
|
||||||
|
nn = nodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if nn == nil {
|
||||||
|
nn, err = dao.FetchNodes(ctx, c.factory, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
c.cache.Add(clusterNodesKey, nn, clusterCacheExpiry)
|
||||||
nmx, err := c.mx.FetchNodesMetrics(ctx)
|
nmx, err := c.mx.FetchNodesMetrics(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -124,11 +124,9 @@ func (d *Describe) updater(ctx context.Context) {
|
||||||
return
|
return
|
||||||
case <-time.After(delay):
|
case <-time.After(delay):
|
||||||
if err := d.refresh(ctx); err != nil {
|
if err := d.refresh(ctx); err != nil {
|
||||||
log.Error().Err(err).Msgf("Describe Failed")
|
|
||||||
d.fireResourceFailed(err)
|
d.fireResourceFailed(err)
|
||||||
delay = backOff.NextBackOff()
|
if delay = backOff.NextBackOff(); delay == backoff.Stop {
|
||||||
if delay == backoff.Stop {
|
log.Error().Err(err).Msgf("Describe gave up!")
|
||||||
log.Error().Err(err).Msgf("Describe done Retrying bailing out!")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -139,7 +137,6 @@ func (d *Describe) updater(ctx context.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (d *Describe) refresh(ctx context.Context) error {
|
func (d *Describe) refresh(ctx context.Context) error {
|
||||||
log.Debug().Msgf("DESCRefresh %v", time.Now())
|
|
||||||
if !atomic.CompareAndSwapInt32(&d.inUpdate, 0, 1) {
|
if !atomic.CompareAndSwapInt32(&d.inUpdate, 0, 1) {
|
||||||
log.Debug().Msgf("Dropping update...")
|
log.Debug().Msgf("Dropping update...")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -135,11 +135,9 @@ func (y *YAML) updater(ctx context.Context) {
|
||||||
return
|
return
|
||||||
case <-time.After(delay):
|
case <-time.After(delay):
|
||||||
if err := y.refresh(ctx); err != nil {
|
if err := y.refresh(ctx); err != nil {
|
||||||
log.Error().Err(err).Msgf("YAML Failed")
|
|
||||||
y.fireResourceFailed(err)
|
y.fireResourceFailed(err)
|
||||||
delay = backOff.NextBackOff()
|
if delay = backOff.NextBackOff(); delay == backoff.Stop {
|
||||||
if delay == backoff.Stop {
|
log.Error().Err(err).Msgf("YAML gave up!")
|
||||||
log.Error().Err(err).Msgf("YAML done Retrying bailing out!")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -151,7 +149,6 @@ func (y *YAML) updater(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *YAML) refresh(ctx context.Context) error {
|
func (y *YAML) refresh(ctx context.Context) error {
|
||||||
log.Debug().Msgf("YAMLRefresh %v", time.Now())
|
|
||||||
if !atomic.CompareAndSwapInt32(&y.inUpdate, 0, 1) {
|
if !atomic.CompareAndSwapInt32(&y.inUpdate, 0, 1) {
|
||||||
log.Debug().Msgf("Dropping update...")
|
log.Debug().Msgf("Dropping update...")
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ func TestPodColorer(t *testing.T) {
|
||||||
func TestPodRender(t *testing.T) {
|
func TestPodRender(t *testing.T) {
|
||||||
pom := render.PodWithMetrics{
|
pom := render.PodWithMetrics{
|
||||||
Raw: load(t, "po"),
|
Raw: load(t, "po"),
|
||||||
MX: makePodMX("nginx", "10m", "10Mi"),
|
MX: makePodMX("nginx", "100m", "50Mi"),
|
||||||
}
|
}
|
||||||
|
|
||||||
var po render.Pod
|
var po render.Pod
|
||||||
|
|
@ -159,7 +159,7 @@ func TestPodRender(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "default/nginx", r.ID)
|
assert.Equal(t, "default/nginx", r.ID)
|
||||||
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Running", "10", "10", "100:0", "70:170", "10", "0", "14", "5", "172.17.0.6", "minikube", "BE"}
|
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Running", "100", "50", "100:0", "70:170", "100", "0", "71", "29", "172.17.0.6", "minikube", "BE"}
|
||||||
assert.Equal(t, e, r.Fields[:17])
|
assert.Equal(t, e, r.Fields[:17])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,9 @@ func (p *Prompt) write(text, suggest string) {
|
||||||
// Event Listener protocol...
|
// Event Listener protocol...
|
||||||
|
|
||||||
// BufferCompleted indicates input was accepted.
|
// BufferCompleted indicates input was accepted.
|
||||||
func (p *Prompt) BufferCompleted(s string) {}
|
func (p *Prompt) BufferCompleted(s string) {
|
||||||
|
p.update(s)
|
||||||
|
}
|
||||||
|
|
||||||
// BufferChanged indicates the buffer was changed.
|
// BufferChanged indicates the buffer was changed.
|
||||||
func (p *Prompt) BufferChanged(s string) {
|
func (p *Prompt) BufferChanged(s string) {
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,6 @@ func (a *App) clusterUpdater(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) refreshCluster() error {
|
func (a *App) refreshCluster() error {
|
||||||
log.Debug().Msgf("Cluster Refresh %v", time.Now())
|
|
||||||
c := a.Content.Top()
|
c := a.Content.Top()
|
||||||
if ok := a.Conn().CheckConnectivity(); ok {
|
if ok := a.Conn().CheckConnectivity(); ok {
|
||||||
if atomic.LoadInt32(&a.conRetry) > 0 {
|
if atomic.LoadInt32(&a.conRetry) > 0 {
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,10 @@ func (h *Help) showGeneral() model.MenuHints {
|
||||||
Mnemonic: "Ctrl-e",
|
Mnemonic: "Ctrl-e",
|
||||||
Description: "Toggle Header",
|
Description: "Toggle Header",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Mnemonic: "Ctrl-g",
|
||||||
|
Description: "Toggle Crumbs",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Mnemonic: ":q",
|
Mnemonic: ":q",
|
||||||
Description: "Quit",
|
Description: "Quit",
|
||||||
|
|
|
||||||
3
main.go
3
main.go
|
|
@ -17,6 +17,9 @@ func init() {
|
||||||
func main() {
|
func main() {
|
||||||
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
mod := os.O_CREATE | os.O_APPEND | os.O_WRONLY
|
||||||
file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod)
|
file, err := os.OpenFile(config.K9sLogs, mod, config.DefaultFileMod)
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue