integration-cli/docker_cli_build_test.go
6db32fde
 package main
 
 import (
24c00c85
 	"archive/tar"
671c1220
 	"bufio"
29be7b43
 	"bytes"
4e74cd49
 	"encoding/json"
6db32fde
 	"fmt"
24c00c85
 	"io/ioutil"
f5b1afae
 	"os"
6db32fde
 	"os/exec"
 	"path/filepath"
fa753e67
 	"reflect"
1150c163
 	"regexp"
d0dc14e5
 	"runtime"
29be7b43
 	"strconv"
f5b1afae
 	"strings"
29be7b43
 	"text/template"
1ce5457d
 	"time"
edcb4145
 
ccde3a1f
 	"github.com/docker/docker/builder/command"
30d5a42c
 	"github.com/docker/docker/pkg/archive"
b80fae73
 	"github.com/docker/docker/pkg/stringutils"
dc944ea7
 	"github.com/go-check/check"
6db32fde
 )
 
dc944ea7
 func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
39343b86
 	name := "testbuildjsonemptyrun"
 
 	_, err := buildImage(
 		name,
 		`
     FROM busybox
     RUN []
     `,
 		true)
 
 	if err != nil {
dc944ea7
 		c.Fatal("error when dealing with a RUN statement with empty JSON array")
39343b86
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyWhitespace(c *check.C) {
09e34674
 	name := "testbuildemptywhitespace"
 
 	_, err := buildImage(
 		name,
 		`
     FROM busybox
e4f02abb
     COPY
09e34674
       quux \
       bar
     `,
 		true)
 
 	if err == nil {
dc944ea7
 		c.Fatal("no error when dealing with a COPY statement with no content on the same line")
09e34674
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) {
24545c18
 	name := "testbuildshcmdjsonentrypoint"
 
 	_, err := buildImage(
 		name,
 		`
     FROM busybox
     ENTRYPOINT ["/bin/echo"]
     CMD echo test
     `,
 		true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
24545c18
 	}
 
 	out, _, err := runCommandWithOutput(
 		exec.Command(
 			dockerBinary,
 			"run",
da3d3b97
 			"--rm",
24545c18
 			name))
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
24545c18
 	}
 
 	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
dc944ea7
 		c.Fatal("CMD did not contain /bin/sh -c")
24545c18
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	_, err := buildImage(name, `
   FROM scratch
   ENV user foo
   USER ${user}
   `, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	res, err := inspectFieldJSON(name, "Config.User")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	if res != `"foo"` {
dc944ea7
 		c.Fatal("User foo from environment not in Config.User on image")
4e74cd49
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	_, err := buildImage(name, `
   FROM scratch
   ENV volume /quux
   VOLUME ${volume}
   `, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	res, err := inspectFieldJSON(name, "Config.Volumes")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	var volumes map[string]interface{}
 
 	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	if _, ok := volumes["/quux"]; !ok {
dc944ea7
 		c.Fatal("Volume /quux from environment not in Config.Volumes on image")
4e74cd49
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	_, err := buildImage(name, `
   FROM scratch
   ENV port 80
   EXPOSE ${port}
   `, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	var exposedPorts map[string]interface{}
 
 	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	if _, ok := exposedPorts["80/tcp"]; !ok {
dc944ea7
 		c.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
4e74cd49
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	_, err := buildImage(name, `
   FROM busybox
   ENV MYWORKDIR /work
   RUN mkdir ${MYWORKDIR}
   WORKDIR ${MYWORKDIR}
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	ctx, err := fakeContext(`
   FROM scratch
   ENV baz foo
   ENV quux bar
   ENV dot .
39908fc6
   ENV fee fff
   ENV gee ggg
4e74cd49
 
   ADD ${baz} ${dot}
   COPY ${quux} ${dot}
39908fc6
   ADD ${zzz:-${fee}} ${dot}
   COPY ${zzz:-${gee}} ${dot}
4e74cd49
   `,
 		map[string]string{
 			"foo": "test1",
 			"bar": "test2",
39908fc6
 			"fff": "test3",
 			"ggg": "test4",
4e74cd49
 		})
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
db7fded1
 	defer ctx.Close()
4e74cd49
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) {
4e74cd49
 	name := "testbuildenvironmentreplacement"
 
 	_, err := buildImage(name,
 		`
6d66e3e7
   FROM busybox
   ENV foo zzz
4e74cd49
   ENV bar ${foo}
6d66e3e7
   ENV abc1='$foo'
   ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   ENV abc2="\$foo"
   RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   ENV abc3 '$foo'
   RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   ENV abc4 "\$foo"
   RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
4e74cd49
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	res, err := inspectFieldJSON(name, "Config.Env")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	envResult := []string{}
 
 	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
dc944ea7
 		c.Fatal(err)
4e74cd49
 	}
 
 	found := false
6d66e3e7
 	envCount := 0
4e74cd49
 
 	for _, env := range envResult {
 		parts := strings.SplitN(env, "=", 2)
 		if parts[0] == "bar" {
 			found = true
6d66e3e7
 			if parts[1] != "zzz" {
dc944ea7
 				c.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
6d66e3e7
 			}
 		} else if strings.HasPrefix(parts[0], "env") {
 			envCount++
 			if parts[1] != "zzz" {
dc944ea7
 				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
4e74cd49
 			}
39908fc6
 		} else if strings.HasPrefix(parts[0], "env") {
 			envCount++
 			if parts[1] != "foo" {
dc944ea7
 				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
39908fc6
 			}
4e74cd49
 		}
 	}
 
 	if !found {
dc944ea7
 		c.Fatal("Never found the `bar` env variable")
4e74cd49
 	}
 
6d66e3e7
 	if envCount != 4 {
dc944ea7
 		c.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
6d66e3e7
 	}
 
4e74cd49
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildHandleEscapes(c *check.C) {
be49867c
 	name := "testbuildhandleescapes"
 
 	_, err := buildImage(name,
 		`
   FROM scratch
   ENV FOO bar
   VOLUME ${FOO}
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	var result map[string]map[string]struct{}
 
 	res, err := inspectFieldJSON(name, "Config.Volumes")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	if err = unmarshalJSON([]byte(res), &result); err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	if _, ok := result["bar"]; !ok {
dc944ea7
 		c.Fatal("Could not find volume bar set from env foo in volumes table")
be49867c
 	}
 
da3d3b97
 	deleteImages(name)
 
be49867c
 	_, err = buildImage(name,
 		`
   FROM scratch
   ENV FOO bar
   VOLUME \${FOO}
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	res, err = inspectFieldJSON(name, "Config.Volumes")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	if err = unmarshalJSON([]byte(res), &result); err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	if _, ok := result["${FOO}"]; !ok {
dc944ea7
 		c.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
be49867c
 	}
 
da3d3b97
 	deleteImages(name)
 
be49867c
 	// this test in particular provides *7* backslashes and expects 6 to come back.
 	// Like above, the first escape is swallowed and the rest are treated as
 	// literals, this one is just less obvious because of all the character noise.
 
 	_, err = buildImage(name,
 		`
   FROM scratch
   ENV FOO bar
   VOLUME \\\\\\\${FOO}
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	res, err = inspectFieldJSON(name, "Config.Volumes")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
 	if err = unmarshalJSON([]byte(res), &result); err != nil {
dc944ea7
 		c.Fatal(err)
be49867c
 	}
 
6d66e3e7
 	if _, ok := result[`\\\${FOO}`]; !ok {
dc944ea7
 		c.Fatal(`Could not find volume \\\${FOO} set from env foo in volumes table`, result)
be49867c
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) {
a34831f0
 	name := "testbuildonbuildlowercase"
 	name2 := "testbuildonbuildlowercase2"
 
 	_, err := buildImage(name,
 		`
   FROM busybox
   onbuild run echo quux
   `, true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
a34831f0
 	}
 
 	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
   FROM %s
   `, name), true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
a34831f0
 	}
 
 	if !strings.Contains(out, "quux") {
dc944ea7
 		c.Fatalf("Did not receive the expected echo text, got %s", out)
a34831f0
 	}
 
 	if strings.Contains(out, "ONBUILD ONBUILD") {
dc944ea7
 		c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
a34831f0
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) {
df0e0c76
 	name := "testbuildenvescapes"
 	_, err := buildImage(name,
 		`
     FROM busybox
     ENV TEST foo
     CMD echo \$
     `,
 		true)
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
df0e0c76
 	}
 
 	if strings.TrimSpace(out) != "$" {
dc944ea7
 		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
df0e0c76
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) {
df0e0c76
 	name := "testbuildenvoverwrite"
 
 	_, err := buildImage(name,
 		`
     FROM busybox
     ENV TEST foo
4e74cd49
     CMD echo ${TEST}
df0e0c76
     `,
 		true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
df0e0c76
 	}
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
df0e0c76
 	}
 
 	if strings.TrimSpace(out) != "bar" {
dc944ea7
 		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
df0e0c76
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainerInSourceImage(c *check.C) {
1150c163
 	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
da3d3b97
 
1150c163
 	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
 	out, _, _, err := runCommandWithStdoutStderr(createCmd)
b1e3c9e9
 	if err != nil {
dc944ea7
 		c.Fatal(out, err)
b1e3c9e9
 	}
1150c163
 
475c6531
 	cleanedContainerID := strings.TrimSpace(out)
1150c163
 
 	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
 
 	if _, err := runCommand(commitCmd); err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	_, err = buildImage(name,
 		`FROM onbuild`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
1150c163
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
1150c163
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenFromInSourceImage(c *check.C) {
1150c163
 	name := "testbuildonbuildforbiddenfrominsourceimage"
da3d3b97
 
1150c163
 	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
 	out, _, _, err := runCommandWithStdoutStderr(createCmd)
b1e3c9e9
 	if err != nil {
dc944ea7
 		c.Fatal(out, err)
b1e3c9e9
 	}
1150c163
 
475c6531
 	cleanedContainerID := strings.TrimSpace(out)
1150c163
 
 	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
 
 	if _, err := runCommand(commitCmd); err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	_, err = buildImage(name,
 		`FROM onbuild`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
1150c163
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
1150c163
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenChainedInSourceImage(c *check.C) {
1150c163
 	name := "testbuildonbuildforbiddenchainedinsourceimage"
da3d3b97
 
1150c163
 	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
 	out, _, _, err := runCommandWithStdoutStderr(createCmd)
b1e3c9e9
 	if err != nil {
dc944ea7
 		c.Fatal(out, err)
b1e3c9e9
 	}
1150c163
 
475c6531
 	cleanedContainerID := strings.TrimSpace(out)
1150c163
 
 	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
 
 	if _, err := runCommand(commitCmd); err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	_, err = buildImage(name,
 		`FROM onbuild`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
1150c163
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
1150c163
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) {
1150c163
 	name1 := "onbuildcmd"
 	name2 := "onbuildgenerated"
 
 	_, err := buildImage(name1, `
 FROM busybox
 ONBUILD CMD ["hello world"]
 ONBUILD ENTRYPOINT ["echo"]
 ONBUILD RUN ["true"]`,
 		false)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	_, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
dc944ea7
 		c.Fatal("did not get echo output from onbuild", out)
1150c163
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) {
1150c163
 	name1 := "onbuildcmd"
 	name2 := "onbuildgenerated"
 
 	_, err := buildImage(name1, `
 FROM busybox
 ONBUILD ENTRYPOINT ["echo"]`,
 		false)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	_, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1150c163
 	}
 
 	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
dc944ea7
 		c.Fatal("got malformed output from onbuild", out)
1150c163
 	}
 
 }
 
ab121345
 func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
075e1bc1
 	name := "testbuildtwoimageswithadd"
 	server, err := fakeStorage(map[string]string{
 		"robots.txt": "hello",
 		"index.html": "world",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
03a109e4
 	}
075e1bc1
 	defer server.Close()
2e95bb5f
 
075e1bc1
 	if _, err := buildImage(name,
 		fmt.Sprintf(`FROM scratch
2e95bb5f
 		ADD %s/robots.txt /`, server.URL()),
075e1bc1
 		true); err != nil {
dc944ea7
 		c.Fatal(err)
075e1bc1
 	}
da3d3b97
 	if err != nil {
dc944ea7
 		c.Fatal(err)
da3d3b97
 	}
 	deleteImages(name)
21dff8cb
 	_, out, err := buildImageWithOut(name,
075e1bc1
 		fmt.Sprintf(`FROM scratch
2e95bb5f
 		ADD %s/index.html /`, server.URL()),
075e1bc1
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
03a109e4
 	}
 	if strings.Contains(out, "Using cache") {
dc944ea7
 		c.Fatal("2nd build used cache on ADD, it shouldn't")
03a109e4
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildLastModified(c *check.C) {
5c05b5c9
 	name := "testbuildlastmodified"
 
 	server, err := fakeStorage(map[string]string{
 		"file": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5c05b5c9
 	}
 	defer server.Close()
 
 	var out, out2 string
 
 	dFmt := `FROM busybox
 ADD %s/file /
 RUN ls -le /file`
 
40c8e787
 	dockerfile := fmt.Sprintf(dFmt, server.URL())
5c05b5c9
 
 	if _, out, err = buildImageWithOut(name, dockerfile, false); err != nil {
dc944ea7
 		c.Fatal(err)
5c05b5c9
 	}
 
 	originMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out)
 	// Make sure our regexp is correct
 	if strings.Index(originMTime, "/file") < 0 {
dc944ea7
 		c.Fatalf("Missing ls info on 'file':\n%s", out)
5c05b5c9
 	}
 
 	// Build it again and make sure the mtime of the file didn't change.
 	// Wait a few seconds to make sure the time changed enough to notice
 	time.Sleep(2 * time.Second)
 
 	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
dc944ea7
 		c.Fatal(err)
5c05b5c9
 	}
 
 	newMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
 	if newMTime != originMTime {
dc944ea7
 		c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", originMTime, newMTime)
5c05b5c9
 	}
 
 	// Now 'touch' the file and make sure the timestamp DID change this time
 	// Create a new fakeStorage instead of just using Add() to help windows
 	server, err = fakeStorage(map[string]string{
 		"file": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5c05b5c9
 	}
 	defer server.Close()
 
40c8e787
 	dockerfile = fmt.Sprintf(dFmt, server.URL())
5c05b5c9
 
 	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
dc944ea7
 		c.Fatal(err)
5c05b5c9
 	}
 
 	newMTime = regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
 	if newMTime == originMTime {
dc944ea7
 		c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", originMTime, newMTime)
5c05b5c9
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildSixtySteps(c *check.C) {
3824ec62
 	name := "foobuildsixtysteps"
 	ctx, err := fakeContext("FROM scratch\n"+strings.Repeat("ADD foo /\n", 60),
 		map[string]string{
 			"foo": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
3824ec62
 	}
db7fded1
 	defer ctx.Close()
 
3824ec62
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
6db32fde
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) {
682fbe01
 	name := "testaddimg"
1a22418f
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
682fbe01
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio /exists
 ADD test_file /
 RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
1a22418f
 RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
682fbe01
 		map[string]string{
 			"test_file": "test1",
 		})
bb431a71
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bb431a71
 	}
db7fded1
 	defer ctx.Close()
 
682fbe01
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
91b7d8eb
 	}
 }
 
1ce5457d
 // Issue #3960: "ADD src ." hangs
dc944ea7
 func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *check.C) {
5e2ea696
 	name := "testaddsinglefiletoworkdir"
 	ctx, err := fakeContext(`FROM busybox
 ADD test_file .`,
 		map[string]string{
 			"test_file": "test1",
 		})
1ce5457d
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1ce5457d
 	}
db7fded1
 	defer ctx.Close()
 
4203230c
 	errChan := make(chan error)
5e2ea696
 	go func() {
4203230c
 		_, err := buildImageFromContext(name, ctx, true)
 		errChan <- err
 		close(errChan)
5e2ea696
 	}()
 	select {
 	case <-time.After(5 * time.Second):
dc944ea7
 		c.Fatal("Build with adding to workdir timed out")
4203230c
 	case err := <-errChan:
 		c.Assert(err, check.IsNil)
1ce5457d
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) {
6bb44b6d
 	name := "testaddsinglefiletoexistdir"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN mkdir /exists
 RUN touch /exists/exists_file
 RUN chown -R dockerio.dockerio /exists
 ADD test_file /exists/
 RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
6bb44b6d
 	}
db7fded1
 	defer ctx.Close()
 
6bb44b6d
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
91b7d8eb
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) {
17b6583a
 	server, err := fakeStorage(map[string]string{
 		"robots.txt": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
17b6583a
 	}
 	defer server.Close()
 
e45c9215
 	name := "testcopymultiplefilestofile"
17b6583a
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
e45c9215
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN mkdir /exists
 RUN touch /exists/exists_file
 RUN chown -R dockerio.dockerio /exists
 COPY test_file1 test_file2 /exists/
17b6583a
 ADD test_file3 test_file4 %s/robots.txt /exists/
e45c9215
 RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
05b8a1eb
 
e45c9215
 RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
05b8a1eb
 
e45c9215
 RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
2e95bb5f
 `, server.URL()),
e45c9215
 		map[string]string{
 			"test_file1": "test1",
 			"test_file2": "test2",
 			"test_file3": "test3",
 			"test_file4": "test4",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
e45c9215
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
e45c9215
 	}
05b8a1eb
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddMultipleFilesToFile(c *check.C) {
05b8a1eb
 	name := "testaddmultiplefilestofile"
 	ctx, err := fakeContext(`FROM scratch
 	ADD file1.txt file2.txt test
cf455017
 	`,
05b8a1eb
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
05b8a1eb
 	}
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
05b8a1eb
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFile(c *check.C) {
cf455017
 	name := "testjsonaddmultiplefilestofile"
 	ctx, err := fakeContext(`FROM scratch
 	ADD ["file1.txt", "file2.txt", "test"]
 	`,
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cf455017
 	}
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
cf455017
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddMultipleFilesToFileWild(c *check.C) {
acd40d50
 	name := "testaddmultiplefilestofilewild"
 	ctx, err := fakeContext(`FROM scratch
 	ADD file*.txt test
cf455017
 	`,
acd40d50
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
acd40d50
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFileWild(c *check.C) {
cf455017
 	name := "testjsonaddmultiplefilestofilewild"
 	ctx, err := fakeContext(`FROM scratch
 	ADD ["file*.txt", "test"]
 	`,
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cf455017
 	}
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
cf455017
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyMultipleFilesToFile(c *check.C) {
05b8a1eb
 	name := "testcopymultiplefilestofile"
 	ctx, err := fakeContext(`FROM scratch
 	COPY file1.txt file2.txt test
cf455017
 	`,
05b8a1eb
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
05b8a1eb
 	}
 
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
05b8a1eb
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildJSONCopyMultipleFilesToFile(c *check.C) {
cf455017
 	name := "testjsoncopymultiplefilestofile"
 	ctx, err := fakeContext(`FROM scratch
 	COPY ["file1.txt", "file2.txt", "test"]
 	`,
 		map[string]string{
 			"file1.txt": "test1",
 			"file2.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cf455017
 	}
 
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
cf455017
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddFileWithWhitespace(c *check.C) {
abfb7138
 	name := "testaddfilewithwhitespace"
 	ctx, err := fakeContext(`FROM busybox
 RUN mkdir "/test dir"
 RUN mkdir "/test_dir"
 ADD [ "test file1", "/test_file1" ]
 ADD [ "test_file2", "/test file2" ]
 ADD [ "test file3", "/test file3" ]
 ADD [ "test dir/test_file4", "/test_dir/test_file4" ]
 ADD [ "test_dir/test_file5", "/test dir/test_file5" ]
 ADD [ "test dir/test_file6", "/test dir/test_file6" ]
 RUN [ $(cat "/test_file1") = 'test1' ]
 RUN [ $(cat "/test file2") = 'test2' ]
 RUN [ $(cat "/test file3") = 'test3' ]
 RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
 RUN [ $(cat "/test dir/test_file5") = 'test5' ]
 RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
 		map[string]string{
 			"test file1":          "test1",
 			"test_file2":          "test2",
 			"test file3":          "test3",
 			"test dir/test_file4": "test4",
 			"test_dir/test_file5": "test5",
 			"test dir/test_file6": "test6",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyFileWithWhitespace(c *check.C) {
abfb7138
 	name := "testcopyfilewithwhitespace"
 	ctx, err := fakeContext(`FROM busybox
 RUN mkdir "/test dir"
 RUN mkdir "/test_dir"
 COPY [ "test file1", "/test_file1" ]
 COPY [ "test_file2", "/test file2" ]
 COPY [ "test file3", "/test file3" ]
 COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
 COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
 COPY [ "test dir/test_file6", "/test dir/test_file6" ]
 RUN [ $(cat "/test_file1") = 'test1' ]
 RUN [ $(cat "/test file2") = 'test2' ]
 RUN [ $(cat "/test file3") = 'test3' ]
 RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
 RUN [ $(cat "/test dir/test_file5") = 'test5' ]
 RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
 		map[string]string{
 			"test file1":          "test1",
 			"test_file2":          "test2",
 			"test file3":          "test3",
 			"test dir/test_file4": "test4",
 			"test_dir/test_file5": "test5",
 			"test dir/test_file6": "test6",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddMultipleFilesToFileWithWhitespace(c *check.C) {
abfb7138
 	name := "testaddmultiplefilestofilewithwhitespace"
 	ctx, err := fakeContext(`FROM busybox
 	ADD [ "test file1", "test file2", "test" ]
cf455017
     `,
abfb7138
 		map[string]string{
 			"test file1": "test1",
 			"test file2": "test2",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 
 	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
abfb7138
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyMultipleFilesToFileWithWhitespace(c *check.C) {
abfb7138
 	name := "testcopymultiplefilestofilewithwhitespace"
 	ctx, err := fakeContext(`FROM busybox
 	COPY [ "test file1", "test file2", "test" ]
         `,
 		map[string]string{
 			"test file1": "test1",
 			"test file2": "test2",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
abfb7138
 	}
 
 	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
abfb7138
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
acd40d50
 	name := "testcopywildcard"
 	server, err := fakeStorage(map[string]string{
 		"robots.txt": "hello",
 		"index.html": "world",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 	defer server.Close()
2e95bb5f
 
acd40d50
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
 	COPY file*.txt /tmp/
 	RUN ls /tmp/file1.txt /tmp/file2.txt
 	RUN mkdir /tmp1
 	COPY dir* /tmp1/
 	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
 	RUN mkdir /tmp2
         ADD dir/*dir %s/robots.txt /tmp2/
 	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
2e95bb5f
 	`, server.URL()),
acd40d50
 		map[string]string{
 			"file1.txt":                     "test1",
 			"file2.txt":                     "test2",
 			"dir/nested_file":               "nested file",
 			"dir/nested_dir/nest_nest_file": "2 times nested",
 			"dirt": "dirty",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
82daa438
 	defer ctx.Close()
acd40d50
 
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	// Now make sure we use a cache the 2nd time
 	id2, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	if id1 != id2 {
dc944ea7
 		c.Fatal("didn't use the cache")
acd40d50
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyWildcardNoFind(c *check.C) {
acd40d50
 	name := "testcopywildcardnofind"
 	ctx, err := fakeContext(`FROM busybox
 	COPY file*.txt /tmp/
 	`, nil)
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	_, err = buildImageFromContext(name, ctx, true)
 	if err == nil {
dc944ea7
 		c.Fatal("should have failed to find a file")
acd40d50
 	}
 	if !strings.Contains(err.Error(), "No source files were specified") {
dc944ea7
 		c.Fatalf("Wrong error %v, must be about no source files", err)
acd40d50
 	}
 
 }
 
82daa438
 func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) {
 	name := "testcopywildcardinname"
 	defer deleteImages(name)
 	ctx, err := fakeContext(`FROM busybox
 	COPY *.txt /tmp/
 	RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ]
 	`, map[string]string{"*.txt": "hi there"})
 
 	if err != nil {
 		// Normally we would do c.Fatal(err) here but given that
 		// the odds of this failing are so rare, it must be because
 		// the OS we're running the client on doesn't support * in
 		// filenames (like windows).  So, instead of failing the test
 		// just let it pass. Then we don't need to explicitly
 		// say which OSs this works on or not.
 		return
 	}
 	defer ctx.Close()
 
 	_, err = buildImageFromContext(name, ctx, true)
 	if err != nil {
 		c.Fatalf("should have built: %q", err)
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
acd40d50
 	name := "testcopywildcardcache"
 	ctx, err := fakeContext(`FROM busybox
8b3fbac1
 	COPY file1.txt /tmp/`,
acd40d50
 		map[string]string{
 			"file1.txt": "test1",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
8b3fbac1
 	// Now make sure we use a cache the 2nd time even with wild cards.
 	// Use the same context so the file is the same and the checksum will match
 	ctx.Add("Dockerfile", `FROM busybox
 	COPY file*.txt /tmp/`)
acd40d50
 
8b3fbac1
 	id2, err := buildImageFromContext(name, ctx, true)
acd40d50
 	if err != nil {
dc944ea7
 		c.Fatal(err)
acd40d50
 	}
 
 	if id1 != id2 {
dc944ea7
 		c.Fatal("didn't use the cache")
acd40d50
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) {
fcfe80f6
 	name := "testaddsinglefiletononexistingdir"
139b6ed3
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio /exists
 ADD test_file /test_dir/
 RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
139b6ed3
 	}
db7fded1
 	defer ctx.Close()
 
139b6ed3
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
91b7d8eb
 	}
fbaa41b5
 
91b7d8eb
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) {
2d802d7f
 	name := "testadddircontenttoroot"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio exists
 ADD test_dir /
 RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2d802d7f
 	}
db7fded1
 	defer ctx.Close()
 
2d802d7f
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
91b7d8eb
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) {
fcfe80f6
 	name := "testadddircontenttoexistingdir"
c58391bb
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN mkdir /exists
 RUN touch /exists/exists_file
 RUN chown -R dockerio.dockerio /exists
 ADD test_dir/ /exists/
 RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c58391bb
 	}
db7fded1
 	defer ctx.Close()
 
c58391bb
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
91b7d8eb
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) {
0c899cef
 	name := "testaddwholedirtoroot"
1a22418f
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
0c899cef
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio exists
 ADD test_dir /test_dir
 RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
 RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
1a22418f
 RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
0c899cef
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
be924087
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bb431a71
 	}
db7fded1
 	defer ctx.Close()
 
0c899cef
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
bb431a71
 	}
91b7d8eb
 }
 
570f1153
 // Testing #5941
dc944ea7
 func (s *DockerSuite) TestBuildAddEtcToRoot(c *check.C) {
570f1153
 	name := "testaddetctoroot"
 	ctx, err := fakeContext(`FROM scratch
 ADD . /`,
 		map[string]string{
 			"etc/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
570f1153
 	}
db7fded1
 	defer ctx.Close()
 
570f1153
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
56a53c72
 	}
 }
 
f3cedce3
 // Testing #9401
dc944ea7
 func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) {
f3cedce3
 	name := "testaddpreservesfilesspecialbits"
 	ctx, err := fakeContext(`FROM busybox
 ADD suidbin /usr/bin/suidbin
 RUN chmod 4755 /usr/bin/suidbin
 RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
 ADD ./data/ /
 RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
 		map[string]string{
 			"suidbin":             "suidbin",
 			"/data/usr/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f3cedce3
 	}
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
f3cedce3
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) {
83c5dced
 	name := "testcopysinglefiletoroot"
1a22418f
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
83c5dced
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio /exists
 COPY test_file /
 RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
1a22418f
 RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
83c5dced
 		map[string]string{
 			"test_file": "test1",
 		})
180c2a67
 	if err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
db7fded1
 	defer ctx.Close()
 
83c5dced
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
 // Issue #3960: "ADD src ." hangs - adapted for COPY
dc944ea7
 func (s *DockerSuite) TestBuildCopySingleFileToWorkdir(c *check.C) {
d41cba6a
 	name := "testcopysinglefiletoworkdir"
 	ctx, err := fakeContext(`FROM busybox
 COPY test_file .`,
 		map[string]string{
 			"test_file": "test1",
 		})
180c2a67
 	if err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
db7fded1
 	defer ctx.Close()
 
4203230c
 	errChan := make(chan error)
d41cba6a
 	go func() {
4203230c
 		_, err := buildImageFromContext(name, ctx, true)
 		errChan <- err
 		close(errChan)
d41cba6a
 	}()
 	select {
 	case <-time.After(5 * time.Second):
dc944ea7
 		c.Fatal("Build with adding to workdir timed out")
4203230c
 	case err := <-errChan:
 		c.Assert(err, check.IsNil)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) {
2248109f
 	name := "testcopysinglefiletoexistdir"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN mkdir /exists
 RUN touch /exists/exists_file
 RUN chown -R dockerio.dockerio /exists
 COPY test_file /exists/
 RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2248109f
 	}
db7fded1
 	defer ctx.Close()
 
2248109f
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) {
24d83afd
 	name := "testcopysinglefiletononexistdir"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio /exists
 COPY test_file /test_dir/
 RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
24d83afd
 	}
db7fded1
 	defer ctx.Close()
 
24d83afd
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) {
832618af
 	name := "testcopydircontenttoroot"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio exists
 COPY test_dir /
 RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
832618af
 	}
db7fded1
 	defer ctx.Close()
 
832618af
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) {
4a029259
 	name := "testcopydircontenttoexistdir"
 	ctx, err := fakeContext(`FROM busybox
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN mkdir /exists
 RUN touch /exists/exists_file
 RUN chown -R dockerio.dockerio /exists
 COPY test_dir/ /exists/
 RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
 RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4a029259
 	}
db7fded1
 	defer ctx.Close()
 
4a029259
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) {
6582ea57
 	name := "testcopywholedirtoroot"
1a22418f
 	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
6582ea57
 RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 RUN echo 'dockerio:x:1001:' >> /etc/group
 RUN touch /exists
 RUN chown dockerio.dockerio exists
 COPY test_dir /test_dir
 RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
 RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
 RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
1a22418f
 RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
 RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
6582ea57
 		map[string]string{
 			"test_dir/test_file": "test1",
 		})
be924087
 	if err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
db7fded1
 	defer ctx.Close()
 
6582ea57
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyEtcToRoot(c *check.C) {
c8a5d56f
 	name := "testcopyetctoroot"
 	ctx, err := fakeContext(`FROM scratch
 COPY . /`,
 		map[string]string{
 			"etc/test_file": "test1",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c8a5d56f
 	}
db7fded1
 	defer ctx.Close()
 
c8a5d56f
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyDisallowRemote(c *check.C) {
98e7608b
 	name := "testcopydisallowremote"
 	_, out, err := buildImageWithOut(name, `FROM scratch
 COPY https://index.docker.io/robots.txt /`,
 		true)
 	if err == nil || !strings.Contains(out, "Source can't be a URL for COPY") {
dc944ea7
 		c.Fatalf("Error should be about disallowed remote source, got err: %s, out: %q", err, out)
180c2a67
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) {
7496cbbc
 	const (
 		dockerfile = `
 			FROM scratch
 			ADD links.tar /
 			ADD foo.txt /symlink/
 			`
 		targetFile = "foo.txt"
 	)
 	var (
 		name = "test-link-absolute"
 	)
 	ctx, err := fakeContext(dockerfile, nil)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 	defer ctx.Close()
 
 	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to create temporary directory: %s", tempDir)
7496cbbc
 	}
 	defer os.RemoveAll(tempDir)
 
d0dc14e5
 	var symlinkTarget string
 	if runtime.GOOS == "windows" {
 		var driveLetter string
 		if abs, err := filepath.Abs(tempDir); err != nil {
dc944ea7
 			c.Fatal(err)
d0dc14e5
 		} else {
 			driveLetter = abs[:1]
 		}
 		tempDirWithoutDrive := tempDir[2:]
 		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
 	} else {
 		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
 	}
 
7496cbbc
 	tarPath := filepath.Join(ctx.Dir, "links.tar")
 	nonExistingFile := filepath.Join(tempDir, targetFile)
 	fooPath := filepath.Join(ctx.Dir, targetFile)
 
 	tarOut, err := os.Create(tarPath)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 
 	tarWriter := tar.NewWriter(tarOut)
 
 	header := &tar.Header{
 		Name:     "symlink",
 		Typeflag: tar.TypeSymlink,
 		Linkname: symlinkTarget,
 		Mode:     0755,
 		Uid:      0,
 		Gid:      0,
 	}
 
 	err = tarWriter.WriteHeader(header)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 
 	tarWriter.Close()
 	tarOut.Close()
 
 	foo, err := os.Create(fooPath)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 	defer foo.Close()
 
 	if _, err := foo.WriteString("test"); err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
7496cbbc
 	}
 
 	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
dc944ea7
 		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
7496cbbc
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddBadLinksVolume(c *check.C) {
a57eee22
 	const (
 		dockerfileTemplate = `
 		FROM busybox
 		RUN ln -s /../../../../../../../../%s /x
 		VOLUME /x
 		ADD foo.txt /x/`
 		targetFile = "foo.txt"
 	)
 	var (
 		name       = "test-link-absolute-volume"
 		dockerfile = ""
 	)
 
 	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to create temporary directory: %s", tempDir)
a57eee22
 	}
 	defer os.RemoveAll(tempDir)
 
 	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
 	nonExistingFile := filepath.Join(tempDir, targetFile)
 
 	ctx, err := fakeContext(dockerfile, nil)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
a57eee22
 	}
 	defer ctx.Close()
 	fooPath := filepath.Join(ctx.Dir, targetFile)
 
 	foo, err := os.Create(fooPath)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
a57eee22
 	}
 	defer foo.Close()
 
 	if _, err := foo.WriteString("test"); err != nil {
dc944ea7
 		c.Fatal(err)
a57eee22
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
a57eee22
 	}
 
 	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
dc944ea7
 		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
a57eee22
 	}
 
 }
 
f5b1afae
 // Issue #5270 - ensure we throw a better error than "unexpected EOF"
 // when we can't access files in the context.
dc944ea7
 func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) {
 	testRequires(c, UnixCli) // test uses chown/chmod: not available on windows
492a58f0
 
f5b1afae
 	{
51a56399
 		name := "testbuildinaccessiblefiles"
 		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
 		if err != nil {
dc944ea7
 			c.Fatal(err)
51a56399
 		}
 		defer ctx.Close()
f5b1afae
 		// This is used to ensure we detect inaccessible files early during build in the cli client
51a56399
 		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
f5b1afae
 
b1e3c9e9
 		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
dc944ea7
 			c.Fatalf("failed to chown file to root: %s", err)
b1e3c9e9
 		}
 		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
dc944ea7
 			c.Fatalf("failed to chmod file to 700: %s", err)
b1e3c9e9
 		}
51a56399
 		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
 		buildCmd.Dir = ctx.Dir
b1e3c9e9
 		out, _, err := runCommandWithOutput(buildCmd)
 		if err == nil {
dc944ea7
 			c.Fatalf("build should have failed: %s %s", err, out)
f5b1afae
 		}
 
 		// check if we've detected the failure before we started building
 		if !strings.Contains(out, "no permission to read from ") {
dc944ea7
 			c.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
f5b1afae
 		}
 
 		if !strings.Contains(out, "Error checking context is accessible") {
dc944ea7
 			c.Fatalf("output should've contained the string: Error checking context is accessible")
f5b1afae
 		}
 	}
 	{
51a56399
 		name := "testbuildinaccessibledirectory"
 		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
 		if err != nil {
dc944ea7
 			c.Fatal(err)
51a56399
 		}
 		defer ctx.Close()
f5b1afae
 		// This is used to ensure we detect inaccessible directories early during build in the cli client
51a56399
 		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
f5b1afae
 		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
 
b1e3c9e9
 		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
dc944ea7
 			c.Fatalf("failed to chown directory to root: %s", err)
b1e3c9e9
 		}
 		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
dc944ea7
 			c.Fatalf("failed to chmod directory to 444: %s", err)
b1e3c9e9
 		}
 		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
dc944ea7
 			c.Fatalf("failed to chmod file to 700: %s", err)
b1e3c9e9
 		}
f5b1afae
 
51a56399
 		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
 		buildCmd.Dir = ctx.Dir
b1e3c9e9
 		out, _, err := runCommandWithOutput(buildCmd)
 		if err == nil {
dc944ea7
 			c.Fatalf("build should have failed: %s %s", err, out)
f5b1afae
 		}
 
 		// check if we've detected the failure before we started building
 		if !strings.Contains(out, "can't stat") {
dc944ea7
 			c.Fatalf("output should've contained the string: can't access %s", out)
f5b1afae
 		}
 
 		if !strings.Contains(out, "Error checking context is accessible") {
dc944ea7
 			c.Fatalf("output should've contained the string: Error checking context is accessible")
f5b1afae
 		}
 
 	}
 	{
51a56399
 		name := "testlinksok"
 		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
 		if err != nil {
dc944ea7
 			c.Fatal(err)
51a56399
 		}
 		defer ctx.Close()
da3d3b97
 
 		target := "../../../../../../../../../../../../../../../../../../../azA"
 		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
dc944ea7
 			c.Fatal(err)
51a56399
 		}
da3d3b97
 		defer os.Remove(target)
f5b1afae
 		// This is used to ensure we don't follow links when checking if everything in the context is accessible
 		// This test doesn't require that we run commands as an unprivileged user
51a56399
 		if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 			c.Fatal(err)
f5b1afae
 		}
 	}
27cca4c7
 	{
51a56399
 		name := "testbuildignoredinaccessible"
 		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
 			map[string]string{
 				"directoryWeCantStat/bar": "foo",
 				".dockerignore":           "directoryWeCantStat",
 			})
 		if err != nil {
dc944ea7
 			c.Fatal(err)
51a56399
 		}
 		defer ctx.Close()
27cca4c7
 		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
51a56399
 		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
27cca4c7
 		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
b1e3c9e9
 		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
dc944ea7
 			c.Fatalf("failed to chown directory to root: %s", err)
b1e3c9e9
 		}
 		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
dc944ea7
 			c.Fatalf("failed to chmod directory to 755: %s", err)
b1e3c9e9
 		}
 		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
dc944ea7
 			c.Fatalf("failed to chmod file to 444: %s", err)
b1e3c9e9
 		}
27cca4c7
 
51a56399
 		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
 		buildCmd.Dir = ctx.Dir
b1e3c9e9
 		if out, _, err := runCommandWithOutput(buildCmd); err != nil {
dc944ea7
 			c.Fatalf("build should have worked: %s %s", err, out)
27cca4c7
 		}
 
 	}
f5b1afae
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildForceRm(c *check.C) {
69dcf767
 	containerCountBefore, err := getContainerCount()
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to get the container count: %s", err)
69dcf767
 	}
1625cbfc
 	name := "testbuildforcerm"
 	ctx, err := fakeContext("FROM scratch\nRUN true\nRUN thiswillfail", nil)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1625cbfc
 	}
 	defer ctx.Close()
