Skip to content

Commit

Permalink
Merge branch 'main' into examples-work
Browse files Browse the repository at this point in the history
* main:
  docs: update method to `nginxC.Terminate` (#627)
  fix: do not prepend garbage in the container.Exec response (#624)
  chore: retire podman pipeline (#625)
  update gotest.md - fix errors in the example (#623)
  chore: sync governance files (#622)
  • Loading branch information
mdelapenya committed Nov 17, 2022
2 parents f4c4ce9 + eb22bbd commit bc0ec00
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 101 deletions.
74 changes: 0 additions & 74 deletions .github/workflows/ci-podman.yml

This file was deleted.

4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -69,8 +69,8 @@ func TestIntegrationNginxLatestReturn(t *testing.T) {

// Clean up the container after the test is complete
defer func() {
if err := nginxC.terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %w", err)
if err := nginxC.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %v", err)
}
}()

Expand Down
3 changes: 2 additions & 1 deletion container.go
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/docker/docker/pkg/archive"
"github.com/docker/go-connections/nat"

tcexec "github.com/testcontainers/testcontainers-go/exec"
"github.com/testcontainers/testcontainers-go/wait"
)

Expand Down Expand Up @@ -54,7 +55,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, io.Reader, error)
Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error)
ContainerIP(context.Context) (string, error) // get container ip
ContainerIPs(context.Context) ([]string, error) // get all container IPs
CopyToContainer(ctx context.Context, fileContent []byte, containerFilePath string, fileMode int64) error
Expand Down
13 changes: 11 additions & 2 deletions docker.go
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/moby/term"
specs "github.com/opencontainers/image-spec/specs-go/v1"

tcexec "github.com/testcontainers/testcontainers-go/exec"
"github.com/testcontainers/testcontainers-go/wait"
)

Expand Down Expand Up @@ -433,7 +434,7 @@ func (c *DockerContainer) NetworkAliases(ctx context.Context) (map[string][]stri
return a, nil
}

func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) {
func (c *DockerContainer) Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error) {
cli := c.provider.client
response, err := cli.ContainerExecCreate(ctx, c.ID, types.ExecConfig{
Cmd: cmd,
Expand All @@ -450,6 +451,14 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reade
return 0, nil, err
}

opt := &tcexec.ProcessOptions{
Reader: hijack.Reader,
}

for _, o := range options {
o.Apply(opt)
}

var exitCode int
for {
execResp, err := cli.ContainerExecInspect(ctx, response.ID)
Expand All @@ -465,7 +474,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string) (int, io.Reade
time.Sleep(100 * time.Millisecond)
}

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

type FileFromContainer struct {
Expand Down
67 changes: 67 additions & 0 deletions docker_exec_test.go
@@ -0,0 +1,67 @@
package testcontainers

import (
"context"
"io"
"strings"
"testing"

"github.com/stretchr/testify/require"
tcexec "github.com/testcontainers/testcontainers-go/exec"
)

func TestExecWithMultiplexedResponse(t *testing.T) {
ctx := context.Background()
req := ContainerRequest{
Image: nginxAlpineImage,
}

container, err := GenericContainer(ctx, GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
})

require.NoError(t, err)
terminateContainerOnEnd(t, ctx, container)

code, reader, err := container.Exec(ctx, []string{"ls", "/usr/share/nginx"}, tcexec.Multiplexed())
require.NoError(t, err)
require.Zero(t, code)
require.NotNil(t, reader)

b, err := io.ReadAll(reader)
require.NoError(t, err)
require.NotNil(t, b)

str := string(b)
require.Equal(t, "html\n", str)
}

func TestExecWithNonMultiplexedResponse(t *testing.T) {
ctx := context.Background()
req := ContainerRequest{
Image: nginxAlpineImage,
}

container, err := GenericContainer(ctx, GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
})

require.NoError(t, err)
terminateContainerOnEnd(t, ctx, container)

code, reader, err := container.Exec(ctx, []string{"ls", "/usr/share/nginx"})
require.NoError(t, err)
require.Zero(t, code)
require.NotNil(t, reader)

b, err := io.ReadAll(reader)
require.NoError(t, err)
require.NotNil(t, b)

str := string(b)
require.True(t, strings.HasSuffix(str, "html\n"))
}
32 changes: 16 additions & 16 deletions docs/language-logos/java.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions docs/quickstart/gotest.md
Expand Up @@ -17,6 +17,9 @@ go get github.com/testcontainers/testcontainers-go

```go
import (
"context"
"testing"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
Expand All @@ -36,8 +39,8 @@ func TestWithRedis(t *testing.T) {
t.Error(err)
}
defer func() {
if err := redisC.terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %w", err)
if err := redisC.Terminate(ctx); err != nil {
t.Fatalf("failed to terminate container: %s", err.Error())
}
}()
}
Expand Down
44 changes: 44 additions & 0 deletions exec/processor.go
@@ -0,0 +1,44 @@
package exec

import (
"bytes"
"io"

"github.com/docker/docker/pkg/stdcopy"
)

// ProcessOptions defines options applicable to the reader processor
type ProcessOptions struct {
Reader io.Reader
}

// ProcessOption defines a common interface to modify the reader processor
// These options can be passed to the Exec function in a variadic way to customize the returned Reader instance
type ProcessOption interface {
Apply(opts *ProcessOptions)
}

type ProcessOptionFunc func(opts *ProcessOptions)

func (fn ProcessOptionFunc) Apply(opts *ProcessOptions) {
fn(opts)
}

func Multiplexed() ProcessOption {
return ProcessOptionFunc(func(opts *ProcessOptions) {
done := make(chan struct{})

var outBuff bytes.Buffer
var errBuff bytes.Buffer
go func() {
if _, err := stdcopy.StdCopy(&outBuff, &errBuff, opts.Reader); err != nil {
return
}
close(done)
}()

<-done

opts.Reader = &outBuff
})
}
3 changes: 2 additions & 1 deletion wait/exec_test.go
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/docker/go-connections/nat"

"github.com/testcontainers/testcontainers-go"
tcexec "github.com/testcontainers/testcontainers-go/exec"
"github.com/testcontainers/testcontainers-go/wait"
)

Expand Down Expand Up @@ -62,7 +63,7 @@ func (st mockExecTarget) Logs(_ context.Context) (io.ReadCloser, error) {
return nil, errors.New("not implemented")
}

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

if err := ctx.Err(); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion wait/exit_test.go
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/docker/docker/api/types"
"github.com/docker/go-connections/nat"
tcexec "github.com/testcontainers/testcontainers-go/exec"
)

type exitStrategyTarget struct {
Expand All @@ -30,7 +31,7 @@ func (st exitStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) {
return nil, nil
}

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

Expand Down
3 changes: 2 additions & 1 deletion wait/log_test.go
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/docker/docker/api/types"
"github.com/docker/go-connections/nat"
tcexec "github.com/testcontainers/testcontainers-go/exec"
)

type noopStrategyTarget struct {
Expand All @@ -31,7 +32,7 @@ func (st noopStrategyTarget) Logs(ctx context.Context) (io.ReadCloser, error) {
return st.ioReaderCloser, nil
}

func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string) (int, io.Reader, error) {
func (st noopStrategyTarget) Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error) {
return 0, nil, nil
}
func (st noopStrategyTarget) State(ctx context.Context) (*types.ContainerState, error) {
Expand Down
3 changes: 2 additions & 1 deletion wait/wait.go
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/docker/docker/api/types"
"github.com/docker/go-connections/nat"
tcexec "github.com/testcontainers/testcontainers-go/exec"
)

type Strategy interface {
Expand All @@ -18,7 +19,7 @@ type StrategyTarget interface {
Ports(ctx context.Context) (nat.PortMap, error)
MappedPort(context.Context, nat.Port) (nat.Port, error)
Logs(context.Context) (io.ReadCloser, error)
Exec(ctx context.Context, cmd []string) (int, io.Reader, error)
Exec(ctx context.Context, cmd []string, options ...tcexec.ProcessOption) (int, io.Reader, error)
State(context.Context) (*types.ContainerState, error)
}

Expand Down

0 comments on commit bc0ec00

Please sign in to comment.