RunAttach executes an `attach` command
(ctx context.Context, dockerCLI command.Cli, containerID string, opts *AttachOptions)
| 70 | |
| 71 | // RunAttach executes an `attach` command |
| 72 | func RunAttach(ctx context.Context, dockerCLI command.Cli, containerID string, opts *AttachOptions) error { |
| 73 | detachKeys := opts.DetachKeys |
| 74 | if detachKeys == "" { |
| 75 | detachKeys = dockerCLI.ConfigFile().DetachKeys |
| 76 | } |
| 77 | if err := validateDetachKeys(detachKeys); err != nil { |
| 78 | return err |
| 79 | } |
| 80 | |
| 81 | apiClient := dockerCLI.Client() |
| 82 | |
| 83 | // request channel to wait for client |
| 84 | waitCtx := context.WithoutCancel(ctx) |
| 85 | waitRes := apiClient.ContainerWait(waitCtx, containerID, client.ContainerWaitOptions{}) |
| 86 | |
| 87 | c, err := inspectContainerAndCheckState(ctx, apiClient, containerID) |
| 88 | if err != nil { |
| 89 | return err |
| 90 | } |
| 91 | |
| 92 | if err := dockerCLI.In().CheckTty(!opts.NoStdin, c.Config.Tty); err != nil { |
| 93 | return err |
| 94 | } |
| 95 | |
| 96 | options := client.ContainerAttachOptions{ |
| 97 | Stream: true, |
| 98 | Stdin: !opts.NoStdin && c.Config.OpenStdin, |
| 99 | Stdout: true, |
| 100 | Stderr: true, |
| 101 | DetachKeys: detachKeys, |
| 102 | } |
| 103 | |
| 104 | var in io.ReadCloser |
| 105 | if options.Stdin { |
| 106 | in = dockerCLI.In() |
| 107 | } |
| 108 | |
| 109 | if opts.Proxy && !c.Config.Tty { |
| 110 | sigc := notifyAllSignals() |
| 111 | // since we're explicitly setting up signal handling here, and the daemon will |
| 112 | // get notified independently of the clients ctx cancellation, we use this context |
| 113 | // but without cancellation to avoid ForwardAllSignals from returning |
| 114 | // before all signals are forwarded. |
| 115 | bgCtx := context.WithoutCancel(ctx) |
| 116 | go ForwardAllSignals(bgCtx, apiClient, containerID, sigc) |
| 117 | defer signal.StopCatch(sigc) |
| 118 | } |
| 119 | |
| 120 | res, err := apiClient.ContainerAttach(ctx, containerID, options) |
| 121 | if err != nil { |
| 122 | return err |
| 123 | } |
| 124 | defer res.HijackedResponse.Close() |
| 125 | |
| 126 | // If use docker attach command to attach to a stop container, it will return |
| 127 | // "You cannot attach to a stopped container" error, it's ok, but when |
| 128 | // attach to a running container, it(docker attach) use inspect to check |
| 129 | // the container's state, if it pass the state check on the client side, |
no test coverage detected
searching dependent graphs…