69dcf767
 
1625cbfc
 	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "--force-rm", ".")
 	buildCmd.Dir = ctx.Dir
b1e3c9e9
 	if out, _, err := runCommandWithOutput(buildCmd); err == nil {
dc944ea7
 		c.Fatalf("failed to build the image: %s, %v", out, err)
69dcf767
 	}
 
 	containerCountAfter, err := getContainerCount()
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to get the container count: %s", err)
69dcf767
 	}
 
 	if containerCountBefore != containerCountAfter {
dc944ea7
 		c.Fatalf("--force-rm shouldn't have left containers behind")
69dcf767
 	}
 
 }
 
671c1220
 // Test that an infinite sleep during a build is killed if the client disconnects.
 // This test is fairly hairy because there are lots of ways to race.
 // Strategy:
 // * Monitor the output of docker events starting from before
 // * Run a 1-year-long sleep from a docker build.
 // * When docker events sees container start, close the "docker build" command
 // * Wait for docker events to emit a dying event.
dc944ea7
 func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
671c1220
 	name := "testbuildcancelation"
 
 	// (Note: one year, will never finish)
 	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
671c1220
 	}
 	defer ctx.Close()
 
 	finish := make(chan struct{})
 	defer close(finish)
 
 	eventStart := make(chan struct{})
 	eventDie := make(chan struct{})
