From e3f83e7aa75864d13bed502469723ec6dc7c9b5a Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Mon, 10 Jun 2019 19:03:58 -0700 Subject: [PATCH] Add test for copying entire container rootfs CID=$(docker create alpine) docker cp $CID:/ out Signed-off-by: Brian Goff Signed-off-by: Tibor Vass (cherry picked from commit 6db9f1c3d6e9ad634554cacaf197a435efcf8833) Signed-off-by: Tibor Vass --- integration/container/copy_test.go | 82 ++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/integration/container/copy_test.go b/integration/container/copy_test.go index 9c5c5ce297..58355b0921 100644 --- a/integration/container/copy_test.go +++ b/integration/container/copy_test.go @@ -1,13 +1,20 @@ package container // import "github.com/docker/docker/integration/container" import ( + "archive/tar" "context" + "encoding/json" "fmt" + "io" + "io/ioutil" + "os" "testing" "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/docker/docker/integration/internal/container" + "github.com/docker/docker/internal/test/fakecontext" + "github.com/docker/docker/pkg/jsonmessage" "gotest.tools/assert" is "gotest.tools/assert/cmp" "gotest.tools/skip" @@ -64,3 +71,78 @@ func TestCopyToContainerPathIsNotDir(t *testing.T) { err := apiclient.CopyToContainer(ctx, cid, "/etc/passwd/", nil, types.CopyToContainerOptions{}) assert.Assert(t, is.ErrorContains(err, "not a directory")) } + +func TestCopyFromContainerRoot(t *testing.T) { + skip.If(t, testEnv.DaemonInfo.OSType == "windows") + defer setupTest(t)() + + ctx := context.Background() + apiClient := testEnv.APIClient() + + dir, err := ioutil.TempDir("", t.Name()) + assert.NilError(t, err) + defer os.RemoveAll(dir) + + buildCtx := fakecontext.New(t, dir, fakecontext.WithFile("foo", "hello"), fakecontext.WithFile("baz", "world"), fakecontext.WithDockerfile(` + FROM scratch + COPY foo /foo + COPY baz /bar/baz + CMD /fake + `)) + defer buildCtx.Close() + + resp, err := apiClient.ImageBuild(ctx, buildCtx.AsTarReader(t), types.ImageBuildOptions{}) + assert.NilError(t, err) + defer resp.Body.Close() + + var imageID string + err = jsonmessage.DisplayJSONMessagesStream(resp.Body, ioutil.Discard, 0, false, func(msg jsonmessage.JSONMessage) { + var r types.BuildResult + assert.NilError(t, json.Unmarshal(*msg.Aux, &r)) + imageID = r.ID + }) + assert.NilError(t, err) + assert.Assert(t, imageID != "") + + cid := container.Create(ctx, t, apiClient, container.WithImage(imageID)) + + rdr, _, err := apiClient.CopyFromContainer(ctx, cid, "/") + assert.NilError(t, err) + defer rdr.Close() + + tr := tar.NewReader(rdr) + expect := map[string]string{ + "/foo": "hello", + "/bar/baz": "world", + } + found := make(map[string]bool, 2) + var numFound int + for { + h, err := tr.Next() + if err == io.EOF { + break + } + assert.NilError(t, err) + + expected, exists := expect[h.Name] + if !exists { + // this archive will have extra stuff in it since we are copying from root + // and docker adds a bunch of stuff + continue + } + + numFound++ + found[h.Name] = true + + buf, err := ioutil.ReadAll(tr) + assert.NilError(t, err) + assert.Check(t, is.Equal(string(buf), expected)) + + if numFound == len(expect) { + break + } + } + + assert.Check(t, found["/foo"], "/foo file not found in archive") + assert.Check(t, found["/bar/baz"], "/bar/baz file not found in archive") +}