github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/integration/internal/container/exec.go (about) 1 package container 2 3 import ( 4 "bytes" 5 "context" 6 7 "github.com/Prakhar-Agarwal-byte/moby/api/types" 8 "github.com/Prakhar-Agarwal-byte/moby/client" 9 ) 10 11 // ExecResult represents a result returned from Exec() 12 type ExecResult struct { 13 ExitCode int 14 outBuffer *bytes.Buffer 15 errBuffer *bytes.Buffer 16 } 17 18 // Stdout returns stdout output of a command run by Exec() 19 func (res *ExecResult) Stdout() string { 20 return res.outBuffer.String() 21 } 22 23 // Stderr returns stderr output of a command run by Exec() 24 func (res *ExecResult) Stderr() string { 25 return res.errBuffer.String() 26 } 27 28 // Combined returns combined stdout and stderr output of a command run by Exec() 29 func (res *ExecResult) Combined() string { 30 return res.outBuffer.String() + res.errBuffer.String() 31 } 32 33 // Exec executes a command inside a container, returning the result 34 // containing stdout, stderr, and exit code. Note: 35 // - this is a synchronous operation; 36 // - cmd stdin is closed. 37 func Exec(ctx context.Context, apiClient client.APIClient, id string, cmd []string, ops ...func(*types.ExecConfig)) (ExecResult, error) { 38 // prepare exec 39 execConfig := types.ExecConfig{ 40 AttachStdout: true, 41 AttachStderr: true, 42 Cmd: cmd, 43 } 44 45 for _, op := range ops { 46 op(&execConfig) 47 } 48 49 cresp, err := apiClient.ContainerExecCreate(ctx, id, execConfig) 50 if err != nil { 51 return ExecResult{}, err 52 } 53 execID := cresp.ID 54 55 // run it, with stdout/stderr attached 56 aresp, err := apiClient.ContainerExecAttach(ctx, execID, types.ExecStartCheck{}) 57 if err != nil { 58 return ExecResult{}, err 59 } 60 61 // read the output 62 s, err := demultiplexStreams(ctx, aresp) 63 if err != nil { 64 return ExecResult{}, err 65 } 66 67 // get the exit code 68 iresp, err := apiClient.ContainerExecInspect(ctx, execID) 69 if err != nil { 70 return ExecResult{}, err 71 } 72 73 return ExecResult{ExitCode: iresp.ExitCode, outBuffer: &s.stdout, errBuffer: &s.stderr}, nil 74 }