From 935d47bbe967808f69f5b7c72fc848a08f447c2d Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 17 Jan 2019 13:38:38 +0000 Subject: [PATCH] Ignore unknown arguments on the top-level command. This allows passing argument to plugins, otherwise they are caught by the parse loop, since cobra does not know about each plugin at this stage (to avoid having to always scan for all plugins) this means that e.g. `docker plugin --foo` would accumulate `plugin` as an arg to the `docker` command, then choke on the unknown `--foo`. This allows unknown global args only, unknown arguments on subcommands (e.g. `docker ps --foo`) are still correctly caught. Add an e2e test covering this case. Signed-off-by: Ian Campbell --- cli-plugins/examples/helloworld/main.go | 5 ++++- cmd/docker/docker.go | 10 ++++++++++ e2e/cli-plugins/run_test.go | 12 ++++++++++++ .../testdata/docker-help-helloworld.golden | 5 ++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/cli-plugins/examples/helloworld/main.go b/cli-plugins/examples/helloworld/main.go index 9a511591ec..cbe015937f 100644 --- a/cli-plugins/examples/helloworld/main.go +++ b/cli-plugins/examples/helloworld/main.go @@ -33,6 +33,7 @@ func main() { }, } + var who string cmd := &cobra.Command{ Use: "helloworld", Short: "A basic Hello World plugin for tests", @@ -41,9 +42,11 @@ func main() { // hook. PersistentPreRunE: plugin.PersistentPreRunE, Run: func(cmd *cobra.Command, args []string) { - fmt.Fprintln(dockerCli.Out(), "Hello World!") + fmt.Fprintf(dockerCli.Out(), "Hello %s!\n", who) }, } + flags := cmd.Flags() + flags.StringVar(&who, "who", "World", "Who are we addressing?") cmd.AddCommand(goodbye, apiversion) return cmd diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 1ebf30a89d..74fab46dcc 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -32,6 +32,16 @@ func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command { SilenceUsage: true, SilenceErrors: true, TraverseChildren: true, + FParseErrWhitelist: cobra.FParseErrWhitelist{ + // UnknownFlags ignores any unknown + // --arguments on the top-level docker command + // only. This is necessary to allow passing + // --arguments to plugins otherwise + // e.g. `docker plugin --foo` is caught here + // in the monolithic CLI and `foo` is reported + // as an unknown argument. + UnknownFlags: true, + }, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { return command.ShowHelp(dockerCli.Err())(cmd, args) diff --git a/e2e/cli-plugins/run_test.go b/e2e/cli-plugins/run_test.go index d16bf3bb8b..e12c51025d 100644 --- a/e2e/cli-plugins/run_test.go +++ b/e2e/cli-plugins/run_test.go @@ -144,6 +144,18 @@ func TestRunGoodSubcommand(t *testing.T) { }) } +// TestRunGoodArgument ensures correct behaviour when running a valid plugin with an `--argument`. +func TestRunGoodArgument(t *testing.T) { + run, cleanup := prepare(t) + defer cleanup() + + res := icmd.RunCmd(run("helloworld", "--who", "Cleveland")) + res.Assert(t, icmd.Expected{ + ExitCode: 0, + Out: "Hello Cleveland!", + }) +} + // TestHelpGoodSubcommand ensures correct behaviour when invoking help on a // valid plugin subcommand. A global argument is included to ensure it does not // interfere. diff --git a/e2e/cli-plugins/testdata/docker-help-helloworld.golden b/e2e/cli-plugins/testdata/docker-help-helloworld.golden index e7252bf2d0..6ff36bc64e 100644 --- a/e2e/cli-plugins/testdata/docker-help-helloworld.golden +++ b/e2e/cli-plugins/testdata/docker-help-helloworld.golden @@ -1,8 +1,11 @@ -Usage: docker helloworld COMMAND +Usage: docker helloworld [OPTIONS] COMMAND A basic Hello World plugin for tests +Options: + --who string Who are we addressing? (default "World") + Commands: apiversion Print the API version of the server goodbye Say Goodbye instead of Hello