Skip to content

Commit 9201360

Browse files
author
Ulysses Souza
committed
Refactor plugins' vendor location on --help
- The placement of the vendor is now in the end of the line. - A '*' is now added as suffix of plugins' top level commands. Signed-off-by: Ulysses Souza <[email protected]>
1 parent db166da commit 9201360

4 files changed

Lines changed: 46 additions & 24 deletions

File tree

cli-plugins/manager/cobra.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ const (
1616
// that plugin.
1717
CommandAnnotationPluginVendor = "com.docker.cli.plugin.vendor"
1818

19+
// CommandAnnotationPluginVersion is added to every stub command
20+
// added by AddPluginCommandStubs and contains the version of
21+
// that plugin.
22+
CommandAnnotationPluginVersion = "com.docker.cli.plugin.version"
23+
1924
// CommandAnnotationPluginInvalid is added to any stub command
2025
// added by AddPluginCommandStubs for an invalid command (that
2126
// is, one which failed it's candidate test) and contains the
@@ -37,8 +42,9 @@ func AddPluginCommandStubs(dockerCli command.Cli, cmd *cobra.Command) error {
3742
vendor = "unknown"
3843
}
3944
annotations := map[string]string{
40-
CommandAnnotationPlugin: "true",
41-
CommandAnnotationPluginVendor: vendor,
45+
CommandAnnotationPlugin: "true",
46+
CommandAnnotationPluginVendor: vendor,
47+
CommandAnnotationPluginVersion: p.Version,
4248
}
4349
if p.Err != nil {
4450
annotations[CommandAnnotationPluginInvalid] = p.Err.Error()

cli/cobra.go

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,18 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *p
2222
flags.StringVar(&opts.ConfigDir, "config", cliconfig.Dir(), "Location of client config files")
2323
opts.Common.InstallFlags(flags)
2424

25+
cobra.AddTemplateFunc("add", func(a, b int) int { return a + b })
2526
cobra.AddTemplateFunc("hasSubCommands", hasSubCommands)
2627
cobra.AddTemplateFunc("hasManagementSubCommands", hasManagementSubCommands)
2728
cobra.AddTemplateFunc("hasInvalidPlugins", hasInvalidPlugins)
2829
cobra.AddTemplateFunc("operationSubCommands", operationSubCommands)
2930
cobra.AddTemplateFunc("managementSubCommands", managementSubCommands)
3031
cobra.AddTemplateFunc("invalidPlugins", invalidPlugins)
3132
cobra.AddTemplateFunc("wrappedFlagUsages", wrappedFlagUsages)
32-
cobra.AddTemplateFunc("commandVendor", commandVendor)
33-
cobra.AddTemplateFunc("isFirstLevelCommand", isFirstLevelCommand) // is it an immediate sub-command of the root
33+
cobra.AddTemplateFunc("vendorAndVersion", vendorAndVersion)
3434
cobra.AddTemplateFunc("invalidPluginReason", invalidPluginReason)
35+
cobra.AddTemplateFunc("isPlugin", isPlugin)
36+
cobra.AddTemplateFunc("decoratedName", decoratedName)
3537

3638
rootCmd.SetUsageTemplate(usageTemplate)
3739
rootCmd.SetHelpTemplate(helpTemplate)
@@ -155,19 +157,23 @@ func wrappedFlagUsages(cmd *cobra.Command) string {
155157
return cmd.Flags().FlagUsagesWrapped(width - 1)
156158
}
157159

158-
func isFirstLevelCommand(cmd *cobra.Command) bool {
159-
return cmd.Parent() == cmd.Root()
160+
func decoratedName(cmd *cobra.Command) string {
161+
decoration := " "
162+
if isPlugin(cmd) {
163+
decoration = "*"
164+
}
165+
return cmd.Name() + decoration
160166
}
161167

162-
func commandVendor(cmd *cobra.Command) string {
163-
width := 13
164-
if v, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVendor]; ok {
165-
if len(v) > width-2 {
166-
v = v[:width-3] + "…"
168+
func vendorAndVersion(cmd *cobra.Command) string {
169+
if vendor, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVendor]; ok && isPlugin(cmd) {
170+
version := ""
171+
if v, ok := cmd.Annotations[pluginmanager.CommandAnnotationPluginVersion]; ok && v != "" {
172+
version = ", " + v
167173
}
168-
return fmt.Sprintf("%-*s", width, "("+v+")")
174+
return fmt.Sprintf("(%s%s)", vendor, version)
169175
}
170-
return strings.Repeat(" ", width)
176+
return ""
171177
}
172178

173179
func managementSubCommands(cmd *cobra.Command) []*cobra.Command {
@@ -230,7 +236,7 @@ Options:
230236
Management Commands:
231237
232238
{{- range managementSubCommands . }}
233-
{{rpad .Name .NamePadding }} {{ if isFirstLevelCommand .}}{{commandVendor .}} {{ end}}{{.Short}}
239+
{{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}}
234240
{{- end}}
235241
236242
{{- end}}
@@ -239,7 +245,7 @@ Management Commands:
239245
Commands:
240246
241247
{{- range operationSubCommands . }}
242-
{{rpad .Name .NamePadding }} {{ if isFirstLevelCommand .}}{{commandVendor .}} {{ end}}{{.Short}}
248+
{{rpad (decoratedName .) (add .NamePadding 1)}}{{.Short}}{{ if isPlugin .}} {{vendorAndVersion .}}{{ end}}
243249
{{- end}}
244250
{{- end}}
245251

cli/cobra_test.go

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,28 +32,29 @@ func TestVisitAll(t *testing.T) {
3232
assert.DeepEqual(t, expected, visited)
3333
}
3434

35-
func TestCommandVendor(t *testing.T) {
35+
func TestVendorAndVersion(t *testing.T) {
3636
// Non plugin.
37-
assert.Equal(t, commandVendor(&cobra.Command{Use: "test"}), " ")
37+
assert.Equal(t, vendorAndVersion(&cobra.Command{Use: "test"}), "")
3838

3939
// Plugins with various lengths of vendor.
4040
for _, tc := range []struct {
4141
vendor string
42+
version string
4243
expected string
4344
}{
44-
{vendor: "vendor", expected: "(vendor) "},
45-
{vendor: "vendor12345", expected: "(vendor12345)"},
46-
{vendor: "vendor123456", expected: "(vendor1234…)"},
47-
{vendor: "vendor1234567", expected: "(vendor1234…)"},
45+
{vendor: "vendor", expected: "(vendor)"},
46+
{vendor: "vendor", version: "testing", expected: "(vendor, testing)"},
4847
} {
4948
t.Run(tc.vendor, func(t *testing.T) {
5049
cmd := &cobra.Command{
5150
Use: "test",
5251
Annotations: map[string]string{
53-
pluginmanager.CommandAnnotationPluginVendor: tc.vendor,
52+
pluginmanager.CommandAnnotationPlugin: "true",
53+
pluginmanager.CommandAnnotationPluginVendor: tc.vendor,
54+
pluginmanager.CommandAnnotationPluginVersion: tc.version,
5455
},
5556
}
56-
assert.Equal(t, commandVendor(cmd), tc.expected)
57+
assert.Equal(t, vendorAndVersion(cmd), tc.expected)
5758
})
5859
}
5960
}
@@ -76,3 +77,12 @@ func TestInvalidPlugin(t *testing.T) {
7677

7778
assert.DeepEqual(t, invalidPlugins(root), []*cobra.Command{sub1}, cmpopts.IgnoreUnexported(cobra.Command{}))
7879
}
80+
81+
func TestDecoratedName(t *testing.T) {
82+
root := &cobra.Command{Use: "root"}
83+
topLevelCommand := &cobra.Command{Use: "pluginTopLevelCommand"}
84+
root.AddCommand(topLevelCommand)
85+
assert.Equal(t, decoratedName(topLevelCommand), "pluginTopLevelCommand ")
86+
topLevelCommand.Annotations = map[string]string{pluginmanager.CommandAnnotationPlugin: "true"}
87+
assert.Equal(t, decoratedName(topLevelCommand), "pluginTopLevelCommand*")
88+
}

e2e/cli-plugins/help_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestGlobalHelp(t *testing.T) {
3434
// - The `badmeta` plugin under the "Invalid Plugins" heading.
3535
//
3636
// Regexps are needed because the width depends on `unix.TIOCGWINSZ` or similar.
37-
helloworldre := regexp.MustCompile(`^ helloworld\s+\(Docker Inc\.\)\s+A basic Hello World plugin for tests$`)
37+
helloworldre := regexp.MustCompile(`^ helloworld\*\s+A basic Hello World plugin for tests \(Docker Inc\., testing\)$`)
3838
badmetare := regexp.MustCompile(`^ badmeta\s+invalid metadata: invalid character 'i' looking for beginning of object key string$`)
3939
var helloworldcount, badmetacount int
4040
for _, expected := range []*regexp.Regexp{

0 commit comments

Comments
 (0)