d38c9014
 	containerID := make(chan string)
671c1220
 
dc944ea7
 	startEpoch := daemonTime(c).Unix()
4203230c
 	// Watch for events since epoch.
 	eventsCmd := exec.Command(
 		dockerBinary, "events",
 		"--since", strconv.FormatInt(startEpoch, 10))
 	stdout, err := eventsCmd.StdoutPipe()
 	if err != nil {
 		c.Fatal(err)
 	}
 	if err := eventsCmd.Start(); err != nil {
 		c.Fatal(err)
 	}
 	defer eventsCmd.Process.Kill()
671c1220
 
d38c9014
 	// Goroutine responsible for watching start/die events from `docker events`
671c1220
 	go func() {
d38c9014
 		cid := <-containerID
645c020f
 
d38c9014
 		matchStart := regexp.MustCompile(cid + `(.*) start$`)
 		matchDie := regexp.MustCompile(cid + `(.*) die$`)
671c1220
 
 		//
 		// Read lines of `docker events` looking for container start and stop.
 		//
 		scanner := bufio.NewScanner(stdout)
 		for scanner.Scan() {
d38c9014
 			switch {
 			case matchStart.MatchString(scanner.Text()):
671c1220
 				close(eventStart)
d38c9014
 			case matchDie.MatchString(scanner.Text()):
671c1220
 				close(eventDie)
 			}
 		}
 	}()
 
 	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
 	buildCmd.Dir = ctx.Dir
 
d38c9014
 	stdoutBuild, err := buildCmd.StdoutPipe()
4203230c
 	if err := buildCmd.Start(); err != nil {
dc944ea7
 		c.Fatalf("failed to run build: %s", err)
671c1220
 	}
 
d38c9014
 	matchCID := regexp.MustCompile("Running in ")
 	scanner := bufio.NewScanner(stdoutBuild)
 	for scanner.Scan() {
 		line := scanner.Text()
 		if ok := matchCID.MatchString(line); ok {
 			containerID <- line[len(line)-12:]
 			break
 		}
 	}
 
671c1220
 	select {
d38c9014
 	case <-time.After(5 * time.Second):
dc944ea7
 		c.Fatal("failed to observe build container start in timely fashion")
671c1220
 	case <-eventStart:
 		// Proceeds from here when we see the container fly past in the
 		// output of "docker events".
 		// Now we know the container is running.
 	}
 
 	// Send a kill to the `docker build` command.
 	// Causes the underlying build to be cancelled due to socket close.
4203230c
 	if err := buildCmd.Process.Kill(); err != nil {
dc944ea7
 		c.Fatalf("error killing build command: %s", err)
671c1220
 	}
 
 	// Get the exit status of `docker build`, check it exited because killed.
4203230c
 	if err := buildCmd.Wait(); err != nil && !IsKilled(err) {
dc944ea7
 		c.Fatalf("wait failed during build run: %T %s", err, err)
671c1220
 	}
 
 	select {
d38c9014
 	case <-time.After(5 * time.Second):
671c1220
 		// If we don't get here in a timely fashion, it wasn't killed.
dc944ea7
 		c.Fatal("container cancel did not succeed")
671c1220
 	case <-eventDie:
 		// We saw the container shut down in the `docker events` stream,
 		// as expected.
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildRm(c *check.C) {
52cf3312
 	name := "testbuildrm"
 	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD foo /", map[string]string{"foo": "bar"})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
52cf3312
 	}
 	defer ctx.Close()
a691fcb2
 	{
 		containerCountBefore, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
dc944ea7
 		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm", "-t", name, ".")
a691fcb2
 
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatal("failed to build the image", out)
a691fcb2
 		}
 
 		containerCountAfter, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
 		if containerCountBefore != containerCountAfter {
dc944ea7
 			c.Fatalf("-rm shouldn't have left containers behind")
a691fcb2
 		}
52cf3312
 		deleteImages(name)
a691fcb2
 	}
 
 	{
 		containerCountBefore, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
dc944ea7
 		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name, ".")
a691fcb2
 
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatal("failed to build the image", out)
a691fcb2
 		}
 
 		containerCountAfter, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
 		if containerCountBefore != containerCountAfter {
dc944ea7
 			c.Fatalf("--rm shouldn't have left containers behind")
a691fcb2
 		}
52cf3312
 		deleteImages(name)
a691fcb2
 	}
 
 	{
 		containerCountBefore, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
dc944ea7
 		out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm=false", "-t", name, ".")
a691fcb2
 
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatal("failed to build the image", out)
a691fcb2
 		}
 
 		containerCountAfter, err := getContainerCount()
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to get the container count: %s", err)
a691fcb2
 		}
 
 		if containerCountBefore == containerCountAfter {
dc944ea7
 			c.Fatalf("--rm=false should have left containers behind")
a691fcb2
 		}
52cf3312
 		deleteImages(name)
a691fcb2
 
 	}
 
 }
a5729879
 
dc944ea7
 func (s *DockerSuite) TestBuildWithVolumes(c *check.C) {
68bb56a4
 	var (
 		result   map[string]map[string]struct{}
 		name     = "testbuildvolumes"
 		emptyMap = make(map[string]struct{})
a5ca549a
 		expected = map[string]map[string]struct{}{
 			"/test1":  emptyMap,
 			"/test2":  emptyMap,
 			"/test3":  emptyMap,
 			"/test4":  emptyMap,
 			"/test5":  emptyMap,
 			"/test6":  emptyMap,
 			"[/test7": emptyMap,
 			"/test8]": emptyMap,
 		}
68bb56a4
 	)
bf4d9070
 	_, err := buildImage(name,
 		`FROM scratch
 		VOLUME /test1
a5ca549a
 		VOLUME /test2
     VOLUME /test3 /test4
     VOLUME ["/test5", "/test6"]
     VOLUME [/test7 /test8]
     `,
bf4d9070
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
68bb56a4
 	res, err := inspectFieldJSON(name, "Config.Volumes")
bf4d9070
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
68bb56a4
 
 	err = unmarshalJSON([]byte(res), &result)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
68bb56a4
 
fa753e67
 	equal := reflect.DeepEqual(&result, &expected)
68bb56a4
 
 	if !equal {
dc944ea7
 		c.Fatalf("Volumes %s, expected %s", result, expected)
68bb56a4
 	}
 
11f7f0bf
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildMaintainer(c *check.C) {
bf4d9070
 	name := "testbuildmaintainer"
 	expected := "dockerio"
 	_, err := buildImage(name,
 		`FROM scratch
         MAINTAINER dockerio`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Author")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Maintainer %s, expected %s", res, expected)
bf4d9070
 	}
3dd4c5f4
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildUser(c *check.C) {
bf4d9070
 	name := "testbuilduser"
 	expected := "dockerio"
 	_, err := buildImage(name,
 		`FROM busybox
360fb3d4
 		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
 		USER dockerio
bf4d9070
 		RUN [ $(whoami) = 'dockerio' ]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.User")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("User %s, expected %s", res, expected)
bf4d9070
 	}
360fb3d4
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
bf4d9070
 	name := "testbuildrelativeworkdir"
 	expected := "/test2/test3"
 	_, err := buildImage(name,
 		`FROM busybox
40630ce4
 		RUN [ "$PWD" = '/' ]
 		WORKDIR test1
 		RUN [ "$PWD" = '/test1' ]
 		WORKDIR /test2
 		RUN [ "$PWD" = '/test2' ]
 		WORKDIR test3
bf4d9070
 		RUN [ "$PWD" = '/test2/test3' ]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.WorkingDir")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Workdir %s, expected %s", res, expected)
bf4d9070
 	}
40630ce4
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
2c5b5cfc
 	name := "testbuildworkdirwithenvvariables"
6d66e3e7
 	expected := "/test1/test2"
2c5b5cfc
 	_, err := buildImage(name,
 		`FROM busybox
 		ENV DIRPATH /test1
 		ENV SUBDIRNAME test2
 		WORKDIR $DIRPATH
 		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2c5b5cfc
 	}
 	res, err := inspectField(name, "Config.WorkingDir")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2c5b5cfc
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Workdir %s, expected %s", res, expected)
2c5b5cfc
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
f21f9f85
 	name := "testbuildrelativecopy"
 	dockerfile := `
 		FROM busybox
 			WORKDIR /test1
 			WORKDIR test2
 			RUN [ "$PWD" = '/test1/test2' ]
 			COPY foo ./
 			RUN [ "$(cat /test1/test2/foo)" = 'hello' ]
 			ADD foo ./bar/baz
 			RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ]
 			COPY foo ./bar/baz2
 			RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ]
 			WORKDIR ..
 			COPY foo ./
 			RUN [ "$(cat /test1/foo)" = 'hello' ]
 			COPY foo /test3/
 			RUN [ "$(cat /test3/foo)" = 'hello' ]
 			WORKDIR /test4
 			COPY . .
 			RUN [ "$(cat /test4/foo)" = 'hello' ]
 			WORKDIR /test5/test6
 			COPY foo ../
 			RUN [ "$(cat /test5/foo)" = 'hello' ]
 			`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f21f9f85
 	}
 	_, err = buildImageFromContext(name, ctx, false)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f21f9f85
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnv(c *check.C) {
bf4d9070
 	name := "testbuildenv"
cb51681a
 	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
bf4d9070
 	_, err := buildImage(name,
 		`FROM busybox
cb51681a
 		ENV PATH /test:$PATH
5febba93
         ENV PORT 2375
 		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
bf4d9070
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.Env")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Env %s, expected %s", res, expected)
bf4d9070
 	}
