Browse code

Merge pull request #23322 from tkopczynski/20784-builder-dockerfile-symlink

Reimplement integration test for symlink Dockerfile as a unit test

Vincent Demeester authored on 2016/06/15 17:52:49
Showing 4 changed files
... ...
@@ -2,8 +2,6 @@ package dockerfile
2 2
 
3 3
 import (
4 4
 	"io/ioutil"
5
-	"os"
6
-	"path/filepath"
7 5
 	"strings"
8 6
 	"testing"
9 7
 
... ...
@@ -195,35 +193,3 @@ func executeTestCase(t *testing.T, testCase dispatchTestCase) {
195 195
 	}
196 196
 
197 197
 }
198
-
199
-// createTestTempDir creates a temporary directory for testing.
200
-// It returns the created path and a cleanup function which is meant to be used as deferred call.
201
-// When an error occurs, it terminates the test.
202
-func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
203
-	path, err := ioutil.TempDir(dir, prefix)
204
-
205
-	if err != nil {
206
-		t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
207
-	}
208
-
209
-	return path, func() {
210
-		err = os.RemoveAll(path)
211
-
212
-		if err != nil {
213
-			t.Fatalf("Error when removing directory %s: %s", path, err)
214
-		}
215
-	}
216
-}
217
-
218
-// createTestTempFile creates a temporary file within dir with specific contents and permissions.
219
-// When an error occurs, it terminates the test
220
-func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
221
-	filePath := filepath.Join(dir, filename)
222
-	err := ioutil.WriteFile(filePath, []byte(contents), perm)
223
-
224
-	if err != nil {
225
-		t.Fatalf("Error when creating %s file: %s", filename, err)
226
-	}
227
-
228
-	return filePath
229
-}
... ...
@@ -1,6 +1,7 @@
1 1
 package dockerfile
2 2
 
3 3
 import (
4
+	"fmt"
4 5
 	"strings"
5 6
 	"testing"
6 7
 
... ...
@@ -15,6 +16,25 @@ func TestEmptyDockerfile(t *testing.T) {
15 15
 
16 16
 	createTestTempFile(t, contextDir, builder.DefaultDockerfileName, "", 0777)
17 17
 
18
+	readAndCheckDockerfile(t, "emptyDockefile", contextDir, "", "The Dockerfile (Dockerfile) cannot be empty")
19
+}
20
+
21
+func TestSymlinkDockerfile(t *testing.T) {
22
+	contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test")
23
+	defer cleanup()
24
+
25
+	createTestSymlink(t, contextDir, builder.DefaultDockerfileName, "/etc/passwd")
26
+
27
+	// The reason the error is "Cannot locate specified Dockerfile" is because
28
+	// in the builder, the symlink is resolved within the context, therefore
29
+	// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
30
+	// a nonexistent file.
31
+	expectedError := fmt.Sprintf("Cannot locate specified Dockerfile: %s", builder.DefaultDockerfileName)
32
+
33
+	readAndCheckDockerfile(t, "symlinkDockerfile", contextDir, builder.DefaultDockerfileName, expectedError)
34
+}
35
+
36
+func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath, expectedError string) {
18 37
 	tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
19 38
 
20 39
 	if err != nil {
... ...
@@ -39,18 +59,20 @@ func TestEmptyDockerfile(t *testing.T) {
39 39
 		}
40 40
 	}()
41 41
 
42
-	options := &types.ImageBuildOptions{}
42
+	options := &types.ImageBuildOptions{
43
+		Dockerfile: dockerfilePath,
44
+	}
43 45
 
44 46
 	b := &Builder{options: options, context: context}
45 47
 
46 48
 	err = b.readDockerfile()
47 49
 
48 50
 	if err == nil {
49
-		t.Fatalf("No error when executing test for empty Dockerfile")
51
+		t.Fatalf("No error when executing test: %s", testName)
50 52
 	}
51 53
 
52
-	if !strings.Contains(err.Error(), "The Dockerfile (Dockerfile) cannot be empty") {
53
-		t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", "The Dockerfile (Dockerfile) cannot be empty", err.Error())
54
+	if !strings.Contains(err.Error(), expectedError) {
55
+		t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", expectedError, err.Error())
54 56
 	}
55 57
 }
56 58
 
57 59
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+package dockerfile
1
+
2
+import (
3
+	"io/ioutil"
4
+	"os"
5
+	"path/filepath"
6
+	"testing"
7
+)
8
+
9
+// createTestTempDir creates a temporary directory for testing.
10
+// It returns the created path and a cleanup function which is meant to be used as deferred call.
11
+// When an error occurs, it terminates the test.
12
+func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
13
+	path, err := ioutil.TempDir(dir, prefix)
14
+
15
+	if err != nil {
16
+		t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
17
+	}
18
+
19
+	return path, func() {
20
+		err = os.RemoveAll(path)
21
+
22
+		if err != nil {
23
+			t.Fatalf("Error when removing directory %s: %s", path, err)
24
+		}
25
+	}
26
+}
27
+
28
+// createTestTempFile creates a temporary file within dir with specific contents and permissions.
29
+// When an error occurs, it terminates the test
30
+func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
31
+	filePath := filepath.Join(dir, filename)
32
+	err := ioutil.WriteFile(filePath, []byte(contents), perm)
33
+
34
+	if err != nil {
35
+		t.Fatalf("Error when creating %s file: %s", filename, err)
36
+	}
37
+
38
+	return filePath
39
+}
40
+
41
+// createTestSymlink creates a symlink file within dir which points to oldname
42
+func createTestSymlink(t *testing.T, dir, filename, oldname string) string {
43
+	filePath := filepath.Join(dir, filename)
44
+	if err := os.Symlink(oldname, filePath); err != nil {
45
+		t.Fatalf("Error when creating %s symlink to %s: %s", filename, oldname, err)
46
+	}
47
+
48
+	return filePath
49
+}
... ...
@@ -193,38 +193,6 @@ RUN echo from dockerfile`,
193 193
 	c.Assert(out, checker.Contains, "from Dockerfile")
194 194
 }
195 195
 
196
-func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
197
-	// Test to make sure we stop people from trying to leave the
198
-	// build context when specifying a symlink as the path to the dockerfile
199
-	buffer := new(bytes.Buffer)
200
-	tw := tar.NewWriter(buffer)
201
-	defer tw.Close()
202
-
203
-	err := tw.WriteHeader(&tar.Header{
204
-		Name:     "Dockerfile",
205
-		Typeflag: tar.TypeSymlink,
206
-		Linkname: "/etc/passwd",
207
-	})
208
-	// failed to write tar file header
209
-	c.Assert(err, checker.IsNil)
210
-
211
-	// failed to close tar archive
212
-	c.Assert(tw.Close(), checker.IsNil)
213
-
214
-	res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
215
-	c.Assert(err, checker.IsNil)
216
-	c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
217
-
218
-	out, err := readBody(body)
219
-	c.Assert(err, checker.IsNil)
220
-
221
-	// The reason the error is "Cannot locate specified Dockerfile" is because
222
-	// in the builder, the symlink is resolved within the context, therefore
223
-	// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
224
-	// a nonexistent file.
225
-	c.Assert(string(out), checker.Contains, "Cannot locate specified Dockerfile: Dockerfile", check.Commentf("Didn't complain about leaving build context"))
226
-}
227
-
228 196
 func (s *DockerSuite) TestBuildApiUnnormalizedTarPaths(c *check.C) {
229 197
 	// Make sure that build context tars with entries of the form
230 198
 	// x/./y don't cause caching false positives.