Skip to content

Commit

Permalink
feat!: build log writer for container request (#2925)
Browse files Browse the repository at this point in the history
* feat: build log writer for container request

* fix: single BuildLogWriter method for ImageBuildInfo interface

* fix: change BuildLogWriter default behavior

* fix: require in Test_BuildContainerFromDockerfileWithBuildLogWriter
  • Loading branch information
zenkovev authored Dec 19, 2024
1 parent 35bf0cd commit ea4feea
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
21 changes: 17 additions & 4 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ type ImageBuildInfo interface {
GetDockerfile() string // the relative path to the Dockerfile, including the file itself
GetRepo() string // get repo label for image
GetTag() string // get tag label for image
ShouldPrintBuildLog() bool // allow build log to be printed to stdout
BuildLogWriter() io.Writer // for output of build log, use io.Discard to disable the output
ShouldBuildImage() bool // return true if the image needs to be built
GetBuildArgs() map[string]*string // return the environment args used to build the from Dockerfile
GetAuthConfigs() map[string]registry.AuthConfig // Deprecated. Testcontainers will detect registry credentials automatically. Return the auth configs to be able to pull from an authenticated docker registry
Expand All @@ -92,7 +92,8 @@ type FromDockerfile struct {
Repo string // the repo label for image, defaults to UUID
Tag string // the tag label for image, defaults to UUID
BuildArgs map[string]*string // enable user to pass build args to docker daemon
PrintBuildLog bool // enable user to print build log
PrintBuildLog bool // Deprecated: Use BuildLogWriter instead
BuildLogWriter io.Writer // for output of build log, defaults to io.Discard
AuthConfigs map[string]registry.AuthConfig // Deprecated. Testcontainers will detect registry credentials automatically. Enable auth configs to be able to pull from an authenticated docker registry
// KeepImage describes whether DockerContainer.Terminate should not delete the
// container image. Useful for images that are built from a Dockerfile and take a
Expand Down Expand Up @@ -410,8 +411,20 @@ func (c *ContainerRequest) ShouldKeepBuiltImage() bool {
return c.FromDockerfile.KeepImage
}

func (c *ContainerRequest) ShouldPrintBuildLog() bool {
return c.FromDockerfile.PrintBuildLog
// BuildLogWriter returns the io.Writer for output of log when building a Docker image from
// a Dockerfile. It returns the BuildLogWriter from the ContainerRequest, defaults to io.Discard.
// For backward compatibility, if BuildLogWriter is default and PrintBuildLog is true,
// the function returns os.Stderr.
func (c *ContainerRequest) BuildLogWriter() io.Writer {
if c.FromDockerfile.BuildLogWriter != nil {
return c.FromDockerfile.BuildLogWriter
}
if c.FromDockerfile.PrintBuildLog {
c.FromDockerfile.BuildLogWriter = os.Stderr
} else {
c.FromDockerfile.BuildLogWriter = io.Discard
}
return c.FromDockerfile.BuildLogWriter
}

// BuildOptions returns the image build options when building a Docker image from a Dockerfile.
Expand Down
5 changes: 1 addition & 4 deletions docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,10 +1004,7 @@ func (p *DockerProvider) BuildImage(ctx context.Context, img ImageBuildInfo) (st
}
defer resp.Body.Close()

output := io.Discard
if img.ShouldPrintBuildLog() {
output = os.Stderr
}
output := img.BuildLogWriter()

// Always process the output, even if it is not printed
// to ensure that errors during the build process are
Expand Down
31 changes: 31 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,37 @@ func Test_BuildContainerFromDockerfileWithBuildLog(t *testing.T) {
assert.Regexpf(t, `^Step\s*1/\d+\s*:\s*FROM alpine$`, temp[0], "Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM alpine", temp[0])
}

func Test_BuildContainerFromDockerfileWithBuildLogWriter(t *testing.T) {
var buffer bytes.Buffer

ctx := context.Background()

// fromDockerfile {
req := ContainerRequest{
FromDockerfile: FromDockerfile{
Context: filepath.Join(".", "testdata"),
Dockerfile: "buildlog.Dockerfile",
BuildLogWriter: &buffer,
},
}
// }

genContainerReq := GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
}

c, err := GenericContainer(ctx, genContainerReq)
CleanupContainer(t, c)
require.NoError(t, err)

out := buffer.String()
temp := strings.Split(out, "\n")
require.NotEmpty(t, temp)
require.Regexpf(t, `^Step\s*1/\d+\s*:\s*FROM alpine$`, temp[0], "Expected stdout first line to be %s. Got '%s'.", "Step 1/* : FROM alpine", temp[0])
}

func TestContainerCreationWaitsForLogAndPortContextTimeout(t *testing.T) {
ctx := context.Background()
req := ContainerRequest{
Expand Down

0 comments on commit ea4feea

Please sign in to comment.