b05be686
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
 	testRequires(c, SameHostDaemon)
b686b65c
 
18587469
 	name := "testbuildcontextcleanup"
 	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to list contents of tmp dir: %s", err)
18587469
 	}
 	_, err = buildImage(name,
 		`FROM scratch
         ENTRYPOINT ["/bin/echo"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
18587469
 	}
 	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to list contents of tmp dir: %s", err)
18587469
 	}
 	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
dc944ea7
 		c.Fatalf("context should have been deleted, but wasn't")
18587469
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
 	testRequires(c, SameHostDaemon)
b686b65c
 
31c00390
 	name := "testbuildcontextcleanup"
 	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to list contents of tmp dir: %s", err)
31c00390
 	}
 	_, err = buildImage(name,
 		`FROM scratch
 	RUN /non/existing/command`,
 		true)
 	if err == nil {
dc944ea7
 		c.Fatalf("expected build to fail, but it didn't")
31c00390
 	}
 	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to list contents of tmp dir: %s", err)
31c00390
 	}
 	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
dc944ea7
 		c.Fatalf("context should have been deleted, but wasn't")
31c00390
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCmd(c *check.C) {
bf4d9070
 	name := "testbuildcmd"
231d362d
 	expected := "{[/bin/echo Hello World]}"
bf4d9070
 	_, err := buildImage(name,
 		`FROM scratch
         CMD ["/bin/echo", "Hello World"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Cmd %s, expected %s", res, expected)
bf4d9070
 	}
c58991f3
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildExpose(c *check.C) {
bf4d9070
 	name := "testbuildexpose"
231d362d
 	expected := "map[2375/tcp:{}]"
bf4d9070
 	_, err := buildImage(name,
 		`FROM scratch
5febba93
         EXPOSE 2375`,
bf4d9070
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Exposed ports %s, expected %s", res, expected)
bf4d9070
 	}
81d16411
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) {
29be7b43
 	// start building docker file with a large number of ports
 	portList := make([]string, 50)
 	line := make([]string, 100)
 	expectedPorts := make([]int, len(portList)*len(line))
 	for i := 0; i < len(portList); i++ {
 		for j := 0; j < len(line); j++ {
 			p := i*len(line) + j + 1
 			line[j] = strconv.Itoa(p)
 			expectedPorts[p-1] = p
 		}
 		if i == len(portList)-1 {
 			portList[i] = strings.Join(line, " ")
 		} else {
 			portList[i] = strings.Join(line, " ") + ` \`
 		}
 	}
 
 	dockerfile := `FROM scratch
 	EXPOSE {{range .}} {{.}}
 	{{end}}`
 	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
 	buf := bytes.NewBuffer(nil)
 	tmpl.Execute(buf, portList)
 
 	name := "testbuildexpose"
 	_, err := buildImage(name, buf.String(), true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
29be7b43
 	}
 
 	// check if all the ports are saved inside Config.ExposedPorts
 	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
29be7b43
 	}
 	var exposedPorts map[string]interface{}
 	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
dc944ea7
 		c.Fatal(err)
29be7b43
 	}
 
 	for _, p := range expectedPorts {
 		ep := fmt.Sprintf("%d/tcp", p)
 		if _, ok := exposedPorts[ep]; !ok {
dc944ea7
 			c.Errorf("Port(%s) is not exposed", ep)
29be7b43
 		} else {
 			delete(exposedPorts, ep)
 		}
 	}
 	if len(exposedPorts) != 0 {
dc944ea7
 		c.Errorf("Unexpected extra exposed ports %v", exposedPorts)
29be7b43
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
1e7ba09b
 	buildID := func(name, exposed string) string {
 		_, err := buildImage(name, fmt.Sprintf(`FROM scratch
 		EXPOSE %s`, exposed), true)
 		if err != nil {
dc944ea7
 			c.Fatal(err)
1e7ba09b
 		}
 		id, err := inspectField(name, "Id")
 		if err != nil {
dc944ea7
 			c.Fatal(err)
1e7ba09b
 		}
 		return id
 	}
 
 	id1 := buildID("testbuildexpose1", "80 2375")
 	id2 := buildID("testbuildexpose2", "2375 80")
 	if id1 != id2 {
dc944ea7
 		c.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
1e7ba09b
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
0552f1a0
 	name := "testbuildexposeuppercaseproto"
231d362d
 	expected := "map[5678/udp:{}]"
0552f1a0
 	_, err := buildImage(name,
 		`FROM scratch
         EXPOSE 5678/UDP`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
0552f1a0
 	}
 	res, err := inspectField(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
0552f1a0
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Exposed ports %s, expected %s", res, expected)
0552f1a0
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildExposeHostPort(c *check.C) {
26e85b0d
 	// start building docker file with ip:hostPort:containerPort
 	name := "testbuildexpose"
231d362d
 	expected := "map[5678/tcp:{}]"
26e85b0d
 	_, out, err := buildImageWithOut(name,
 		`FROM scratch
         EXPOSE 192.168.1.2:2375:5678`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
26e85b0d
 	}
 
 	if !strings.Contains(out, "to map host ports to container ports (ip:hostPort:containerPort) is deprecated.") {
dc944ea7
 		c.Fatal("Missing warning message")
26e85b0d
 	}
 
 	res, err := inspectField(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
26e85b0d
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Exposed ports %s, expected %s", res, expected)
26e85b0d
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
cdd6e979
 	name := "testbuildentrypointinheritance"
 	name2 := "testbuildentrypointinheritance2"
 
 	_, err := buildImage(name,
 		`FROM busybox
         ENTRYPOINT ["/bin/echo"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdd6e979
 	}
 	res, err := inspectField(name, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdd6e979
 	}
 
231d362d
 	expected := "{[/bin/echo]}"
cdd6e979
 	if res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
cdd6e979
 	}
 
 	_, err = buildImage(name2,
 		fmt.Sprintf(`FROM %s
         ENTRYPOINT []`, name),
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdd6e979
 	}
 	res, err = inspectField(name2, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdd6e979
 	}
 
231d362d
 	expected = "{[]}"
cdd6e979
 
 	if res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
cdd6e979
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
bf4d9070
 	name := "testbuildentrypoint"
231d362d
 	expected := "{[]}"
576416c9
 
bf4d9070
 	_, err := buildImage(name,
576416c9
 		`FROM busybox
         ENTRYPOINT []`,
bf4d9070
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	res, err := inspectField(name, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
bf4d9070
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
bf4d9070
 	}
78a847a4
 
576416c9
 }
78a847a4
 
dc944ea7
 func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
576416c9
 	name := "testbuildentrypoint"
231d362d
 	expected := "{[/bin/echo]}"
576416c9
 	_, err := buildImage(name,
 		`FROM scratch
         ENTRYPOINT ["/bin/echo"]`,
78a847a4
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
78a847a4
 	}
576416c9
 	res, err := inspectField(name, "Config.Entrypoint")
78a847a4
 	if err != nil {
dc944ea7
 		c.Fatal(err)
78a847a4
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
78a847a4
 	}
 
b25a9b71
 }
 
a5729879
 // #6445 ensure ONBUILD triggers aren't committed to grandchildren
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) {
372f9bb5
 	var (
 		out2, out3 string
 	)
 	{
 		name1 := "testonbuildtrigger1"
 		dockerfile1 := `
a5729879
 		FROM busybox
 		RUN echo "GRANDPARENT"
 		ONBUILD RUN echo "ONBUILD PARENT"
372f9bb5
 		`
 		ctx, err := fakeContext(dockerfile1, nil)
 		if err != nil {
dc944ea7
 			c.Fatal(err)
372f9bb5
 		}
db7fded1
 		defer ctx.Close()
a5729879
 
dc944ea7
 		out1, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name1, ".")
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatalf("build failed to complete: %s, %v", out1, err)
b1e3c9e9
 		}
a5729879
 	}
372f9bb5
 	{
 		name2 := "testonbuildtrigger2"
 		dockerfile2 := `
 		FROM testonbuildtrigger1
 		`
 		ctx, err := fakeContext(dockerfile2, nil)
 		if err != nil {
dc944ea7
 			c.Fatal(err)
372f9bb5
 		}
db7fded1
 		defer ctx.Close()
a5729879
 
dc944ea7
 		out2, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name2, ".")
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatalf("build failed to complete: %s, %v", out2, err)
b1e3c9e9
 		}
a5729879
 	}
372f9bb5
 	{
 		name3 := "testonbuildtrigger3"
 		dockerfile3 := `
 		FROM testonbuildtrigger2
 		`
 		ctx, err := fakeContext(dockerfile3, nil)
 		if err != nil {
dc944ea7
 			c.Fatal(err)
372f9bb5
 		}
db7fded1
 		defer ctx.Close()
a5729879
 
dc944ea7
 		out3, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name3, ".")
b1e3c9e9
 		if err != nil {
dc944ea7
 			c.Fatalf("build failed to complete: %s, %v", out3, err)
b1e3c9e9
 		}
 
372f9bb5
 	}
a5729879
 
 	// ONBUILD should be run in second build.
 	if !strings.Contains(out2, "ONBUILD PARENT") {
dc944ea7
 		c.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
a5729879
 	}
 
 	// ONBUILD should *not* be run in third build.
 	if strings.Contains(out3, "ONBUILD PARENT") {
dc944ea7
 		c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
a5729879
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildWithCache(c *check.C) {
ae128437
 	name := "testbuildwithcache"
 	id1, err := buildImage(name,
 		`FROM scratch
 		MAINTAINER dockerio
 		EXPOSE 5432
         ENTRYPOINT ["/bin/echo"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id2, err := buildImage(name,
 		`FROM scratch
 		MAINTAINER dockerio
 		EXPOSE 5432
         ENTRYPOINT ["/bin/echo"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
ae128437
 	}
 }
6db32fde
 
dc944ea7
 func (s *DockerSuite) TestBuildWithoutCache(c *check.C) {
ae128437
 	name := "testbuildwithoutcache"
da3d3b97
 	name2 := "testbuildwithoutcache2"
ae128437
 	id1, err := buildImage(name,
 		`FROM scratch
 		MAINTAINER dockerio
 		EXPOSE 5432
         ENTRYPOINT ["/bin/echo"]`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 
 	id2, err := buildImage(name2,
ae128437
 		`FROM scratch
 		MAINTAINER dockerio
 		EXPOSE 5432
         ENTRYPOINT ["/bin/echo"]`,
 		false)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
6f20b957
 	name := "testbuildconditionalcache"
 
 	dockerfile := `
 		FROM busybox
         ADD foo /tmp/`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
f6e95ef3
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f6e95ef3
 	}
 	defer ctx.Close()
6f20b957
 
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatalf("Error building #1: %s", err)
6f20b957
 	}
 
 	if err := ctx.Add("foo", "bye"); err != nil {
dc944ea7
 		c.Fatalf("Error modifying foo: %s", err)
6f20b957
 	}
 
 	id2, err := buildImageFromContext(name, ctx, false)
 	if err != nil {
dc944ea7
 		c.Fatalf("Error building #2: %s", err)
6f20b957
 	}
 	if id2 == id1 {
dc944ea7
 		c.Fatal("Should not have used the cache")
6f20b957
 	}
 
 	id3, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatalf("Error building #3: %s", err)
6f20b957
 	}
 	if id3 != id2 {
dc944ea7
 		c.Fatal("Should have used the cache")
6f20b957
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddLocalFileWithCache(c *check.C) {
ae128437
 	name := "testbuildaddlocalfilewithcache"
da3d3b97
 	name2 := "testbuildaddlocalfilewithcache2"
ae128437
 	dockerfile := `
 		FROM busybox
         MAINTAINER dockerio
         ADD foo /usr/lib/bla/bar
 		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, true)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
ae128437
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) {
05b8a1eb
 	name := "testbuildaddmultiplelocalfilewithcache"
da3d3b97
 	name2 := "testbuildaddmultiplelocalfilewithcache2"
05b8a1eb
 	dockerfile := `
 		FROM busybox
         MAINTAINER dockerio
         ADD foo Dockerfile /usr/lib/bla/
 		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
05b8a1eb
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
05b8a1eb
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, true)
05b8a1eb
 	if err != nil {
dc944ea7
 		c.Fatal(err)
05b8a1eb
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
05b8a1eb
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddLocalFileWithoutCache(c *check.C) {
ae128437
 	name := "testbuildaddlocalfilewithoutcache"
da3d3b97
 	name2 := "testbuildaddlocalfilewithoutcache2"
ae128437
 	dockerfile := `
 		FROM busybox
         MAINTAINER dockerio
         ADD foo /usr/lib/bla/bar
 		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, false)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
cd329d06
 	name := "testbuildcopydirbutnotfile"
da3d3b97
 	name2 := "testbuildcopydirbutnotfile2"
cd329d06
 	dockerfile := `
         FROM scratch
         COPY dir /tmp/`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"dir/foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cd329d06
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cd329d06
 	}
 	// Check that adding file with similar name doesn't mess with cache
 	if err := ctx.Add("dir_file", "hello2"); err != nil {
dc944ea7
 		c.Fatal(err)
cd329d06
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, true)
cd329d06
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cd329d06
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but wasn't")
cd329d06
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) {
ae128437
 	name := "testbuildaddcurrentdirwithcache"
da3d3b97
 	name2 := name + "2"
 	name3 := name + "3"
 	name4 := name + "4"
 	name5 := name + "5"
ae128437
 	dockerfile := `
         FROM scratch
         MAINTAINER dockerio
         ADD . /usr/lib/bla`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	// Check that adding file invalidate cache of "ADD ."
 	if err := ctx.Add("bar", "hello2"); err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, true)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 	// Check that changing file invalidate cache of "ADD ."
 	if err := ctx.Add("foo", "hello1"); err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id3, err := buildImageFromContext(name3, ctx, true)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id2 == id3 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 	// Check that changing file to same content invalidate cache of "ADD ."
 	time.Sleep(1 * time.Second) // wait second because of mtime precision
 	if err := ctx.Add("foo", "hello1"); err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id4, err := buildImageFromContext(name4, ctx, true)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id3 == id4 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
da3d3b97
 	id5, err := buildImageFromContext(name5, ctx, true)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id4 != id5 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
ae128437
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) {
ae128437
 	name := "testbuildaddcurrentdirwithoutcache"
da3d3b97
 	name2 := "testbuildaddcurrentdirwithoutcache2"
ae128437
 	dockerfile := `
         FROM scratch
         MAINTAINER dockerio
         ADD . /usr/lib/bla`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo": "hello",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, false)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddRemoteFileWithCache(c *check.C) {
ae128437
 	name := "testbuildaddremotefilewithcache"
 	server, err := fakeStorage(map[string]string{
 		"baz": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer server.Close()
2e95bb5f
 
ae128437
 	id1, err := buildImage(name,
 		fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id2, err := buildImage(name,
 		fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
ae128437
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddRemoteFileWithoutCache(c *check.C) {
ae128437
 	name := "testbuildaddremotefilewithoutcache"
da3d3b97
 	name2 := "testbuildaddremotefilewithoutcache2"
ae128437
 	server, err := fakeStorage(map[string]string{
 		"baz": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer server.Close()
2e95bb5f
 
ae128437
 	id1, err := buildImage(name,
 		fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImage(name2,
ae128437
 		fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		false)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) {
2e482c86
 	name := "testbuildaddremotefilemtime"
da3d3b97
 	name2 := name + "2"
 	name3 := name + "3"
 	name4 := name + "4"
 
2e95bb5f
 	files := map[string]string{"baz": "hello"}
 	server, err := fakeStorage(files)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 	defer server.Close()
 
 	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 	defer ctx.Close()
 
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, true)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but wasn't - #1")
2e482c86
 	}
 
2e95bb5f
 	// Now create a different server withsame contents (causes different mtim)
2e482c86
 	// This time the cache should not be used
2e95bb5f
 
 	// allow some time for clock to pass as mtime precision is only 1s
 	time.Sleep(2 * time.Second)
 
 	server2, err := fakeStorage(files)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
2e95bb5f
 	defer server2.Close()
2e482c86
 
2e95bb5f
 	ctx2, err := fakeContext(fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
         ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e95bb5f
 	}
 	defer ctx2.Close()
 	id3, err := buildImageFromContext(name3, ctx2, true)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 	if id1 == id3 {
dc944ea7
 		c.Fatal("The cache should not have been used but was")
2e482c86
 	}
 
 	// And for good measure do it again and make sure cache is used this time
2e95bb5f
 	id4, err := buildImageFromContext(name4, ctx2, true)
2e482c86
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2e482c86
 	}
 	if id3 != id4 {
dc944ea7
 		c.Fatal("The cache should have been used but wasn't - #2")
2e482c86
 	}
 }
 
ab121345
 func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithCache(c *check.C) {
ae128437
 	name := "testbuildaddlocalandremotefilewithcache"
 	server, err := fakeStorage(map[string]string{
 		"baz": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer server.Close()
2e95bb5f
 
ae128437
 	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
         ADD foo /usr/lib/bla/bar
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		map[string]string{
 			"foo": "hello world",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer ctx.Close()
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	id2, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatal("The cache should have been used but hasn't.")
ae128437
 	}
 }
 
dc944ea7
 func testContextTar(c *check.C, compression archive.Compression) {
d302d929
 	ctx, err := fakeContext(
 		`FROM busybox
 ADD foo /foo
 CMD ["cat", "/foo"]`,
 		map[string]string{
 			"foo": "bar",
 		},
 	)
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
d302d929
 	}
 	context, err := archive.Tar(ctx.Dir, compression)
edcb4145
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to build context tar: %v", err)
edcb4145
 	}
d302d929
 	name := "contexttar"
 	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
edcb4145
 	buildCmd.Stdin = context
 
b1e3c9e9
 	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
dc944ea7
 		c.Fatalf("build failed to complete: %v %v", out, err)
edcb4145
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) {
 	testContextTar(c, archive.Gzip)
edcb4145
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) {
 	testContextTar(c, archive.Uncompressed)
edcb4145
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildNoContext(c *check.C) {
edcb4145
 	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
 	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
 
b1e3c9e9
 	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
dc944ea7
 		c.Fatalf("build failed to complete: %v %v", out, err)
edcb4145
 	}
 
dc944ea7
 	if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" {
 		c.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
edcb4145
 	}
 }
 
c024c9bd
 // TODO: TestCaching
ab121345
 func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithoutCache(c *check.C) {
ae128437
 	name := "testbuildaddlocalandremotefilewithoutcache"
da3d3b97
 	name2 := "testbuildaddlocalandremotefilewithoutcache2"
ae128437
 	server, err := fakeStorage(map[string]string{
 		"baz": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer server.Close()
2e95bb5f
 
ae128437
 	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
         MAINTAINER dockerio
         ADD foo /usr/lib/bla/bar
2e95bb5f
         ADD %s/baz /usr/lib/baz/quux`, server.URL()),
ae128437
 		map[string]string{
 			"foo": "hello world",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	defer ctx.Close()
 	id1, err := buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
da3d3b97
 	id2, err := buildImageFromContext(name2, ctx, false)
ae128437
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ae128437
 	}
 	if id1 == id2 {
dc944ea7
 		c.Fatal("The cache should have been invalided but hasn't.")
ae128437
 	}
 }
c024c9bd
 
dc944ea7
 func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) {
c024c9bd
 	name := "testbuildimg"
 
 	_, err := buildImage(name,
 		`FROM busybox:latest
         RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
         VOLUME /test`,
 		true)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c024c9bd
 	}
 
 	cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
 	out, _, err := runCommandWithOutput(cmd)
 	if err != nil {
dc944ea7
 		c.Fatal(out, err)
c024c9bd
 	}
 
 	if expected := "drw-------"; !strings.Contains(out, expected) {
dc944ea7
 		c.Fatalf("expected %s received %s", expected, out)
c024c9bd
 	}
 
 	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
dc944ea7
 		c.Fatalf("expected %s received %s", expected, out)
c024c9bd
 	}
 
 }
