Browse Source

Merge branch '1582_fix_volume_content' of https://github.com/griff/docker into griff-1582_fix_volume_content

Victor Vieux 12 years ago
parent
commit
27ca0c225a
3 changed files with 82 additions and 7 deletions
  1. 27 6
      container.go
  2. 54 0
      container_test.go
  3. 1 1
      network.go

+ 27 - 6
container.go

@@ -664,11 +664,13 @@ func (container *Container) Start(hostConfig *HostConfig) error {
 		if _, exists := container.Volumes[volPath]; exists {
 			continue
 		}
+		var srcPath string
+		srcRW := false
 		// 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
+			srcPath = bindMap.SrcPath
 			if strings.ToLower(bindMap.Mode) == "rw" {
-				container.VolumesRW[volPath] = true
+				srcRW = true
 			}
 			// Otherwise create an directory in $ROOT/volumes/ and use that
 		} else {
@@ -676,17 +678,36 @@ func (container *Container) Start(hostConfig *HostConfig) error {
 			if err != nil {
 				return err
 			}
-			srcPath, err := c.layer()
+			srcPath, err = c.layer()
 			if err != nil {
 				return err
 			}
-			container.Volumes[volPath] = srcPath
-			container.VolumesRW[volPath] = true // RW by default
+			srcRW = true // RW by default
 		}
+		container.Volumes[volPath] = srcPath
+		container.VolumesRW[volPath] = srcRW
 		// Create the mountpoint
-		if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
+		rootVolPath := path.Join(container.RootfsPath(), volPath)
+		if err := os.MkdirAll(rootVolPath, 0755); err != nil {
 			return nil
 		}
+		if srcRW {
+			volList, err := ioutil.ReadDir(rootVolPath)
+			if err != nil {
+				return err
+			}
+			if len(volList) > 0 {
+				srcList, err := ioutil.ReadDir(srcPath)
+				if err != nil {
+					return err
+				}
+				if len(srcList) == 0 {
+					if err := CopyWithTar(rootVolPath, srcPath); err != nil {
+						return err
+					}
+				}
+			}
+		}
 	}
 
 	if err := container.generateLXCConfig(hostConfig); err != nil {

+ 54 - 0
container_test.go

@@ -1196,6 +1196,60 @@ func tempDir(t *testing.T) string {
 	return tmpDir
 }
 
+// Test for #1582
+func TestCopyVolumeContent(t *testing.T) {
+	r := mkRuntime(t)
+	defer nuke(r)
+
+	// Put some content in a directory of a container and commit it
+	container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello/local && echo hello > /hello/local/world"}, t)
+	defer r.Destroy(container1)
+
+	if container1.State.Running {
+		t.Errorf("Container shouldn't be running")
+	}
+	if err := container1.Run(); err != nil {
+		t.Fatal(err)
+	}
+	if container1.State.Running {
+		t.Errorf("Container shouldn't be running")
+	}
+
+	rwTar, err := container1.ExportRw()
+	if err != nil {
+		t.Error(err)
+	}
+	img, err := r.graph.Create(rwTar, container1, "unit test commited image", "", nil)
+	if err != nil {
+		t.Error(err)
+	}
+
+	// Test that the content is copied from the image to the volume
+	tmpDir1 := tempDir(t)
+	defer os.RemoveAll(tmpDir1)
+	stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "find", "/hello"}, t)
+	if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
+		t.Fatal("Container failed to transfer content to volume")
+	}
+
+	// Test that the content is not copied when the volume is readonly
+	tmpDir2 := tempDir(t)
+	defer os.RemoveAll(tmpDir2)
+	stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "find", "/hello"}, t)
+	if strings.Contains(stdout2, "/hello/local/world") || strings.Contains(stdout2, "/hello/local") {
+		t.Fatal("Container transfered content to readonly volume")
+	}
+
+	// Test that the content is not copied when the volume is non-empty
+	tmpDir3 := tempDir(t)
+	defer os.RemoveAll(tmpDir3)
+	writeFile(path.Join(tmpDir3, "touch-me"), "", t)
+	stdout3, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:rw", tmpDir3), img.ID, "find", "/hello"}, t)
+	if strings.Contains(stdout3, "/hello/local/world") || strings.Contains(stdout3, "/hello/local") || !strings.Contains(stdout3, "/hello/touch-me") {
+		t.Fatal("Container transfered content to non-empty volume")
+	}
+}
+
 func TestBindMounts(t *testing.T) {
 	r := mkRuntime(t)
 	defer nuke(r)

+ 1 - 1
network.go

@@ -642,7 +642,7 @@ func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
 	if err != nil {
 		return nil, err
 	}
-	// avoid duplicate IP 
+	// avoid duplicate IP
 	ipNum := ipToInt(ip)
 	firstIP := manager.ipAllocator.network.IP.To4().Mask(manager.ipAllocator.network.Mask)
 	firstIPNum := ipToInt(firstIP) + 1