Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return a Reader from the Exec function #435

Merged
merged 1 commit into from
May 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion container.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type Container interface {
State(context.Context) (*types.ContainerState, error) // returns container's running state
Networks(context.Context) ([]string, error) // get container networks
NetworkAliases(context.Context) (map[string][]string, error) // get container network aliases for a network
Exec(ctx context.Context, cmd []string) (int, error)
Exec(ctx context.Context, cmd []string) (int, io.Reader, error)
ContainerIP(context.Context) (string, error) // get container ip
CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error
CopyFileToContainer(ctx context.Context, hostFilePath string, containerFilePath string, fileMode int64) error
Expand Down
21 changes: 14 additions & 7 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,28 +342,35 @@ func (c *DockerContainer) NetworkAliases(ctx context.Context) (map[string][]stri
return a, nil
}

func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) {
func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) {
cli := c.provider.client
response, err := cli.ContainerExecCreate(ctx, c.ID, types.ExecConfig{
Cmd: cmd,
Detach: false,
Cmd: cmd,
Detach: false,
AttachStdout: true,
AttachStderr: true,
})
if err != nil {
return 0, err
return 0, nil, err
}

hijack, err := cli.ContainerExecAttach(ctx, response.ID, types.ExecStartCheck{})
if err != nil {
return 0, nil, err
}

err = cli.ContainerExecStart(ctx, response.ID, types.ExecStartCheck{
Detach: false,
})
if err != nil {
return 0, err
return 0, nil, err
}

var exitCode int
for {
execResp, err := cli.ContainerExecInspect(ctx, response.ID)
if err != nil {
return 0, err
return 0, nil, err
}

if !execResp.Running {
Expand All @@ -374,7 +381,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, error) {
time.Sleep(100 * time.Millisecond)
}

return exitCode, nil
return exitCode, hijack.Reader, nil
}

type FileFromContainer struct {
Expand Down
14 changes: 7 additions & 7 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1561,23 +1561,23 @@ func TestContainerWithTmpFs(t *testing.T) {

path := "/testtmpfs/test.file"

c, err := container.Exec(ctx, []string{"ls", path})
c, _, err := container.Exec(ctx, []string{"ls", path})
if err != nil {
t.Fatal(err)
}
if c != 1 {
t.Fatalf("File %s should not have existed, expected return code 1, got %v", path, c)
}

c, err = container.Exec(ctx, []string{"touch", path})
c, _, err = container.Exec(ctx, []string{"touch", path})
if err != nil {
t.Fatal(err)
}
if c != 0 {
t.Fatalf("File %s should have been created successfully, expected return code 0, got %v", path, c)
}

c, err = container.Exec(ctx, []string{"ls", path})
c, _, err = container.Exec(ctx, []string{"ls", path})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1740,7 +1740,7 @@ func TestDockerContainerCopyFileToContainer(t *testing.T) {

copiedFileName := "hello_copy.sh"
_ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700)
c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1769,7 +1769,7 @@ func TestDockerContainerCopyToContainer(t *testing.T) {
t.Fatal(err)
}
_ = nginxC.CopyToContainer(ctx, fileContent, "/"+copiedFileName, 700)
c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1797,7 +1797,7 @@ func TestDockerContainerCopyFileFromContainer(t *testing.T) {

copiedFileName := "hello_copy.sh"
_ = nginxC.CopyFileToContainer(ctx, "./testresources/hello.sh", "/"+copiedFileName, 700)
c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -1832,7 +1832,7 @@ func TestDockerContainerCopyEmptyFileFromContainer(t *testing.T) {

copiedFileName := "hello_copy.sh"
_ = nginxC.CopyFileToContainer(ctx, "./testresources/empty.sh", "/"+copiedFileName, 700)
c, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
c, _, err := nginxC.Exec(ctx, []string{"bash", copiedFileName})
if err != nil {
t.Fatal(err)
}
Expand Down
6 changes: 3 additions & 3 deletions logconsumer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ func TestContainerLogWithErrClosed(t *testing.T) {
existingLogs := len(consumer.Msgs)

hitNginx := func() {
i, err := dind.Exec(ctx, []string{"wget", "--spider", "localhost:" + port.Port()})
i, _, err := dind.Exec(ctx, []string{"wget", "--spider", "localhost:" + port.Port()})
if err != nil || i > 0 {
t.Fatalf("Can't make request to nginx container from dind container")
}
Expand All @@ -264,11 +264,11 @@ func TestContainerLogWithErrClosed(t *testing.T) {
"-j", "REJECT", "--reject-with", "tcp-reset",
}
// Simulate a transient closed connection to the docker daemon
i, err := dind.Exec(ctx, append([]string{"iptables", "-A"}, iptableArgs...))
i, _, err := dind.Exec(ctx, append([]string{"iptables", "-A"}, iptableArgs...))
if err != nil || i > 0 {
t.Fatalf("Failed to close connection to dind daemon")
}
i, err = dind.Exec(ctx, append([]string{"iptables", "-D"}, iptableArgs...))
i, _, err = dind.Exec(ctx, append([]string{"iptables", "-D"}, iptableArgs...))
if err != nil || i > 0 {
t.Fatalf("Failed to re-open connection to dind daemon")
}
Expand Down
2 changes: 1 addition & 1 deletion wait/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (ws ExecStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget
case <-ctx.Done():
return ctx.Err()
case <-time.After(ws.PollInterval):
exitCode, err := target.Exec(ctx, ws.cmd)
exitCode, _, err := target.Exec(ctx, ws.cmd)
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions wait/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,18 @@ func (st mockExecTarget) Logs(_ context.Context) (io.ReadCloser, error) {
return nil, errors.New("not implemented")
}

func (st mockExecTarget) Exec(ctx context.Context, _ []string) (int, error) {
func (st mockExecTarget) Exec(ctx context.Context, _ []string) (int, io.Reader, error) {
time.Sleep(st.waitDuration)

if err := ctx.Err(); err != nil {
return st.exitCode, err
return st.exitCode, nil, err
}

if !st.successAfter.IsZero() && time.Now().After(st.successAfter) {
return 0, st.failure
return 0, nil, st.failure
}

return st.exitCode, st.failure
return st.exitCode, nil, st.failure
}

func (st mockExecTarget) State(_ context.Context) (*types.ContainerState, error) {
Expand Down
4 changes: 2 additions & 2 deletions wait/exit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ func (st exitStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) {
return nil, nil
}

func (st exitStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) {
return 0, nil
func (st exitStrategyTarget) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) {
return 0, nil, nil
}

func (st exitStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) {
Expand Down
2 changes: 1 addition & 1 deletion wait/host_port.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (hp *HostPortStrategy) WaitUntilReady(ctx context.Context, target StrategyT
if ctx.Err() != nil {
return ctx.Err()
}
exitCode, err := target.Exec(ctx, []string{"/bin/sh", "-c", command})
exitCode, _, err := target.Exec(ctx, []string{"/bin/sh", "-c", command})
if err != nil {
return fmt.Errorf("%w, host port waiting failed", err)
}
Expand Down
4 changes: 2 additions & 2 deletions wait/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func (st noopStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) {
return st.ioReaderCloser, nil
}

func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, error) {
return 0, nil
func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) {
return 0, nil, nil
}
func (st noopStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) {
return nil, nil
Expand Down
2 changes: 1 addition & 1 deletion wait/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type StrategyTarget interface {
Host(context.Context) (string, error)
MappedPort(context.Context, nat.Port) (nat.Port, error)
Logs(context.Context) (io.ReadCloser, error)
Exec(ctx context.Context, cmd []string) (int, error)
Exec(ctx context.Context, cmd []string) (int, io.Reader, error)
State(context.Context) (*types.ContainerState, error)
}

Expand Down