12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package container
- import (
- "bytes"
- "context"
- "testing"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/client"
- )
- // ExecResult represents a result returned from Exec()
- type ExecResult struct {
- ExitCode int
- outBuffer *bytes.Buffer
- errBuffer *bytes.Buffer
- }
- // Stdout returns stdout output of a command run by Exec()
- func (res ExecResult) Stdout() string {
- return res.outBuffer.String()
- }
- // Stderr returns stderr output of a command run by Exec()
- func (res ExecResult) Stderr() string {
- return res.errBuffer.String()
- }
- // Combined returns combined stdout and stderr output of a command run by Exec()
- func (res ExecResult) Combined() string {
- return res.outBuffer.String() + res.errBuffer.String()
- }
- // AssertSuccess fails the test and stops execution if the command exited with a
- // nonzero status code.
- func (res ExecResult) AssertSuccess(t testing.TB) {
- t.Helper()
- if res.ExitCode != 0 {
- t.Logf("expected exit code 0, got %d", res.ExitCode)
- t.Logf("stdout: %s", res.Stdout())
- t.Logf("stderr: %s", res.Stderr())
- t.FailNow()
- }
- }
- // Exec executes a command inside a container, returning the result
- // containing stdout, stderr, and exit code. Note:
- // - this is a synchronous operation;
- // - cmd stdin is closed.
- func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*types.ExecConfig)) (ExecResult, error) {
- // prepare exec
- execConfig := types.ExecConfig{
- AttachStdout: true,
- AttachStderr: true,
- Cmd: cmd,
- }
- for _, op := range ops {
- op(&execConfig)
- }
- cresp, err := apiClient.ContainerExecCreate(ctx, id, execConfig)
- if err != nil {
- return ExecResult{}, err
- }
- execID := cresp.ID
- // run it, with stdout/stderr attached
- aresp, err := apiClient.ContainerExecAttach(ctx, execID, types.ExecStartCheck{})
- if err != nil {
- return ExecResult{}, err
- }
- // read the output
- s, err := demultiplexStreams(ctx, aresp)
- if err != nil {
- return ExecResult{}, err
- }
- // get the exit code
- iresp, err := apiClient.ContainerExecInspect(ctx, execID)
- if err != nil {
- return ExecResult{}, err
- }
- return ExecResult{ExitCode: iresp.ExitCode, outBuffer: &s.stdout, errBuffer: &s.stderr}, nil
- }
- // ExecT calls Exec() and aborts the test if an error occurs.
- func ExecT(ctx context.Context, t testing.TB, apiClient client.APIClient, id string, cmd []string, ops ...func(*types.ExecConfig)) ExecResult {
- t.Helper()
- res, err := Exec(ctx, apiClient, id, cmd, ops...)
- if err != nil {
- t.Fatal(err)
- }
- return res
- }
|