mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #23322 from tkopczynski/20784-builder-dockerfile-symlink
Reimplement integration test for symlink Dockerfile as a unit test
This commit is contained in:
commit
e08aed59df
4 changed files with 76 additions and 70 deletions
|
@ -2,8 +2,6 @@ package dockerfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -195,35 +193,3 @@ func executeTestCase(t *testing.T, testCase dispatchTestCase) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createTestTempDir creates a temporary directory for testing.
|
|
||||||
// It returns the created path and a cleanup function which is meant to be used as deferred call.
|
|
||||||
// When an error occurs, it terminates the test.
|
|
||||||
func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
|
|
||||||
path, err := ioutil.TempDir(dir, prefix)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path, func() {
|
|
||||||
err = os.RemoveAll(path)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when removing directory %s: %s", path, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// createTestTempFile creates a temporary file within dir with specific contents and permissions.
|
|
||||||
// When an error occurs, it terminates the test
|
|
||||||
func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
|
|
||||||
filePath := filepath.Join(dir, filename)
|
|
||||||
err := ioutil.WriteFile(filePath, []byte(contents), perm)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error when creating %s file: %s", filename, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return filePath
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package dockerfile
|
package dockerfile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -15,6 +16,25 @@ func TestEmptyDockerfile(t *testing.T) {
|
||||||
|
|
||||||
createTestTempFile(t, contextDir, builder.DefaultDockerfileName, "", 0777)
|
createTestTempFile(t, contextDir, builder.DefaultDockerfileName, "", 0777)
|
||||||
|
|
||||||
|
readAndCheckDockerfile(t, "emptyDockefile", contextDir, "", "The Dockerfile (Dockerfile) cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSymlinkDockerfile(t *testing.T) {
|
||||||
|
contextDir, cleanup := createTestTempDir(t, "", "builder-dockerfile-test")
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
createTestSymlink(t, contextDir, builder.DefaultDockerfileName, "/etc/passwd")
|
||||||
|
|
||||||
|
// The reason the error is "Cannot locate specified Dockerfile" is because
|
||||||
|
// in the builder, the symlink is resolved within the context, therefore
|
||||||
|
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
|
||||||
|
// a nonexistent file.
|
||||||
|
expectedError := fmt.Sprintf("Cannot locate specified Dockerfile: %s", builder.DefaultDockerfileName)
|
||||||
|
|
||||||
|
readAndCheckDockerfile(t, "symlinkDockerfile", contextDir, builder.DefaultDockerfileName, expectedError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath, expectedError string) {
|
||||||
tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
|
tarStream, err := archive.Tar(contextDir, archive.Uncompressed)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -39,18 +59,20 @@ func TestEmptyDockerfile(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
options := &types.ImageBuildOptions{}
|
options := &types.ImageBuildOptions{
|
||||||
|
Dockerfile: dockerfilePath,
|
||||||
|
}
|
||||||
|
|
||||||
b := &Builder{options: options, context: context}
|
b := &Builder{options: options, context: context}
|
||||||
|
|
||||||
err = b.readDockerfile()
|
err = b.readDockerfile()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("No error when executing test for empty Dockerfile")
|
t.Fatalf("No error when executing test: %s", testName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !strings.Contains(err.Error(), "The Dockerfile (Dockerfile) cannot be empty") {
|
if !strings.Contains(err.Error(), expectedError) {
|
||||||
t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", "The Dockerfile (Dockerfile) cannot be empty", err.Error())
|
t.Fatalf("Wrong error message. Should be \"%s\". Got \"%s\"", expectedError, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
50
builder/dockerfile/utils_test.go
Normal file
50
builder/dockerfile/utils_test.go
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
package dockerfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// createTestTempDir creates a temporary directory for testing.
|
||||||
|
// It returns the created path and a cleanup function which is meant to be used as deferred call.
|
||||||
|
// When an error occurs, it terminates the test.
|
||||||
|
func createTestTempDir(t *testing.T, dir, prefix string) (string, func()) {
|
||||||
|
path, err := ioutil.TempDir(dir, prefix)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when creating directory %s with prefix %s: %s", dir, prefix, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return path, func() {
|
||||||
|
err = os.RemoveAll(path)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when removing directory %s: %s", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// createTestTempFile creates a temporary file within dir with specific contents and permissions.
|
||||||
|
// When an error occurs, it terminates the test
|
||||||
|
func createTestTempFile(t *testing.T, dir, filename, contents string, perm os.FileMode) string {
|
||||||
|
filePath := filepath.Join(dir, filename)
|
||||||
|
err := ioutil.WriteFile(filePath, []byte(contents), perm)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error when creating %s file: %s", filename, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// createTestSymlink creates a symlink file within dir which points to oldname
|
||||||
|
func createTestSymlink(t *testing.T, dir, filename, oldname string) string {
|
||||||
|
filePath := filepath.Join(dir, filename)
|
||||||
|
if err := os.Symlink(oldname, filePath); err != nil {
|
||||||
|
t.Fatalf("Error when creating %s symlink to %s: %s", filename, oldname, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath
|
||||||
|
}
|
|
@ -193,38 +193,6 @@ RUN echo from dockerfile`,
|
||||||
c.Assert(out, checker.Contains, "from Dockerfile")
|
c.Assert(out, checker.Contains, "from Dockerfile")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
|
|
||||||
// Test to make sure we stop people from trying to leave the
|
|
||||||
// build context when specifying a symlink as the path to the dockerfile
|
|
||||||
buffer := new(bytes.Buffer)
|
|
||||||
tw := tar.NewWriter(buffer)
|
|
||||||
defer tw.Close()
|
|
||||||
|
|
||||||
err := tw.WriteHeader(&tar.Header{
|
|
||||||
Name: "Dockerfile",
|
|
||||||
Typeflag: tar.TypeSymlink,
|
|
||||||
Linkname: "/etc/passwd",
|
|
||||||
})
|
|
||||||
// failed to write tar file header
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
// failed to close tar archive
|
|
||||||
c.Assert(tw.Close(), checker.IsNil)
|
|
||||||
|
|
||||||
res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
|
|
||||||
|
|
||||||
out, err := readBody(body)
|
|
||||||
c.Assert(err, checker.IsNil)
|
|
||||||
|
|
||||||
// The reason the error is "Cannot locate specified Dockerfile" is because
|
|
||||||
// in the builder, the symlink is resolved within the context, therefore
|
|
||||||
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
|
|
||||||
// a nonexistent file.
|
|
||||||
c.Assert(string(out), checker.Contains, "Cannot locate specified Dockerfile: Dockerfile", check.Commentf("Didn't complain about leaving build context"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DockerSuite) TestBuildApiUnnormalizedTarPaths(c *check.C) {
|
func (s *DockerSuite) TestBuildApiUnnormalizedTarPaths(c *check.C) {
|
||||||
// Make sure that build context tars with entries of the form
|
// Make sure that build context tars with entries of the form
|
||||||
// x/./y don't cause caching false positives.
|
// x/./y don't cause caching false positives.
|
||||||
|
|
Loading…
Reference in a new issue