From b47c181729d4b76c50586ff8ca4f0e28e6bd5cd7 Mon Sep 17 00:00:00 2001 From: Hernan Garcia Date: Tue, 30 Jun 2026 21:59:18 -0500 Subject: [PATCH] fix: show swarm init help instead of docker-init plugin help When the docker-init CLI plugin is installed, `docker swarm init --help` incorrectly delegated to the plugin because help handling matched on the command name "init" without checking whether the target was a plugin stub. Fixes docker/cli#4400 Co-authored-by: Cursor Signed-off-by: Hernan Garcia --- cmd/docker/docker.go | 15 ++++++--------- cmd/docker/docker_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index 0efcc70118fe..68ac2760cfb2 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -229,14 +229,11 @@ func setupHelpCommand(dockerCli command.Cli, rootCmd, helpCmd *cobra.Command) { } } -func tryRunPluginHelp(dockerCli command.Cli, ccmd *cobra.Command, cargs []string) error { - root := ccmd.Root() - - cmd, _, err := root.Traverse(cargs) - if err != nil { - return err +func tryRunPluginHelp(dockerCli command.Cli, ccmd *cobra.Command) error { + if !pluginmanager.IsPluginCommand(ccmd) { + return errdefs.ErrNotFound } - helpcmd, err := pluginmanager.PluginRunCommand(dockerCli, cmd.Name(), root) + helpcmd, err := pluginmanager.PluginRunCommand(dockerCli, ccmd.Name(), ccmd.Root()) if err != nil { return err } @@ -251,8 +248,8 @@ func setHelpFunc(dockerCli command.Cli, cmd *cobra.Command) { return } - if len(args) >= 1 { - err := tryRunPluginHelp(dockerCli, ccmd, args) + if pluginmanager.IsPluginCommand(ccmd) { + err := tryRunPluginHelp(dockerCli, ccmd) if err == nil { return } diff --git a/cmd/docker/docker_test.go b/cmd/docker/docker_test.go index 928fcc6ee201..e86eb3df419f 100644 --- a/cmd/docker/docker_test.go +++ b/cmd/docker/docker_test.go @@ -7,6 +7,8 @@ import ( "fmt" "io" "os" + "path/filepath" + "strings" "syscall" "testing" "time" @@ -205,3 +207,39 @@ func TestVisitAll(t *testing.T) { expected := []string{"sub1sub1", "sub1sub2", "sub1", "sub2", "root"} assert.DeepEqual(t, expected, visited) } + +func TestSwarmInitHelpNotDelegatedToInitPlugin(t *testing.T) { + tmpDir := t.TempDir() + pluginScript := `#!/bin/sh +if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then + echo "PLUGIN INIT HELP" + exit 0 +fi +printf '%s' '{"SchemaVersion":"0.1.0","ShortDescription":"Docker Init"}' +` + pluginPath := filepath.Join(tmpDir, "docker-init") + err := os.WriteFile(pluginPath, []byte(pluginScript), 0o755) + assert.NilError(t, err) + + var b bytes.Buffer + ctx := context.Background() + cli, err := command.NewDockerCli( + command.WithBaseContext(ctx), + command.WithCombinedStreams(&b), + ) + assert.NilError(t, err) + cli.ConfigFile().CLIPluginsExtraDirs = []string{tmpDir} + + tcmd := newDockerCommand(cli) + tcmd.SetArgs([]string{"swarm", "init", "--help"}) + cmd, args, err := tcmd.HandleGlobalFlags() + assert.NilError(t, err) + assert.NilError(t, tcmd.Initialize()) + cmd.SetArgs(args) + err = cmd.Execute() + assert.NilError(t, err) + + out := b.String() + assert.Assert(t, is.Contains(out, "Initialize a swarm")) + assert.Assert(t, !strings.Contains(out, "PLUGIN INIT HELP"), "output: %s", out) +}