From 2777a7d5104ea9e4844a306eb44e27e57b87b99f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C4=9Bmec?= Date: Wed, 29 Apr 2020 17:51:12 +0200 Subject: [PATCH 1/2] Optionally allow plugin commands to have confirm dialog --- internal/config/plugin.go | 1 + internal/view/actions.go | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/internal/config/plugin.go b/internal/config/plugin.go index b0b50d4e..2979deea 100644 --- a/internal/config/plugin.go +++ b/internal/config/plugin.go @@ -18,6 +18,7 @@ type Plugins struct { // Plugin describes a K9s plugin type Plugin struct { ShortCut string `yaml:"shortCut"` + Confirm bool `yaml:"confirm"` Scopes []string `yaml:"scopes"` Description string `yaml:"description"` Command string `yaml:"command"` diff --git a/internal/view/actions.go b/internal/view/actions.go index 1d5abcc1..c05b38fd 100644 --- a/internal/view/actions.go +++ b/internal/view/actions.go @@ -2,9 +2,11 @@ package view import ( "fmt" + "strings" "github.com/derailed/k9s/internal/config" "github.com/derailed/k9s/internal/ui" + "github.com/derailed/k9s/internal/ui/dialog" "github.com/gdamore/tcell" "github.com/rs/zerolog/log" ) @@ -107,12 +109,12 @@ func pluginActions(r Runner, aa ui.KeyActions) { } aa[key] = ui.NewKeyAction( plugin.Description, - execCmd(r, plugin.Command, plugin.Background, plugin.Args...), + pluginAction(r, plugin), 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 { path := r.GetSelectedItem() if path == "" { @@ -123,19 +125,28 @@ func execCmd(r Runner, bin string, bg bool, args ...string) ui.ActionHandler { return nil } - aa := make([]string, len(args)) - for i, a := range args { + args := make([]string, len(p.Args)) + for i, a := range p.Args { arg, err := r.EnvFn()().Substitute(a) if err != nil { log.Error().Err(err).Msg("Plugin Args match failed") return nil } - aa[i] = arg + args[i] = arg } - if run(r.App(), shellOpts{clear: true, binary: bin, background: bg, args: aa}) { - r.App().Flash().Info("Plugin command launched successfully!") + 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!") + } else { + 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 { - r.App().Flash().Info("Plugin command failed!") + fn() } return nil From 2c79dcfda83e1b84b2c507014658e736d8ebdbde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C4=9Bmec?= Date: Fri, 1 May 2020 22:26:08 +0200 Subject: [PATCH 2/2] Update readme and examples --- README.md | 2 ++ internal/config/plugin_test.go | 2 ++ internal/config/testdata/plugin.yml | 2 ++ plugins/dive.yml | 1 + plugins/job_suspend.yml | 1 + plugins/log_jq.yml | 1 + plugins/log_stern.yml | 1 + 7 files changed, 10 insertions(+) diff --git a/README.md b/README.md index b0177c21..261b5e14 100644 --- a/README.md +++ b/README.md @@ -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: * 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 * 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 @@ -346,6 +347,7 @@ plugin: # Defines a plugin to provide a `ctrl-l` shorcut to tail the logs while in pod view. fred: shortCut: Ctrl-L + confirm: false description: Pod logs scopes: - pods diff --git a/internal/config/plugin_test.go b/internal/config/plugin_test.go index 43f8e278..961118fc 100644 --- a/internal/config/plugin_test.go +++ b/internal/config/plugin_test.go @@ -15,8 +15,10 @@ func TestPluginLoad(t *testing.T) { k, ok := p.Plugin["blah"] assert.True(t, ok) assert.Equal(t, "shift-s", k.ShortCut) + assert.True(t, k.Confirm) assert.Equal(t, "blee", k.Description) assert.Equal(t, []string{"po", "dp"}, k.Scopes) assert.Equal(t, "duh", k.Command) + assert.False(t, k.Background) assert.Equal(t, []string{"-n", "$NAMESPACE", "-boolean"}, k.Args) } diff --git a/internal/config/testdata/plugin.yml b/internal/config/testdata/plugin.yml index 783eb72f..0563f6f8 100644 --- a/internal/config/testdata/plugin.yml +++ b/internal/config/testdata/plugin.yml @@ -1,11 +1,13 @@ plugin: blah: shortCut: shift-s + confirm: true description: blee scopes: - po - dp command: duh + background: false args: - -n - $NAMESPACE diff --git a/plugins/dive.yml b/plugins/dive.yml index 8824d132..c92205ac 100644 --- a/plugins/dive.yml +++ b/plugins/dive.yml @@ -1,6 +1,7 @@ plugin: dive: shortCut: d + confirm: false description: "Dive image" scopes: - containers diff --git a/plugins/job_suspend.yml b/plugins/job_suspend.yml index c8a4b3ba..d674dd2d 100644 --- a/plugins/job_suspend.yml +++ b/plugins/job_suspend.yml @@ -2,6 +2,7 @@ plugin: # Suspends/Resumes a cronjob toggleCronjob: shortCut: Ctrl-S + confirm: true scopes: - cj description: Toggle to suspend or resume a running cronjob diff --git a/plugins/log_jq.yml b/plugins/log_jq.yml index 4e6d6d3c..f4c40e02 100644 --- a/plugins/log_jq.yml +++ b/plugins/log_jq.yml @@ -2,6 +2,7 @@ plugin: # Sends logs over to jq for processing. This leverages kubectl plugin kubectl-jq. jqlogs: shortCut: Ctrl-J + confirm: false description: "Logs (jq)" scopes: - po diff --git a/plugins/log_stern.yml b/plugins/log_stern.yml index 83dbe6f1..c3c28119 100644 --- a/plugins/log_stern.yml +++ b/plugins/log_stern.yml @@ -2,6 +2,7 @@ plugin: # Leverage stern (https://github.com/wercker/stern) to output logs. stern: shortCut: Ctrl-L + confirm: false description: "Logs " scopes: - pods