From 92cbb7cc80a63299b5670a9fcbb2d11789200696 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Sun, 14 Jul 2013 15:26:57 -0900 Subject: [PATCH] Do not overwrite container volumes from config Fixes #819 Use same persistent volume when a container is restarted --- container.go | 51 +++++++++++++++++++++++++---------------------- container_test.go | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 24 deletions(-) diff --git a/container.go b/container.go index c714e9f0e1..53d720b771 100644 --- a/container.go +++ b/container.go @@ -516,8 +516,6 @@ func (container *Container) Start(hostConfig *HostConfig) error { log.Printf("WARNING: Your kernel does not support swap limit capabilities. Limitation discarded.\n") container.Config.MemorySwap = -1 } - container.Volumes = make(map[string]string) - container.VolumesRW = make(map[string]bool) // Create the requested bind mounts binds := make(map[string]BindMap) @@ -557,30 +555,35 @@ func (container *Container) Start(hostConfig *HostConfig) error { // FIXME: evaluate volumes-from before individual volumes, so that the latter can override the former. // Create the requested volumes volumes - for volPath := range container.Config.Volumes { - volPath = path.Clean(volPath) - // If an external bind is defined for this volume, use that as a source - if bindMap, exists := binds[volPath]; exists { - container.Volumes[volPath] = bindMap.SrcPath - if strings.ToLower(bindMap.Mode) == "rw" { - container.VolumesRW[volPath] = true + if container.Volumes == nil || len(container.Volumes) == 0 { + container.Volumes = make(map[string]string) + container.VolumesRW = make(map[string]bool) + + for volPath := range container.Config.Volumes { + volPath = path.Clean(volPath) + // If an external bind is defined for this volume, use that as a source + if bindMap, exists := binds[volPath]; exists { + container.Volumes[volPath] = bindMap.SrcPath + if strings.ToLower(bindMap.Mode) == "rw" { + container.VolumesRW[volPath] = true + } + // Otherwise create an directory in $ROOT/volumes/ and use that + } else { + c, err := container.runtime.volumes.Create(nil, container, "", "", nil) + if err != nil { + return err + } + srcPath, err := c.layer() + if err != nil { + return err + } + container.Volumes[volPath] = srcPath + container.VolumesRW[volPath] = true // RW by default } - // Otherwise create an directory in $ROOT/volumes/ and use that - } else { - c, err := container.runtime.volumes.Create(nil, container, "", "", nil) - if err != nil { - return err + // Create the mountpoint + if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { + return nil } - srcPath, err := c.layer() - if err != nil { - return err - } - container.Volumes[volPath] = srcPath - container.VolumesRW[volPath] = true // RW by default - } - // Create the mountpoint - if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { - return nil } } diff --git a/container_test.go b/container_test.go index f431c7dc9a..2209bc0be0 100644 --- a/container_test.go +++ b/container_test.go @@ -1300,3 +1300,46 @@ func TestVolumesFromReadonlyMount(t *testing.T) { t.Fail() } } + +// Test that restarting a container with a volume does not create a new volume on restart. Regression test for #819. +func TestRestartWithVolumes(t *testing.T) { + runtime := mkRuntime(t) + defer nuke(runtime) + + container, err := NewBuilder(runtime).Create(&Config{ + Image: GetTestImage(runtime).ID, + Cmd: []string{"echo", "-n", "foobar"}, + Volumes: map[string]struct{}{"/test": {}}, + }, + ) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container) + + for key := range container.Config.Volumes { + if key != "/test" { + t.Fail() + } + } + + _, err = container.Output() + if err != nil { + t.Fatal(err) + } + + expected := container.Volumes["/test"] + if expected == "" { + t.Fail() + } + // Run the container again to verify the volume path persists + _, err = container.Output() + if err != nil { + t.Fatal(err) + } + + actual := container.Volumes["/test"] + if expected != actual { + t.Fatalf("Expected volume path: %s Actual path: %s", expected, actual) + } +}