c5b82f5e
 
 // testing #1405 - config.Cmd does not get cleaned up if
 // utilizing cache
dc944ea7
 func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
c5b82f5e
 	name := "testbuildcmdcleanup"
 	if _, err := buildImage(name,
 		`FROM busybox
         RUN echo "hello"`,
 		true); err != nil {
dc944ea7
 		c.Fatal(err)
c5b82f5e
 	}
 
 	ctx, err := fakeContext(`FROM busybox
         RUN echo "hello"
         ADD foo /foo
         ENTRYPOINT ["/bin/echo"]`,
 		map[string]string{
 			"foo": "hello",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c5b82f5e
 	}
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
c5b82f5e
 	}
 	res, err := inspectField(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c5b82f5e
 	}
1b6546b8
 	// Cmd must be cleaned up
231d362d
 	if res != "<nil>" {
 		c.Fatalf("Cmd %s, expected nil", res)
c5b82f5e
 	}
 }
686786f1
 
dc944ea7
 func (s *DockerSuite) TestBuildForbiddenContextPath(c *check.C) {
686786f1
 	name := "testbuildforbidpath"
 	ctx, err := fakeContext(`FROM scratch
         ADD ../../ test/
         `,
 		map[string]string{
 			"test.txt":  "test1",
 			"other.txt": "other",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
686786f1
 	}
5e20b002
 
 	expected := "Forbidden path outside the build context: ../../ "
 	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
dc944ea7
 		c.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
686786f1
 	}
5e20b002
 
686786f1
 }
62d97afa
 
ab121345
 func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) {
62d97afa
 	name := "testbuildaddnotfound"
 	ctx, err := fakeContext(`FROM scratch
         ADD foo /usr/local/bar`,
 		map[string]string{"bar": "hello"})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
62d97afa
 	}
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
 		if !strings.Contains(err.Error(), "foo: no such file or directory") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
62d97afa
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
62d97afa
 	}
 }
f1d7ed35
 
dc944ea7
 func (s *DockerSuite) TestBuildInheritance(c *check.C) {
f1d7ed35
 	name := "testbuildinheritance"
 
 	_, err := buildImage(name,
 		`FROM scratch
 		EXPOSE 2375`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f1d7ed35
 	}
 	ports1, err := inspectField(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f1d7ed35
 	}
 
 	_, err = buildImage(name,
 		fmt.Sprintf(`FROM %s
 		ENTRYPOINT ["/bin/echo"]`, name),
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f1d7ed35
 	}
 
 	res, err := inspectField(name, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f1d7ed35
 	}
231d362d
 	if expected := "{[/bin/echo]}"; res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
f1d7ed35
 	}
 	ports2, err := inspectField(name, "Config.ExposedPorts")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
f1d7ed35
 	}
 	if ports1 != ports2 {
dc944ea7
 		c.Fatalf("Ports must be same: %s != %s", ports1, ports2)
f1d7ed35
 	}
 }
d3023f25
 
dc944ea7
 func (s *DockerSuite) TestBuildFails(c *check.C) {
d3023f25
 	name := "testbuildfails"
 	_, err := buildImage(name,
 		`FROM busybox
 		RUN sh -c "exit 23"`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about non-zero code 23", err)
d3023f25
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
d3023f25
 	}
 }
08a10f93
 
dc944ea7
 func (s *DockerSuite) TestBuildFailsDockerfileEmpty(c *check.C) {
08a10f93
 	name := "testbuildfails"
 	_, err := buildImage(name, ``, true)
 	if err != nil {
8b02d85e
 		if !strings.Contains(err.Error(), "The Dockerfile (Dockerfile) cannot be empty") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
08a10f93
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
08a10f93
 	}
 }
2629e2ec
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuild(c *check.C) {
2629e2ec
 	name := "testbuildonbuild"
 	_, err := buildImage(name,
 		`FROM busybox
 		ONBUILD RUN touch foobar`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2629e2ec
 	}
 	_, err = buildImage(name,
 		fmt.Sprintf(`FROM %s
 		RUN [ -f foobar ]`, name),
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
2629e2ec
 	}
 }
1e0e8636
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenChained(c *check.C) {
1e0e8636
 	name := "testbuildonbuildforbiddenchained"
 	_, err := buildImage(name,
 		`FROM busybox
 		ONBUILD ONBUILD RUN touch foobar`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
1e0e8636
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
1e0e8636
 	}
 }
1c8ec01c
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenFrom(c *check.C) {
1c8ec01c
 	name := "testbuildonbuildforbiddenfrom"
 	_, err := buildImage(name,
 		`FROM busybox
 		ONBUILD FROM scratch`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about FROM forbidden", err)
1c8ec01c
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
1c8ec01c
 	}
 }
690711b5
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainer(c *check.C) {
690711b5
 	name := "testbuildonbuildforbiddenmaintainer"
 	_, err := buildImage(name,
 		`FROM busybox
 		ONBUILD MAINTAINER docker.io`,
 		true)
 	if err != nil {
 		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
dc944ea7
 			c.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
690711b5
 		}
 	} else {
dc944ea7
 		c.Fatal("Error must not be nil")
690711b5
 	}
 }
cc42eeac
 
 // gh #2446
dc944ea7
 func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
cc42eeac
 	name := "testbuildaddtosymlinkdest"
 	ctx, err := fakeContext(`FROM busybox
         RUN mkdir /foo
         RUN ln -s /foo /bar
         ADD foo /bar/
         RUN [ -f /bar/foo ]
         RUN [ -f /foo/foo ]`,
 		map[string]string{
 			"foo": "hello",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cc42eeac
 	}
 	defer ctx.Close()
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
cc42eeac
 	}
 }
03c5c193
 
dc944ea7
 func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) {
03c5c193
 	name := "testbuildescaping"
 
 	_, err := buildImage(name, `
   FROM busybox
   MAINTAINER "Docker \
 IO <io@\
 docker.com>"
   `, true)
 
 	res, err := inspectField(name, "Author")
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
03c5c193
 	}
 
d942c59b
 	if res != "\"Docker IO <io@docker.com>\"" {
dc944ea7
 		c.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
03c5c193
 	}
 
 }
9189db3a
 
dc944ea7
 func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) {
d942c59b
 	// Verify that strings that look like ints are still passed as strings
 	name := "testbuildstringing"
 
 	_, err := buildImage(name, `
   FROM busybox
   MAINTAINER 123
   `, true)
 
 	out, rc, err := runCommandWithOutput(exec.Command(dockerBinary, "inspect", name))
 	if rc != 0 || err != nil {
3941623f
 		c.Fatalf("Unexpected error from inspect: rc: %v  err: %v", rc, err)
d942c59b
 	}
 
 	if !strings.Contains(out, "\"123\"") {
dc944ea7
 		c.Fatalf("Output does not contain the int as a string:\n%s", out)
d942c59b
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignore(c *check.C) {
9189db3a
 	name := "testbuilddockerignore"
 	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 ]]
6fd8e485
 		RUN [[ ! -e /bla/dir/foo ]]
 		RUN [[ ! -e /bla/foo ]]
9189db3a
 		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",
6fd8e485
 		"dir/foo":          "",
9189db3a
 		".gitignore":       "",
 		"README.md":        "readme",
6fd8e485
 		".dockerignore": `
 .git
 pkg
 .gitignore
 src/_vendor
 *.md
 dir`,
9189db3a
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
9189db3a
 	}
6fd8e485
 	defer ctx.Close()
