Reimplement integration test for symlink Dockerfile as a unit test
Vincent Demeester authored on 2016/06/15 17:52:49... | ... |
@@ -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. |