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  }