mirror of https://github.com/docker/cli.git
cli/command: use shallower interface for completions
The completion functions only need the API-client, and not all of the CLI. However, passing the API-client as argument would mean that the API-client is initialized early, which may not be what we want, so instead, defining an APIClientProvider interface to preserve the behavior of initializing when needed only. While updating, also simplify stack.format to only require an io.Writer. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
ce85b24440
commit
20d1b661bc
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue