Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -137,10 +137,13 @@ type ChildConfig struct {
|
| 137 | 137 |
// NewChildImage creates a new Image as a child of this image. |
| 138 | 138 |
func NewChildImage(img *Image, child ChildConfig, platform string) *Image {
|
| 139 | 139 |
isEmptyLayer := layer.IsEmpty(child.DiffID) |
| 140 |
- rootFS := img.RootFS |
|
| 141 |
- if rootFS == nil {
|
|
| 140 |
+ var rootFS *RootFS |
|
| 141 |
+ if img.RootFS != nil {
|
|
| 142 |
+ rootFS = img.RootFS.Clone() |
|
| 143 |
+ } else {
|
|
| 142 | 144 |
rootFS = NewRootFS() |
| 143 | 145 |
} |
| 146 |
+ |
|
| 144 | 147 |
if !isEmptyLayer {
|
| 145 | 148 |
rootFS.Append(child.DiffID) |
| 146 | 149 |
} |
| ... | ... |
@@ -6,6 +6,8 @@ import ( |
| 6 | 6 |
"strings" |
| 7 | 7 |
"testing" |
| 8 | 8 |
|
| 9 |
+ "github.com/docker/docker/api/types/container" |
|
| 10 |
+ "github.com/docker/docker/layer" |
|
| 9 | 11 |
"github.com/stretchr/testify/assert" |
| 10 | 12 |
"github.com/stretchr/testify/require" |
| 11 | 13 |
) |
| ... | ... |
@@ -51,3 +53,38 @@ func TestMarshalKeyOrder(t *testing.T) {
|
| 51 | 51 |
t.Fatal("invalid key order in JSON: ", string(b))
|
| 52 | 52 |
} |
| 53 | 53 |
} |
| 54 |
+ |
|
| 55 |
+func TestNewChildImageFromImageWithRootFS(t *testing.T) {
|
|
| 56 |
+ rootFS := NewRootFS() |
|
| 57 |
+ rootFS.Append(layer.DiffID("ba5e"))
|
|
| 58 |
+ parent := &Image{
|
|
| 59 |
+ RootFS: rootFS, |
|
| 60 |
+ History: []History{
|
|
| 61 |
+ NewHistory("a", "c", "r", false),
|
|
| 62 |
+ }, |
|
| 63 |
+ } |
|
| 64 |
+ childConfig := ChildConfig{
|
|
| 65 |
+ DiffID: layer.DiffID("abcdef"),
|
|
| 66 |
+ Author: "author", |
|
| 67 |
+ Comment: "comment", |
|
| 68 |
+ ContainerConfig: &container.Config{
|
|
| 69 |
+ Cmd: []string{"echo", "foo"},
|
|
| 70 |
+ }, |
|
| 71 |
+ Config: &container.Config{},
|
|
| 72 |
+ } |
|
| 73 |
+ |
|
| 74 |
+ newImage := NewChildImage(parent, childConfig, "platform") |
|
| 75 |
+ expectedDiffIDs := []layer.DiffID{layer.DiffID("ba5e"), layer.DiffID("abcdef")}
|
|
| 76 |
+ assert.Equal(t, expectedDiffIDs, newImage.RootFS.DiffIDs) |
|
| 77 |
+ assert.Equal(t, childConfig.Author, newImage.Author) |
|
| 78 |
+ assert.Equal(t, childConfig.Config, newImage.Config) |
|
| 79 |
+ assert.Equal(t, *childConfig.ContainerConfig, newImage.ContainerConfig) |
|
| 80 |
+ assert.Equal(t, "platform", newImage.OS) |
|
| 81 |
+ assert.Equal(t, childConfig.Config, newImage.Config) |
|
| 82 |
+ |
|
| 83 |
+ assert.Len(t, newImage.History, 2) |
|
| 84 |
+ assert.Equal(t, childConfig.Comment, newImage.History[1].Comment) |
|
| 85 |
+ |
|
| 86 |
+ // RootFS should be copied not mutated |
|
| 87 |
+ assert.NotEqual(t, parent.RootFS.DiffIDs, newImage.RootFS.DiffIDs) |
|
| 88 |
+} |
| ... | ... |
@@ -34,6 +34,14 @@ func (r *RootFS) Append(id layer.DiffID) {
|
| 34 | 34 |
r.DiffIDs = append(r.DiffIDs, id) |
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 |
+// Clone returns a copy of the RootFS |
|
| 38 |
+func (r *RootFS) Clone() *RootFS {
|
|
| 39 |
+ newRoot := NewRootFS() |
|
| 40 |
+ newRoot.Type = r.Type |
|
| 41 |
+ newRoot.DiffIDs = append(r.DiffIDs) |
|
| 42 |
+ return newRoot |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 37 | 45 |
// ChainID returns the ChainID for the top layer in RootFS. |
| 38 | 46 |
func (r *RootFS) ChainID() layer.ChainID {
|
| 39 | 47 |
if runtime.GOOS == "windows" && r.Type == typeLayersWithBase {
|