Merge pull request #6444 from thaJeztah/inspect_completion

cli/command/system: add shell completion for "docker inspect"
This commit is contained in:
Sebastiaan van Stijn
2025-09-10 11:36:23 +02:00
committed by GitHub
2 changed files with 121 additions and 1 deletions

View File

@ -1,10 +1,14 @@
package system
import (
"fmt"
"strings"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/cli/command/idresolver"
"github.com/moby/moby/api/types/events"
"github.com/moby/moby/api/types/filters"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/client"
"github.com/spf13/cobra"
)
@ -157,6 +161,20 @@ func validEventNames() []string {
return names
}
// configNames contacts the API to get a list of config names.
// In case of an error, an empty list is returned.
func configNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
list, err := dockerCLI.Client().ConfigList(cmd.Context(), client.ConfigListOptions{})
if err != nil {
return []string{}
}
names := make([]string, 0, len(list))
for _, v := range list {
names = append(names, v.Spec.Name)
}
return names
}
// containerNames contacts the API to get names and optionally IDs of containers.
// In case of an error, an empty list is returned.
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
return names
}
// pluginNames contacts the API to get a list of plugin names.
// In case of an error, an empty list is returned.
func pluginNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
list, err := dockerCLI.Client().PluginList(cmd.Context(), filters.Args{})
if err != nil {
return []string{}
}
names := make([]string, 0, len(list))
for _, v := range list {
names = append(names, v.Name)
}
return names
}
// secretNames contacts the API to get a list of secret names.
// In case of an error, an empty list is returned.
func secretNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
list, err := dockerCLI.Client().SecretList(cmd.Context(), client.SecretListOptions{})
if err != nil {
return []string{}
}
names := make([]string, 0, len(list))
for _, v := range list {
names = append(names, v.Spec.Name)
}
return names
}
// serviceNames contacts the API to get a list of service names.
// In case of an error, an empty list is returned.
func serviceNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
list, err := dockerCLI.Client().ServiceList(cmd.Context(), client.ServiceListOptions{})
if err != nil {
return []string{}
}
names := make([]string, 0, len(list))
for _, v := range list {
names = append(names, v.Spec.Name)
}
return names
}
// taskNames contacts the API to get a list of service names.
// In case of an error, an empty list is returned.
func taskNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
list, err := dockerCLI.Client().TaskList(cmd.Context(), client.TaskListOptions{})
if err != nil || len(list) == 0 {
return []string{}
}
resolver := idresolver.New(dockerCLI.Client(), false)
names := make([]string, 0, len(list))
for _, task := range list {
serviceName, err := resolver.Resolve(cmd.Context(), swarm.Service{}, task.ServiceID)
if err != nil {
continue
}
if task.Slot != 0 {
names = append(names, fmt.Sprintf("%v.%v", serviceName, task.Slot))
} else {
names = append(names, fmt.Sprintf("%v.%v", serviceName, task.NodeID))
}
}
return names
}
// volumeNames contacts the API to get a list of volume names.
// In case of an error, an empty list is returned.
func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []string {
@ -232,3 +316,39 @@ func volumeNames(dockerCLI completion.APIClientProvider, cmd *cobra.Command) []s
}
return names
}
// completeObjectNames completes names of objects based on the "--type" flag
//
// TODO(thaJeztah): completion functions in this package don't remove names that have already been completed
// this causes completion to continue even if a given name was already completed.
func completeObjectNames(dockerCLI completion.APIClientProvider) cobra.CompletionFunc {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if f := cmd.Flags().Lookup("type"); f != nil && f.Changed {
switch f.Value.String() {
case typeConfig:
return configNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeContainer:
return containerNames(dockerCLI, cmd, args, toComplete), cobra.ShellCompDirectiveNoFileComp
case typeImage:
return imageNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeNetwork:
return networkNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeNode:
return nodeNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typePlugin:
return pluginNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeSecret:
return secretNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeService:
return serviceNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeTask:
return taskNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
case typeVolume:
return volumeNames(dockerCLI, cmd), cobra.ShellCompDirectiveNoFileComp
default:
return nil, cobra.ShellCompDirectiveNoFileComp
}
}
return nil, cobra.ShellCompDirectiveNoFileComp
}
}

View File

@ -72,7 +72,7 @@ func newInspectCommand(dockerCLI command.Cli) *cobra.Command {
return runInspect(cmd.Context(), dockerCLI, opts)
},
// TODO(thaJeztah): should we consider adding completion for common object-types? (images, containers?)
ValidArgsFunction: cobra.NoFileCompletions,
ValidArgsFunction: completeObjectNames(dockerCLI),
DisableFlagsInUseLine: true,
}