9189db3a
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
9189db3a
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) {
c0f0f5c9
 	name := "testbuilddockerignorecleanpaths"
 	dockerfile := `
         FROM busybox
         ADD . /tmp/
         RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"foo":           "foo",
 		"foo2":          "foo2",
 		"dir1/foo":      "foo in dir1",
 		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c0f0f5c9
 	}
 	defer ctx.Close()
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
c0f0f5c9
 	}
 }
 
6fd8e485
 func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) {
 	name := "testbuilddockerignoreexceptions"
 	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/dir/dir/foo ]]
 		RUN [[ ! -e /bla/dir/foo1 ]]
 		RUN [[ -f /bla/dir/e ]]
 		RUN [[ -f /bla/dir/e-dir/foo ]]
 		RUN [[ ! -e /bla/foo ]]
 		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",
 		"dir/foo":          "",
 		"dir/foo1":         "",
 		"dir/dir/f1":       "",
 		"dir/dir/foo":      "",
 		"dir/e":            "",
 		"dir/e-dir/foo":    "",
 		".gitignore":       "",
 		"README.md":        "readme",
 		".dockerignore": `
 .git
 pkg
 .gitignore
 src/_vendor
 *.md
 dir
 !dir/e*
 !dir/dir/foo`,
 	})
 	if err != nil {
 		c.Fatal(err)
 	}
 	defer ctx.Close()
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
 		c.Fatal(err)
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) {
9189db3a
 	name := "testbuilddockerignoredockerfile"
 	dockerfile := `
6d801a3c
         FROM busybox
 		ADD . /tmp/
 		RUN ! ls /tmp/Dockerfile
 		RUN ls /tmp/.dockerignore`
9189db3a
 	ctx, err := fakeContext(dockerfile, map[string]string{
6d801a3c
 		"Dockerfile":    dockerfile,
9189db3a
 		".dockerignore": "Dockerfile\n",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
9189db3a
 	}
f6e95ef3
 	defer ctx.Close()
 
6d801a3c
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't ignore Dockerfile correctly:%s", err)
9189db3a
 	}
c0f0f5c9
 
 	// now try it with ./Dockerfile
 	ctx.Add(".dockerignore", "./Dockerfile\n")
6d801a3c
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err)
c0f0f5c9
 	}
 
9189db3a
 }
1d4862b7
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) {
eb3ea3b4
 	name := "testbuilddockerignoredockerfile"
 	dockerfile := `
         FROM busybox
 		ADD . /tmp/
 		RUN ls /tmp/Dockerfile
 		RUN ! ls /tmp/MyDockerfile
 		RUN ls /tmp/.dockerignore`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"Dockerfile":    "Should not use me",
 		"MyDockerfile":  dockerfile,
 		".dockerignore": "MyDockerfile\n",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
eb3ea3b4
 	}
f6e95ef3
 	defer ctx.Close()
 
eb3ea3b4
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't ignore MyDockerfile correctly:%s", err)
eb3ea3b4
 	}
 
 	// now try it with ./MyDockerfile
 	ctx.Add(".dockerignore", "./MyDockerfile\n")
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err)
eb3ea3b4
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) {
6d801a3c
 	name := "testbuilddockerignoredockerignore"
 	dockerfile := `
         FROM busybox
 		ADD . /tmp/
 		RUN ! ls /tmp/.dockerignore
 		RUN ls /tmp/Dockerfile`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"Dockerfile":    dockerfile,
 		".dockerignore": ".dockerignore\n",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
6d801a3c
 	}
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't ignore .dockerignore correctly:%s", err)
6d801a3c
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) {
6d801a3c
 	var id1 string
 	var id2 string
 
 	name := "testbuilddockerignoretouchdockerfile"
 	dockerfile := `
         FROM busybox
 		ADD . /tmp/`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"Dockerfile":    dockerfile,
 		".dockerignore": "Dockerfile\n",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
6d801a3c
 	}
 
 	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't build it correctly:%s", err)
6d801a3c
 	}
 
 	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't build it correctly:%s", err)
6d801a3c
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatalf("Didn't use the cache - 1")
6d801a3c
 	}
 
 	// Now make sure touching Dockerfile doesn't invalidate the cache
 	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
dc944ea7
 		c.Fatalf("Didn't add Dockerfile: %s", err)
6d801a3c
 	}
 	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't build it correctly:%s", err)
6d801a3c
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatalf("Didn't use the cache - 2")
6d801a3c
 	}
 
 	// One more time but just 'touch' it instead of changing the content
 	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
dc944ea7
 		c.Fatalf("Didn't add Dockerfile: %s", err)
6d801a3c
 	}
 	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("Didn't build it correctly:%s", err)
6d801a3c
 	}
 	if id1 != id2 {
dc944ea7
 		c.Fatalf("Didn't use the cache - 3")
6d801a3c
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) {
7d97a5f4
 	name := "testbuilddockerignorewholedir"
 	dockerfile := `
         FROM busybox
 		COPY . /
 		RUN [[ ! -e /.gitignore ]]
 		RUN [[ -f /Makefile ]]`
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"Dockerfile":    "FROM scratch",
 		"Makefile":      "all:",
6fd8e485
 		".gitignore":    "",
7d97a5f4
 		".dockerignore": ".*\n",
 	})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
7d97a5f4
 	}
 	if _, err = buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
7d97a5f4
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildLineBreak(c *check.C) {
1d4862b7
 	name := "testbuildlinebreak"
 	_, 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 {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEOLInLine(c *check.C) {
1d4862b7
 	name := "testbuildeolinline"
 	_, 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 {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) {
1d4862b7
 	name := "testbuildcomments"
 	_, 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 {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) {
1d4862b7
 	name := "testbuildusers"
 	_, 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 {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
1d4862b7
 	name := "testbuildenvusage"
 	dockerfile := `FROM busybox
4e74cd49
 ENV    HOME /root
cb51681a
 ENV    PATH $HOME/bin:$PATH
 ENV    PATH /tmp:$PATH
 RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
1d4862b7
 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
cb51681a
 RUN    [ "$(cat $TO)" = "hello" ]
ed3bc3b9
 ENV    abc=def
 ENV    ghi=$abc
 RUN    [ "$ghi" = "def" ]
cb51681a
 `
1d4862b7
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"hello/docker/world": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
db7fded1
 	defer ctx.Close()
 
1d4862b7
 	_, err = buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
1314e158
 	name := "testbuildenvusage2"
 	dockerfile := `FROM busybox
 ENV    abc=def
 RUN    [ "$abc" = "def" ]
 ENV    def="hello world"
 RUN    [ "$def" = "hello world" ]
 ENV    def=hello\ world
 RUN    [ "$def" = "hello world" ]
 ENV    v1=abc v2="hi there"
 RUN    [ "$v1" = "abc" ]
 RUN    [ "$v2" = "hi there" ]
 ENV    v3='boogie nights' v4="with'quotes too"
 RUN    [ "$v3" = "boogie nights" ]
 RUN    [ "$v4" = "with'quotes too" ]
 ENV    abc=zzz FROM=hello/docker/world
 ENV    abc=zzz TO=/docker/world/hello
 ADD    $FROM $TO
 RUN    [ "$(cat $TO)" = "hello" ]
 ENV    abc "zzz"
6d66e3e7
 RUN    [ $abc = "zzz" ]
1314e158
 ENV    abc 'yyy'
6d66e3e7
 RUN    [ $abc = 'yyy' ]
1314e158
 ENV    abc=
 RUN    [ "$abc" = "" ]
ed3bc3b9
 
 # use grep to make sure if the builder substitutes \$foo by mistake
 # we don't get a false positive
 ENV    abc=\$foo
 RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
 ENV    abc \$foo
 RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
 
 ENV    abc=\'foo\'
 RUN    [ "$abc" = "'foo'" ]
 ENV    abc=\"foo\"
 RUN    [ "$abc" = "\"foo\"" ]
 ENV    abc "foo"
6d66e3e7
 RUN    [ "$abc" = "foo" ]
ed3bc3b9
 ENV    abc 'foo'
6d66e3e7
 RUN    [ "$abc" = 'foo' ]
ed3bc3b9
 ENV    abc \'foo\'
6d66e3e7
 RUN    [ "$abc" = "'foo'" ]
ed3bc3b9
 ENV    abc \"foo\"
6d66e3e7
 RUN    [ "$abc" = '"foo"' ]
 
39908fc6
 ENV    abc=ABC
 RUN    [ "$abc" = "ABC" ]
 ENV    def=${abc:-DEF}
 RUN    [ "$def" = "ABC" ]
 ENV    def=${ccc:-DEF}
 RUN    [ "$def" = "DEF" ]
 ENV    def=${ccc:-${def}xx}
 RUN    [ "$def" = "DEFxx" ]
 ENV    def=${def:+ALT}
 RUN    [ "$def" = "ALT" ]
 ENV    def=${def:+${abc}:}
 RUN    [ "$def" = "ABC:" ]
 ENV    def=${ccc:-\$abc:}
 RUN    [ "$def" = '$abc:' ]
 ENV    def=${ccc:-\${abc}:}
 RUN    [ "$def" = '${abc:}' ]
 ENV    mypath=${mypath:+$mypath:}/home
 RUN    [ "$mypath" = '/home' ]
 ENV    mypath=${mypath:+$mypath:}/away
 RUN    [ "$mypath" = '/home:/away' ]
 
6d66e3e7
 ENV    e1=bar
 ENV    e2=$e1
 ENV    e3=$e11
 ENV    e4=\$e1
 ENV    e5=\$e11
 RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
 
 ENV    ee1 bar
 ENV    ee2 $ee1
 ENV    ee3 $ee11
 ENV    ee4 \$ee1
 ENV    ee5 \$ee11
 RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
 
 ENV    eee1="foo"
 ENV    eee2='foo'
 ENV    eee3 "foo"
 ENV    eee4 'foo'
 RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
 
1314e158
 `
 	ctx, err := fakeContext(dockerfile, map[string]string{
 		"hello/docker/world": "hello",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1314e158
 	}
f6e95ef3
 	defer ctx.Close()
 
1314e158
 	_, err = buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1314e158
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddScript(c *check.C) {
1d4862b7
 	name := "testbuildaddscript"
 	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 {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
db7fded1
 	defer ctx.Close()
 
1d4862b7
 	_, err = buildImageFromContext(name, ctx, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1d4862b7
 	}
 }
cfa4999d
 
dc944ea7
 func (s *DockerSuite) TestBuildAddTar(c *check.C) {
fc2631b4
 	name := "testbuildaddtar"
cfa4999d
 
24c00c85
 	ctx := func() *FakeContext {
5d8e80ba
 		dockerfile := `
 FROM busybox
 ADD test.tar /
 RUN cat /test/foo | grep Hi
 ADD test.tar /test.tar
 RUN cat /test.tar/test/foo | grep Hi
 ADD test.tar /unlikely-to-exist
 RUN cat /unlikely-to-exist/test/foo | grep Hi
 ADD test.tar /unlikely-to-exist-trailing-slash/
 RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
 RUN mkdir /existing-directory
 ADD test.tar /existing-directory
 RUN cat /existing-directory/test/foo | grep Hi
 ADD test.tar /existing-directory-trailing-slash/
 RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
24c00c85
 		tmpDir, err := ioutil.TempDir("", "fake-context")
 		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to create test.tar archive: %v", err)
cfa4999d
 		}
24c00c85
 		defer testTar.Close()
 
 		tw := tar.NewWriter(testTar)
 
 		if err := tw.WriteHeader(&tar.Header{
 			Name: "test/foo",
 			Size: 2,
 		}); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file header: %v", err)
24c00c85
 		}
 		if _, err := tw.Write([]byte("Hi")); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file content: %v", err)
24c00c85
 		}
 		if err := tw.Close(); err != nil {
dc944ea7
 			c.Fatalf("failed to close tar archive: %v", err)
cfa4999d
 		}
 
5d8e80ba
 		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
dc944ea7
 			c.Fatalf("failed to open destination dockerfile: %v", err)
24c00c85
 		}
44ffb199
 		return fakeContextFromDir(tmpDir)
24c00c85
 	}()
db7fded1
 	defer ctx.Close()
24c00c85
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
cfa4999d
 	}
30519330
 
cfa4999d
 }
5b0d4cf2
 
dc944ea7
 func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
e4ba82d5
 	name := "testbuildaddtarxz"
 
 	ctx := func() *FakeContext {
 		dockerfile := `
 			FROM busybox
 			ADD test.tar.xz /
 			RUN cat /test/foo | grep Hi`
 		tmpDir, err := ioutil.TempDir("", "fake-context")
 		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to create test.tar archive: %v", err)
e4ba82d5
 		}
 		defer testTar.Close()
 
 		tw := tar.NewWriter(testTar)
 
 		if err := tw.WriteHeader(&tar.Header{
 			Name: "test/foo",
 			Size: 2,
 		}); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file header: %v", err)
e4ba82d5
 		}
 		if _, err := tw.Write([]byte("Hi")); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file content: %v", err)
e4ba82d5
 		}
 		if err := tw.Close(); err != nil {
dc944ea7
 			c.Fatalf("failed to close tar archive: %v", err)
e4ba82d5
 		}
2f53820c
 		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
e4ba82d5
 		xzCompressCmd.Dir = tmpDir
 		out, _, err := runCommandWithOutput(xzCompressCmd)
 		if err != nil {
dc944ea7
 			c.Fatal(err, out)
e4ba82d5
 		}
 
 		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
dc944ea7
 			c.Fatalf("failed to open destination dockerfile: %v", err)
e4ba82d5
 		}
44ffb199
 		return fakeContextFromDir(tmpDir)
e4ba82d5
 	}()
 
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
e4ba82d5
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildAddTarXzGz(c *check.C) {
e4ba82d5
 	name := "testbuildaddtarxzgz"
 
 	ctx := func() *FakeContext {
 		dockerfile := `
 			FROM busybox
 			ADD test.tar.xz.gz /
 			RUN ls /test.tar.xz.gz`
 		tmpDir, err := ioutil.TempDir("", "fake-context")
 		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
 		if err != nil {
dc944ea7
 			c.Fatalf("failed to create test.tar archive: %v", err)
e4ba82d5
 		}
 		defer testTar.Close()
 
 		tw := tar.NewWriter(testTar)
 
 		if err := tw.WriteHeader(&tar.Header{
 			Name: "test/foo",
 			Size: 2,
 		}); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file header: %v", err)
e4ba82d5
 		}
 		if _, err := tw.Write([]byte("Hi")); err != nil {
dc944ea7
 			c.Fatalf("failed to write tar file content: %v", err)
e4ba82d5
 		}
 		if err := tw.Close(); err != nil {
dc944ea7
 			c.Fatalf("failed to close tar archive: %v", err)
e4ba82d5
 		}
 
2f53820c
 		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
e4ba82d5
 		xzCompressCmd.Dir = tmpDir
 		out, _, err := runCommandWithOutput(xzCompressCmd)
 		if err != nil {
dc944ea7
 			c.Fatal(err, out)
e4ba82d5
 		}
 
 		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
 		gzipCompressCmd.Dir = tmpDir
 		out, _, err = runCommandWithOutput(gzipCompressCmd)
 		if err != nil {
dc944ea7
 			c.Fatal(err, out)
e4ba82d5
 		}
 
 		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
dc944ea7
 			c.Fatalf("failed to open destination dockerfile: %v", err)
e4ba82d5
 		}
44ffb199
 		return fakeContextFromDir(tmpDir)
e4ba82d5
 	}()
 
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
e4ba82d5
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildFromGIT(c *check.C) {
5b0d4cf2
 	name := "testbuildfromgit"
 	git, err := fakeGIT("repo", map[string]string{
 		"Dockerfile": `FROM busybox
 					ADD first /first
 					RUN [ -f /first ]
 					MAINTAINER docker`,
 		"first": "test git data",
44ffb199
 	}, true)
5b0d4cf2
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5b0d4cf2
 	}
 	defer git.Close()
 
 	_, err = buildImageFromPath(name, git.RepoURL, true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5b0d4cf2
 	}
 	res, err := inspectField(name, "Author")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5b0d4cf2
 	}
 	if res != "docker" {
dc944ea7
 		c.Fatalf("Maintainer should be docker, got %s", res)
5b0d4cf2
 	}
 }
1b6546b8
 
49fd83a2
 func (s *DockerSuite) TestBuildFromGITWithContext(c *check.C) {
 	name := "testbuildfromgit"
 	defer deleteImages(name)
 	git, err := fakeGIT("repo", map[string]string{
 		"docker/Dockerfile": `FROM busybox
 					ADD first /first
 					RUN [ -f /first ]
 					MAINTAINER docker`,
 		"docker/first": "test git data",
 	}, true)
 	if err != nil {
 		c.Fatal(err)
 	}
 	defer git.Close()
 
 	u := fmt.Sprintf("%s#master:docker", git.RepoURL)
 	_, err = buildImageFromPath(name, u, true)
 	if err != nil {
 		c.Fatal(err)
 	}
 	res, err := inspectField(name, "Author")
 	if err != nil {
 		c.Fatal(err)
 	}
 	if res != "docker" {
 		c.Fatalf("Maintainer should be docker, got %s", res)
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
1b6546b8
 	name := "testbuildcmdcleanuponentrypoint"
 	if _, err := buildImage(name,
 		`FROM scratch
         CMD ["test"]
 		ENTRYPOINT ["echo"]`,
 		true); err != nil {
dc944ea7
 		c.Fatal(err)
1b6546b8
 	}
 	if _, err := buildImage(name,
 		fmt.Sprintf(`FROM %s
 		ENTRYPOINT ["cat"]`, name),
 		true); err != nil {
dc944ea7
 		c.Fatal(err)
1b6546b8
 	}
 	res, err := inspectField(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1b6546b8
 	}
231d362d
 	if res != "<nil>" {
 		c.Fatalf("Cmd %s, expected nil", res)
1b6546b8
 	}
231d362d
 
1b6546b8
 	res, err = inspectField(name, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
1b6546b8
 	}
231d362d
 	if expected := "{[cat]}"; res != expected {
dc944ea7
 		c.Fatalf("Entrypoint %s, expected %s", res, expected)
1b6546b8
 	}
 }
ac107995
 
dc944ea7
 func (s *DockerSuite) TestBuildClearCmd(c *check.C) {
ac107995
 	name := "testbuildclearcmd"
 	_, err := buildImage(name,
 		`From scratch
    ENTRYPOINT ["/bin/bash"]
    CMD []`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ac107995
 	}
 	res, err := inspectFieldJSON(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
ac107995
 	}
 	if res != "[]" {
dc944ea7
 		c.Fatalf("Cmd %s, expected %s", res, "[]")
ac107995
 	}
 }
d1613e1d
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) {
d1613e1d
 	name := "testbuildemptycmd"
 	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
d1613e1d
 	}
 	res, err := inspectFieldJSON(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
d1613e1d
 	}
 	if res != "null" {
dc944ea7
 		c.Fatalf("Cmd %s, expected %s", res, "null")
d1613e1d
 	}
 }
8edacc67
 
dc944ea7
 func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) {
8edacc67
 	name := "testbuildonbuildparent"
 	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
8edacc67
 	}
 
 	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
8edacc67
 	}
 
1150c163
 	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
dc944ea7
 		c.Fatal("failed to find the ONBUILD output", out)
8edacc67
 	}
 
 }
8833d800
 
dc944ea7
 func (s *DockerSuite) TestBuildInvalidTag(c *check.C) {
b80fae73
 	name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200)
8833d800
 	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
 	// if the error doesnt check for illegal tag name, or the image is built
 	// then this should fail
de32f48e
 	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
dc944ea7
 		c.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
8833d800
 	}
 }
9f142bf9
 
dc944ea7
 func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) {
9f142bf9
 	name := "testbuildcmdshc"
 	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
9f142bf9
 	}
 
 	res, err := inspectFieldJSON(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err, res)
9f142bf9
 	}
 
 	expected := `["/bin/sh","-c","echo cmd"]`
 
 	if res != expected {
dc944ea7
 		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
9f142bf9
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) {
88905793
 	// Test to make sure that when we strcat arrays we take into account
 	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
 	// look the same
 	name := "testbuildcmdspaces"
 	var id1 string
 	var id2 string
 	var err error
 
 	if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
88905793
 	}
 
 	if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
88905793
 	}
 
 	if id1 == id2 {
dc944ea7
 		c.Fatal("Should not have resulted in the same CMD")
88905793
 	}
 
 	// Now do the same with ENTRYPOINT
 	if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
88905793
 	}
 
 	if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil {
dc944ea7
 		c.Fatal(err)
88905793
 	}
 
 	if id1 == id2 {
dc944ea7
 		c.Fatal("Should not have resulted in the same ENTRYPOINT")
88905793
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) {
9f142bf9
 	name := "testbuildcmdjson"
 	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
dc944ea7
 		c.Fatal(err)
9f142bf9
 	}
 
 	res, err := inspectFieldJSON(name, "Config.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err, res)
9f142bf9
 	}
 
 	expected := `["echo","cmd"]`
 
 	if res != expected {
dc944ea7
 		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
9f142bf9
 	}
 
 }
9fe1dd31
 
dc944ea7
 func (s *DockerSuite) TestBuildErrorInvalidInstruction(c *check.C) {
9fe1dd31
 	name := "testbuildignoreinvalidinstruction"
 
 	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
8a5b50d6
 	if err == nil {
dc944ea7
 		c.Fatalf("Should have failed: %s", out)
9fe1dd31
 	}
 
 }
