summaryrefslogtreecommitdiff
path: root/integration-cli/docker_cli_build_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'integration-cli/docker_cli_build_test.go')
-rw-r--r--integration-cli/docker_cli_build_test.go319
1 files changed, 319 insertions, 0 deletions
diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go
index 9a360c1964..039423e06c 100644
--- a/integration-cli/docker_cli_build_test.go
+++ b/integration-cli/docker_cli_build_test.go
@@ -9,6 +9,8 @@ import (
"strings"
"testing"
"time"
+
+ "github.com/dotcloud/docker/archive"
)
func TestBuildCacheADD(t *testing.T) {
@@ -1130,6 +1132,50 @@ func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
logDone("build - add local and remote file with cache")
}
+func testContextTar(t *testing.T, compression archive.Compression) {
+ contextDirectory := filepath.Join(workingDirectory, "build_tests", "TestContextTar")
+ context, err := archive.Tar(contextDirectory, compression)
+
+ if err != nil {
+ t.Fatalf("failed to build context tar: %v", err)
+ }
+ buildCmd := exec.Command(dockerBinary, "build", "-t", "contexttar", "-")
+ buildCmd.Stdin = context
+
+ out, exitCode, err := runCommandWithOutput(buildCmd)
+ if err != nil || exitCode != 0 {
+ t.Fatalf("build failed to complete: %v %v", out, err)
+ }
+ deleteImages("contexttar")
+ logDone(fmt.Sprintf("build - build an image with a context tar, compression: %v", compression))
+}
+
+func TestContextTarGzip(t *testing.T) {
+ testContextTar(t, archive.Gzip)
+}
+
+func TestContextTarNoCompression(t *testing.T) {
+ testContextTar(t, archive.Uncompressed)
+}
+
+func TestNoContext(t *testing.T) {
+ buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
+ buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
+
+ out, exitCode, err := runCommandWithOutput(buildCmd)
+ if err != nil || exitCode != 0 {
+ t.Fatalf("build failed to complete: %v %v", out, err)
+ }
+
+ out, exitCode, err = cmd(t, "run", "nocontext")
+ if out != "ok\n" {
+ t.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
+ }
+
+ deleteImages("nocontext")
+ logDone("build - build an image with no context")
+}
+
// TODO: TestCaching
func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
name := "testbuildaddlocalandremotefilewithoutcache"
@@ -1444,3 +1490,276 @@ func TestBuildAddToSymlinkDest(t *testing.T) {
}
logDone("build - add to symlink destination")
}
+
+func TestBuildEscapeWhitespace(t *testing.T) {
+ name := "testbuildescaping"
+ defer deleteImages(name)
+
+ _, err := buildImage(name, `
+ FROM busybox
+ MAINTAINER "Docker \
+IO <io@\
+docker.com>"
+ `, true)
+
+ res, err := inspectField(name, "Author")
+
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if res != "Docker IO <io@docker.com>" {
+ t.Fatal("Parsed string did not match the escaped string")
+ }
+
+ logDone("build - validate escaping whitespace")
+}
+
+func TestDockerignore(t *testing.T) {
+ name := "testbuilddockerignore"
+ defer deleteImages(name)
+ dockerfile := `
+ FROM busybox
+ ADD . /bla
+ RUN [[ -f /bla/src/x.go ]]
+ RUN [[ -f /bla/Makefile ]]
+ RUN [[ ! -e /bla/src/_vendor ]]
+ RUN [[ ! -e /bla/.gitignore ]]
+ RUN [[ ! -e /bla/README.md ]]
+ RUN [[ ! -e /bla/.git ]]`
+ ctx, err := fakeContext(dockerfile, map[string]string{
+ "Makefile": "all:",
+ ".git/HEAD": "ref: foo",
+ "src/x.go": "package main",
+ "src/_vendor/v.go": "package main",
+ ".gitignore": "",
+ "README.md": "readme",
+ ".dockerignore": ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
+ })
+ defer ctx.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err := buildImageFromContext(name, ctx, true); err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - test .dockerignore")
+}
+
+func TestDockerignoringDockerfile(t *testing.T) {
+ name := "testbuilddockerignoredockerfile"
+ defer deleteImages(name)
+ dockerfile := `
+ FROM scratch`
+ ctx, err := fakeContext(dockerfile, map[string]string{
+ "Dockerfile": "FROM scratch",
+ ".dockerignore": "Dockerfile\n",
+ })
+ defer ctx.Close()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if _, err = buildImageFromContext(name, ctx, true); err == nil {
+ t.Fatalf("Didn't get expected error from ignoring Dockerfile")
+ }
+ logDone("build - test .dockerignore of Dockerfile")
+}
+
+func TestBuildLineBreak(t *testing.T) {
+ name := "testbuildlinebreak"
+ defer deleteImages(name)
+ _, err := buildImage(name,
+ `FROM busybox
+RUN sh -c 'echo root:testpass \
+ > /tmp/passwd'
+RUN mkdir -p /var/run/sshd
+RUN [ "$(cat /tmp/passwd)" = "root:testpass" ]
+RUN [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
+ true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - line break with \\")
+}
+
+func TestBuildEOLInLine(t *testing.T) {
+ name := "testbuildeolinline"
+ defer deleteImages(name)
+ _, err := buildImage(name,
+ `FROM busybox
+RUN sh -c 'echo root:testpass > /tmp/passwd'
+RUN echo "foo \n bar"; echo "baz"
+RUN mkdir -p /var/run/sshd
+RUN [ "$(cat /tmp/passwd)" = "root:testpass" ]
+RUN [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
+ true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - end of line in dockerfile instruction")
+}
+
+func TestBuildCommentsShebangs(t *testing.T) {
+ name := "testbuildcomments"
+ defer deleteImages(name)
+ _, err := buildImage(name,
+ `FROM busybox
+# This is an ordinary comment.
+RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
+RUN [ ! -x /hello.sh ]
+# comment with line break \
+RUN chmod +x /hello.sh
+RUN [ -x /hello.sh ]
+RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
+RUN [ "$(/hello.sh)" = "hello world" ]`,
+ true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - comments and shebangs")
+}
+
+func TestBuildUsersAndGroups(t *testing.T) {
+ name := "testbuildusers"
+ defer deleteImages(name)
+ _, err := buildImage(name,
+ `FROM busybox
+
+# Make sure our defaults work
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
+
+# TODO decide if "args.user = strconv.Itoa(syscall.Getuid())" is acceptable behavior for changeUser in sysvinit instead of "return nil" when "USER" isn't specified (so that we get the proper group list even if that is the empty list, even in the default case of not supplying an explicit USER to run as, which implies USER 0)
+USER root
+RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
+
+# Setup dockerio user and group
+RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
+RUN echo 'dockerio:x:1001:' >> /etc/group
+
+# Make sure we can switch to our user and all the information is exactly as we expect it to be
+USER dockerio
+RUN id -G
+RUN id -Gn
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
+
+# Switch back to root and double check that worked exactly as we might expect it to
+USER root
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
+
+# Add a "supplementary" group for our dockerio user
+RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
+
+# ... and then go verify that we get it like we expect
+USER dockerio
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
+USER 1001
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
+
+# super test the new "user:group" syntax
+USER dockerio:dockerio
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
+USER 1001:dockerio
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
+USER dockerio:1001
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
+USER 1001:1001
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
+USER dockerio:supplementary
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
+USER dockerio:1002
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
+USER 1001:supplementary
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
+USER 1001:1002
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
+
+# make sure unknown uid/gid still works properly
+USER 1042:1043
+RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
+ true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - users and groups")
+}
+
+func TestBuildEnvUsage(t *testing.T) {
+ name := "testbuildenvusage"
+ defer deleteImages(name)
+ dockerfile := `FROM busybox
+ENV FOO /foo/baz
+ENV BAR /bar
+ENV BAZ $BAR
+ENV FOOPATH $PATH:$FOO
+RUN [ "$BAR" = "$BAZ" ]
+RUN [ "$FOOPATH" = "$PATH:/foo/baz" ]
+ENV FROM hello/docker/world
+ENV TO /docker/world/hello
+ADD $FROM $TO
+RUN [ "$(cat $TO)" = "hello" ]`
+ ctx, err := fakeContext(dockerfile, map[string]string{
+ "hello/docker/world": "hello",
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = buildImageFromContext(name, ctx, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - environment variables usage")
+}
+
+func TestBuildAddScript(t *testing.T) {
+ name := "testbuildaddscript"
+ defer deleteImages(name)
+ dockerfile := `
+FROM busybox
+ADD test /test
+RUN ["chmod","+x","/test"]
+RUN ["/test"]
+RUN [ "$(cat /testfile)" = 'test!' ]`
+ ctx, err := fakeContext(dockerfile, map[string]string{
+ "test": "#!/bin/sh\necho 'test!' > /testfile",
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = buildImageFromContext(name, ctx, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+ logDone("build - add and run script")
+}
+
+func TestBuildAddTar(t *testing.T) {
+
+ checkOutput := func(out string) {
+ n := -1
+ x := ""
+ for i, line := range strings.Split(out, "\n") {
+ if strings.HasPrefix(line, "Step 2") {
+ n = i + 2
+ x = line[strings.Index(line, "cat ")+4:]
+ }
+ if i == n {
+ if line != "Hi" {
+ t.Fatalf("Could not find contents of %s (expected 'Hi' got '%s'", x, line)
+ }
+ n = -2
+ }
+ }
+ if n > -2 {
+ t.Fatalf("Could not find contents of %s in build output", x)
+ }
+ }
+
+ for _, n := range []string{"1", "2"} {
+ buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildAddTar", n)
+ buildCmd := exec.Command(dockerBinary, "build", "-t", "testbuildaddtar", ".")
+ buildCmd.Dir = buildDirectory
+ out, _, err := runCommandWithOutput(buildCmd)
+ errorOut(err, t, fmt.Sprintf("build failed to complete for TestBuildAddTar/%s: %v", n, err))
+ checkOutput(out)
+ }
+}