Skip to content

Commit

Permalink
Merge branch 'main' into v1
Browse files Browse the repository at this point in the history
* main:
  fix: never cache JSON representation of a container (#2606)
  chore: remove most uses of  TestcontainersConfig and deprecated TestcontainersConfig fields. (#2614)
  chore(deps): bump github.com/docker/docker from v27.0.2 to v27.0.3 (#2615)
  chore(deps): bump github.com/docker/docker from v26.1.4 to v27.0.2 (#2593)
  • Loading branch information
mdelapenya committed Jul 2, 2024
2 parents 2599be8 + 59cf064 commit 3a6fa88
Show file tree
Hide file tree
Showing 109 changed files with 486 additions and 514 deletions.
4 changes: 1 addition & 3 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,10 +345,8 @@ func reuseOrCreateContainer(ctx context.Context, req Request) (*DockerContainer,

sessionID := core.SessionID()

tcConfig := config.Read()

var termSignal chan bool
if !tcConfig.RyukDisabled {
if !config.Read().RyukDisabled {
_, err := NewReaper(context.Background(), core.SessionID())
if err != nil {
return nil, fmt.Errorf("failed to create reaper: %w", err)
Expand Down
1 change: 0 additions & 1 deletion container_started.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ func (c *DockerContainer) StartLogProduction(ctx context.Context, logConfig log.
default:
_, _ = fmt.Fprintf(os.Stderr, "container log error: %+v. %s", err, log.StoppedForOutOfSyncMessage)
// if we would continue here, the next header-read will result into random data...
return
}
return
}
Expand Down
46 changes: 18 additions & 28 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ var (
// DockerContainer represents a container started using Docker
type DockerContainer struct {
ID string
raw *types.ContainerJSON
exposedPorts []string // a reference to the container's requested exposed ports. It allows checking they are ready before any wait strategy
isRunning bool
WaitingFor wait.Strategy
logger log.Logging
Expand Down Expand Up @@ -82,19 +82,29 @@ func containerFromDockerResponse(ctx context.Context, response types.Container)
ctr.terminationSignal = nil

// populate the raw representation of the container
_, err := ctr.inspectRawContainer(ctx)
jsonRaw, err := ctr.inspectRawContainer(ctx)
if err != nil {
return nil, err
}

// the health status of the container, if any
if health := ctr.raw.State.Health; health != nil {
if health := jsonRaw.State.Health; health != nil {
ctr.healthStatus = health.Status
}

return &ctr, nil
}

// Inspect gets the raw container info
func (c *DockerContainer) Inspect(ctx context.Context) (*types.ContainerJSON, error) {
jsonRaw, err := c.inspectRawContainer(ctx)
if err != nil {
return nil, err
}

return jsonRaw, nil
}

// ContainerIP gets the IP address of the primary network within the container.
func (c *DockerContainer) ContainerIP(ctx context.Context) (string, error) {
inspect, err := c.Inspect(ctx)
Expand Down Expand Up @@ -160,7 +170,7 @@ func (c *DockerContainer) CopyDirToContainer(ctx context.Context, hostDirPath st
}
defer cli.Close()

err = cli.CopyToContainer(ctx, c.ID, parent, buff, types.CopyToContainerOptions{})
err = cli.CopyToContainer(ctx, c.ID, parent, buff, container.CopyToContainerOptions{})
if err != nil {
return err
}
Expand Down Expand Up @@ -252,7 +262,7 @@ func (c *DockerContainer) copyToContainer(ctx context.Context, fileContent func(
}
defer cli.Close()

err = cli.CopyToContainer(ctx, c.ID, "/", buffer, types.CopyToContainerOptions{})
err = cli.CopyToContainer(ctx, c.ID, "/", buffer, container.CopyToContainerOptions{})
if err != nil {
return err
}
Expand Down Expand Up @@ -307,7 +317,7 @@ func (c *DockerContainer) Exec(ctx context.Context, cmd []string, options ...tce
return 0, nil, err
}

hijack, err := cli.ContainerExecAttach(ctx, response.ID, types.ExecStartCheck{})
hijack, err := cli.ContainerExecAttach(ctx, response.ID, container.ExecAttachOptions{})
if err != nil {
return 0, nil, err
}
Expand Down Expand Up @@ -358,20 +368,6 @@ func (c *DockerContainer) Host(ctx context.Context) (string, error) {
return host, nil
}

// Inspect gets the raw container info, caching the result for subsequent calls
func (c *DockerContainer) Inspect(ctx context.Context) (*types.ContainerJSON, error) {
if c.raw != nil {
return c.raw, nil
}

jsonRaw, err := c.inspectRawContainer(ctx)
if err != nil {
return nil, err
}

return jsonRaw, nil
}

// update container raw info
func (c *DockerContainer) inspectRawContainer(ctx context.Context) (*types.ContainerJSON, error) {
cli, err := core.NewClient(ctx)
Expand All @@ -380,13 +376,12 @@ func (c *DockerContainer) inspectRawContainer(ctx context.Context) (*types.Conta
}
defer cli.Close()

inspect, err := cli.ContainerInspect(ctx, c.ID)
jsonRaw, err := cli.ContainerInspect(ctx, c.ID)
if err != nil {
return nil, err
}

c.raw = &inspect
return c.raw, nil
return &jsonRaw, nil
}

func (c *DockerContainer) IsRunning() bool {
Expand Down Expand Up @@ -614,9 +609,6 @@ func (c *DockerContainer) Start(ctx context.Context) error {
func (c *DockerContainer) State(ctx context.Context) (*types.ContainerState, error) {
inspect, err := c.inspectRawContainer(ctx)
if err != nil {
if c.raw != nil {
return c.raw.State, err
}
return nil, err
}
return inspect.State, nil
Expand Down Expand Up @@ -655,7 +647,6 @@ func (c *DockerContainer) Stop(ctx context.Context, timeout *time.Duration) erro
}

c.isRunning = false
c.raw = nil // invalidate the cache, as the container representation will change after stopping

err = c.stoppedHook(ctx)
if err != nil {
Expand Down Expand Up @@ -702,7 +693,6 @@ func (c *DockerContainer) Terminate(ctx context.Context) error {

c.sessionID = ""
c.isRunning = false
c.raw = nil // invalidate the cache here too

return errors.Join(errs...)
}
Expand Down
39 changes: 26 additions & 13 deletions docker_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,26 @@ func removeImageFromLocalCache(t *testing.T, img string) {
}

func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) {
mappedPort := prepareLocalRegistryWithAuth(t)

// using the same credentials as in the Docker Registry
base64 := "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" // testuser:testpassword
t.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"localhost:5001": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" }
"localhost:`+mappedPort+`": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

prepareLocalRegistryWithAuth(t)

ctx := context.Background()

req := Request{
FromDockerfile: FromDockerfile{
Context: "./testdata",
Dockerfile: "auth.Dockerfile",
BuildArgs: map[string]*string{
"REGISTRY_PORT": &mappedPort,
},
},
AlwaysPullImage: true, // make sure the authentication takes place
ExposedPorts: []string{"6379/tcp"},
Expand All @@ -81,23 +84,26 @@ func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) {
}

func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *testing.T) {
mappedPort := prepareLocalRegistryWithAuth(t)

// using different credentials than in the Docker Registry
base64 := "Zm9vOmJhcg==" // foo:bar
t.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"localhost:5001": { "username": "foo", "password": "bar", "auth": "`+base64+`" }
"localhost:`+mappedPort+`": { "username": "foo", "password": "bar", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

prepareLocalRegistryWithAuth(t)

ctx := context.Background()

req := Request{
FromDockerfile: FromDockerfile{
Context: "./testdata",
Dockerfile: "auth.Dockerfile",
BuildArgs: map[string]*string{
"REGISTRY_PORT": &mappedPort,
},
},
AlwaysPullImage: true, // make sure the authentication takes place
ExposedPorts: []string{"6379/tcp"},
Expand All @@ -111,20 +117,20 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test
}

func TestCreateContainerFromPrivateRegistry(t *testing.T) {
mappedPort := prepareLocalRegistryWithAuth(t)

// using the same credentials as in the Docker Registry
base64 := "dGVzdHVzZXI6dGVzdHBhc3N3b3Jk" // testuser:testpassword
t.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"localhost:5001": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" }
"localhost:`+mappedPort+`": { "username": "testuser", "password": "testpassword", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

prepareLocalRegistryWithAuth(t)

ctx := context.Background()
req := Request{
Image: "localhost:5001/redis:5.0-alpine",
Image: "localhost:" + mappedPort + "/redis:5.0-alpine",
AlwaysPullImage: true, // make sure the authentication takes place
ExposedPorts: []string{"6379/tcp"},
WaitingFor: wait.ForLog("Ready to accept connections"),
Expand All @@ -136,14 +142,14 @@ func TestCreateContainerFromPrivateRegistry(t *testing.T) {
TerminateContainerOnEnd(t, ctx, redisContainer)
}

func prepareLocalRegistryWithAuth(t *testing.T) {
func prepareLocalRegistryWithAuth(t *testing.T) string {
ctx := context.Background()
wd, err := os.Getwd()
require.NoError(t, err)

req := Request{
Image: "registry:2",
ExposedPorts: []string{"5001:5000/tcp"},
ExposedPorts: []string{"5000/tcp"},
Env: map[string]string{
"REGISTRY_AUTH": "htpasswd",
"REGISTRY_AUTH_HTPASSWD_REALM": "Registry",
Expand All @@ -167,13 +173,20 @@ func prepareLocalRegistryWithAuth(t *testing.T) {
registryC, err := Run(ctx, req)
require.NoError(t, err)

mappedPort, err := registryC.MappedPort(ctx, "5000/tcp")
require.NoError(t, err)

mp := mappedPort.Port()

t.Cleanup(func() {
removeImageFromLocalCache(t, "localhost:5001/redis:5.0-alpine")
removeImageFromLocalCache(t, "localhost:"+mp+"/redis:5.0-alpine")
})
t.Cleanup(func() {
require.NoError(t, registryC.Terminate(context.Background()))
})

_, cancel := context.WithCancel(context.Background())
t.Cleanup(cancel)

return mp
}
Loading

0 comments on commit 3a6fa88

Please sign in to comment.