2022-03-30 09:27:25 -04:00
|
|
|
package completion
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2024-07-05 08:01:07 -04:00
|
|
|
"strings"
|
2022-03-30 09:27:25 -04:00
|
|
|
|
|
|
|
"github.com/docker/cli/cli/command/formatter"
|
|
|
|
"github.com/docker/docker/api/types"
|
2023-10-13 14:34:32 -04:00
|
|
|
"github.com/docker/docker/api/types/container"
|
2024-01-24 08:32:07 -05:00
|
|
|
"github.com/docker/docker/api/types/image"
|
2024-06-04 03:17:20 -04:00
|
|
|
"github.com/docker/docker/api/types/network"
|
2023-02-07 10:52:18 -05:00
|
|
|
"github.com/docker/docker/api/types/volume"
|
2024-06-04 04:56:26 -04:00
|
|
|
"github.com/docker/docker/client"
|
2022-03-30 09:27:25 -04:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
|
|
|
// ValidArgsFn a function to be used by cobra command as `ValidArgsFunction` to offer command line completion
|
|
|
|
type ValidArgsFn func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
|
|
|
|
|
2024-06-04 04:56:26 -04:00
|
|
|
// APIClientProvider provides a method to get an [client.APIClient], initializing
|
|
|
|
// it if needed.
|
|
|
|
//
|
|
|
|
// It's a smaller interface than [command.Cli], and used in situations where an
|
|
|
|
// APIClient is needed, but we want to postpone initializing the client until
|
|
|
|
// it's used.
|
|
|
|
type APIClientProvider interface {
|
|
|
|
Client() client.APIClient
|
|
|
|
}
|
|
|
|
|
2022-03-30 09:27:25 -04:00
|
|
|
// ImageNames offers completion for images present within the local store
|
2024-06-04 04:56:26 -04:00
|
|
|
func ImageNames(dockerCLI APIClientProvider) ValidArgsFn {
|
2022-03-30 09:27:25 -04:00
|
|
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
2024-06-04 04:56:26 -04:00
|
|
|
list, err := dockerCLI.Client().ImageList(cmd.Context(), image.ListOptions{})
|
2022-03-30 09:27:25 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
var names []string
|
2024-06-04 03:17:20 -04:00
|
|
|
for _, img := range list {
|
|
|
|
names = append(names, img.RepoTags...)
|
2022-03-30 09:27:25 -04:00
|
|
|
}
|
|
|
|
return names, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContainerNames offers completion for container names and IDs
|
|
|
|
// By default, only names are returned.
|
|
|
|
// Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs.
|
2024-06-04 04:56:26 -04:00
|
|
|
func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(types.Container) bool) ValidArgsFn {
|
2022-03-30 09:27:25 -04:00
|
|
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
2024-06-04 04:56:26 -04:00
|
|
|
list, err := dockerCLI.Client().ContainerList(cmd.Context(), container.ListOptions{
|
2022-03-30 09:27:25 -04:00
|
|
|
All: all,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
|
|
|
|
showContainerIDs := os.Getenv("DOCKER_COMPLETION_SHOW_CONTAINER_IDS") == "yes"
|
|
|
|
|
|
|
|
var names []string
|
2024-06-04 03:17:20 -04:00
|
|
|
for _, ctr := range list {
|
2022-03-30 09:27:25 -04:00
|
|
|
skip := false
|
|
|
|
for _, fn := range filters {
|
2024-06-04 03:17:20 -04:00
|
|
|
if !fn(ctr) {
|
2022-03-30 09:27:25 -04:00
|
|
|
skip = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if skip {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if showContainerIDs {
|
2024-06-04 03:17:20 -04:00
|
|
|
names = append(names, ctr.ID)
|
2022-03-30 09:27:25 -04:00
|
|
|
}
|
2024-06-04 03:17:20 -04:00
|
|
|
names = append(names, formatter.StripNamePrefix(ctr.Names)...)
|
2022-03-30 09:27:25 -04:00
|
|
|
}
|
|
|
|
return names, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// VolumeNames offers completion for volumes
|
2024-06-04 04:56:26 -04:00
|
|
|
func VolumeNames(dockerCLI APIClientProvider) ValidArgsFn {
|
2022-03-30 09:27:25 -04:00
|
|
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
2024-06-04 04:56:26 -04:00
|
|
|
list, err := dockerCLI.Client().VolumeList(cmd.Context(), volume.ListOptions{})
|
2022-03-30 09:27:25 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
var names []string
|
2023-02-07 10:52:18 -05:00
|
|
|
for _, vol := range list.Volumes {
|
|
|
|
names = append(names, vol.Name)
|
2022-03-30 09:27:25 -04:00
|
|
|
}
|
|
|
|
return names, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NetworkNames offers completion for networks
|
2024-06-04 04:56:26 -04:00
|
|
|
func NetworkNames(dockerCLI APIClientProvider) ValidArgsFn {
|
2022-03-30 09:27:25 -04:00
|
|
|
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
2024-06-04 04:56:26 -04:00
|
|
|
list, err := dockerCLI.Client().NetworkList(cmd.Context(), network.ListOptions{})
|
2022-03-30 09:27:25 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, cobra.ShellCompDirectiveError
|
|
|
|
}
|
|
|
|
var names []string
|
2024-06-04 03:17:20 -04:00
|
|
|
for _, nw := range list {
|
|
|
|
names = append(names, nw.Name)
|
2022-03-30 09:27:25 -04:00
|
|
|
}
|
|
|
|
return names, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-05 08:01:07 -04:00
|
|
|
// EnvVarNames offers completion for environment-variable names. This
|
|
|
|
// completion can be used for "--env" and "--build-arg" flags, which
|
|
|
|
// allow obtaining the value of the given environment-variable if present
|
|
|
|
// in the local environment, so we only should complete the names of the
|
|
|
|
// environment variables, and not their value. This also prevents the
|
|
|
|
// completion script from printing values of environment variables
|
|
|
|
// containing sensitive values.
|
|
|
|
//
|
|
|
|
// For example;
|
|
|
|
//
|
|
|
|
// export MY_VAR=hello
|
|
|
|
// docker run --rm --env MY_VAR alpine printenv MY_VAR
|
|
|
|
// hello
|
|
|
|
func EnvVarNames(_ *cobra.Command, _ []string, _ string) (names []string, _ cobra.ShellCompDirective) {
|
|
|
|
envs := os.Environ()
|
|
|
|
names = make([]string, 0, len(envs))
|
|
|
|
for _, env := range envs {
|
|
|
|
name, _, _ := strings.Cut(env, "=")
|
|
|
|
names = append(names, name)
|
|
|
|
}
|
|
|
|
return names, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|
|
|
|
|
2024-07-05 07:42:46 -04:00
|
|
|
// FileNames is a convenience function to use [cobra.ShellCompDirectiveDefault],
|
|
|
|
// which indicates to let the shell perform its default behavior after
|
|
|
|
// completions have been provided.
|
|
|
|
func FileNames(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
|
|
|
|
return nil, cobra.ShellCompDirectiveDefault
|
|
|
|
}
|
|
|
|
|
2022-03-30 09:27:25 -04:00
|
|
|
// NoComplete is used for commands where there's no relevant completion
|
2024-06-04 03:17:20 -04:00
|
|
|
func NoComplete(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
|
2022-03-30 09:27:25 -04:00
|
|
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
|
|
|
}
|