cli/command/container: rename some variables

Rename some variables to prevent shadowing and for clarity.
Also made some minor formatting changes.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2024-06-09 14:34:01 +02:00
parent 1a83595c7c
commit 851277f966
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
2 changed files with 57 additions and 66 deletions

View File

@ -433,18 +433,18 @@ func copyToContainer(ctx context.Context, dockerCli command.Cli, copyConfig cpCo
// so we have to check for a `/` or `.` prefix. Also, in the case of a Windows // so we have to check for a `/` or `.` prefix. Also, in the case of a Windows
// client, a `:` could be part of an absolute Windows path, in which case it // client, a `:` could be part of an absolute Windows path, in which case it
// is immediately proceeded by a backslash. // is immediately proceeded by a backslash.
func splitCpArg(arg string) (container, path string) { func splitCpArg(arg string) (ctr, path string) {
if system.IsAbs(arg) { if system.IsAbs(arg) {
// Explicit local absolute path, e.g., `C:\foo` or `/foo`. // Explicit local absolute path, e.g., `C:\foo` or `/foo`.
return "", arg return "", arg
} }
container, path, ok := strings.Cut(arg, ":") ctr, path, ok := strings.Cut(arg, ":")
if !ok || strings.HasPrefix(container, ".") { if !ok || strings.HasPrefix(ctr, ".") {
// Either there's no `:` in the arg // Either there's no `:` in the arg
// OR it's an explicit local relative path like `./file:name.txt`. // OR it's an explicit local relative path like `./file:name.txt`.
return "", arg return "", arg
} }
return container, path return ctr, path
} }

View File

@ -12,7 +12,7 @@ import (
"github.com/docker/cli/cli/config/configfile" "github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
apiclient "github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -43,19 +43,18 @@ func NewExecOptions() ExecOptions {
// NewExecCommand creates a new cobra.Command for `docker exec` // NewExecCommand creates a new cobra.Command for `docker exec`
func NewExecCommand(dockerCli command.Cli) *cobra.Command { func NewExecCommand(dockerCli command.Cli) *cobra.Command {
options := NewExecOptions() options := NewExecOptions()
var container string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "exec [OPTIONS] CONTAINER COMMAND [ARG...]", Use: "exec [OPTIONS] CONTAINER COMMAND [ARG...]",
Short: "Execute a command in a running container", Short: "Execute a command in a running container",
Args: cli.RequiresMinArgs(2), Args: cli.RequiresMinArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
container = args[0] containerIDorName := args[0]
options.Command = args[1:] options.Command = args[1:]
return RunExec(cmd.Context(), dockerCli, container, options) return RunExec(cmd.Context(), dockerCli, containerIDorName, options)
}, },
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool { ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(ctr types.Container) bool {
return container.State != "paused" return ctr.State != "paused"
}), }),
Annotations: map[string]string{ Annotations: map[string]string{
"category-top": "2", "category-top": "2",
@ -79,47 +78,41 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
flags.StringVarP(&options.Workdir, "workdir", "w", "", "Working directory inside the container") flags.StringVarP(&options.Workdir, "workdir", "w", "", "Working directory inside the container")
flags.SetAnnotation("workdir", "version", []string{"1.35"}) flags.SetAnnotation("workdir", "version", []string{"1.35"})
cmd.RegisterFlagCompletionFunc( _ = cmd.RegisterFlagCompletionFunc("env", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
"env", return os.Environ(), cobra.ShellCompDirectiveNoFileComp
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { })
return os.Environ(), cobra.ShellCompDirectiveNoFileComp _ = cmd.RegisterFlagCompletionFunc("env-file", func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective) {
}, return nil, cobra.ShellCompDirectiveDefault // _filedir
) })
cmd.RegisterFlagCompletionFunc(
"env-file",
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveDefault // _filedir
},
)
return cmd return cmd
} }
// RunExec executes an `exec` command // RunExec executes an `exec` command
func RunExec(ctx context.Context, dockerCli command.Cli, container string, options ExecOptions) error { func RunExec(ctx context.Context, dockerCli command.Cli, containerIDorName string, options ExecOptions) error {
execConfig, err := parseExec(options, dockerCli.ConfigFile()) execOptions, err := parseExec(options, dockerCli.ConfigFile())
if err != nil { if err != nil {
return err return err
} }
client := dockerCli.Client() apiClient := dockerCli.Client()
// We need to check the tty _before_ we do the ContainerExecCreate, because // We need to check the tty _before_ we do the ContainerExecCreate, because
// otherwise if we error out we will leak execIDs on the server (and // otherwise if we error out we will leak execIDs on the server (and
// there's no easy way to clean those up). But also in order to make "not // there's no easy way to clean those up). But also in order to make "not
// exist" errors take precedence we do a dummy inspect first. // exist" errors take precedence we do a dummy inspect first.
if _, err := client.ContainerInspect(ctx, container); err != nil { if _, err := apiClient.ContainerInspect(ctx, containerIDorName); err != nil {
return err return err
} }
if !execConfig.Detach { if !execOptions.Detach {
if err := dockerCli.In().CheckTty(execConfig.AttachStdin, execConfig.Tty); err != nil { if err := dockerCli.In().CheckTty(execOptions.AttachStdin, execOptions.Tty); err != nil {
return err return err
} }
} }
fillConsoleSize(execConfig, dockerCli) fillConsoleSize(execOptions, dockerCli)
response, err := client.ContainerExecCreate(ctx, container, *execConfig) response, err := apiClient.ContainerExecCreate(ctx, containerIDorName, *execOptions)
if err != nil { if err != nil {
return err return err
} }
@ -129,15 +122,14 @@ func RunExec(ctx context.Context, dockerCli command.Cli, container string, optio
return errors.New("exec ID empty") return errors.New("exec ID empty")
} }
if execConfig.Detach { if execOptions.Detach {
execStartCheck := types.ExecStartCheck{ return apiClient.ContainerExecStart(ctx, execID, types.ExecStartCheck{
Detach: execConfig.Detach, Detach: execOptions.Detach,
Tty: execConfig.Tty, Tty: execOptions.Tty,
ConsoleSize: execConfig.ConsoleSize, ConsoleSize: execOptions.ConsoleSize,
} })
return client.ContainerExecStart(ctx, execID, execStartCheck)
} }
return interactiveExec(ctx, dockerCli, execConfig, execID) return interactiveExec(ctx, dockerCli, execOptions, execID)
} }
func fillConsoleSize(execConfig *types.ExecConfig, dockerCli command.Cli) { func fillConsoleSize(execConfig *types.ExecConfig, dockerCli command.Cli) {
@ -147,34 +139,33 @@ func fillConsoleSize(execConfig *types.ExecConfig, dockerCli command.Cli) {
} }
} }
func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *types.ExecConfig, execID string) error { func interactiveExec(ctx context.Context, dockerCli command.Cli, execOptions *types.ExecConfig, execID string) error {
// Interactive exec requested. // Interactive exec requested.
var ( var (
out, stderr io.Writer out, stderr io.Writer
in io.ReadCloser in io.ReadCloser
) )
if execConfig.AttachStdin { if execOptions.AttachStdin {
in = dockerCli.In() in = dockerCli.In()
} }
if execConfig.AttachStdout { if execOptions.AttachStdout {
out = dockerCli.Out() out = dockerCli.Out()
} }
if execConfig.AttachStderr { if execOptions.AttachStderr {
if execConfig.Tty { if execOptions.Tty {
stderr = dockerCli.Out() stderr = dockerCli.Out()
} else { } else {
stderr = dockerCli.Err() stderr = dockerCli.Err()
} }
} }
fillConsoleSize(execConfig, dockerCli) fillConsoleSize(execOptions, dockerCli)
client := dockerCli.Client() apiClient := dockerCli.Client()
execStartCheck := types.ExecStartCheck{ resp, err := apiClient.ContainerExecAttach(ctx, execID, types.ExecStartCheck{
Tty: execConfig.Tty, Tty: execOptions.Tty,
ConsoleSize: execConfig.ConsoleSize, ConsoleSize: execOptions.ConsoleSize,
} })
resp, err := client.ContainerExecAttach(ctx, execID, execStartCheck)
if err != nil { if err != nil {
return err return err
} }
@ -191,17 +182,17 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *typ
outputStream: out, outputStream: out,
errorStream: stderr, errorStream: stderr,
resp: resp, resp: resp,
tty: execConfig.Tty, tty: execOptions.Tty,
detachKeys: execConfig.DetachKeys, detachKeys: execOptions.DetachKeys,
} }
return streamer.stream(ctx) return streamer.stream(ctx)
}() }()
}() }()
if execConfig.Tty && dockerCli.In().IsTerminal() { if execOptions.Tty && dockerCli.In().IsTerminal() {
if err := MonitorTtySize(ctx, dockerCli, execID, true); err != nil { if err := MonitorTtySize(ctx, dockerCli, execID, true); err != nil {
fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err) _, _ = fmt.Fprintln(dockerCli.Err(), "Error monitoring TTY size:", err)
} }
} }
@ -210,14 +201,14 @@ func interactiveExec(ctx context.Context, dockerCli command.Cli, execConfig *typ
return err return err
} }
return getExecExitStatus(ctx, client, execID) return getExecExitStatus(ctx, apiClient, execID)
} }
func getExecExitStatus(ctx context.Context, client apiclient.ContainerAPIClient, execID string) error { func getExecExitStatus(ctx context.Context, apiClient client.ContainerAPIClient, execID string) error {
resp, err := client.ContainerExecInspect(ctx, execID) resp, err := apiClient.ContainerExecInspect(ctx, execID)
if err != nil { if err != nil {
// If we can't connect, then the daemon probably died. // If we can't connect, then the daemon probably died.
if !apiclient.IsErrConnectionFailed(err) { if !client.IsErrConnectionFailed(err) {
return err return err
} }
return cli.StatusError{StatusCode: -1} return cli.StatusError{StatusCode: -1}
@ -232,7 +223,7 @@ func getExecExitStatus(ctx context.Context, client apiclient.ContainerAPIClient,
// parseExec parses the specified args for the specified command and generates // parseExec parses the specified args for the specified command and generates
// an ExecConfig from it. // an ExecConfig from it.
func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*types.ExecConfig, error) { func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*types.ExecConfig, error) {
execConfig := &types.ExecConfig{ execOptions := &types.ExecConfig{
User: execOpts.User, User: execOpts.User,
Privileged: execOpts.Privileged, Privileged: execOpts.Privileged,
Tty: execOpts.TTY, Tty: execOpts.TTY,
@ -243,23 +234,23 @@ func parseExec(execOpts ExecOptions, configFile *configfile.ConfigFile) (*types.
// collect all the environment variables for the container // collect all the environment variables for the container
var err error var err error
if execConfig.Env, err = opts.ReadKVEnvStrings(execOpts.EnvFile.GetAll(), execOpts.Env.GetAll()); err != nil { if execOptions.Env, err = opts.ReadKVEnvStrings(execOpts.EnvFile.GetAll(), execOpts.Env.GetAll()); err != nil {
return nil, err return nil, err
} }
// If -d is not set, attach to everything by default // If -d is not set, attach to everything by default
if !execOpts.Detach { if !execOpts.Detach {
execConfig.AttachStdout = true execOptions.AttachStdout = true
execConfig.AttachStderr = true execOptions.AttachStderr = true
if execOpts.Interactive { if execOpts.Interactive {
execConfig.AttachStdin = true execOptions.AttachStdin = true
} }
} }
if execOpts.DetachKeys != "" { if execOpts.DetachKeys != "" {
execConfig.DetachKeys = execOpts.DetachKeys execOptions.DetachKeys = execOpts.DetachKeys
} else { } else {
execConfig.DetachKeys = configFile.DetachKeys execOptions.DetachKeys = configFile.DetachKeys
} }
return execConfig, nil return execOptions, nil
} }