From 71ef96afaf4f6cfa4c7013672538c0fed17b9bdc Mon Sep 17 00:00:00 2001 From: Nir Soffer Date: Wed, 16 Aug 2023 19:21:17 +0300 Subject: [PATCH] Support usage as plugin for tools like kubectl In this case the executable is `kubectl-plugin`, but we run it as: kubectl plugin And the help text should reflect the actual usage of the command. To create a plugin create the root command like: rootCmd := &cobra.Command{ CommandName: "kubectl plugin", } When `CommandName` is set, Name() use it as is instead of guessing the command name from the `Use` line. Issues: - Need to update the docs. Fixes: #2017 Signed-off-by: Nir Soffer --- command.go | 9 ++++++++- command_test.go | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/command.go b/command.go index 01f7c6f1c5..80c7829a06 100644 --- a/command.go +++ b/command.go @@ -57,6 +57,10 @@ type Command struct { // Example: add [-F file | -D dir]... [-f format] profile Use string + // CommandName is the command name if set. Otherwise the command + // name is the first word of the `Use` line. + CommandName string + // Aliases is an array of aliases that can be used instead of the first word in Use. Aliases []string @@ -1441,8 +1445,11 @@ func (c *Command) DebugFlags() { debugflags(c) } -// Name returns the command's name: the first word in the use line. +// Name returns CommandName or the first word in the use line. func (c *Command) Name() string { + if c.CommandName != "" { + return c.CommandName + } name := c.Use i := strings.Index(name, " ") if i >= 0 { diff --git a/command_test.go b/command_test.go index b0f5e860ee..832f4e7879 100644 --- a/command_test.go +++ b/command_test.go @@ -366,6 +366,29 @@ func TestAliasPrefixMatching(t *testing.T) { EnablePrefixMatching = defaultPrefixMatching } +// TestPlugin checks usage as plugin for aother commmand such as kubectl. The +// executable is `kubectl-plugin`, but we run it as `kubectl plugin`. The help +// text should reflect the way we run the commmand. +func TestPlugin(t *testing.T) { + rootCmd := &Command{CommandName: "kubectl plugin", Args: NoArgs} + subCmd := &Command{Use: "sub [flags]", Args: NoArgs, Run: emptyRun} + rootCmd.AddCommand(subCmd) + + rootHelp, err := executeCommand(rootCmd, "-h") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + checkStringContains(t, rootHelp, "kubectl plugin [command]") + + childHelp, err := executeCommand(rootCmd, "sub", "-h") + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + + checkStringContains(t, childHelp, "kubectl plugin sub [flags]") +} + // TestChildSameName checks the correct behaviour of cobra in cases, // when an application with name "foo" and with subcommand "foo" // is executed with args "foo foo".