mirror of https://github.com/docker/cli.git
Output broken CLI plugins in `help` output.
Signed-off-by: Ian Campbell <ijc@docker.com>
This commit is contained in:
parent
e5e578abc7
commit
0ab8ec0e4c
44
cli/cobra.go
44
cli/cobra.go
|
@ -24,11 +24,14 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
|
|||
|
||||
cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
|
||||
cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
|
||||
cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins)
|
||||
cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
|
||||
cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
|
||||
cobra.AddTemplateFunc("invalidPlugins", invalidPlugins)
|
||||
cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages)
|
||||
cobra.AddTemplateFunc("commandVendor", commandVendor)
|
||||
cobra.AddTemplateFunc("isFirstLevelCommand", isFirstLevelCommand) // is it an immediate sub-command of the root
|
||||
cobra.AddTemplateFunc("invalidPluginReason", invalidPluginReason)
|
||||
|
||||
rootCmd.SetUsageTemplate(usageTemplate)
|
||||
rootCmd.SetHelpTemplate(helpTemplate)
|
||||
|
@ -115,6 +118,10 @@ var helpCommand = &cobra.Command{
|
|||
},
|
||||
}
|
||||
|
||||
func isPlugin(cmd *cobra.Command) bool {
|
||||
return cmd.Annotations[pluginmanager.CommandAnnotationPlugin] == "true"
|
||||
}
|
||||
|
||||
func hasSubCommands(cmd *cobra.Command) bool {
|
||||
return len(operationSubCommands(cmd)) > 0
|
||||
}
|
||||
|
@ -123,9 +130,16 @@ func hasManagementSubCommands(cmd *cobra.Command) bool {
|
|||
return len(managementSubCommands(cmd)) > 0
|
||||
}
|
||||
|
||||
func hasInvalidPlugins(cmd *cobra.Command) bool {
|
||||
return len(invalidPlugins(cmd)) > 0
|
||||
}
|
||||
|
||||
func operationSubCommands(cmd *cobra.Command) []*cobra.Command {
|
||||
cmds := []*cobra.Command{}
|
||||
for _, sub := range cmd.Commands() {
|
||||
if isPlugin(sub) && invalidPluginReason(sub) != "" {
|
||||
continue
|
||||
}
|
||||
if sub.IsAvailableCommand() && !sub.HasSubCommands() {
|
||||
cmds = append(cmds, sub)
|
||||
}
|
||||
|
@ -159,6 +173,9 @@ func commandVendor(cmd *cobra.Command) string {
|
|||
func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
|
||||
cmds := []*cobra.Command{}
|
||||
for _, sub := range cmd.Commands() {
|
||||
if isPlugin(sub) && invalidPluginReason(sub) != "" {
|
||||
continue
|
||||
}
|
||||
if sub.IsAvailableCommand() && sub.HasSubCommands() {
|
||||
cmds = append(cmds, sub)
|
||||
}
|
||||
|
@ -166,6 +183,23 @@ func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
|
|||
return cmds
|
||||
}
|
||||
|
||||
func invalidPlugins(cmd *cobra.Command) []*cobra.Command {
|
||||
cmds := []*cobra.Command{}
|
||||
for _, sub := range cmd.Commands() {
|
||||
if !isPlugin(sub) {
|
||||
continue
|
||||
}
|
||||
if invalidPluginReason(sub) != "" {
|
||||
cmds = append(cmds, sub)
|
||||
}
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
func invalidPluginReason(cmd *cobra.Command) string {
|
||||
return cmd.Annotations[pluginmanager.CommandAnnotationPluginInvalid]
|
||||
}
|
||||
|
||||
var usageTemplate = `Usage:
|
||||
|
||||
{{- if not .HasSubCommands}} {{.UseLine}}{{end}}
|
||||
|
@ -209,6 +243,16 @@ Commands:
|
|||
{{- end}}
|
||||
{{- end}}
|
||||
|
||||
{{- if hasInvalidPlugins . }}
|
||||
|
||||
Invalid Plugins:
|
||||
|
||||
{{- range invalidPlugins . }}
|
||||
{{rpad .Name .NamePadding }} {{invalidPluginReason .}}
|
||||
{{- end}}
|
||||
|
||||
{{- end}}
|
||||
|
||||
{{- if .HasSubCommands }}
|
||||
|
||||
Run '{{.CommandPath}} COMMAND --help' for more information on a command.
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"testing"
|
||||
|
||||
pluginmanager "github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/spf13/cobra"
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
)
|
||||
|
||||
func TestVisitAll(t *testing.T) {
|
||||
|
@ -55,3 +57,22 @@ func TestCommandVendor(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidPlugin(t *testing.T) {
|
||||
root := &cobra.Command{Use: "root"}
|
||||
sub1 := &cobra.Command{Use: "sub1"}
|
||||
sub1sub1 := &cobra.Command{Use: "sub1sub1"}
|
||||
sub1sub2 := &cobra.Command{Use: "sub1sub2"}
|
||||
sub2 := &cobra.Command{Use: "sub2"}
|
||||
|
||||
assert.Assert(t, is.Len(invalidPlugins(root), 0))
|
||||
|
||||
sub1.Annotations = map[string]string{
|
||||
pluginmanager.CommandAnnotationPlugin: "true",
|
||||
pluginmanager.CommandAnnotationPluginInvalid: "foo",
|
||||
}
|
||||
root.AddCommand(sub1, sub2)
|
||||
sub1.AddCommand(sub1sub1, sub1sub2)
|
||||
|
||||
assert.DeepEqual(t, invalidPlugins(root), []*cobra.Command{sub1}, cmpopts.IgnoreUnexported(cobra.Command{}))
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ func TestGlobalHelp(t *testing.T) {
|
|||
// - Each of the main headings
|
||||
// - Some builtin commands under the main headings
|
||||
// - The `helloworld` plugin in the appropriate place
|
||||
// - The `badmeta` plugin under the "Invalid Plugins" heading.
|
||||
//
|
||||
// Regexps are needed because the width depends on `unix.TIOCGWINSZ` or similar.
|
||||
for _, expected := range []*regexp.Regexp{
|
||||
|
@ -41,6 +42,8 @@ func TestGlobalHelp(t *testing.T) {
|
|||
regexp.MustCompile(`^ create\s+Create a new container$`),
|
||||
regexp.MustCompile(`^ helloworld\s+\(Docker Inc\.\)\s+A basic Hello World plugin for tests$`),
|
||||
regexp.MustCompile(`^ ps\s+List containers$`),
|
||||
regexp.MustCompile(`^Invalid Plugins:$`),
|
||||
regexp.MustCompile(`^ badmeta\s+invalid metadata: invalid character 'i' looking for beginning of object key string$`),
|
||||
} {
|
||||
var found bool
|
||||
for scanner.Scan() {
|
||||
|
|
Loading…
Reference in New Issue