Browse code

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

Victor Vieux authored on 2013/09/11 01:52:46
Showing 3 changed files
... ...
@@ -664,11 +664,13 @@ func (container *Container) Start(hostConfig *HostConfig) error {
664 664
 		if _, exists := container.Volumes[volPath]; exists {
665 665
 			continue
666 666
 		}
667
+		var srcPath string
668
+		srcRW := false
667 669
 		// If an external bind is defined for this volume, use that as a source
668 670
 		if bindMap, exists := binds[volPath]; exists {
669
-			container.Volumes[volPath] = bindMap.SrcPath
671
+			srcPath = bindMap.SrcPath
670 672
 			if strings.ToLower(bindMap.Mode) == "rw" {
671
-				container.VolumesRW[volPath] = true
673
+				srcRW = true
672 674
 			}
673 675
 			// Otherwise create an directory in $ROOT/volumes/ and use that
674 676
 		} else {
... ...
@@ -676,17 +678,36 @@ func (container *Container) Start(hostConfig *HostConfig) error {
676 676
 			if err != nil {
677 677
 				return err
678 678
 			}
679
-			srcPath, err := c.layer()
679
+			srcPath, err = c.layer()
680 680
 			if err != nil {
681 681
 				return err
682 682
 			}
683
-			container.Volumes[volPath] = srcPath
684
-			container.VolumesRW[volPath] = true // RW by default
683
+			srcRW = true // RW by default
685 684
 		}
685
+		container.Volumes[volPath] = srcPath
686
+		container.VolumesRW[volPath] = srcRW
686 687
 		// Create the mountpoint
687
-		if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil {
688
+		rootVolPath := path.Join(container.RootfsPath(), volPath)
689
+		if err := os.MkdirAll(rootVolPath, 0755); err != nil {
688 690
 			return nil
689 691
 		}
692
+		if srcRW {
693
+			volList, err := ioutil.ReadDir(rootVolPath)
694
+			if err != nil {
695
+				return err
696
+			}
697
+			if len(volList) > 0 {
698
+				srcList, err := ioutil.ReadDir(srcPath)
699
+				if err != nil {
700
+					return err
701
+				}
702
+				if len(srcList) == 0 {
703
+					if err := CopyWithTar(rootVolPath, srcPath); err != nil {
704
+						return err
705
+					}
706
+				}
707
+			}
708
+		}
690 709
 	}
691 710
 
692 711
 	if err := container.generateLXCConfig(hostConfig); err != nil {
... ...
@@ -1196,6 +1196,60 @@ func tempDir(t *testing.T) string {
1196 1196
 	return tmpDir
1197 1197
 }
1198 1198
 
1199
+// Test for #1582
1200
+func TestCopyVolumeContent(t *testing.T) {
1201
+	r := mkRuntime(t)
1202
+	defer nuke(r)
1203
+
1204
+	// Put some content in a directory of a container and commit it
1205
+	container1, _, _ := mkContainer(r, []string{"_", "/bin/sh", "-c", "mkdir -p /hello/local && echo hello > /hello/local/world"}, t)
1206
+	defer r.Destroy(container1)
1207
+
1208
+	if container1.State.Running {
1209
+		t.Errorf("Container shouldn't be running")
1210
+	}
1211
+	if err := container1.Run(); err != nil {
1212
+		t.Fatal(err)
1213
+	}
1214
+	if container1.State.Running {
1215
+		t.Errorf("Container shouldn't be running")
1216
+	}
1217
+
1218
+	rwTar, err := container1.ExportRw()
1219
+	if err != nil {
1220
+		t.Error(err)
1221
+	}
1222
+	img, err := r.graph.Create(rwTar, container1, "unit test commited image", "", nil)
1223
+	if err != nil {
1224
+		t.Error(err)
1225
+	}
1226
+
1227
+	// Test that the content is copied from the image to the volume
1228
+	tmpDir1 := tempDir(t)
1229
+	defer os.RemoveAll(tmpDir1)
1230
+	stdout1, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello", tmpDir1), img.ID, "find", "/hello"}, t)
1231
+	if !(strings.Contains(stdout1, "/hello/local/world") && strings.Contains(stdout1, "/hello/local")) {
1232
+		t.Fatal("Container failed to transfer content to volume")
1233
+	}
1234
+
1235
+	// Test that the content is not copied when the volume is readonly
1236
+	tmpDir2 := tempDir(t)
1237
+	defer os.RemoveAll(tmpDir2)
1238
+	stdout2, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:ro", tmpDir2), img.ID, "find", "/hello"}, t)
1239
+	if strings.Contains(stdout2, "/hello/local/world") || strings.Contains(stdout2, "/hello/local") {
1240
+		t.Fatal("Container transfered content to readonly volume")
1241
+	}
1242
+
1243
+	// Test that the content is not copied when the volume is non-empty
1244
+	tmpDir3 := tempDir(t)
1245
+	defer os.RemoveAll(tmpDir3)
1246
+	writeFile(path.Join(tmpDir3, "touch-me"), "", t)
1247
+	stdout3, _ := runContainer(r, []string{"-v", fmt.Sprintf("%s:/hello:rw", tmpDir3), img.ID, "find", "/hello"}, t)
1248
+	if strings.Contains(stdout3, "/hello/local/world") || strings.Contains(stdout3, "/hello/local") || !strings.Contains(stdout3, "/hello/touch-me") {
1249
+		t.Fatal("Container transfered content to non-empty volume")
1250
+	}
1251
+}
1252
+
1199 1253
 func TestBindMounts(t *testing.T) {
1200 1254
 	r := mkRuntime(t)
1201 1255
 	defer nuke(r)
... ...
@@ -642,7 +642,7 @@ func (manager *NetworkManager) Allocate() (*NetworkInterface, error) {
642 642
 	if err != nil {
643 643
 		return nil, err
644 644
 	}
645
-	// avoid duplicate IP 
645
+	// avoid duplicate IP
646 646
 	ipNum := ipToInt(ip)
647 647
 	firstIP := manager.ipAllocator.network.IP.To4().Mask(manager.ipAllocator.network.Mask)
648 648
 	firstIPNum := ipToInt(firstIP) + 1