Skip to content

Commit 8b23c2b

Browse files
authored
Merge pull request #6444 from thaJeztah/inspect_completion
cli/command/system: add shell completion for "docker inspect"
2 parents 69972b6 + 8bb5595 commit 8b23c2b

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

cli/command/system/completion.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package system
22

33
import (
4+
"fmt"
45
"strings"
56

67
"github.com/docker/cli/cli/command/completion"
8+
"github.com/docker/cli/cli/command/idresolver"
79
"github.com/moby/moby/api/types/events"
10+
"github.com/moby/moby/api/types/filters"
11+
"github.com/moby/moby/api/types/swarm"
812
"github.com/moby/moby/client"
913
"github.com/spf13/cobra"
1014
)
@@ -157,6 +161,20 @@ func validEventNames() []string {
157161
return names
158162
}
159163

164+
// configNames contacts the API to get a list of config names.
165+
// In case of an error, an empty list is returned.
166+
func configNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
167+
list, err := dockerCLI.Client().ConfigList(cmd.Context(), client.ConfigListOptions{})
168+
if err != nil {
169+
return []string{}
170+
}
171+
names := make([]string, 0, len(list))
172+
for _, v := range list {
173+
names = append(names, v.Spec.Name)
174+
}
175+
return names
176+
}
177+
160178
// containerNames contacts the API to get names and optionally IDs of containers.
161179
// In case of an error, an empty list is returned.
162180
func containerNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command, args []string, toComplete string) []string {
@@ -219,6 +237,72 @@ func nodeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []str
219237
return names
220238
}
221239

240+
// pluginNames contacts the API to get a list of plugin names.
241+
// In case of an error, an empty list is returned.
242+
func pluginNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
243+
list, err := dockerCLI.Client().PluginList(cmd.Context(), filters.Args{})
244+
if err != nil {
245+
return []string{}
246+
}
247+
names := make([]string, 0, len(list))
248+
for _, v := range list {
249+
names = append(names, v.Name)
250+
}
251+
return names
252+
}
253+
254+
// secretNames contacts the API to get a list of secret names.
255+
// In case of an error, an empty list is returned.
256+
func secretNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
257+
list, err := dockerCLI.Client().SecretList(cmd.Context(), client.SecretListOptions{})
258+
if err != nil {
259+
return []string{}
260+
}
261+
names := make([]string, 0, len(list))
262+
for _, v := range list {
263+
names = append(names, v.Spec.Name)
264+
}
265+
return names
266+
}
267+
268+
// serviceNames contacts the API to get a list of service names.
269+
// In case of an error, an empty list is returned.
270+
func serviceNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
271+
list, err := dockerCLI.Client().ServiceList(cmd.Context(), client.ServiceListOptions{})
272+
if err != nil {
273+
return []string{}
274+
}
275+
names := make([]string, 0, len(list))
276+
for _, v := range list {
277+
names = append(names, v.Spec.Name)
278+
}
279+
return names
280+
}
281+
282+
// taskNames contacts the API to get a list of service names.
283+
// In case of an error, an empty list is returned.
284+
func taskNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
285+
list, err := dockerCLI.Client().TaskList(cmd.Context(), client.TaskListOptions{})
286+
if err != nil || len(list) == 0 {
287+
return []string{}
288+
}
289+
290+
resolver := idresolver.New(dockerCLI.Client(), false)
291+
names := make([]string, 0, len(list))
292+
for _, task := range list {
293+
serviceName, err := resolver.Resolve(cmd.Context(), swarm.Service{}, task.ServiceID)
294+
if err != nil {
295+
continue
296+
}
297+
if task.Slot != 0 {
298+
names = append(names, fmt.Sprintf("%v.%v", serviceName, task.Slot))
299+
} else {
300+
names = append(names, fmt.Sprintf("%v.%v", serviceName, task.NodeID))
301+
}
302+
}
303+
return names
304+
}
305+
222306
// volumeNames contacts the API to get a list of volume names.
223307
// In case of an error, an empty list is returned.
224308
func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
@@ -232,3 +316,39 @@ func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []s
232316
}
233317
return names
234318
}
319+
320+
// completeObjectNames completes names of objects based on the "--type" flag
321+
//
322+
// TODO(thaJeztah): completion functions in this package don't remove names that have already been completed
323+
// this causes completion to continue even if a given name was already completed.
324+
func completeObjectNames(dockerCLI completion.APIClientProvider) cobra.CompletionFunc {
325+
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
326+
if f := cmd.Flags().Lookup("type"); f != nil && f.Changed {
327+
switch f.Value.String() {
328+
case typeConfig:
329+
return configNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
330+
case typeContainer:
331+
return containerNames(dockerCLI, cmd, args, toComplete), cobra.ShellCompDirectiveNoFileComp
332+
case typeImage:
333+
return imageNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
334+
case typeNetwork:
335+
return networkNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
336+
case typeNode:
337+
return nodeNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
338+
case typePlugin:
339+
return pluginNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
340+
case typeSecret:
341+
return secretNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
342+
case typeService:
343+
return serviceNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
344+
case typeTask:
345+
return taskNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
346+
case typeVolume:
347+
return volumeNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
348+
default:
349+
return nil, cobra.ShellCompDirectiveNoFileComp
350+
}
351+
}
352+
return nil, cobra.ShellCompDirectiveNoFileComp
353+
}
354+
}

cli/command/system/inspect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func newInspectCommand(dockerCLI command.Cli) *cobra.Command {
7272
return runInspect(cmd.Context(), dockerCLI, opts)
7373
},
7474
// TODO(thaJeztah): should we consider adding completion for common object-types? (images, containers?)
75-
ValidArgsFunction: cobra.NoFileCompletions,
75+
ValidArgsFunction: completeObjectNames(dockerCLI),
7676
DisableFlagsInUseLine: true,
7777
}
7878

0 commit comments

Comments
 (0)