Browse code

Merge pull request #15039 from jlhawn/fix_build_context_is_symlink

[api/client] Fix build when context dir is symlink

Michael Crosby authored on 2015/07/28 07:11:36
Showing 2 changed files
... ...
@@ -302,6 +302,22 @@ func getDockerfileRelPath(givenContextDir, givenDockerfile string) (absContextDi
302 302
 		return "", "", fmt.Errorf("unable to get absolute context directory: %v", err)
303 303
 	}
304 304
 
305
+	// The context dir might be a symbolic link, so follow it to the actual
306
+	// target directory.
307
+	absContextDir, err = filepath.EvalSymlinks(absContextDir)
308
+	if err != nil {
309
+		return "", "", fmt.Errorf("unable to evaluate symlinks in context path: %v", err)
310
+	}
311
+
312
+	stat, err := os.Lstat(absContextDir)
313
+	if err != nil {
314
+		return "", "", fmt.Errorf("unable to stat context directory %q: %v", absContextDir, err)
315
+	}
316
+
317
+	if !stat.IsDir() {
318
+		return "", "", fmt.Errorf("context must be a directory: %s", absContextDir)
319
+	}
320
+
305 321
 	absDockerfile := givenDockerfile
306 322
 	if absDockerfile == "" {
307 323
 		// No -f/--file was specified so use the default relative to the
... ...
@@ -5394,3 +5394,41 @@ func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
5394 5394
 		c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
5395 5395
 	}
5396 5396
 }
5397
+
5398
+func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) {
5399
+	tempDir, err := ioutil.TempDir("", "test-build-dir-is-symlink-")
5400
+	if err != nil {
5401
+		c.Fatal(err)
5402
+	}
5403
+	defer os.RemoveAll(tempDir)
5404
+
5405
+	// Make a real context directory in this temp directory with a simple
5406
+	// Dockerfile.
5407
+	realContextDirname := filepath.Join(tempDir, "context")
5408
+	if err := os.Mkdir(realContextDirname, os.FileMode(0755)); err != nil {
5409
+		c.Fatal(err)
5410
+	}
5411
+
5412
+	if err = ioutil.WriteFile(
5413
+		filepath.Join(realContextDirname, "Dockerfile"),
5414
+		[]byte(`
5415
+			FROM busybox
5416
+			RUN echo hello world
5417
+		`),
5418
+		os.FileMode(0644),
5419
+	); err != nil {
5420
+		c.Fatal(err)
5421
+	}
5422
+
5423
+	// Make a symlink to the real context directory.
5424
+	contextSymlinkName := filepath.Join(tempDir, "context_link")
5425
+	if err := os.Symlink(realContextDirname, contextSymlinkName); err != nil {
5426
+		c.Fatal(err)
5427
+	}
5428
+
5429
+	// Executing the build with the symlink as the specified context should
5430
+	// *not* fail.
5431
+	if out, exitStatus := dockerCmd(c, "build", contextSymlinkName); exitStatus != 0 {
5432
+		c.Fatalf("build failed with exit status %d: %s", exitStatus, out)
5433
+	}
5434
+}