50fa9dff
 
dc944ea7
 func (s *DockerSuite) TestBuildEntrypointInheritance(c *check.C) {
50fa9dff
 
 	if _, err := buildImage("parent", `
     FROM busybox
     ENTRYPOINT exit 130
     `, true); err != nil {
dc944ea7
 		c.Fatal(err)
50fa9dff
 	}
 
 	status, _ := runCommand(exec.Command(dockerBinary, "run", "parent"))
 
 	if status != 130 {
dc944ea7
 		c.Fatalf("expected exit code 130 but received %d", status)
50fa9dff
 	}
 
 	if _, err := buildImage("child", `
     FROM parent
     ENTRYPOINT exit 5
     `, true); err != nil {
dc944ea7
 		c.Fatal(err)
50fa9dff
 	}
 
 	status, _ = runCommand(exec.Command(dockerBinary, "run", "child"))
 
 	if status != 5 {
dc944ea7
 		c.Fatalf("expected exit code 5 but received %d", status)
50fa9dff
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildEntrypointInheritanceInspect(c *check.C) {
50fa9dff
 	var (
 		name     = "testbuildepinherit"
 		name2    = "testbuildepinherit2"
 		expected = `["/bin/sh","-c","echo quux"]`
 	)
 
 	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
dc944ea7
 		c.Fatal(err)
50fa9dff
 	}
 
 	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
dc944ea7
 		c.Fatal(err)
50fa9dff
 	}
 
 	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
 	if err != nil {
dc944ea7
 		c.Fatal(err, res)
50fa9dff
 	}
 
 	if res != expected {
dc944ea7
 		c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
50fa9dff
 	}
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
 	if err != nil {
dc944ea7
 		c.Fatal(err, out)
50fa9dff
 	}
 
 	expected = "quux"
 
 	if strings.TrimSpace(out) != expected {
dc944ea7
 		c.Fatalf("Expected output is %s, got %s", expected, out)
50fa9dff
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) {
50fa9dff
 	name := "testbuildentrypoint"
 	_, err := buildImage(name,
 		`FROM busybox
                                 ENTRYPOINT /bin/echo`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
50fa9dff
 	}
 
da3d3b97
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
50fa9dff
 
 	if err != nil {
dc944ea7
 		c.Fatal(err, out)
50fa9dff
 	}
 
 }
24189b2c
 
dc944ea7
 func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) {
24189b2c
 	name := "testbuildexoticshellinterpolation"
 
 	_, err := buildImage(name, `
 		FROM busybox
f3680e74
 
24189b2c
 		ENV SOME_VAR a.b.c
 
 		RUN [ "$SOME_VAR"       = 'a.b.c' ]
 		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
 		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
 		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
 		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
 		RUN [ "${SOME_VAR##*.}" = 'c'     ]
 		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
 		RUN [ "${#SOME_VAR}"    = '5'     ]
 
 		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
 		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
 		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
 		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
 	`, false)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
24189b2c
 	}
 
 }
9edf9678
 
dc944ea7
 func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) {
9edf9678
 	// This testcase is supposed to generate an error because the
 	// JSON array we're passing in on the CMD uses single quotes instead
 	// of double quotes (per the JSON spec). This means we interpret it
 	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
 	// it should barf on it.
 	name := "testbuildsinglequotefails"
 
 	_, err := buildImage(name,
 		`FROM busybox
 		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
 		true)
da3d3b97
 	_, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
9edf9678
 
 	if err == nil {
dc944ea7
 		c.Fatal("The image was not supposed to be able to run")
9edf9678
 	}
 
 }
6f09d064
 
dc944ea7
 func (s *DockerSuite) TestBuildVerboseOut(c *check.C) {
6f09d064
 	name := "testbuildverboseout"
 
 	_, out, err := buildImageWithOut(name,
 		`FROM busybox
 RUN echo 123`,
 		false)
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
6f09d064
 	}
 	if !strings.Contains(out, "\n123\n") {
dc944ea7
 		c.Fatalf("Output should contain %q: %q", "123", out)
6f09d064
 	}
 
 }
c980fe09
 
dc944ea7
 func (s *DockerSuite) TestBuildWithTabs(c *check.C) {
c980fe09
 	name := "testbuildwithtabs"
 	_, err := buildImage(name,
 		"FROM busybox\nRUN echo\tone\t\ttwo", true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c980fe09
 	}
 	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
c980fe09
 	}
14236945
 	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
 	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
 	if res != expected1 && res != expected2 {
dc944ea7
 		c.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
c980fe09
 	}
 }
5c91bb93
 
dc944ea7
 func (s *DockerSuite) TestBuildLabels(c *check.C) {
cdfdfbfb
 	name := "testbuildlabel"
 	expected := `{"License":"GPL","Vendor":"Acme"}`
 	_, err := buildImage(name,
 		`FROM busybox
 		LABEL Vendor=Acme
                 LABEL License GPL`,
 		true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdfdfbfb
 	}
 	res, err := inspectFieldJSON(name, "Config.Labels")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cdfdfbfb
 	}
 	if res != expected {
dc944ea7
 		c.Fatalf("Labels %s, expected %s", res, expected)
cdfdfbfb
 	}
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
97c573bf
 	name := "testbuildlabelcache"
 
 	id1, err := buildImage(name,
 		`FROM busybox
 		LABEL Vendor=Acme`, false)
 	if err != nil {
dc944ea7
 		c.Fatalf("Build 1 should have worked: %v", err)
97c573bf
 	}
 
 	id2, err := buildImage(name,
 		`FROM busybox
 		LABEL Vendor=Acme`, true)
 	if err != nil || id1 != id2 {
dc944ea7
 		c.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
97c573bf
 	}
 
 	id2, err = buildImage(name,
 		`FROM busybox
 		LABEL Vendor=Acme1`, true)
 	if err != nil || id1 == id2 {
dc944ea7
 		c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
97c573bf
 	}
 
 	id2, err = buildImage(name,
 		`FROM busybox
 		LABEL Vendor Acme`, true) // Note: " " and "=" should be same
 	if err != nil || id1 != id2 {
dc944ea7
 		c.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
b4beb063
 	}
 
 	// Now make sure the cache isn't used by mistake
 	id1, err = buildImage(name,
 		`FROM busybox
        LABEL f1=b1 f2=b2`, false)
 	if err != nil {
dc944ea7
 		c.Fatalf("Build 5 should have worked: %q", err)
b4beb063
 	}
 
 	id2, err = buildImage(name,
 		`FROM busybox
        LABEL f1="b1 f2=b2"`, true)
 	if err != nil || id1 == id2 {
dc944ea7
 		c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
97c573bf
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildStderr(c *check.C) {
5c91bb93
 	// This test just makes sure that no non-error output goes
 	// to stderr
 	name := "testbuildstderr"
 	_, _, stderr, err := buildImageWithStdoutStderr(name,
 		"FROM busybox\nRUN echo one", true)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
5c91bb93
 	}
4a8b3cad
 
 	if runtime.GOOS == "windows" {
 		// stderr might contain a security warning on windows
 		lines := strings.Split(stderr, "\n")
 		for _, v := range lines {
 			if v != "" && !strings.Contains(v, "SECURITY WARNING:") {
dc944ea7
 				c.Fatalf("Stderr contains unexpected output line: %q", v)
4a8b3cad
 			}
 		}
 	} else {
 		if stderr != "" {
dc944ea7
 			c.Fatalf("Stderr should have been empty, instead its: %q", stderr)
4a8b3cad
 		}
5c91bb93
 	}
 }
cfc24769
 
dc944ea7
 func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) {
 	testRequires(c, UnixCli) // test uses chown: not available on windows
492a58f0
 
cfc24769
 	name := "testbuildchownsinglefile"
 
 	ctx, err := fakeContext(`
 FROM busybox
 COPY test /
 RUN ls -l /test
 RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
 `, map[string]string{
 		"test": "test",
 	})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
cfc24769
 	}
 	defer ctx.Close()
 
 	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
dc944ea7
 		c.Fatal(err)
cfc24769
 	}
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
cfc24769
 	}
 
 }
0e71a48d
 
dc944ea7
 func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
0e71a48d
 	name := "testbuildsymlinkbreakout"
 	tmpdir, err := ioutil.TempDir("", name)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	defer os.RemoveAll(tmpdir)
 	ctx := filepath.Join(tmpdir, "context")
 	if err := os.MkdirAll(ctx, 0755); err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
 	from busybox
 	add symlink.tar /
 	add inject /symlink/
 	`), 0644); err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	inject := filepath.Join(ctx, "inject")
 	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
 	if err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	w := tar.NewWriter(f)
 	w.WriteHeader(&tar.Header{
 		Name:     "symlink2",
 		Typeflag: tar.TypeSymlink,
 		Linkname: "/../../../../../../../../../../../../../../",
 		Uid:      os.Getuid(),
 		Gid:      os.Getgid(),
 	})
 	w.WriteHeader(&tar.Header{
 		Name:     "symlink",
 		Typeflag: tar.TypeSymlink,
 		Linkname: filepath.Join("symlink2", tmpdir),
 		Uid:      os.Getuid(),
 		Gid:      os.Getgid(),
 	})
 	w.Close()
 	f.Close()
44ffb199
 	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
dc944ea7
 		c.Fatal(err)
0e71a48d
 	}
 	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
dc944ea7
 		c.Fatal("symlink breakout - inject")
0e71a48d
 	} else if !os.IsNotExist(err) {
dc944ea7
 		c.Fatalf("unexpected error: %v", err)
0e71a48d
 	}
 }
af202195
 
dc944ea7
 func (s *DockerSuite) TestBuildXZHost(c *check.C) {
af202195
 	name := "testbuildxzhost"
 
 	ctx, err := fakeContext(`
 FROM busybox
 ADD xz /usr/local/sbin/
 RUN chmod 755 /usr/local/sbin/xz
 ADD test.xz /
 RUN [ ! -e /injected ]`,
 		map[string]string{
 			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
 				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
 				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
 			"xz": "#!/bin/sh\ntouch /injected",
 		})
 
 	if err != nil {
dc944ea7
 		c.Fatal(err)
af202195
 	}
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, true); err != nil {
dc944ea7
 		c.Fatal(err)
af202195
 	}
 
 }
4856ec07
 
dc944ea7
 func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
4856ec07
 	var (
 		name     = "testbuildvolumescontent"
 		expected = "some text"
 	)
 	ctx, err := fakeContext(`
 FROM busybox
 COPY content /foo/file
 VOLUME /foo
 CMD cat /foo/file`,
 		map[string]string{
 			"content": expected,
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4856ec07
 	}
 	defer ctx.Close()
 
 	if _, err := buildImageFromContext(name, ctx, false); err != nil {
dc944ea7
 		c.Fatal(err)
4856ec07
 	}
 
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
 	if err != nil {
dc944ea7
 		c.Fatal(err)
4856ec07
 	}
 	if out != expected {
dc944ea7
 		c.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
4856ec07
 	}
 
 }
eb3ea3b4
 
dc944ea7
 func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
