diff --git a/cli-plugins/examples/helloworld/main.go b/cli-plugins/examples/helloworld/main.go index cfbae368b0c1..6251e85916b5 100644 --- a/cli-plugins/examples/helloworld/main.go +++ b/cli-plugins/examples/helloworld/main.go @@ -44,7 +44,10 @@ func main() { }, } - var who string + var ( + who, context string + debug bool + ) cmd := &cobra.Command{ Use: "helloworld", Short: "A basic Hello World plugin for tests", @@ -53,6 +56,18 @@ func main() { // hook. PersistentPreRunE: plugin.PersistentPreRunE, RunE: func(cmd *cobra.Command, args []string) error { + if debug { + fmt.Fprintf(dockerCli.Err(), "Plugin debug mode enabled") + } + + switch context { + case "Christmas": + fmt.Fprintf(dockerCli.Out(), "Merry Christmas!\n") + return nil + case "": + // nothing + } + if who == "" { who, _ = dockerCli.ConfigFile().PluginConfig("helloworld", "who") } @@ -68,6 +83,10 @@ func main() { flags := cmd.Flags() flags.StringVar(&who, "who", "", "Who are we addressing?") + // These are intended to deliberately clash with the CLIs own top + // level arguments. + flags.BoolVarP(&debug, "debug", "D", false, "Enable debug") + flags.StringVarP(&context, "context", "c", "", "Is it Christmas?") cmd.AddCommand(goodbye, apiversion, exitStatus2) return cmd diff --git a/e2e/cli-plugins/flags_test.go b/e2e/cli-plugins/flags_test.go index d472257b9ec7..4bf01b9c4725 100644 --- a/e2e/cli-plugins/flags_test.go +++ b/e2e/cli-plugins/flags_test.go @@ -3,6 +3,8 @@ package cliplugins import ( "testing" + "gotest.tools/assert" + is "gotest.tools/assert/cmp" "gotest.tools/icmd" ) @@ -17,3 +19,82 @@ func TestRunGoodArgument(t *testing.T) { Out: "Hello Cleveland!", }) } + +// TestClashWithGlobalArgs ensures correct behaviour when a plugin +// has an argument with the same name as one of the globals. +func TestClashWithGlobalArgs(t *testing.T) { + run, _, cleanup := prepare(t) + defer cleanup() + + for _, tc := range []struct { + name string + args []string + expectedOut, expectedErr string + }{ + { + name: "short-without-val", + args: []string{"-D"}, + expectedOut: "Hello World!", + expectedErr: "Plugin debug mode enabled", + }, + { + name: "long-without-val", + args: []string{"--debug"}, + expectedOut: "Hello World!", + expectedErr: "Plugin debug mode enabled", + }, + { + name: "short-with-val", + args: []string{"-c", "Christmas"}, + expectedOut: "Merry Christmas!", + expectedErr: "", + }, + { + name: "short-with-val", + args: []string{"--context", "Christmas"}, + expectedOut: "Merry Christmas!", + expectedErr: "", + }, + } { + t.Run(tc.name, func(t *testing.T) { + args := append([]string{"helloworld"}, tc.args...) + res := icmd.RunCmd(run(args...)) + res.Assert(t, icmd.Expected{ + ExitCode: 0, + Out: tc.expectedOut, + Err: tc.expectedErr, + }) + }) + } +} + +// TestUnknownGlobal checks that unknown globals report errors +func TestUnknownGlobal(t *testing.T) { + run, _, cleanup := prepare(t) + defer cleanup() + + t.Run("no-val", func(t *testing.T) { + res := icmd.RunCmd(run("--unknown", "helloworld")) + res.Assert(t, icmd.Expected{ + ExitCode: 125, + }) + assert.Assert(t, is.Equal(res.Stdout(), "")) + assert.Assert(t, is.Contains(res.Stderr(), "unknown flag: --unknown")) + }) + t.Run("separate-val", func(t *testing.T) { + res := icmd.RunCmd(run("--unknown", "foo", "helloworld")) + res.Assert(t, icmd.Expected{ + ExitCode: 125, + }) + assert.Assert(t, is.Equal(res.Stdout(), "")) + assert.Assert(t, is.Contains(res.Stderr(), "unknown flag: --unknown")) + }) + t.Run("joined-val", func(t *testing.T) { + res := icmd.RunCmd(run("--unknown=foo", "helloworld")) + res.Assert(t, icmd.Expected{ + ExitCode: 125, + }) + assert.Assert(t, is.Equal(res.Stdout(), "")) + assert.Assert(t, is.Contains(res.Stderr(), "unknown flag: --unknown")) + }) +} diff --git a/e2e/cli-plugins/testdata/docker-help-helloworld.golden b/e2e/cli-plugins/testdata/docker-help-helloworld.golden index 59959637cb31..24bc424bd7ca 100644 --- a/e2e/cli-plugins/testdata/docker-help-helloworld.golden +++ b/e2e/cli-plugins/testdata/docker-help-helloworld.golden @@ -4,7 +4,9 @@ Usage: docker helloworld [OPTIONS] COMMAND A basic Hello World plugin for tests Options: - --who string Who are we addressing? + -c, --context string Is it Christmas? + -D, --debug Enable debug + --who string Who are we addressing? Commands: apiversion Print the API version of the server