ExecContainer runs a command in a container. It returns the output and any error. If an error occurs during the execution of the command, the output is appended to the error.
(ctx context.Context, client Client, config ExecConfig)
| 27 | // ExecContainer runs a command in a container. It returns the output and any error. |
| 28 | // If an error occurs during the execution of the command, the output is appended to the error. |
| 29 | func ExecContainer(ctx context.Context, client Client, config ExecConfig) ([]byte, error) { |
| 30 | exec, err := client.ContainerExecCreate(ctx, config.ContainerID, container.ExecOptions{ |
| 31 | Detach: config.Detach, |
| 32 | Cmd: append([]string{config.Cmd}, config.Args...), |
| 33 | User: config.User, |
| 34 | AttachStderr: true, |
| 35 | AttachStdout: true, |
| 36 | AttachStdin: config.Stdin != nil, |
| 37 | Env: config.Env, |
| 38 | }) |
| 39 | if err != nil { |
| 40 | return nil, xerrors.Errorf("exec create: %w", err) |
| 41 | } |
| 42 | |
| 43 | resp, err := client.ContainerExecAttach(ctx, exec.ID, container.ExecAttachOptions{}) |
| 44 | if err != nil { |
| 45 | return nil, xerrors.Errorf("attach to exec: %w", err) |
| 46 | } |
| 47 | defer resp.Close() |
| 48 | |
| 49 | if config.Stdin != nil { |
| 50 | _, err = io.Copy(resp.Conn, config.Stdin) |
| 51 | if err != nil { |
| 52 | return nil, xerrors.Errorf("copy stdin: %w", err) |
| 53 | } |
| 54 | err = resp.CloseWrite() |
| 55 | if err != nil { |
| 56 | return nil, xerrors.Errorf("close write: %w", err) |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | var ( |
| 61 | buf bytes.Buffer |
| 62 | // Avoid capturing too much output. We want to prevent |
| 63 | // a memory leak. This is especially important when |
| 64 | // we run the bootstrap script since we do not return. |
| 65 | psw = &xio.PrefixSuffixWriter{ |
| 66 | W: &buf, |
| 67 | N: 1 << 10, |
| 68 | } |
| 69 | wr io.Writer = psw |
| 70 | ) |
| 71 | |
| 72 | if config.StdOutErr != nil { |
| 73 | wr = io.MultiWriter(psw, config.StdOutErr) |
| 74 | } |
| 75 | |
| 76 | _, err = io.Copy(wr, resp.Reader) |
| 77 | if err != nil { |
| 78 | return nil, xerrors.Errorf("copy cmd output: %w", err) |
| 79 | } |
| 80 | resp.Close() |
| 81 | |
| 82 | inspect, err := client.ContainerExecInspect(ctx, exec.ID) |
| 83 | if err != nil { |
| 84 | return nil, xerrors.Errorf("exec inspect: %w", err) |
| 85 | } |
| 86 |
no test coverage detected