Merge branch 'master' of github.com-derailed:derailed/k9s
commit
4c0b02e9d2
|
|
@ -198,7 +198,7 @@ This defines a plugin for viewing logs on a selected pod using `CtrlL` mnemonic.
|
||||||
|
|
||||||
The shortcut option represents the command a user would type to activate the plugin. The command represents adhoc commands the plugin runs upon activation. The scopes defines a collection of views shortnames for which the plugin shortcut will be made available to the user.
|
The shortcut option represents the command a user would type to activate the plugin. The command represents adhoc commands the plugin runs upon activation. The scopes defines a collection of views shortnames for which the plugin shortcut will be made available to the user.
|
||||||
|
|
||||||
K9s does provide additional enviroment variables for you to customize your plugins. Currently the available environment are as follows:
|
K9s does provide additional environment variables for you to customize your plugins. Currently, the available environment variables are as follows:
|
||||||
|
|
||||||
* `$NAMESPACE` -- the selected resource namespace
|
* `$NAMESPACE` -- the selected resource namespace
|
||||||
* `$NAME` -- the selected resource name
|
* `$NAME` -- the selected resource name
|
||||||
|
|
@ -215,9 +215,9 @@ NOTE: This is an experimental feature! Options and layout may change in future K
|
||||||
|
|
||||||
## Benchmarking
|
## Benchmarking
|
||||||
|
|
||||||
K9s integrates [Hey](https://github.com/rakyll/hey) from the brilliant and super talented [Jaana Dogan](https://github.com/rakyll) of Google fame. Hey is a CLI tool to benchmak HTTP endpoints similar to AB bench. This preliminary feature currently supports benchmarking port-forwards and services (Read the paint on this is way fresh!).
|
K9s integrates [Hey](https://github.com/rakyll/hey) from the brilliant and super talented [Jaana Dogan](https://github.com/rakyll) of Google fame. Hey is a CLI tool to benchmark HTTP endpoints similar to AB bench. This preliminary feature currently supports benchmarking port-forwards and services (Read the paint on this is way fresh!).
|
||||||
|
|
||||||
To setup a port-forward, you will need to navigate to the PodView, select a pod and a container that exposes a given port. Using `SHIFT-F` a dialog comes up to allow you to specify a local port to forward. Once acknowledged, you can navigate to the PortForward view (alias `pf`) listing out you active port-forwards. Selecting a port-forward and using `CTRL-B` will run a benchmark on that HTTP endpoint. To view the results of your benchmark runs, go to the Benchmarks view (alias `be`). You should now be able to select a benchmark and view the run stats details by pressing `<ENTER>`. NOTE: Port-forwards only last for the duration of the K9s session and will be terminated upon exit.
|
To setup a port-forward, you will need to navigate to the PodView, select a pod and a container that exposes a given port. Using `SHIFT-F` a dialog comes up to allow you to specify a local port to forward. Once acknowledged, you can navigate to the PortForward view (alias `pf`) listing out your active port-forwards. Selecting a port-forward and using `CTRL-B` will run a benchmark on that HTTP endpoint. To view the results of your benchmark runs, go to the Benchmarks view (alias `be`). You should now be able to select a benchmark and view the run stats details by pressing `<ENTER>`. NOTE: Port-forwards only last for the duration of the K9s session and will be terminated upon exit.
|
||||||
|
|
||||||
Initially, the benchmarks will run with the following defaults:
|
Initially, the benchmarks will run with the following defaults:
|
||||||
|
|
||||||
|
|
@ -279,7 +279,7 @@ benchmarks:
|
||||||
|
|
||||||
## K9s RBAC FU
|
## K9s RBAC FU
|
||||||
|
|
||||||
On RBAC enabled clusters, you would need to give your users/groups capabilities so that they can use K9s to explore their Kubernetes cluster. K9s needs minimaly read privileges at both the cluster and namespace level to display resources and metrics.
|
On RBAC enabled clusters, you would need to give your users/groups capabilities so that they can use K9s to explore their Kubernetes cluster. K9s needs minimally read privileges at both the cluster and namespace level to display resources and metrics.
|
||||||
|
|
||||||
These rules below are just suggestions. You will need to customize them based on your environment policies. If you need to edit/delete resources extra Fu will be necessary.
|
These rules below are just suggestions. You will need to customize them based on your environment policies. If you need to edit/delete resources extra Fu will be necessary.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ func printInfo() {
|
||||||
const sectionFmt = "%-15s "
|
const sectionFmt = "%-15s "
|
||||||
|
|
||||||
printLogo(color.Cyan)
|
printLogo(color.Cyan)
|
||||||
printTuple(sectionFmt, "Configuration", config.K9sConfigFile)
|
printTuple(sectionFmt, "Configuration", config.K9sConfigFile, color.Cyan)
|
||||||
printTuple(sectionFmt, "Logs", config.K9sLogs)
|
printTuple(sectionFmt, "Logs", config.K9sLogs, color.Cyan)
|
||||||
printTuple(sectionFmt, "Screen Dumps", config.K9sDumpDir)
|
printTuple(sectionFmt, "Screen Dumps", config.K9sDumpDir, color.Cyan)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printLogo(c color.Paint) {
|
func printLogo(c color.Paint) {
|
||||||
|
|
|
||||||
|
|
@ -8,26 +8,41 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func versionCmd() *cobra.Command {
|
func versionCmd() *cobra.Command {
|
||||||
return &cobra.Command{
|
var short bool
|
||||||
|
|
||||||
|
command := cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print version/build info",
|
Short: "Print version/build info",
|
||||||
Long: "Print version/build information",
|
Long: "Print version/build information",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
printVersion()
|
printVersion(short)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command.PersistentFlags().BoolVarP(&short, "short", "s", false, "Prints K9s version info in short format")
|
||||||
|
|
||||||
|
return &command
|
||||||
}
|
}
|
||||||
|
|
||||||
func printVersion() {
|
func printVersion(short bool) {
|
||||||
const secFmt = "%-10s "
|
const secFmt = "%-10s "
|
||||||
|
var outputColor color.Paint
|
||||||
|
|
||||||
printLogo(color.Cyan)
|
if short {
|
||||||
printTuple(secFmt, "Version", version)
|
outputColor = -1
|
||||||
printTuple(secFmt, "Commit", commit)
|
} else {
|
||||||
printTuple(secFmt, "Date", date)
|
outputColor = color.Cyan
|
||||||
|
printLogo(outputColor)
|
||||||
|
}
|
||||||
|
printTuple(secFmt, "Version", version, outputColor)
|
||||||
|
printTuple(secFmt, "Commit", commit, outputColor)
|
||||||
|
printTuple(secFmt, "Date", date, outputColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printTuple(format, section, value string) {
|
func printTuple(format, section, value string, outputColor color.Paint) {
|
||||||
fmt.Printf(color.Colorize(fmt.Sprintf(format, section+":"), color.Cyan))
|
if outputColor != -1 {
|
||||||
fmt.Println(color.Colorize(value, color.White))
|
section = color.Colorize(fmt.Sprintf(section+":"), outputColor)
|
||||||
|
value = color.Colorize(value, color.White)
|
||||||
|
}
|
||||||
|
fmt.Println(fmt.Sprintf(format, section), value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package watch
|
package watch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -112,6 +113,7 @@ func (n *nodeMxWatcher) Run() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-n.doneChan:
|
case <-n.doneChan:
|
||||||
|
close(n.eventChan)
|
||||||
return
|
return
|
||||||
case <-time.After(nodeMXRefresh):
|
case <-time.After(nodeMXRefresh):
|
||||||
list, err := c.MetricsV1beta1().NodeMetricses().List(metav1.ListOptions{})
|
list, err := c.MetricsV1beta1().NodeMetricses().List(metav1.ListOptions{})
|
||||||
|
|
@ -127,7 +129,6 @@ func (n *nodeMxWatcher) Run() {
|
||||||
func (n *nodeMxWatcher) Stop() {
|
func (n *nodeMxWatcher) Stop() {
|
||||||
log.Debug().Msg("Stopping NodeMetrix informer!")
|
log.Debug().Msg("Stopping NodeMetrix informer!")
|
||||||
close(n.doneChan)
|
close(n.doneChan)
|
||||||
close(n.eventChan)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResultChan retrieves event channel.
|
// ResultChan retrieves event channel.
|
||||||
|
|
@ -135,6 +136,15 @@ func (n *nodeMxWatcher) ResultChan() <-chan watch.Event {
|
||||||
return n.eventChan
|
return n.eventChan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *nodeMxWatcher) notify(event watch.Event) error {
|
||||||
|
select {
|
||||||
|
case n.eventChan <- event:
|
||||||
|
return nil
|
||||||
|
case <-n.doneChan:
|
||||||
|
return errors.New("watcher has ben closed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *nodeMxWatcher) update(list *mv1beta1.NodeMetricsList, notify bool) {
|
func (n *nodeMxWatcher) update(list *mv1beta1.NodeMetricsList, notify bool) {
|
||||||
fqns := map[string]runtime.Object{}
|
fqns := map[string]runtime.Object{}
|
||||||
for i := range list.Items {
|
for i := range list.Items {
|
||||||
|
|
@ -144,9 +154,8 @@ func (n *nodeMxWatcher) update(list *mv1beta1.NodeMetricsList, notify bool) {
|
||||||
for k, v := range n.cache {
|
for k, v := range n.cache {
|
||||||
if _, ok := fqns[k]; !ok {
|
if _, ok := fqns[k]; !ok {
|
||||||
if notify {
|
if notify {
|
||||||
n.eventChan <- watch.Event{
|
if err := n.notify(watch.Event{Type: watch.Deleted, Object: v}); err != nil {
|
||||||
Type: watch.Deleted,
|
return
|
||||||
Object: v,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(n.cache, k)
|
delete(n.cache, k)
|
||||||
|
|
@ -161,7 +170,9 @@ func (n *nodeMxWatcher) update(list *mv1beta1.NodeMetricsList, notify bool) {
|
||||||
kind = watch.Modified
|
kind = watch.Modified
|
||||||
}
|
}
|
||||||
if notify {
|
if notify {
|
||||||
n.eventChan <- watch.Event{Type: kind, Object: v}
|
if err := n.notify(watch.Event{Type: kind, Object: v}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
n.cache[k] = v
|
n.cache[k] = v
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package watch
|
package watch
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -124,6 +125,7 @@ func (p *podMxWatcher) Run() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-p.doneChan:
|
case <-p.doneChan:
|
||||||
|
close(p.eventChan)
|
||||||
return
|
return
|
||||||
case <-time.After(podMXRefresh):
|
case <-time.After(podMXRefresh):
|
||||||
list, err := c.MetricsV1beta1().PodMetricses(p.ns).List(metav1.ListOptions{})
|
list, err := c.MetricsV1beta1().PodMetricses(p.ns).List(metav1.ListOptions{})
|
||||||
|
|
@ -135,6 +137,15 @@ func (p *podMxWatcher) Run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *podMxWatcher) notify(event watch.Event) error {
|
||||||
|
select {
|
||||||
|
case p.eventChan <- event:
|
||||||
|
return nil
|
||||||
|
case <-p.doneChan:
|
||||||
|
return errors.New("watcher has ben closed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *podMxWatcher) update(list *mv1beta1.PodMetricsList, notify bool) {
|
func (p *podMxWatcher) update(list *mv1beta1.PodMetricsList, notify bool) {
|
||||||
fqns := map[string]runtime.Object{}
|
fqns := map[string]runtime.Object{}
|
||||||
for i := range list.Items {
|
for i := range list.Items {
|
||||||
|
|
@ -145,9 +156,8 @@ func (p *podMxWatcher) update(list *mv1beta1.PodMetricsList, notify bool) {
|
||||||
for k, v := range p.cache {
|
for k, v := range p.cache {
|
||||||
if _, ok := fqns[k]; !ok {
|
if _, ok := fqns[k]; !ok {
|
||||||
if notify {
|
if notify {
|
||||||
p.eventChan <- watch.Event{
|
if err := p.notify(watch.Event{Type: watch.Deleted, Object: v}); err != nil {
|
||||||
Type: watch.Deleted,
|
return
|
||||||
Object: v,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete(p.cache, k)
|
delete(p.cache, k)
|
||||||
|
|
@ -163,7 +173,9 @@ func (p *podMxWatcher) update(list *mv1beta1.PodMetricsList, notify bool) {
|
||||||
kind = watch.Modified
|
kind = watch.Modified
|
||||||
}
|
}
|
||||||
if notify {
|
if notify {
|
||||||
p.eventChan <- watch.Event{Type: kind, Object: v}
|
if err := p.notify(watch.Event{Type: kind, Object: v}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.cache[k] = v
|
p.cache[k] = v
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +185,6 @@ func (p *podMxWatcher) update(list *mv1beta1.PodMetricsList, notify bool) {
|
||||||
func (p *podMxWatcher) Stop() {
|
func (p *podMxWatcher) Stop() {
|
||||||
log.Debug().Msg("Stopping PodMetrix informer!!")
|
log.Debug().Msg("Stopping PodMetrix informer!!")
|
||||||
close(p.doneChan)
|
close(p.doneChan)
|
||||||
close(p.eventChan)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResultChan retrieves event channel.
|
// ResultChan retrieves event channel.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue