From b50ade0bfb67dae7867f4f5c3da12c1f778b6c7e Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Tue, 11 Jul 2017 17:17:38 -0400 Subject: [PATCH] Fix multiple copy from Signed-off-by: Daniel Nephin --- image/image.go | 7 +++++-- image/image_test.go | 37 +++++++++++++++++++++++++++++++++++++ image/rootfs.go | 8 ++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/image/image.go b/image/image.go index ab95d93dab..c63aec5237 100644 --- a/image/image.go +++ b/image/image.go @@ -137,10 +137,13 @@ type ChildConfig struct { // NewChildImage creates a new Image as a child of this image. func NewChildImage(img *Image, child ChildConfig, platform string) *Image { isEmptyLayer := layer.IsEmpty(child.DiffID) - rootFS := img.RootFS - if rootFS == nil { + var rootFS *RootFS + if img.RootFS != nil { + rootFS = img.RootFS.Clone() + } else { rootFS = NewRootFS() } + if !isEmptyLayer { rootFS.Append(child.DiffID) } diff --git a/image/image_test.go b/image/image_test.go index 1455947df2..e04587edae 100644 --- a/image/image_test.go +++ b/image/image_test.go @@ -6,6 +6,8 @@ import ( "strings" "testing" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/layer" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -51,3 +53,38 @@ func TestMarshalKeyOrder(t *testing.T) { t.Fatal("invalid key order in JSON: ", string(b)) } } + +func TestNewChildImageFromImageWithRootFS(t *testing.T) { + rootFS := NewRootFS() + rootFS.Append(layer.DiffID("ba5e")) + parent := &Image{ + RootFS: rootFS, + History: []History{ + NewHistory("a", "c", "r", false), + }, + } + childConfig := ChildConfig{ + DiffID: layer.DiffID("abcdef"), + Author: "author", + Comment: "comment", + ContainerConfig: &container.Config{ + Cmd: []string{"echo", "foo"}, + }, + Config: &container.Config{}, + } + + newImage := NewChildImage(parent, childConfig, "platform") + expectedDiffIDs := []layer.DiffID{layer.DiffID("ba5e"), layer.DiffID("abcdef")} + assert.Equal(t, expectedDiffIDs, newImage.RootFS.DiffIDs) + assert.Equal(t, childConfig.Author, newImage.Author) + assert.Equal(t, childConfig.Config, newImage.Config) + assert.Equal(t, *childConfig.ContainerConfig, newImage.ContainerConfig) + assert.Equal(t, "platform", newImage.OS) + assert.Equal(t, childConfig.Config, newImage.Config) + + assert.Len(t, newImage.History, 2) + assert.Equal(t, childConfig.Comment, newImage.History[1].Comment) + + // RootFS should be copied not mutated + assert.NotEqual(t, parent.RootFS.DiffIDs, newImage.RootFS.DiffIDs) +} diff --git a/image/rootfs.go b/image/rootfs.go index 7b24e3ed1e..5a9020f0ed 100644 --- a/image/rootfs.go +++ b/image/rootfs.go @@ -34,6 +34,14 @@ func (r *RootFS) Append(id layer.DiffID) { r.DiffIDs = append(r.DiffIDs, id) } +// Clone returns a copy of the RootFS +func (r *RootFS) Clone() *RootFS { + newRoot := NewRootFS() + newRoot.Type = r.Type + newRoot.DiffIDs = append(r.DiffIDs) + return newRoot +} + // ChainID returns the ChainID for the top layer in RootFS. func (r *RootFS) ChainID() layer.ChainID { if runtime.GOOS == "windows" && r.Type == typeLayersWithBase {