Merge pull request #5111 from thaJeztah/completion_use_apiClient

cli/command: use shallower interface for completions
This commit is contained in:
Sebastiaan van Stijn 2024-06-04 13:42:03 +02:00 committed by GitHub
commit 8b924a5119
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 35 additions and 24 deletions

View File

@ -3,23 +3,33 @@ package completion
import ( import (
"os" "os"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/formatter" "github.com/docker/cli/cli/command/formatter"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image" "github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume" "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/client"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// ValidArgsFn a function to be used by cobra command as `ValidArgsFunction` to offer command line completion // 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) type ValidArgsFn func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective)
// 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
}
// ImageNames offers completion for images present within the local store // ImageNames offers completion for images present within the local store
func ImageNames(dockerCli command.Cli) ValidArgsFn { func ImageNames(dockerCLI APIClientProvider) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().ImageList(cmd.Context(), image.ListOptions{}) list, err := dockerCLI.Client().ImageList(cmd.Context(), image.ListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }
@ -34,9 +44,9 @@ func ImageNames(dockerCli command.Cli) ValidArgsFn {
// ContainerNames offers completion for container names and IDs // ContainerNames offers completion for container names and IDs
// By default, only names are returned. // By default, only names are returned.
// Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs. // Set DOCKER_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs.
func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Container) bool) ValidArgsFn { func ContainerNames(dockerCLI APIClientProvider, all bool, filters ...func(types.Container) bool) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().ContainerList(cmd.Context(), container.ListOptions{ list, err := dockerCLI.Client().ContainerList(cmd.Context(), container.ListOptions{
All: all, All: all,
}) })
if err != nil { if err != nil {
@ -67,9 +77,9 @@ func ContainerNames(dockerCli command.Cli, all bool, filters ...func(types.Conta
} }
// VolumeNames offers completion for volumes // VolumeNames offers completion for volumes
func VolumeNames(dockerCli command.Cli) ValidArgsFn { func VolumeNames(dockerCLI APIClientProvider) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().VolumeList(cmd.Context(), volume.ListOptions{}) list, err := dockerCLI.Client().VolumeList(cmd.Context(), volume.ListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }
@ -82,9 +92,9 @@ func VolumeNames(dockerCli command.Cli) ValidArgsFn {
} }
// NetworkNames offers completion for networks // NetworkNames offers completion for networks
func NetworkNames(dockerCli command.Cli) ValidArgsFn { func NetworkNames(dockerCLI APIClientProvider) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().NetworkList(cmd.Context(), network.ListOptions{}) list, err := dockerCLI.Client().NetworkList(cmd.Context(), network.ListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@ -30,9 +30,9 @@ func NewConfigCommand(dockerCli command.Cli) *cobra.Command {
} }
// completeNames offers completion for swarm configs // completeNames offers completion for swarm configs
func completeNames(dockerCli command.Cli) completion.ValidArgsFn { func completeNames(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().ConfigList(cmd.Context(), types.ConfigListOptions{}) list, err := dockerCLI.Client().ConfigList(cmd.Context(), types.ConfigListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@ -30,9 +30,9 @@ func NewSecretCommand(dockerCli command.Cli) *cobra.Command {
} }
// completeNames offers completion for swarm secrets // completeNames offers completion for swarm secrets
func completeNames(dockerCli command.Cli) completion.ValidArgsFn { func completeNames(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().SecretList(cmd.Context(), types.SecretListOptions{}) list, err := dockerCLI.Client().SecretList(cmd.Context(), types.SecretListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@ -35,9 +35,9 @@ func NewServiceCommand(dockerCli command.Cli) *cobra.Command {
} }
// CompletionFn offers completion for swarm services // CompletionFn offers completion for swarm services
func CompletionFn(dockerCli command.Cli) completion.ValidArgsFn { func CompletionFn(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := dockerCli.Client().ServiceList(cmd.Context(), types.ServiceListOptions{}) list, err := dockerCLI.Client().ServiceList(cmd.Context(), types.ServiceListOptions{})
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@ -46,9 +46,9 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
} }
// completeNames offers completion for swarm stacks // completeNames offers completion for swarm stacks
func completeNames(dockerCli command.Cli) completion.ValidArgsFn { func completeNames(dockerCLI completion.APIClientProvider) completion.ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
list, err := swarm.GetStacks(cmd.Context(), dockerCli) list, err := swarm.GetStacks(cmd.Context(), dockerCLI.Client())
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@ -2,6 +2,7 @@ package stack
import ( import (
"context" "context"
"io"
"sort" "sort"
"github.com/docker/cli/cli" "github.com/docker/cli/cli"
@ -36,22 +37,22 @@ func newListCommand(dockerCli command.Cli) *cobra.Command {
// RunList performs a stack list against the specified swarm cluster // RunList performs a stack list against the specified swarm cluster
func RunList(ctx context.Context, dockerCli command.Cli, opts options.List) error { func RunList(ctx context.Context, dockerCli command.Cli, opts options.List) error {
ss, err := swarm.GetStacks(ctx, dockerCli) ss, err := swarm.GetStacks(ctx, dockerCli.Client())
if err != nil { if err != nil {
return err return err
} }
stacks := make([]*formatter.Stack, 0, len(ss)) stacks := make([]*formatter.Stack, 0, len(ss))
stacks = append(stacks, ss...) stacks = append(stacks, ss...)
return format(dockerCli, opts, stacks) return format(dockerCli.Out(), opts, stacks)
} }
func format(dockerCli command.Cli, opts options.List, stacks []*formatter.Stack) error { func format(out io.Writer, opts options.List, stacks []*formatter.Stack) error {
fmt := formatter.Format(opts.Format) fmt := formatter.Format(opts.Format)
if fmt == "" || fmt == formatter.TableFormatKey { if fmt == "" || fmt == formatter.TableFormatKey {
fmt = formatter.SwarmStackTableFormat fmt = formatter.SwarmStackTableFormat
} }
stackCtx := formatter.Context{ stackCtx := formatter.Context{
Output: dockerCli.Out(), Output: out,
Format: fmt, Format: fmt,
} }
sort.Slice(stacks, func(i, j int) bool { sort.Slice(stacks, func(i, j int) bool {

View File

@ -3,16 +3,16 @@ package swarm
import ( import (
"context" "context"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/stack/formatter" "github.com/docker/cli/cli/command/stack/formatter"
"github.com/docker/cli/cli/compose/convert" "github.com/docker/cli/cli/compose/convert"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// GetStacks lists the swarm stacks. // GetStacks lists the swarm stacks.
func GetStacks(ctx context.Context, dockerCli command.Cli) ([]*formatter.Stack, error) { func GetStacks(ctx context.Context, apiClient client.ServiceAPIClient) ([]*formatter.Stack, error) {
services, err := dockerCli.Client().ServiceList( services, err := apiClient.ServiceList(
ctx, ctx,
types.ServiceListOptions{Filters: getAllStacksFilter()}) types.ServiceListOptions{Filters: getAllStacksFilter()})
if err != nil { if err != nil {