eb3ea3b4
 
 	ctx, err := fakeContext(`FROM busybox
 	RUN echo from Dockerfile`,
 		map[string]string{
 			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
 			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
 			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
 			"dFile":            "FROM busybox\nRUN echo from dFile",
c42d2625
 			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
eb3ea3b4
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatalf("Failed to build: %s\n%s", out, err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from Dockerfile") {
dc944ea7
 		c.Fatalf("test1 should have used Dockerfile, output:%s", out)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatal(err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from files/Dockerfile") {
dc944ea7
 		c.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatal(err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from files/dFile") {
dc944ea7
 		c.Fatalf("test3 should have used files/dFile, output:%s", out)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatal(err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from dFile") {
dc944ea7
 		c.Fatalf("test4 should have used dFile, output:%s", out)
eb3ea3b4
 	}
 
967d85a2
 	dirWithNoDockerfile, _ := ioutil.TempDir(os.TempDir(), "test5")
 	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
 	if _, err = os.Create(nonDockerfileFile); err != nil {
dc944ea7
 		c.Fatal(err)
967d85a2
 	}
dc944ea7
 	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
967d85a2
 
eb3ea3b4
 	if err == nil {
dc944ea7
 		c.Fatalf("test5 was supposed to fail to find passwd")
eb3ea3b4
 	}
967d85a2
 
0024935f
 	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) {
dc944ea7
 		c.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatalf("test6 failed: %s", err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from Dockerfile") {
dc944ea7
 		c.Fatalf("test6 should have used root Dockerfile, output:%s", out)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatalf("test7 failed: %s", err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from files/Dockerfile") {
dc944ea7
 		c.Fatalf("test7 should have used files Dockerfile, output:%s", out)
eb3ea3b4
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
eb3ea3b4
 	if err == nil || !strings.Contains(out, "must be within the build context") {
dc944ea7
 		c.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
eb3ea3b4
 	}
 
c42d2625
 	tmpDir := os.TempDir()
dc944ea7
 	out, _, err = dockerCmdInDir(c, tmpDir, "build", "-t", "test9", ctx.Dir)
eb3ea3b4
 	if err != nil {
dc944ea7
 		c.Fatalf("test9 - failed: %s", err)
eb3ea3b4
 	}
 	if !strings.Contains(out, "from Dockerfile") {
dc944ea7
 		c.Fatalf("test9 should have used root Dockerfile, output:%s", out)
c42d2625
 	}
 
dc944ea7
 	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
c42d2625
 	if err != nil {
dc944ea7
 		c.Fatalf("test10 should have worked: %s", err)
c42d2625
 	}
 	if !strings.Contains(out, "from files/dFile2") {
dc944ea7
 		c.Fatalf("test10 should have used files/dFile2, output:%s", out)
eb3ea3b4
 	}
 
 }
568f86eb
 
dc944ea7
 func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) {
 	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
15924f23
 
 	ctx, err := fakeContext(`FROM busybox
 	RUN echo from dockerfile`,
 		map[string]string{
 			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
15924f23
 	}
 
dc944ea7
 	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
15924f23
 	if err != nil {
dc944ea7
 		c.Fatalf("Failed to build: %s\n%s", out, err)
15924f23
 	}
 
 	if !strings.Contains(out, "from dockerfile") {
dc944ea7
 		c.Fatalf("Missing proper output: %s", out)
15924f23
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildWithTwoDockerfiles(c *check.C) {
 	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
15924f23
 
 	ctx, err := fakeContext(`FROM busybox
 RUN echo from Dockerfile`,
 		map[string]string{
 			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
 		})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
15924f23
 	}
 
dc944ea7
 	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
15924f23
 	if err != nil {
dc944ea7
 		c.Fatalf("Failed to build: %s\n%s", out, err)
15924f23
 	}
 
 	if !strings.Contains(out, "from Dockerfile") {
dc944ea7
 		c.Fatalf("Missing proper output: %s", out)
15924f23
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) {
15924f23
 
 	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
 RUN echo from baz
 COPY * /tmp/
 RUN find /tmp/`})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
15924f23
 	}
 	defer server.Close()
 
 	ctx, err := fakeContext(`FROM busybox
 RUN echo from Dockerfile`,
 		map[string]string{})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
15924f23
 	}
 
 	// Make sure that -f is ignored and that we don't use the Dockerfile
 	// that's in the current dir
dc944ea7
 	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz")
15924f23
 	if err != nil {
dc944ea7
 		c.Fatalf("Failed to build: %s\n%s", out, err)
15924f23
 	}
 
 	if !strings.Contains(out, "from baz") ||
 		strings.Contains(out, "/tmp/baz") ||
 		!strings.Contains(out, "/tmp/Dockerfile") {
dc944ea7
 		c.Fatalf("Missing proper output: %s", out)
15924f23
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildFromStdinWithF(c *check.C) {
15924f23
 
 	ctx, err := fakeContext(`FROM busybox
 RUN echo from Dockerfile`,
 		map[string]string{})
 	defer ctx.Close()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
15924f23
 	}
 
 	// Make sure that -f is ignored and that we don't use the Dockerfile
 	// that's in the current dir
 	dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-")
 	dockerCommand.Dir = ctx.Dir
 	dockerCommand.Stdin = strings.NewReader(`FROM busybox
 RUN echo from baz
 COPY * /tmp/
 RUN find /tmp/`)
 	out, status, err := runCommandWithOutput(dockerCommand)
 	if err != nil || status != 0 {
dc944ea7
 		c.Fatalf("Error building: %s", err)
15924f23
 	}
 
 	if !strings.Contains(out, "from baz") ||
 		strings.Contains(out, "/tmp/baz") ||
 		!strings.Contains(out, "/tmp/Dockerfile") {
dc944ea7
 		c.Fatalf("Missing proper output: %s", out)
15924f23
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) {
568f86eb
 	name := "testbuildfromofficial"
 	fromNames := []string{
 		"busybox",
 		"docker.io/busybox",
 		"index.docker.io/busybox",
 		"library/busybox",
 		"docker.io/library/busybox",
 		"index.docker.io/library/busybox",
 	}
 	for idx, fromName := range fromNames {
 		imgName := fmt.Sprintf("%s%d", name, idx)
 		_, err := buildImage(imgName, "FROM "+fromName, true)
 		if err != nil {
dc944ea7
 			c.Errorf("Build failed using FROM %s: %s", fromName, err)
568f86eb
 		}
 		deleteImages(imgName)
 	}
 }
73d5baf5
 
dc944ea7
 func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) {
 	testRequires(c, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
492a58f0
 
73d5baf5
 	name := "testbuilddockerfileoutsidecontext"
 	tmpdir, err := ioutil.TempDir("", name)
 	if err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
 	defer os.RemoveAll(tmpdir)
 	ctx := filepath.Join(tmpdir, "context")
 	if err := os.MkdirAll(ctx, 0755); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
c42d2625
 	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
 	wd, err := os.Getwd()
 	if err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
 	defer os.Chdir(wd)
 	if err := os.Chdir(ctx); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
c42d2625
 	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
4581240e
 	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
 	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
dc944ea7
 		c.Fatal(err)
73d5baf5
 	}
4581240e
 
73d5baf5
 	for _, dockerfilePath := range []string{
4581240e
 		filepath.Join("..", "outsideDockerfile"),
73d5baf5
 		filepath.Join(ctx, "dockerfile1"),
 		filepath.Join(ctx, "dockerfile2"),
 	} {
 		out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
 		if err == nil {
dc944ea7
 			c.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
73d5baf5
 		}
c42d2625
 		if !strings.Contains(out, "must be within the build context") && !strings.Contains(out, "Cannot locate Dockerfile") {
dc944ea7
 			c.Fatalf("Unexpected error with %s. Out: %s", dockerfilePath, out)
c42d2625
 		}
73d5baf5
 		deleteImages(name)
 	}
 
 	os.Chdir(tmpdir)
 
 	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
 	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
 	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
 	if err == nil {
dc944ea7
 		c.Fatalf("Expected error. Out: %s", out)
73d5baf5
 	}
 }
3859c485
 
dc944ea7
 func (s *DockerSuite) TestBuildSpaces(c *check.C) {
3859c485
 	// Test to make sure that leading/trailing spaces on a command
 	// doesn't change the error msg we get
 	var (
 		err1 error
 		err2 error
 	)
 
 	name := "testspaces"
d1e9d07c
 	ctx, err := fakeContext("FROM busybox\nCOPY\n",
3859c485
 		map[string]string{
d1e9d07c
 			"Dockerfile": "FROM busybox\nCOPY\n",
3859c485
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
3859c485
 	}
 	defer ctx.Close()
 
 	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
dc944ea7
 		c.Fatal("Build 1 was supposed to fail, but didn't")
3859c485
 	}
 
d1e9d07c
 	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
3859c485
 	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
dc944ea7
 		c.Fatal("Build 2 was supposed to fail, but didn't")
3859c485
 	}
 
28a34dff
 	removeLogTimestamps := func(s string) string {
 		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
 	}
 
3859c485
 	// Skip over the times
28a34dff
 	e1 := removeLogTimestamps(err1.Error())
 	e2 := removeLogTimestamps(err2.Error())
3859c485
 
 	// Ignore whitespace since that's what were verifying doesn't change stuff
 	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
dc944ea7
 		c.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
3859c485
 	}
 
d1e9d07c
 	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
3859c485
 	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
dc944ea7
 		c.Fatal("Build 3 was supposed to fail, but didn't")
3859c485
 	}
 
 	// Skip over the times
28a34dff
 	e1 = removeLogTimestamps(err1.Error())
 	e2 = removeLogTimestamps(err2.Error())
3859c485
 
 	// Ignore whitespace since that's what were verifying doesn't change stuff
 	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
dc944ea7
 		c.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
3859c485
 	}
 
d1e9d07c
 	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
3859c485
 	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
dc944ea7
 		c.Fatal("Build 4 was supposed to fail, but didn't")
3859c485
 	}
 
 	// Skip over the times
28a34dff
 	e1 = removeLogTimestamps(err1.Error())
 	e2 = removeLogTimestamps(err2.Error())
3859c485
 
 	// Ignore whitespace since that's what were verifying doesn't change stuff
 	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
dc944ea7
 		c.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
3859c485
 	}
 
 }
 
dc944ea7
 func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) {
3859c485
 	// Test to make sure that spaces in quotes aren't lost
 	name := "testspacesquotes"
 
 	dockerfile := `FROM busybox
 RUN echo "  \
   foo  "`
 
 	_, out, err := buildImageWithOut(name, dockerfile, false)
 	if err != nil {
dc944ea7
 		c.Fatal("Build failed:", err)
3859c485
 	}
 
 	expecting := "\n    foo  \n"
 	if !strings.Contains(out, expecting) {
3941623f
 		c.Fatalf("Bad output: %q expecting to contain %q", out, expecting)
3859c485
 	}
 
 }
c73e3bf4
 
 // #4393
dc944ea7
 func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) {
c73e3bf4
 	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-")
 	buildCmd.Stdin = strings.NewReader(`
 	FROM busybox
 	RUN touch /foo
 	VOLUME /foo
 	`)
 
 	out, _, err := runCommandWithOutput(buildCmd)
 	if err == nil || !strings.Contains(out, "file exists") {
dc944ea7
 		c.Fatalf("expected build to fail when file exists in container at requested volume path")
c73e3bf4
 	}
 
 }
e4f02abb
 
dc944ea7
 func (s *DockerSuite) TestBuildMissingArgs(c *check.C) {
d1e9d07c
 	// Test to make sure that all Dockerfile commands (except the ones listed
 	// in skipCmds) will generate an error if no args are provided.
 	// Note: INSERT is deprecated so we exclude it because of that.
 	skipCmds := map[string]struct{}{
 		"CMD":        {},
 		"RUN":        {},
 		"ENTRYPOINT": {},
 		"INSERT":     {},
e4f02abb
 	}
 
6ecf2386
 	for cmd := range command.Commands {
d1e9d07c
 		cmd = strings.ToUpper(cmd)
 		if _, ok := skipCmds[cmd]; ok {
 			continue
 		}
 
ccde3a1f
 		var dockerfile string
e4f02abb
 		if cmd == "FROM" {
 			dockerfile = cmd
 		} else {
 			// Add FROM to make sure we don't complain about it missing
 			dockerfile = "FROM busybox\n" + cmd
 		}
 
 		ctx, err := fakeContext(dockerfile, map[string]string{})
 		if err != nil {
dc944ea7
 			c.Fatal(err)
e4f02abb
 		}
 		defer ctx.Close()
 		var out string
 		if out, err = buildImageFromContext("args", ctx, true); err == nil {
dc944ea7
 			c.Fatalf("%s was supposed to fail. Out:%s", cmd, out)
e4f02abb
 		}
 		if !strings.Contains(err.Error(), cmd+" requires") {
dc944ea7
 			c.Fatalf("%s returned the wrong type of error:%s", cmd, err)
e4f02abb
 		}
 	}
 
 }
1654dfdf
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) {
1654dfdf
 	_, out, err := buildImageWithOut("sc", "FROM scratch", true)
 	if err == nil {
dc944ea7
 		c.Fatalf("Build was supposed to fail")
1654dfdf
 	}
 	if !strings.Contains(out, "No image was generated") {
dc944ea7
 		c.Fatalf("Wrong error message: %v", out)
1654dfdf
 	}
 }
0826ac15
 
dc944ea7
 func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
0826ac15
 	ctx, err := fakeContext("FROM busybox\n",
 		map[string]string{
 			"..gitme": "",
 		})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
0826ac15
 	}
 	defer ctx.Close()
 
 	if _, err = buildImageFromContext("sc", ctx, false); err != nil {
dc944ea7
 		c.Fatalf("Build was supposed to work: %s", err)
0826ac15
 	}
 }
92c35358
 
dc944ea7
 func (s *DockerSuite) TestBuildNotVerbose(c *check.C) {
92c35358
 
 	ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
92c35358
 	}
 	defer ctx.Close()
 
 	// First do it w/verbose - baseline
 	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", "verbose", ".")
 	buildCmd.Dir = ctx.Dir
 	out, _, err := runCommandWithOutput(buildCmd)
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
92c35358
 	}
 	if !strings.Contains(out, "hi there") {
dc944ea7
 		c.Fatalf("missing output:%s\n", out)
92c35358
 	}
 
 	// Now do it w/o verbose
 	buildCmd = exec.Command(dockerBinary, "build", "--no-cache", "-q", "-t", "verbose", ".")
 	buildCmd.Dir = ctx.Dir
 	out, _, err = runCommandWithOutput(buildCmd)
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
92c35358
 	}
 	if strings.Contains(out, "hi there") {
dc944ea7
 		c.Fatalf("Bad output, should not contain 'hi there':%s", out)
92c35358
 	}
 
 }
645f8a32
 
dc944ea7
 func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
645f8a32
 	name := "testbuildrunonejson"
 
636037c3
 	ctx, err := fakeContext(`FROM hello-world:frozen
645f8a32
 RUN [ "/hello" ]`, map[string]string{})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
645f8a32
 	}
 	defer ctx.Close()
 
 	buildCmd := exec.Command(dockerBinary, "build", "--no-cache", "-t", name, ".")
 	buildCmd.Dir = ctx.Dir
 	out, _, err := runCommandWithOutput(buildCmd)
 	if err != nil {
dc944ea7
 		c.Fatalf("failed to build the image: %s, %v", out, err)
645f8a32
 	}
 
 	if !strings.Contains(out, "Hello from Docker") {
dc944ea7
 		c.Fatalf("bad output: %s", out)
645f8a32
 	}
 
 }
e6ae89a4
 
dc944ea7
 func (s *DockerSuite) TestBuildResourceConstraintsAreUsed(c *check.C) {
e6ae89a4
 	name := "testbuildresourceconstraints"
 
 	ctx, err := fakeContext(`
 	FROM hello-world:frozen
 	RUN ["/hello"]
 	`, map[string]string{})
 	if err != nil {
dc944ea7
 		c.Fatal(err)
e6ae89a4
 	}
 
5f4fb8be
 	cmd := exec.Command(dockerBinary, "build", "--no-cache", "--rm=false", "--memory=64m", "--memory-swap=-1", "--cpuset-cpus=0", "--cpuset-mems=0", "--cpu-shares=100", "--cpu-quota=8000", "-t", name, ".")
e6ae89a4
 	cmd.Dir = ctx.Dir
 
 	out, _, err := runCommandWithOutput(cmd)
 	if err != nil {
dc944ea7
 		c.Fatal(err, out)
e6ae89a4
 	}
dc944ea7
 	out, _ = dockerCmd(c, "ps", "-lq")
e6ae89a4
 
475c6531
 	cID := strings.TrimSpace(out)
e6ae89a4
 
 	type hostConfig struct {
b0ef3194
 		Memory     int64
 		MemorySwap int64
e6ae89a4
 		CpusetCpus string
f8dc7e87
 		CpusetMems string
b0ef3194
 		CpuShares  int64
5f4fb8be
 		CpuQuota   int64
e6ae89a4
 	}
 
 	cfg, err := inspectFieldJSON(cID, "HostConfig")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
e6ae89a4
 	}
 
 	var c1 hostConfig
 	if err := json.Unmarshal([]byte(cfg), &c1); err != nil {
dc944ea7
 		c.Fatal(err, cfg)
e6ae89a4
 	}
5f4fb8be
 	if c1.Memory != 67108864 || c1.MemorySwap != -1 || c1.CpusetCpus != "0" || c1.CpusetMems != "0" || c1.CpuShares != 100 || c1.CpuQuota != 8000 {
 		c.Fatalf("resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d",
 			c1.Memory, c1.MemorySwap, c1.CpusetCpus, c1.CpusetMems, c1.CpuShares, c1.CpuQuota)
e6ae89a4
 	}
 
 	// Make sure constraints aren't saved to image
dc944ea7
 	_, _ = dockerCmd(c, "run", "--name=test", name)
621b601b
 
e6ae89a4
 	cfg, err = inspectFieldJSON("test", "HostConfig")
 	if err != nil {
dc944ea7
 		c.Fatal(err)
e6ae89a4
 	}
 	var c2 hostConfig
 	if err := json.Unmarshal([]byte(cfg), &c2); err != nil {
dc944ea7
 		c.Fatal(err, cfg)
e6ae89a4
 	}
5f4fb8be
 	if c2.Memory == 67108864 || c2.MemorySwap == -1 || c2.CpusetCpus == "0" || c2.CpusetMems == "0" || c2.CpuShares == 100 || c2.CpuQuota == 8000 {
 		c.Fatalf("resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d",
 			c2.Memory, c2.MemorySwap, c2.CpusetCpus, c2.CpusetMems, c2.CpuShares, c2.CpuQuota)
e6ae89a4
 	}
 
 }
8071bf39
 
dc944ea7
 func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
8071bf39
 	name := "testbuildemptystringvolume"
 
 	_, err := buildImage(name, `
   FROM busybox
   ENV foo=""
   VOLUME $foo
   `, false)
 	if err == nil {
dc944ea7
 		c.Fatal("Should have failed to build")
8071bf39
 	}
 
 }
f40dd69c
 
9dbe12b7
 func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
 	testRequires(c, NativeExecDriver)
 	testRequires(c, SameHostDaemon)
f40dd69c
 	defer deleteImages()
 
 	cgroupParent := "test"
 	data, err := ioutil.ReadFile("/proc/self/cgroup")
 	if err != nil {
9dbe12b7
 		c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
f40dd69c
 	}
 	selfCgroupPaths := parseCgroupPaths(string(data))
 	_, found := selfCgroupPaths["memory"]
 	if !found {
9dbe12b7
 		c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
f40dd69c
 	}
f039c699
 	cmd := exec.Command(dockerBinary, "build", "--cgroup-parent", cgroupParent, "-")
f40dd69c
 	cmd.Stdin = strings.NewReader(`
 FROM busybox
 RUN cat /proc/self/cgroup
 `)
 
 	out, _, err := runCommandWithOutput(cmd)
 	if err != nil {
9dbe12b7
 		c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
f40dd69c
 	}
 }
08b7f30f
 
 func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
 	// Check to make sure our build output prints the Dockerfile cmd
 	// property - there was a bug that caused it to be duplicated on the
 	// Step X  line
 	name := "testbuildnodupoutput"
 
 	_, out, err := buildImageWithOut(name, `
   FROM busybox
   RUN env`, false)
 	if err != nil {
 		c.Fatalf("Build should have worked: %q", err)
 	}
 
 	exp := "\nStep 1 : RUN env\n"
 	if !strings.Contains(out, exp) {
 		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
 	}
 }
 
 func (s *DockerSuite) TestBuildBadCmdFlag(c *check.C) {
 	name := "testbuildbadcmdflag"
 
 	_, out, err := buildImageWithOut(name, `
   FROM busybox
   MAINTAINER --boo joe@example.com`, false)
 	if err == nil {
 		c.Fatal("Build should have failed")
 	}
 
0024935f
 	exp := "\nUnknown flag: boo\n"
08b7f30f
 	if !strings.Contains(out, exp) {
 		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
 	}
 }
54662eae
 
 func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
 	// Test to make sure the bad command is quoted with just "s and
 	// not as a Go []string
 	name := "testbuildbadrunerrmsg"
 	_, out, err := buildImageWithOut(name, `
   FROM busybox
006c066b
   RUN badEXE a1 \& a2	a3`, false) // tab between a2 and a3
54662eae
 	if err == nil {
 		c.Fatal("Should have failed to build")
 	}
 
0024935f
 	exp := `The command '/bin/sh -c badEXE a1 \& a2	a3' returned a non-zero code: 127`
54662eae
 	if !strings.Contains(out, exp) {
 		c.Fatalf("RUN doesn't have the correct output:\nGot:%s\nExpected:%s", out, exp)
 	}
 }