mirror of https://github.com/docker/cli.git
Integrate CLI plugins with `docker «plugin» --help`.
To achieve this we hook in at the beginning of our custom `HelpFunc` and detect the plugin case by adding stub commands. Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
parent
20a284721c
commit
53f018120a
|
@ -123,6 +123,21 @@ func setupHelpCommand(dockerCli *command.DockerCli, rootCmd, helpCmd *cobra.Comm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func tryRunPluginHelp(dockerCli command.Cli, ccmd *cobra.Command, cargs []string) error {
|
||||||
|
root := ccmd.Root()
|
||||||
|
pluginmanager.AddPluginCommandStubs(dockerCli, root, false)
|
||||||
|
|
||||||
|
cmd, _, err := root.Traverse(cargs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
helpcmd, err := pluginmanager.PluginRunCommand(dockerCli, cmd.Name(), root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return helpcmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.FlagSet, opts *cliflags.ClientOptions) {
|
func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.FlagSet, opts *cliflags.ClientOptions) {
|
||||||
defaultHelpFunc := cmd.HelpFunc()
|
defaultHelpFunc := cmd.HelpFunc()
|
||||||
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
|
cmd.SetHelpFunc(func(ccmd *cobra.Command, args []string) {
|
||||||
|
@ -130,6 +145,17 @@ func setHelpFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.
|
||||||
ccmd.Println(err)
|
ccmd.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if len(args) >= 1 {
|
||||||
|
err := tryRunPluginHelp(dockerCli, ccmd, args)
|
||||||
|
if err == nil { // Successfully ran the plugin
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !pluginmanager.IsNotFound(err) {
|
||||||
|
ccmd.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := isSupported(ccmd, dockerCli); err != nil {
|
if err := isSupported(ccmd, dockerCli); err != nil {
|
||||||
ccmd.Println(err)
|
ccmd.Println(err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -35,6 +35,22 @@ func TestHelpNonexisting(t *testing.T) {
|
||||||
golden.Assert(t, res.Stderr(), "docker-help-nonexistent-err.golden")
|
golden.Assert(t, res.Stderr(), "docker-help-nonexistent-err.golden")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestNonexistingHelp ensures correct behaviour when invoking a
|
||||||
|
// nonexistent plugin with `--help`.
|
||||||
|
func TestNonexistingHelp(t *testing.T) {
|
||||||
|
run, cleanup := prepare(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
res := icmd.RunCmd(run("nonexistent", "--help"))
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 0,
|
||||||
|
// This should actually be the whole docker help
|
||||||
|
// output, so spot check instead having of a golden
|
||||||
|
// with everything in, which will change too frequently.
|
||||||
|
Out: "Usage: docker [OPTIONS] COMMAND\n\nA self-sufficient runtime for containers",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestRunBad ensures correct behaviour when running an existent but invalid plugin
|
// TestRunBad ensures correct behaviour when running an existent but invalid plugin
|
||||||
func TestRunBad(t *testing.T) {
|
func TestRunBad(t *testing.T) {
|
||||||
run, cleanup := prepare(t)
|
run, cleanup := prepare(t)
|
||||||
|
@ -61,6 +77,22 @@ func TestHelpBad(t *testing.T) {
|
||||||
golden.Assert(t, res.Stderr(), "docker-help-badmeta-err.golden")
|
golden.Assert(t, res.Stderr(), "docker-help-badmeta-err.golden")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestBadHelp ensures correct behaviour when invoking an
|
||||||
|
// existent but invalid plugin with `--help`.
|
||||||
|
func TestBadHelp(t *testing.T) {
|
||||||
|
run, cleanup := prepare(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
res := icmd.RunCmd(run("badmeta", "--help"))
|
||||||
|
res.Assert(t, icmd.Expected{
|
||||||
|
ExitCode: 0,
|
||||||
|
// This should be literally the whole docker help
|
||||||
|
// output, so spot check instead of a golden with
|
||||||
|
// everything in which will change all the time.
|
||||||
|
Out: "Usage: docker [OPTIONS] COMMAND\n\nA self-sufficient runtime for containers",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TestRunGood ensures correct behaviour when running a valid plugin
|
// TestRunGood ensures correct behaviour when running a valid plugin
|
||||||
func TestRunGood(t *testing.T) {
|
func TestRunGood(t *testing.T) {
|
||||||
run, cleanup := prepare(t)
|
run, cleanup := prepare(t)
|
||||||
|
@ -86,6 +118,20 @@ func TestHelpGood(t *testing.T) {
|
||||||
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGoodHelp ensures correct behaviour when calling a valid plugin
|
||||||
|
// with `--help`. A global argument is used to ensure it does not
|
||||||
|
// interfere.
|
||||||
|
func TestGoodHelp(t *testing.T) {
|
||||||
|
run, cleanup := prepare(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
res := icmd.RunCmd(run("-D", "helloworld", "--help"))
|
||||||
|
res.Assert(t, icmd.Success)
|
||||||
|
// This is the same golden file as `TestHelpGood`, above.
|
||||||
|
golden.Assert(t, res.Stdout(), "docker-help-helloworld.golden")
|
||||||
|
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
||||||
|
}
|
||||||
|
|
||||||
// TestRunGoodSubcommand ensures correct behaviour when running a valid plugin with a subcommand
|
// TestRunGoodSubcommand ensures correct behaviour when running a valid plugin with a subcommand
|
||||||
func TestRunGoodSubcommand(t *testing.T) {
|
func TestRunGoodSubcommand(t *testing.T) {
|
||||||
run, cleanup := prepare(t)
|
run, cleanup := prepare(t)
|
||||||
|
@ -110,3 +156,17 @@ func TestHelpGoodSubcommand(t *testing.T) {
|
||||||
golden.Assert(t, res.Stdout(), "docker-help-helloworld-goodbye.golden")
|
golden.Assert(t, res.Stdout(), "docker-help-helloworld-goodbye.golden")
|
||||||
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGoodSubcommandHelp ensures correct behaviour when calling a valid plugin
|
||||||
|
// with a subcommand and `--help`. A global argument is used to ensure it does not
|
||||||
|
// interfere.
|
||||||
|
func TestGoodSubcommandHelp(t *testing.T) {
|
||||||
|
run, cleanup := prepare(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
res := icmd.RunCmd(run("-D", "helloworld", "goodbye", "--help"))
|
||||||
|
res.Assert(t, icmd.Success)
|
||||||
|
// This is the same golden file as `TestHelpGoodSubcommand`, above.
|
||||||
|
golden.Assert(t, res.Stdout(), "docker-help-helloworld-goodbye.golden")
|
||||||
|
assert.Assert(t, is.Equal(res.Stderr(), ""))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue