Browse code

Change owner only on copied content

Fixes #5110
Docker-DCO-1.1-Signed-off-by: Alexandr Morozov <lk4d4math@gmail.com> (github: LK4D4)

LK4D4 authored on 2014/04/09 23:21:22
Showing 15 changed files
... ...
@@ -418,6 +418,9 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error {
418 418
 		// the layer is also a directory. Then we want to merge them (i.e.
419 419
 		// just apply the metadata from the layer).
420 420
 		if fi, err := os.Lstat(path); err == nil {
421
+			if fi.IsDir() && hdr.Name == "." {
422
+				continue
423
+			}
421 424
 			if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
422 425
 				if err := os.RemoveAll(path); err != nil {
423 426
 					return err
424 427
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN mkdir /exists
4
+RUN touch /exists/exists_file
5
+RUN chown -R dockerio.dockerio /exists
6
+ADD test_dir/ /exists/
7
+RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
8
+RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
9
+RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
0 10
new file mode 100644
1 11
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN touch /exists
4
+RUN chown dockerio.dockerio exists
5
+ADD test_dir /
6
+RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
7
+RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
0 8
new file mode 100644
1 9
new file mode 100644
... ...
@@ -0,0 +1,10 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN mkdir /exists
4
+RUN touch /exists/exists_file
5
+RUN chown -R dockerio.dockerio /exists
6
+ADD test_file /exists/
7
+RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
8
+RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
9
+RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
0 10
new file mode 100644
1 11
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN touch /exists
4
+RUN chown dockerio.dockerio /exists
5
+ADD test_file /test_dir/
6
+RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
7
+RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
8
+RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
0 9
new file mode 100644
1 10
new file mode 100644
... ...
@@ -0,0 +1,8 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN touch /exists
4
+RUN chown dockerio.dockerio /exists
5
+ADD test_file /
6
+RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
7
+RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
0 8
new file mode 100644
1 9
new file mode 100644
... ...
@@ -0,0 +1,9 @@
0
+FROM busybox
1
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
2
+RUN echo 'dockerio:x:1001:' >> /etc/group
3
+RUN touch /exists
4
+RUN chown dockerio.dockerio exists
5
+ADD test_dir /test_dir
6
+RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
7
+RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
8
+RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
0 9
new file mode 100644
... ...
@@ -23,6 +23,102 @@ func TestBuildSixtySteps(t *testing.T) {
23 23
 	logDone("build - build an image with sixty build steps")
24 24
 }
25 25
 
26
+func TestAddSingleFileToRoot(t *testing.T) {
27
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
28
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToRoot")
29
+	buildCmd.Dir = buildDirectory
30
+	out, exitCode, err := runCommandWithOutput(buildCmd)
31
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
32
+
33
+	if err != nil || exitCode != 0 {
34
+		t.Fatal("failed to build the image")
35
+	}
36
+
37
+	deleteImages("testaddimg")
38
+
39
+	logDone("build - add single file to root")
40
+}
41
+
42
+func TestAddSingleFileToExistDir(t *testing.T) {
43
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
44
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToExistDir")
45
+	buildCmd.Dir = buildDirectory
46
+	out, exitCode, err := runCommandWithOutput(buildCmd)
47
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
48
+
49
+	if err != nil || exitCode != 0 {
50
+		t.Fatal("failed to build the image")
51
+	}
52
+
53
+	deleteImages("testaddimg")
54
+
55
+	logDone("build - add single file to existing dir")
56
+}
57
+
58
+func TestAddSingleFileToNonExistDir(t *testing.T) {
59
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
60
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToNonExistDir")
61
+	buildCmd.Dir = buildDirectory
62
+	out, exitCode, err := runCommandWithOutput(buildCmd)
63
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
64
+
65
+	if err != nil || exitCode != 0 {
66
+		t.Fatal("failed to build the image")
67
+	}
68
+
69
+	deleteImages("testaddimg")
70
+
71
+	logDone("build - add single file to non-existing dir")
72
+}
73
+
74
+func TestAddDirContentToRoot(t *testing.T) {
75
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
76
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToRoot")
77
+	buildCmd.Dir = buildDirectory
78
+	out, exitCode, err := runCommandWithOutput(buildCmd)
79
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
80
+
81
+	if err != nil || exitCode != 0 {
82
+		t.Fatal("failed to build the image")
83
+	}
84
+
85
+	deleteImages("testaddimg")
86
+
87
+	logDone("build - add directory contents to root")
88
+}
89
+
90
+func TestAddDirContentToExistDir(t *testing.T) {
91
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
92
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToExistDir")
93
+	buildCmd.Dir = buildDirectory
94
+	out, exitCode, err := runCommandWithOutput(buildCmd)
95
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
96
+
97
+	if err != nil || exitCode != 0 {
98
+		t.Fatal("failed to build the image")
99
+	}
100
+
101
+	deleteImages("testaddimg")
102
+
103
+	logDone("build - add directory contents to existing dir")
104
+}
105
+
106
+func TestAddWholeDirToRoot(t *testing.T) {
107
+	buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
108
+	buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "WholeDirToRoot")
109
+	buildCmd.Dir = buildDirectory
110
+	out, exitCode, err := runCommandWithOutput(buildCmd)
111
+	errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
112
+
113
+	if err != nil || exitCode != 0 {
114
+		t.Fatal("failed to build the image")
115
+	}
116
+
117
+	deleteImages("testaddimg")
118
+
119
+	logDone("build - add whole directory to root")
120
+}
121
+
26 122
 // TODO: TestCaching
27 123
 
28 124
 // TODO: TestADDCacheInvalidation
... ...
@@ -386,9 +386,10 @@ func (b *buildFile) checkPathForAddition(orig string) error {
386 386
 
387 387
 func (b *buildFile) addContext(container *daemon.Container, orig, dest string, remote bool) error {
388 388
 	var (
389
-		err      error
390
-		origPath = path.Join(b.contextPath, orig)
391
-		destPath = path.Join(container.RootfsPath(), dest)
389
+		err        error
390
+		destExists = true
391
+		origPath   = path.Join(b.contextPath, orig)
392
+		destPath   = path.Join(container.RootfsPath(), dest)
392 393
 	)
393 394
 
394 395
 	if destPath != container.RootfsPath() {
... ...
@@ -402,6 +403,14 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
402 402
 	if strings.HasSuffix(dest, "/") {
403 403
 		destPath = destPath + "/"
404 404
 	}
405
+	destStat, err := os.Stat(destPath)
406
+	if err != nil {
407
+		if os.IsNotExist(err) {
408
+			destExists = false
409
+		} else {
410
+			return err
411
+		}
412
+	}
405 413
 	fi, err := os.Stat(origPath)
406 414
 	if err != nil {
407 415
 		if os.IsNotExist(err) {
... ...
@@ -423,8 +432,20 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
423 423
 		if err := archive.CopyWithTar(origPath, destPath); err != nil {
424 424
 			return err
425 425
 		}
426
-		if err := chownR(destPath, 0, 0); err != nil {
427
-			return err
426
+		if destExists {
427
+			files, err := ioutil.ReadDir(origPath)
428
+			if err != nil {
429
+				return err
430
+			}
431
+			for _, file := range files {
432
+				if err := chownR(filepath.Join(destPath, file.Name()), 0, 0); err != nil {
433
+					return err
434
+				}
435
+			}
436
+		} else {
437
+			if err := chownR(destPath, 0, 0); err != nil {
438
+				return err
439
+			}
428 440
 		}
429 441
 		return nil
430 442
 	}
... ...
@@ -456,7 +477,12 @@ func (b *buildFile) addContext(container *daemon.Container, orig, dest string, r
456 456
 		return err
457 457
 	}
458 458
 
459
-	if err := chownR(destPath, 0, 0); err != nil {
459
+	resPath := destPath
460
+	if destExists && destStat.IsDir() {
461
+		resPath = path.Join(destPath, path.Base(origPath))
462
+	}
463
+
464
+	if err := chownR(resPath, 0, 0); err != nil {
460 465
 		return err
461 466
 	}
462 467
 	return nil