26184de8ab
The argument specified the json data to save to disk when registering a new image into the image graph. If it is nil, then the given image is serialized to json and that is written by default. This default behavior is sufficient if the given image was originally deserialzed from this jsonData to begin with which has always been the case. Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
318 lines
7.4 KiB
Go
318 lines
7.4 KiB
Go
package docker
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/docker/docker/daemon/graphdriver"
|
|
"github.com/docker/docker/dockerversion"
|
|
"github.com/docker/docker/graph"
|
|
"github.com/docker/docker/image"
|
|
"github.com/docker/docker/pkg/archive"
|
|
"github.com/docker/docker/utils"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestMount(t *testing.T) {
|
|
graph, driver := tempGraph(t)
|
|
defer os.RemoveAll(graph.Root)
|
|
defer driver.Cleanup()
|
|
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
image, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tmp, err := ioutil.TempDir("", "docker-test-graph-mount-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(tmp)
|
|
rootfs := path.Join(tmp, "rootfs")
|
|
if err := os.MkdirAll(rootfs, 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
rw := path.Join(tmp, "rw")
|
|
if err := os.MkdirAll(rw, 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := driver.Get(image.ID, ""); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestInit(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
// Root should exist
|
|
if _, err := os.Stat(graph.Root); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Map() should be empty
|
|
if l, err := graph.Map(); err != nil {
|
|
t.Fatal(err)
|
|
} else if len(l) != 0 {
|
|
t.Fatalf("len(Map()) should return %d, not %d", 0, len(l))
|
|
}
|
|
}
|
|
|
|
// Test that Register can be interrupted cleanly without side effects
|
|
func TestInterruptedRegister(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
|
|
image := &image.Image{
|
|
ID: utils.GenerateRandomID(),
|
|
Comment: "testing",
|
|
Created: time.Now(),
|
|
}
|
|
w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
|
|
graph.Register(image, badArchive)
|
|
if _, err := graph.Get(image.ID); err == nil {
|
|
t.Fatal("Image should not exist after Register is interrupted")
|
|
}
|
|
// Registering the same image again should succeed if the first register was interrupted
|
|
goodArchive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := graph.Register(image, goodArchive); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
|
|
// create multiple, check the amount of images and paths, etc..)
|
|
func TestGraphCreate(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
img, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := utils.ValidateID(img.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if img.Comment != "Testing" {
|
|
t.Fatalf("Wrong comment: should be '%s', not '%s'", "Testing", img.Comment)
|
|
}
|
|
if img.DockerVersion != dockerversion.VERSION {
|
|
t.Fatalf("Wrong docker_version: should be '%s', not '%s'", dockerversion.VERSION, img.DockerVersion)
|
|
}
|
|
images, err := graph.Map()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
} else if l := len(images); l != 1 {
|
|
t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
|
|
}
|
|
if images[img.ID] == nil {
|
|
t.Fatalf("Could not find image with id %s", img.ID)
|
|
}
|
|
}
|
|
|
|
func TestRegister(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
image := &image.Image{
|
|
ID: utils.GenerateRandomID(),
|
|
Comment: "testing",
|
|
Created: time.Now(),
|
|
}
|
|
err = graph.Register(image, archive)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if images, err := graph.Map(); err != nil {
|
|
t.Fatal(err)
|
|
} else if l := len(images); l != 1 {
|
|
t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l)
|
|
}
|
|
if resultImg, err := graph.Get(image.ID); err != nil {
|
|
t.Fatal(err)
|
|
} else {
|
|
if resultImg.ID != image.ID {
|
|
t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID)
|
|
}
|
|
if resultImg.Comment != image.Comment {
|
|
t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test that an image can be deleted by its shorthand prefix
|
|
func TestDeletePrefix(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
img := createTestImage(graph, t)
|
|
if err := graph.Delete(utils.TruncateID(img.ID)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 0)
|
|
}
|
|
|
|
func createTestImage(graph *graph.Graph, t *testing.T) *image.Image {
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
img, err := graph.Create(archive, "", "", "Test image", "", nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return img
|
|
}
|
|
|
|
func TestDelete(t *testing.T) {
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 0)
|
|
img, err := graph.Create(archive, "", "", "Bla bla", "", nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 1)
|
|
if err := graph.Delete(img.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 0)
|
|
|
|
archive, err = fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Test 2 create (same name) / 1 delete
|
|
img1, err := graph.Create(archive, "", "", "Testing", "", nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
archive, err = fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err = graph.Create(archive, "", "", "Testing", "", nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 2)
|
|
if err := graph.Delete(img1.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 1)
|
|
|
|
// Test delete wrong name
|
|
if err := graph.Delete("Not_foo"); err == nil {
|
|
t.Fatalf("Deleting wrong ID should return an error")
|
|
}
|
|
assertNImages(graph, t, 1)
|
|
|
|
archive, err = fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Test delete twice (pull -> rm -> pull -> rm)
|
|
if err := graph.Register(img1, archive); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := graph.Delete(img1.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
assertNImages(graph, t, 1)
|
|
}
|
|
|
|
func TestByParent(t *testing.T) {
|
|
archive1, _ := fakeTar()
|
|
archive2, _ := fakeTar()
|
|
archive3, _ := fakeTar()
|
|
|
|
graph, _ := tempGraph(t)
|
|
defer nukeGraph(graph)
|
|
parentImage := &image.Image{
|
|
ID: utils.GenerateRandomID(),
|
|
Comment: "parent",
|
|
Created: time.Now(),
|
|
Parent: "",
|
|
}
|
|
childImage1 := &image.Image{
|
|
ID: utils.GenerateRandomID(),
|
|
Comment: "child1",
|
|
Created: time.Now(),
|
|
Parent: parentImage.ID,
|
|
}
|
|
childImage2 := &image.Image{
|
|
ID: utils.GenerateRandomID(),
|
|
Comment: "child2",
|
|
Created: time.Now(),
|
|
Parent: parentImage.ID,
|
|
}
|
|
_ = graph.Register(parentImage, archive1)
|
|
_ = graph.Register(childImage1, archive2)
|
|
_ = graph.Register(childImage2, archive3)
|
|
|
|
byParent, err := graph.ByParent()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
numChildren := len(byParent[parentImage.ID])
|
|
if numChildren != 2 {
|
|
t.Fatalf("Expected 2 children, found %d", numChildren)
|
|
}
|
|
}
|
|
|
|
/*
|
|
* HELPER FUNCTIONS
|
|
*/
|
|
|
|
func assertNImages(graph *graph.Graph, t *testing.T, n int) {
|
|
if images, err := graph.Map(); err != nil {
|
|
t.Fatal(err)
|
|
} else if actualN := len(images); actualN != n {
|
|
t.Fatalf("Expected %d images, found %d", n, actualN)
|
|
}
|
|
}
|
|
|
|
func tempGraph(t *testing.T) (*graph.Graph, graphdriver.Driver) {
|
|
tmp, err := ioutil.TempDir("", "docker-graph-")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
driver, err := graphdriver.New(tmp, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
graph, err := graph.NewGraph(tmp, driver)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return graph, driver
|
|
}
|
|
|
|
func nukeGraph(graph *graph.Graph) {
|
|
graph.Driver().Cleanup()
|
|
os.RemoveAll(graph.Root)
|
|
}
|
|
|
|
func testArchive(t *testing.T) archive.Archive {
|
|
archive, err := fakeTar()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return archive
|
|
}
|