Merge branch 'master' of github.com-derailed:derailed/k9s
commit
d4f6700ce1
|
|
@ -316,6 +316,7 @@ Entering the command mode and typing a resource name or alias, could be cumberso
|
||||||
K9s allows you to extend your command line and tooling by defining your very own cluster commands via plugins. K9s will look at `$HOME/.k9s/plugin.yml` to locate all available plugins. A plugin is defined as follows:
|
K9s allows you to extend your command line and tooling by defining your very own cluster commands via plugins. K9s will look at `$HOME/.k9s/plugin.yml` to locate all available plugins. A plugin is defined as follows:
|
||||||
|
|
||||||
* Shortcut option represents the key combination a user would type to activate the plugin
|
* Shortcut option represents the key combination a user would type to activate the plugin
|
||||||
|
* Confirm option (when enabled) lets you see the command that is going to be executed and gives you an option to confirm or prevent execution
|
||||||
* Description will be printed next to the shortcut in the k9s menu
|
* Description will be printed next to the shortcut in the k9s menu
|
||||||
* Scopes defines a collection of resources names/shortnames for the views associated with the plugin. You can specify `all` to provide this shortcut for all views.
|
* Scopes defines a collection of resources names/shortnames for the views associated with the plugin. You can specify `all` to provide this shortcut for all views.
|
||||||
* Command represents adhoc commands the plugin runs upon activation
|
* Command represents adhoc commands the plugin runs upon activation
|
||||||
|
|
@ -346,6 +347,7 @@ plugin:
|
||||||
# Defines a plugin to provide a `ctrl-l` shorcut to tail the logs while in pod view.
|
# Defines a plugin to provide a `ctrl-l` shorcut to tail the logs while in pod view.
|
||||||
fred:
|
fred:
|
||||||
shortCut: Ctrl-L
|
shortCut: Ctrl-L
|
||||||
|
confirm: false
|
||||||
description: Pod logs
|
description: Pod logs
|
||||||
scopes:
|
scopes:
|
||||||
- pods
|
- pods
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ type Plugins struct {
|
||||||
// Plugin describes a K9s plugin
|
// Plugin describes a K9s plugin
|
||||||
type Plugin struct {
|
type Plugin struct {
|
||||||
ShortCut string `yaml:"shortCut"`
|
ShortCut string `yaml:"shortCut"`
|
||||||
|
Confirm bool `yaml:"confirm"`
|
||||||
Scopes []string `yaml:"scopes"`
|
Scopes []string `yaml:"scopes"`
|
||||||
Description string `yaml:"description"`
|
Description string `yaml:"description"`
|
||||||
Command string `yaml:"command"`
|
Command string `yaml:"command"`
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@ func TestPluginLoad(t *testing.T) {
|
||||||
k, ok := p.Plugin["blah"]
|
k, ok := p.Plugin["blah"]
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, "shift-s", k.ShortCut)
|
assert.Equal(t, "shift-s", k.ShortCut)
|
||||||
|
assert.True(t, k.Confirm)
|
||||||
assert.Equal(t, "blee", k.Description)
|
assert.Equal(t, "blee", k.Description)
|
||||||
assert.Equal(t, []string{"po", "dp"}, k.Scopes)
|
assert.Equal(t, []string{"po", "dp"}, k.Scopes)
|
||||||
assert.Equal(t, "duh", k.Command)
|
assert.Equal(t, "duh", k.Command)
|
||||||
|
assert.False(t, k.Background)
|
||||||
assert.Equal(t, []string{"-n", "$NAMESPACE", "-boolean"}, k.Args)
|
assert.Equal(t, []string{"-n", "$NAMESPACE", "-boolean"}, k.Args)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
plugin:
|
plugin:
|
||||||
blah:
|
blah:
|
||||||
shortCut: shift-s
|
shortCut: shift-s
|
||||||
|
confirm: true
|
||||||
description: blee
|
description: blee
|
||||||
scopes:
|
scopes:
|
||||||
- po
|
- po
|
||||||
- dp
|
- dp
|
||||||
command: duh
|
command: duh
|
||||||
|
background: false
|
||||||
args:
|
args:
|
||||||
- -n
|
- -n
|
||||||
- $NAMESPACE
|
- $NAMESPACE
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/config"
|
"github.com/derailed/k9s/internal/config"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
|
"github.com/derailed/k9s/internal/ui/dialog"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
@ -107,12 +109,12 @@ func pluginActions(r Runner, aa ui.KeyActions) {
|
||||||
}
|
}
|
||||||
aa[key] = ui.NewKeyAction(
|
aa[key] = ui.NewKeyAction(
|
||||||
plugin.Description,
|
plugin.Description,
|
||||||
execCmd(r, plugin.Command, plugin.Background, plugin.Args...),
|
pluginAction(r, plugin),
|
||||||
true)
|
true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func execCmd(r Runner, bin string, bg bool, args ...string) ui.ActionHandler {
|
func pluginAction(r Runner, p config.Plugin) ui.ActionHandler {
|
||||||
return func(evt *tcell.EventKey) *tcell.EventKey {
|
return func(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
path := r.GetSelectedItem()
|
path := r.GetSelectedItem()
|
||||||
if path == "" {
|
if path == "" {
|
||||||
|
|
@ -123,20 +125,29 @@ func execCmd(r Runner, bin string, bg bool, args ...string) ui.ActionHandler {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
aa := make([]string, len(args))
|
args := make([]string, len(p.Args))
|
||||||
for i, a := range args {
|
for i, a := range p.Args {
|
||||||
arg, err := r.EnvFn()().Substitute(a)
|
arg, err := r.EnvFn()().Substitute(a)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Plugin Args match failed")
|
log.Error().Err(err).Msg("Plugin Args match failed")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
aa[i] = arg
|
args[i] = arg
|
||||||
}
|
}
|
||||||
if run(r.App(), shellOpts{clear: true, binary: bin, background: bg, args: aa}) {
|
fn := func() {
|
||||||
|
if run(r.App(), shellOpts{clear: true, binary: p.Command, background: p.Background, args: args}) {
|
||||||
r.App().Flash().Info("Plugin command launched successfully!")
|
r.App().Flash().Info("Plugin command launched successfully!")
|
||||||
} else {
|
} else {
|
||||||
r.App().Flash().Info("Plugin command failed!")
|
r.App().Flash().Info("Plugin command failed!")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if p.Confirm {
|
||||||
|
dialog.ShowConfirm(r.App().Content.Pages, "Confirm plugin action", fmt.Sprintf("Will execute:\n%s %s", p.Command, strings.Join(args, " ")), func() {
|
||||||
|
fn()
|
||||||
|
}, func() {})
|
||||||
|
} else {
|
||||||
|
fn()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
plugin:
|
plugin:
|
||||||
dive:
|
dive:
|
||||||
shortCut: d
|
shortCut: d
|
||||||
|
confirm: false
|
||||||
description: "Dive image"
|
description: "Dive image"
|
||||||
scopes:
|
scopes:
|
||||||
- containers
|
- containers
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ plugin:
|
||||||
# Suspends/Resumes a cronjob
|
# Suspends/Resumes a cronjob
|
||||||
toggleCronjob:
|
toggleCronjob:
|
||||||
shortCut: Ctrl-S
|
shortCut: Ctrl-S
|
||||||
|
confirm: true
|
||||||
scopes:
|
scopes:
|
||||||
- cj
|
- cj
|
||||||
description: Toggle to suspend or resume a running cronjob
|
description: Toggle to suspend or resume a running cronjob
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ plugin:
|
||||||
# Sends logs over to jq for processing. This leverages kubectl plugin kubectl-jq.
|
# Sends logs over to jq for processing. This leverages kubectl plugin kubectl-jq.
|
||||||
jqlogs:
|
jqlogs:
|
||||||
shortCut: Ctrl-J
|
shortCut: Ctrl-J
|
||||||
|
confirm: false
|
||||||
description: "Logs (jq)"
|
description: "Logs (jq)"
|
||||||
scopes:
|
scopes:
|
||||||
- po
|
- po
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ plugin:
|
||||||
# Leverage stern (https://github.com/wercker/stern) to output logs.
|
# Leverage stern (https://github.com/wercker/stern) to output logs.
|
||||||
stern:
|
stern:
|
||||||
shortCut: Ctrl-L
|
shortCut: Ctrl-L
|
||||||
|
confirm: false
|
||||||
description: "Logs <Stern>"
|
description: "Logs <Stern>"
|
||||||
scopes:
|
scopes:
|
||||||
- pods
|
- pods
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue