Skip to content

Commit

Permalink
Clear old parent reference on resetting image parent
Browse files Browse the repository at this point in the history
On migration 2 different images can end up with same
content addressable ID, meaning `SetParent` will be called
multiple times. Previous version did not clear the old
in-memory reference.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
  • Loading branch information
tonistiigi committed Feb 6, 2016
1 parent b3bacb4 commit 4852932
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
3 changes: 3 additions & 0 deletions image/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ func (is *store) SetParent(id, parent ID) error {
if parentMeta == nil {
return fmt.Errorf("unknown parent image ID %s", parent.String())
}
if parent, err := is.GetParent(id); err == nil && is.images[parent] != nil {
delete(is.images[parent].children, id)
}
parentMeta.children[id] = struct{}{}
return is.fs.SetMetadata(id, "parent", []byte(parent))
}
Expand Down
56 changes: 56 additions & 0 deletions image/store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,62 @@ func TestSearchAfterDelete(t *testing.T) {
}
}

func TestParentReset(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "images-fs-store")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
fs, err := NewFSStoreBackend(tmpdir)
if err != nil {
t.Fatal(err)
}

is, err := NewImageStore(fs, &mockLayerGetReleaser{})
if err != nil {
t.Fatal(err)
}

id, err := is.Create([]byte(`{"comment": "abc1", "rootfs": {"type": "layers"}}`))
if err != nil {
t.Fatal(err)
}

id2, err := is.Create([]byte(`{"comment": "abc2", "rootfs": {"type": "layers"}}`))
if err != nil {
t.Fatal(err)
}

id3, err := is.Create([]byte(`{"comment": "abc3", "rootfs": {"type": "layers"}}`))
if err != nil {
t.Fatal(err)
}

if err := is.SetParent(id, id2); err != nil {
t.Fatal(err)
}

ids := is.Children(id2)
if actual, expected := len(ids), 1; expected != actual {
t.Fatalf("wrong number of children: %d, got %d", expected, actual)
}

if err := is.SetParent(id, id3); err != nil {
t.Fatal(err)
}

ids = is.Children(id2)
if actual, expected := len(ids), 0; expected != actual {
t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual)
}

ids = is.Children(id3)
if actual, expected := len(ids), 1; expected != actual {
t.Fatalf("wrong number of children after parent reset: %d, got %d", expected, actual)
}

}

type mockLayerGetReleaser struct{}

func (ls *mockLayerGetReleaser) Get(layer.ChainID) (layer.Layer, error) {
Expand Down

0 comments on commit 4852932

Please sign in to comment.