mirror of https://github.com/docker/cli.git
make runAttach public and allow passing context
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
9cb175f02a
commit
a4abe42cbd
|
@ -17,12 +17,13 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type attachOptions struct {
|
||||
noStdin bool
|
||||
proxy bool
|
||||
detachKeys string
|
||||
// AttachOptions group options for `attach` command
|
||||
type AttachOptions struct {
|
||||
NoStdin bool
|
||||
Proxy bool
|
||||
DetachKeys string
|
||||
|
||||
container string
|
||||
Container string
|
||||
}
|
||||
|
||||
func inspectContainerAndCheckState(ctx context.Context, cli client.APIClient, args string) (*types.ContainerJSON, error) {
|
||||
|
@ -45,15 +46,15 @@ func inspectContainerAndCheckState(ctx context.Context, cli client.APIClient, ar
|
|||
|
||||
// NewAttachCommand creates a new cobra.Command for `docker attach`
|
||||
func NewAttachCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts attachOptions
|
||||
var opts AttachOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "attach [OPTIONS] CONTAINER",
|
||||
Short: "Attach local standard input, output, and error streams to a running container",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
opts.container = args[0]
|
||||
return runAttach(dockerCli, &opts)
|
||||
opts.Container = args[0]
|
||||
return RunAttach(context.Background(), dockerCli, &opts)
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"aliases": "docker container attach, docker attach",
|
||||
|
@ -64,36 +65,36 @@ func NewAttachCommand(dockerCli command.Cli) *cobra.Command {
|
|||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVar(&opts.noStdin, "no-stdin", false, "Do not attach STDIN")
|
||||
flags.BoolVar(&opts.proxy, "sig-proxy", true, "Proxy all received signals to the process")
|
||||
flags.StringVar(&opts.detachKeys, "detach-keys", "", "Override the key sequence for detaching a container")
|
||||
flags.BoolVar(&opts.NoStdin, "no-stdin", false, "Do not attach STDIN")
|
||||
flags.BoolVar(&opts.Proxy, "sig-proxy", true, "Proxy all received signals to the process")
|
||||
flags.StringVar(&opts.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
||||
ctx := context.Background()
|
||||
// RunAttach executes an `attach` command
|
||||
func RunAttach(ctx context.Context, dockerCli command.Cli, opts *AttachOptions) error {
|
||||
apiClient := dockerCli.Client()
|
||||
|
||||
// request channel to wait for client
|
||||
resultC, errC := apiClient.ContainerWait(ctx, opts.container, "")
|
||||
resultC, errC := apiClient.ContainerWait(ctx, opts.Container, "")
|
||||
|
||||
c, err := inspectContainerAndCheckState(ctx, apiClient, opts.container)
|
||||
c, err := inspectContainerAndCheckState(ctx, apiClient, opts.Container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dockerCli.In().CheckTty(!opts.noStdin, c.Config.Tty); err != nil {
|
||||
if err := dockerCli.In().CheckTty(!opts.NoStdin, c.Config.Tty); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
detachKeys := dockerCli.ConfigFile().DetachKeys
|
||||
if opts.detachKeys != "" {
|
||||
detachKeys = opts.detachKeys
|
||||
if opts.DetachKeys != "" {
|
||||
detachKeys = opts.DetachKeys
|
||||
}
|
||||
|
||||
options := container.AttachOptions{
|
||||
Stream: true,
|
||||
Stdin: !opts.noStdin && c.Config.OpenStdin,
|
||||
Stdin: !opts.NoStdin && c.Config.OpenStdin,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
DetachKeys: detachKeys,
|
||||
|
@ -104,13 +105,13 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
|||
in = dockerCli.In()
|
||||
}
|
||||
|
||||
if opts.proxy && !c.Config.Tty {
|
||||
if opts.Proxy && !c.Config.Tty {
|
||||
sigc := notifyAllSignals()
|
||||
go ForwardAllSignals(ctx, dockerCli, opts.container, sigc)
|
||||
go ForwardAllSignals(ctx, dockerCli, opts.Container, sigc)
|
||||
defer signal.StopCatch(sigc)
|
||||
}
|
||||
|
||||
resp, errAttach := apiClient.ContainerAttach(ctx, opts.container, options)
|
||||
resp, errAttach := apiClient.ContainerAttach(ctx, opts.Container, options)
|
||||
if errAttach != nil {
|
||||
return errAttach
|
||||
}
|
||||
|
@ -124,13 +125,13 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
|||
// the container and not exit.
|
||||
//
|
||||
// Recheck the container's state to avoid attach block.
|
||||
_, err = inspectContainerAndCheckState(ctx, apiClient, opts.container)
|
||||
_, err = inspectContainerAndCheckState(ctx, apiClient, opts.Container)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Config.Tty && dockerCli.Out().IsTerminal() {
|
||||
resizeTTY(ctx, dockerCli, opts.container)
|
||||
resizeTTY(ctx, dockerCli, opts.Container)
|
||||
}
|
||||
|
||||
streamer := hijackedIOStreamer{
|
||||
|
|
|
@ -52,7 +52,7 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
|
|||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
options.Container = args[0]
|
||||
options.Command = args[1:]
|
||||
return RunExec(dockerCli, options)
|
||||
return RunExec(context.Background(), dockerCli, options)
|
||||
},
|
||||
ValidArgsFunction: completion.ContainerNames(dockerCli, false, func(container types.Container) bool {
|
||||
return container.State != "paused"
|
||||
|
@ -96,13 +96,12 @@ func NewExecCommand(dockerCli command.Cli) *cobra.Command {
|
|||
}
|
||||
|
||||
// RunExec executes an `exec` command
|
||||
func RunExec(dockerCli command.Cli, options ExecOptions) error {
|
||||
func RunExec(ctx context.Context, dockerCli command.Cli, options ExecOptions) error {
|
||||
execConfig, err := parseExec(options, dockerCli.ConfigFile())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
client := dockerCli.Client()
|
||||
|
||||
// We need to check the tty _before_ we do the ContainerExecCreate, because
|
||||
|
|
|
@ -195,7 +195,7 @@ func TestRunExec(t *testing.T) {
|
|||
t.Run(testcase.doc, func(t *testing.T) {
|
||||
cli := test.NewFakeCli(&testcase.client)
|
||||
|
||||
err := RunExec(cli, testcase.options)
|
||||
err := RunExec(context.Background(), cli, testcase.options)
|
||||
if testcase.expectedError != "" {
|
||||
assert.ErrorContains(t, err, testcase.expectedError)
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue