Add method to flatten and extract image fs#99
Conversation
| return fmt.Errorf("Error creating tar file: %v", err) | ||
| } | ||
| defer tarFile.Close() | ||
| fileWriter := bufio.NewWriter(tarFile) |
There was a problem hiding this comment.
why do we need the bufio writer?
| if err != nil { | ||
| return fmt.Errorf("Error retriving image layers: %v", err) | ||
| } | ||
| for i := len(layers) - 1; i >= 0; i-- { |
There was a problem hiding this comment.
Can you add a comment on why we go in reverse?
An overall link to the python implementation might help people understand.
| return nil | ||
| } | ||
|
|
||
| func inWhiteoutDir(fileMap map[string]bool, file string) bool { |
There was a problem hiding this comment.
some unit tests for this helper would be useful.
| // any entries with a matching (or child) name | ||
| fileMap[name] = tombstone || !(header.Typeflag == tar.TypeDir) | ||
| if !tombstone { | ||
| buf := make([]byte, header.Size) |
There was a problem hiding this comment.
I think you can use io.Copy from one tar into the other here, after writing the header.
You only have to do it if size != 0.
There was a problem hiding this comment.
ah yeah, for some reason I thought I couldn't copy straight from the tar reader. fixed
|
|
||
| layers, err := img.Layers() | ||
| if err != nil { | ||
| return fmt.Errorf("Error retriving image layers: %v", err) |
| if err != nil { | ||
| t.Errorf("Error when opening tar file for reading: %v", err) | ||
| } | ||
| r := bufio.NewReader(f) |
There was a problem hiding this comment.
Don't need the bufio.Reader here either.
| tarWriter := tar.NewWriter(tarFile) | ||
| defer tarWriter.Close() | ||
|
|
||
| fileMap := make(map[string]bool, 0) |
There was a problem hiding this comment.
nit: I find the map literal form a bit more straightforward: fileMap := map[string]bool{}
| "github.com/google/go-containerregistry/v1/v1util" | ||
| ) | ||
|
|
||
| const whiteoutPrefix string = ".wh." |
There was a problem hiding this comment.
I think you can drop the "string" here.
| if !tombstone { | ||
| tarWriter.WriteHeader(header) | ||
| if header.Size > 0 { | ||
| io.Copy(tarWriter, tarReader) |
| ) | ||
|
|
||
| func TestFlatten(t *testing.T) { | ||
| img, err := ImageFromPath("testdata/whiteout.tar", nil) |
There was a problem hiding this comment.
Would it be possible to construct this with bazel and reference it as a dependency of the test, instead of checking it in? It would make the contents/functionality of this test more transparent.
There was a problem hiding this comment.
yep, updated to use container_layer to manually create a whiteout layer and test that that file isn't in the final tarball
| name := header.Name | ||
| // this image was built by creating a directory called "foo", | ||
| // touching "/foo/bar", and then removing the whole directory. | ||
| for _, part := range filepath.SplitList(name) { |
There was a problem hiding this comment.
We should also add a file to the tar that exercises a file being overwritten in a subsequent layer.
|
Is it possible to make this just a generic For example, to flatten a remote image: Or to flatten a local tarball: This currently just writes the output to a tarball on disk, which seems like it would be hard to use as a library. Or even if it just took a |
|
@jonjohnsonjr I think I was a little off with the naming/description of this method. this is an adaptation of the that being said, there's not really any reason why this can't be a little more generic so it can be used modularly. @dlorenc had suggested returning either a extracting the final filesystem from a remote image: we should be able to use this to flatten any arbitrary image (and actually return a |
|
SGTM! |
| return tar.NewReader(&b), nil | ||
| } | ||
|
|
||
| func InWhiteoutDir(fileMap map[string]bool, file string) bool { |
There was a problem hiding this comment.
Does this need to be public?
There was a problem hiding this comment.
whoops, nope thanks
This will let us pass in any image tar and extract its flattened filesystem. We'll use this in https://github.com/GoogleContainerTools/container-diff to do image filesystem comparisons among other things. This can also be used later to implement flattening of arbitrary images.