Skip to content

Commit

Permalink
Don't require file to exist in container for copy operation to comple…
Browse files Browse the repository at this point in the history
…te successfully

<layers>/generated/build isn't guaranteed to exist

Signed-off-by: Natalie Arellano <narellano@vmware.com>
  • Loading branch information
natalieparellano committed Apr 6, 2023
1 parent d9b7132 commit 1ba8367
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 4 deletions.
5 changes: 4 additions & 1 deletion acceptance/assertions/lifecycle_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ func (l LifecycleOutputAssertionManager) IncludesSeparatePhases() {
func (l LifecycleOutputAssertionManager) IncludesSeparatePhasesWithExtension() {
l.testObject.Helper()

l.assert.ContainsAll(l.output, "[detector]", "[analyzer]", "[extender]", "[exporter]")
// Earlier pack versions print `[extender]`, later pack versions print `[extender (build)]`.
// Removing the `]` for the extend phase allows us to navigate compat suite complexity without undo headache.
// When previous pack is old enough, we can make the matcher more precise.
l.assert.ContainsAll(l.output, "[detector]", "[analyzer]", "[extender", "[exporter]")
}

func (l LifecycleOutputAssertionManager) IncludesLifecycleImageTag(tag string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
#!/usr/bin/env bash

echo "---> Generate: Read Env Extension"

# 1. GET ARGS
output_dir=$CNB_OUTPUT_DIR

# 2. GENERATE build.Dockerfile
cat >> "${output_dir}/build.Dockerfile" <<EOL
ARG base_image
FROM \${base_image}
RUN echo "Hello World"
EOL
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ require (
golang.org/x/crypto v0.7.0
golang.org/x/mod v0.10.0
golang.org/x/oauth2 v0.6.0
golang.org/x/sync v0.1.0
golang.org/x/term v0.7.0
golang.org/x/text v0.8.0
gopkg.in/yaml.v3 v3.0.1
Expand Down Expand Up @@ -113,7 +114,6 @@ require (
github.com/vbatts/tar-split v0.11.2 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
Expand Down
37 changes: 37 additions & 0 deletions internal/build/container_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/buildpacks/lifecycle/platform"
"github.com/docker/docker/api/types"
dcontainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/errdefs"
darchive "github.com/docker/docker/pkg/archive"
"github.com/pkg/errors"

Expand Down Expand Up @@ -42,6 +43,30 @@ func CopyOut(handler func(closer io.ReadCloser) error, srcs ...string) Container
}
}

// CopyOutErr copies container directories to a handler function. The handler is responsible for closing the Reader.
// CopyOutErr differs from CopyOut in that it does not require the source files to exist in the container
// in order to exit without error.
func CopyOutErr(handler func(closer io.ReadCloser) error, srcs ...string) ContainerOperation {
return func(ctrClient DockerClient, ctx context.Context, containerID string, stdout, stderr io.Writer) error {
for _, src := range srcs {
reader, _, err := ctrClient.CopyFromContainer(ctx, containerID, src)
if err != nil {
if errdefs.IsNotFound(err) {
continue
}
return err
}

err = handler(reader)
if err != nil {
return err
}
}

return nil
}
}

func CopyOutTo(src, dest string) ContainerOperation {
return CopyOut(func(reader io.ReadCloser) error {
info := darchive.CopyInfo{
Expand All @@ -54,6 +79,18 @@ func CopyOutTo(src, dest string) ContainerOperation {
}, src)
}

func CopyOutToErr(src, dest string) ContainerOperation {
return CopyOutErr(func(reader io.ReadCloser) error {
info := darchive.CopyInfo{
Path: src,
IsDir: true,
}

defer reader.Close()
return darchive.CopyTo(reader, info, dest)
}, src)
}

// CopyDir copies a local directory (src) to the destination on the container while filtering files and changing it's UID/GID.
// if includeRoot is set the UID/GID will be set on the dst directory.
func CopyDir(src, dst string, uid, gid int, os string, includeRoot bool, fileFilter func(string) bool) ContainerOperation {
Expand Down
4 changes: 2 additions & 2 deletions internal/build/lifecycle_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,9 @@ func (l *LifecycleExecution) Detect(ctx context.Context, phaseFactory PhaseFacto
),
WithFlags(flags...),
If(l.hasExtensions(), WithPostContainerRunOperations(
CopyOutTo(filepath.Join(l.mountPaths.layersDir(), "analyzed.toml"), l.TmpDir))),
CopyOutToErr(filepath.Join(l.mountPaths.layersDir(), "analyzed.toml"), l.TmpDir))),
If(l.hasExtensions(), WithPostContainerRunOperations(
CopyOutTo(filepath.Join(l.mountPaths.layersDir(), "generated", "build"), l.TmpDir))),
CopyOutToErr(filepath.Join(l.mountPaths.layersDir(), "generated", "build"), l.TmpDir))),
envOp,
)

Expand Down

0 comments on commit 1ba8367

Please sign in to comment.