github.com/flavio/docker@v0.1.3-0.20170117145210-f63d1a6eec47/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"reflect"
    13  	"regexp"
    14  	"runtime"
    15  	"strconv"
    16  	"strings"
    17  	"text/template"
    18  	"time"
    19  
    20  	"github.com/docker/docker/builder/dockerfile/command"
    21  	"github.com/docker/docker/integration-cli/checker"
    22  	"github.com/docker/docker/pkg/archive"
    23  	"github.com/docker/docker/pkg/stringutils"
    24  	"github.com/docker/docker/pkg/testutil"
    25  	icmd "github.com/docker/docker/pkg/testutil/cmd"
    26  	"github.com/go-check/check"
    27  )
    28  
    29  func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) {
    30  	buildImageSuccessfully(c, "testbuildjsonemptyrun", withDockerfile(`
    31      FROM busybox
    32      RUN []
    33      `))
    34  }
    35  
    36  func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) {
    37  	name := "testbuildshcmdjsonentrypoint"
    38  	expected := "/bin/sh -c echo test"
    39  	if testEnv.DaemonPlatform() == "windows" {
    40  		expected = "cmd /S /C echo test"
    41  	}
    42  
    43  	buildImageSuccessfully(c, name, withDockerfile(`
    44      FROM busybox
    45      ENTRYPOINT ["echo"]
    46      CMD echo test
    47      `))
    48  	out, _ := dockerCmd(c, "run", "--rm", name)
    49  
    50  	if strings.TrimSpace(out) != expected {
    51  		c.Fatalf("CMD did not contain %q : %q", expected, out)
    52  	}
    53  }
    54  
    55  func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) {
    56  	// Windows does not support FROM scratch or the USER command
    57  	testRequires(c, DaemonIsLinux)
    58  	name := "testbuildenvironmentreplacement"
    59  
    60  	buildImageSuccessfully(c, name, withDockerfile(`
    61    FROM scratch
    62    ENV user foo
    63    USER ${user}
    64    `))
    65  	res := inspectFieldJSON(c, name, "Config.User")
    66  
    67  	if res != `"foo"` {
    68  		c.Fatal("User foo from environment not in Config.User on image")
    69  	}
    70  }
    71  
    72  func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) {
    73  	name := "testbuildenvironmentreplacement"
    74  
    75  	var volumePath string
    76  
    77  	if testEnv.DaemonPlatform() == "windows" {
    78  		volumePath = "c:/quux"
    79  	} else {
    80  		volumePath = "/quux"
    81  	}
    82  
    83  	buildImageSuccessfully(c, name, withDockerfile(`
    84    FROM `+minimalBaseImage()+`
    85    ENV volume `+volumePath+`
    86    VOLUME ${volume}
    87    `))
    88  
    89  	var volumes map[string]interface{}
    90  	inspectFieldAndUnmarshall(c, name, "Config.Volumes", &volumes)
    91  	if _, ok := volumes[volumePath]; !ok {
    92  		c.Fatal("Volume " + volumePath + " from environment not in Config.Volumes on image")
    93  	}
    94  
    95  }
    96  
    97  func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) {
    98  	// Windows does not support FROM scratch or the EXPOSE command
    99  	testRequires(c, DaemonIsLinux)
   100  	name := "testbuildenvironmentreplacement"
   101  
   102  	buildImageSuccessfully(c, name, withDockerfile(`
   103    FROM scratch
   104    ENV port 80
   105    EXPOSE ${port}
   106    ENV ports "  99   100 "
   107    EXPOSE ${ports}
   108    `))
   109  
   110  	var exposedPorts map[string]interface{}
   111  	inspectFieldAndUnmarshall(c, name, "Config.ExposedPorts", &exposedPorts)
   112  	exp := []int{80, 99, 100}
   113  	for _, p := range exp {
   114  		tmp := fmt.Sprintf("%d/tcp", p)
   115  		if _, ok := exposedPorts[tmp]; !ok {
   116  			c.Fatalf("Exposed port %d from environment not in Config.ExposedPorts on image", p)
   117  		}
   118  	}
   119  
   120  }
   121  
   122  func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) {
   123  	name := "testbuildenvironmentreplacement"
   124  
   125  	buildImageSuccessfully(c, name, withDockerfile(`
   126    FROM busybox
   127    ENV MYWORKDIR /work
   128    RUN mkdir ${MYWORKDIR}
   129    WORKDIR ${MYWORKDIR}
   130    `))
   131  	res := inspectFieldJSON(c, name, "Config.WorkingDir")
   132  
   133  	expected := `"/work"`
   134  	if testEnv.DaemonPlatform() == "windows" {
   135  		expected = `"C:\\work"`
   136  	}
   137  	if res != expected {
   138  		c.Fatalf("Workdir /workdir from environment not in Config.WorkingDir on image: %s", res)
   139  	}
   140  }
   141  
   142  func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) {
   143  	name := "testbuildenvironmentreplacement"
   144  
   145  	buildImageSuccessfully(c, name, withBuildContext(c,
   146  		withFile("Dockerfile", `
   147    FROM `+minimalBaseImage()+`
   148    ENV baz foo
   149    ENV quux bar
   150    ENV dot .
   151    ENV fee fff
   152    ENV gee ggg
   153  
   154    ADD ${baz} ${dot}
   155    COPY ${quux} ${dot}
   156    ADD ${zzz:-${fee}} ${dot}
   157    COPY ${zzz:-${gee}} ${dot}
   158    `),
   159  		withFile("foo", "test1"),
   160  		withFile("bar", "test2"),
   161  		withFile("fff", "test3"),
   162  		withFile("ggg", "test4"),
   163  	))
   164  }
   165  
   166  func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) {
   167  	// ENV expansions work differently in Windows
   168  	testRequires(c, DaemonIsLinux)
   169  	name := "testbuildenvironmentreplacement"
   170  
   171  	buildImageSuccessfully(c, name, withDockerfile(`
   172    FROM busybox
   173    ENV foo zzz
   174    ENV bar ${foo}
   175    ENV abc1='$foo'
   176    ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   177    RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   178    ENV abc2="\$foo"
   179    RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   180    ENV abc3 '$foo'
   181    RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   182    ENV abc4 "\$foo"
   183    RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
   184    `))
   185  
   186  	envResult := []string{}
   187  	inspectFieldAndUnmarshall(c, name, "Config.Env", &envResult)
   188  	found := false
   189  	envCount := 0
   190  
   191  	for _, env := range envResult {
   192  		parts := strings.SplitN(env, "=", 2)
   193  		if parts[0] == "bar" {
   194  			found = true
   195  			if parts[1] != "zzz" {
   196  				c.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
   197  			}
   198  		} else if strings.HasPrefix(parts[0], "env") {
   199  			envCount++
   200  			if parts[1] != "zzz" {
   201  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   202  			}
   203  		} else if strings.HasPrefix(parts[0], "env") {
   204  			envCount++
   205  			if parts[1] != "foo" {
   206  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   207  			}
   208  		}
   209  	}
   210  
   211  	if !found {
   212  		c.Fatal("Never found the `bar` env variable")
   213  	}
   214  
   215  	if envCount != 4 {
   216  		c.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
   217  	}
   218  
   219  }
   220  
   221  func (s *DockerSuite) TestBuildHandleEscapesInVolume(c *check.C) {
   222  	// The volume paths used in this test are invalid on Windows
   223  	testRequires(c, DaemonIsLinux)
   224  	name := "testbuildhandleescapes"
   225  
   226  	testCases := []struct {
   227  		volumeValue string
   228  		expected    string
   229  	}{
   230  		{
   231  			volumeValue: "${FOO}",
   232  			expected:    "bar",
   233  		},
   234  		{
   235  			volumeValue: `\${FOO}`,
   236  			expected:    "${FOO}",
   237  		},
   238  		// this test in particular provides *7* backslashes and expects 6 to come back.
   239  		// Like above, the first escape is swallowed and the rest are treated as
   240  		// literals, this one is just less obvious because of all the character noise.
   241  		{
   242  			volumeValue: `\\\\\\\${FOO}`,
   243  			expected:    `\\\${FOO}`,
   244  		},
   245  	}
   246  
   247  	for _, tc := range testCases {
   248  		buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`
   249    FROM scratch
   250    ENV FOO bar
   251    VOLUME %s
   252    `, tc.volumeValue)))
   253  
   254  		var result map[string]map[string]struct{}
   255  		inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result)
   256  		if _, ok := result[tc.expected]; !ok {
   257  			c.Fatalf("Could not find volume %s set from env foo in volumes table, got %q", tc.expected, result)
   258  		}
   259  
   260  		// Remove the image for the next iteration
   261  		dockerCmd(c, "rmi", name)
   262  	}
   263  }
   264  
   265  func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) {
   266  	name := "testbuildonbuildlowercase"
   267  	name2 := "testbuildonbuildlowercase2"
   268  
   269  	buildImageSuccessfully(c, name, withDockerfile(`
   270    FROM busybox
   271    onbuild run echo quux
   272    `))
   273  
   274  	result := buildImageNew(name2, withDockerfile(fmt.Sprintf(`
   275    FROM %s
   276    `, name)))
   277  	result.Assert(c, icmd.Success)
   278  
   279  	if !strings.Contains(result.Combined(), "quux") {
   280  		c.Fatalf("Did not receive the expected echo text, got %s", result.Combined())
   281  	}
   282  
   283  	if strings.Contains(result.Combined(), "ONBUILD ONBUILD") {
   284  		c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", result.Combined())
   285  	}
   286  
   287  }
   288  
   289  func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) {
   290  	// ENV expansions work differently in Windows
   291  	testRequires(c, DaemonIsLinux)
   292  	name := "testbuildenvescapes"
   293  	buildImageSuccessfully(c, name, withDockerfile(`
   294      FROM busybox
   295      ENV TEST foo
   296      CMD echo \$
   297      `))
   298  
   299  	out, _ := dockerCmd(c, "run", "-t", name)
   300  	if strings.TrimSpace(out) != "$" {
   301  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   302  	}
   303  
   304  }
   305  
   306  func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) {
   307  	// ENV expansions work differently in Windows
   308  	testRequires(c, DaemonIsLinux)
   309  	name := "testbuildenvoverwrite"
   310  	buildImageSuccessfully(c, name, withDockerfile(`
   311      FROM busybox
   312      ENV TEST foo
   313      CMD echo ${TEST}
   314      `))
   315  
   316  	out, _ := dockerCmd(c, "run", "-e", "TEST=bar", "-t", name)
   317  	if strings.TrimSpace(out) != "bar" {
   318  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   319  	}
   320  
   321  }
   322  
   323  // FIXME(vdemeester) why we disabled cache here ?
   324  func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) {
   325  	name1 := "onbuildcmd"
   326  	name2 := "onbuildgenerated"
   327  
   328  	buildImageSuccessfully(c, name1, withDockerfile(`
   329  FROM busybox
   330  ONBUILD CMD ["hello world"]
   331  ONBUILD ENTRYPOINT ["echo"]
   332  ONBUILD RUN ["true"]`))
   333  
   334  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s`, name1)))
   335  
   336  	out, _ := dockerCmd(c, "run", name2)
   337  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   338  		c.Fatalf("did not get echo output from onbuild. Got: %q", out)
   339  	}
   340  
   341  }
   342  
   343  // FIXME(vdemeester) why we disabled cache here ?
   344  func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) {
   345  	name1 := "onbuildcmd"
   346  	name2 := "onbuildgenerated"
   347  
   348  	buildImageSuccessfully(c, name1, withDockerfile(`
   349  FROM busybox
   350  ONBUILD ENTRYPOINT ["echo"]`))
   351  
   352  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1)))
   353  
   354  	out, _ := dockerCmd(c, "run", name2)
   355  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   356  		c.Fatal("got malformed output from onbuild", out)
   357  	}
   358  
   359  }
   360  
   361  func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
   362  	testRequires(c, DaemonIsLinux) // Windows doesn't have httpserver image yet
   363  	name := "testbuildtwoimageswithadd"
   364  	server, err := fakeStorage(map[string]string{
   365  		"robots.txt": "hello",
   366  		"index.html": "world",
   367  	})
   368  	if err != nil {
   369  		c.Fatal(err)
   370  	}
   371  	defer server.Close()
   372  
   373  	if _, err := buildImage(name,
   374  		fmt.Sprintf(`FROM scratch
   375  		ADD %s/robots.txt /`, server.URL()),
   376  		true); err != nil {
   377  		c.Fatal(err)
   378  	}
   379  	if err != nil {
   380  		c.Fatal(err)
   381  	}
   382  	deleteImages(name)
   383  	_, out, err := buildImageWithOut(name,
   384  		fmt.Sprintf(`FROM scratch
   385  		ADD %s/index.html /`, server.URL()),
   386  		true)
   387  	if err != nil {
   388  		c.Fatal(err)
   389  	}
   390  	if strings.Contains(out, "Using cache") {
   391  		c.Fatal("2nd build used cache on ADD, it shouldn't")
   392  	}
   393  
   394  }
   395  
   396  func (s *DockerSuite) TestBuildLastModified(c *check.C) {
   397  	name := "testbuildlastmodified"
   398  
   399  	server, err := fakeStorage(map[string]string{
   400  		"file": "hello",
   401  	})
   402  	if err != nil {
   403  		c.Fatal(err)
   404  	}
   405  	defer server.Close()
   406  
   407  	var out, out2 string
   408  
   409  	dFmt := `FROM busybox
   410  ADD %s/file /`
   411  
   412  	dockerfile := fmt.Sprintf(dFmt, server.URL())
   413  
   414  	if _, _, err = buildImageWithOut(name, dockerfile, false); err != nil {
   415  		c.Fatal(err)
   416  	}
   417  
   418  	out, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   419  
   420  	// Build it again and make sure the mtime of the file didn't change.
   421  	// Wait a few seconds to make sure the time changed enough to notice
   422  	time.Sleep(2 * time.Second)
   423  
   424  	if _, _, err = buildImageWithOut(name, dockerfile, false); err != nil {
   425  		c.Fatal(err)
   426  	}
   427  	out2, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   428  
   429  	if out != out2 {
   430  		c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", out, out2)
   431  	}
   432  
   433  	// Now 'touch' the file and make sure the timestamp DID change this time
   434  	// Create a new fakeStorage instead of just using Add() to help windows
   435  	server, err = fakeStorage(map[string]string{
   436  		"file": "hello",
   437  	})
   438  	if err != nil {
   439  		c.Fatal(err)
   440  	}
   441  	defer server.Close()
   442  
   443  	dockerfile = fmt.Sprintf(dFmt, server.URL())
   444  
   445  	if _, _, err = buildImageWithOut(name, dockerfile, false); err != nil {
   446  		c.Fatal(err)
   447  	}
   448  	out2, _ = dockerCmd(c, "run", name, "ls", "-le", "/file")
   449  
   450  	if out == out2 {
   451  		c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", out, out2)
   452  	}
   453  
   454  }
   455  
   456  // Regression for https://github.com/docker/docker/pull/27805
   457  // Makes sure that we don't use the cache if the contents of
   458  // a file in a subfolder of the context is modified and we re-build.
   459  func (s *DockerSuite) TestBuildModifyFileInFolder(c *check.C) {
   460  	name := "testbuildmodifyfileinfolder"
   461  
   462  	ctx, err := fakeContext(`FROM busybox
   463  RUN ["mkdir", "/test"]
   464  ADD folder/file /test/changetarget`,
   465  		map[string]string{})
   466  	if err != nil {
   467  		c.Fatal(err)
   468  	}
   469  	defer ctx.Close()
   470  	if err := ctx.Add("folder/file", "first"); err != nil {
   471  		c.Fatal(err)
   472  	}
   473  	id1, err := buildImageFromContext(name, ctx, true)
   474  	if err != nil {
   475  		c.Fatal(err)
   476  	}
   477  	if err := ctx.Add("folder/file", "second"); err != nil {
   478  		c.Fatal(err)
   479  	}
   480  	id2, err := buildImageFromContext(name, ctx, true)
   481  	if err != nil {
   482  		c.Fatal(err)
   483  	}
   484  	if id1 == id2 {
   485  		c.Fatal("cache was used even though file contents in folder was changed")
   486  	}
   487  }
   488  
   489  func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) {
   490  	testRequires(c, DaemonIsLinux) // Linux specific test
   491  	buildImageSuccessfully(c, "testaddimg", withBuildContext(c,
   492  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   493  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   494  RUN echo 'dockerio:x:1001:' >> /etc/group
   495  RUN touch /exists
   496  RUN chown dockerio.dockerio /exists
   497  ADD test_file /
   498  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   499  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   500  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   501  		withFile("test_file", "test1")))
   502  }
   503  
   504  // Issue #3960: "ADD src ." hangs
   505  func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *check.C) {
   506  	name := "testaddsinglefiletoworkdir"
   507  	ctx, err := fakeContext(`FROM busybox
   508  ADD test_file .`,
   509  		map[string]string{
   510  			"test_file": "test1",
   511  		})
   512  	if err != nil {
   513  		c.Fatal(err)
   514  	}
   515  	defer ctx.Close()
   516  
   517  	errChan := make(chan error)
   518  	go func() {
   519  		_, err := buildImageFromContext(name, ctx, true)
   520  		errChan <- err
   521  		close(errChan)
   522  	}()
   523  	select {
   524  	case <-time.After(15 * time.Second):
   525  		c.Fatal("Build with adding to workdir timed out")
   526  	case err := <-errChan:
   527  		c.Assert(err, check.IsNil)
   528  	}
   529  }
   530  
   531  func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) {
   532  	testRequires(c, DaemonIsLinux) // Linux specific test
   533  	buildImageSuccessfully(c, "testaddsinglefiletoexistdir", withBuildContext(c,
   534  		withFile("Dockerfile", `FROM busybox
   535  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   536  RUN echo 'dockerio:x:1001:' >> /etc/group
   537  RUN mkdir /exists
   538  RUN touch /exists/exists_file
   539  RUN chown -R dockerio.dockerio /exists
   540  ADD test_file /exists/
   541  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   542  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   543  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   544  		withFile("test_file", "test1")))
   545  }
   546  
   547  func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) {
   548  	testRequires(c, DaemonIsLinux) // Linux specific test
   549  	server, err := fakeStorage(map[string]string{
   550  		"robots.txt": "hello",
   551  	})
   552  	if err != nil {
   553  		c.Fatal(err)
   554  	}
   555  	defer server.Close()
   556  
   557  	buildImageSuccessfully(c, "testcopymultiplefilestofile", withBuildContext(c,
   558  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   559  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   560  RUN echo 'dockerio:x:1001:' >> /etc/group
   561  RUN mkdir /exists
   562  RUN touch /exists/exists_file
   563  RUN chown -R dockerio.dockerio /exists
   564  COPY test_file1 test_file2 /exists/
   565  ADD test_file3 test_file4 %s/robots.txt /exists/
   566  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   567  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   568  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   569  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   570  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   571  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   572  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   573  `, server.URL())),
   574  		withFile("test_file1", "test1"),
   575  		withFile("test_file2", "test2"),
   576  		withFile("test_file3", "test3"),
   577  		withFile("test_file3", "test3"),
   578  		withFile("test_file4", "test4")))
   579  }
   580  
   581  // These tests are mainly for user namespaces to verify that new directories
   582  // are created as the remapped root uid/gid pair
   583  func (s *DockerSuite) TestBuildUsernamespaceValidateRemappedRoot(c *check.C) {
   584  	testRequires(c, DaemonIsLinux)
   585  	testCases := []string{
   586  		"ADD . /new_dir",
   587  		"COPY test_dir /new_dir",
   588  		"WORKDIR /new_dir",
   589  	}
   590  	name := "testbuildusernamespacevalidateremappedroot"
   591  	for _, tc := range testCases {
   592  		buildImageSuccessfully(c, name, withBuildContext(c,
   593  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   594  %s
   595  RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, tc)),
   596  			withFile("test_dir/test_file", "test file")))
   597  
   598  		dockerCmd(c, "rmi", name)
   599  	}
   600  }
   601  
   602  func (s *DockerSuite) TestBuildAddAndCopyFileWithWhitespace(c *check.C) {
   603  	testRequires(c, DaemonIsLinux) // Not currently passing on Windows
   604  	name := "testaddfilewithwhitespace"
   605  
   606  	for _, command := range []string{"ADD", "COPY"} {
   607  		buildImageSuccessfully(c, name, withBuildContext(c,
   608  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   609  RUN mkdir "/test dir"
   610  RUN mkdir "/test_dir"
   611  %s [ "test file1", "/test_file1" ]
   612  %s [ "test_file2", "/test file2" ]
   613  %s [ "test file3", "/test file3" ]
   614  %s [ "test dir/test_file4", "/test_dir/test_file4" ]
   615  %s [ "test_dir/test_file5", "/test dir/test_file5" ]
   616  %s [ "test dir/test_file6", "/test dir/test_file6" ]
   617  RUN [ $(cat "/test_file1") = 'test1' ]
   618  RUN [ $(cat "/test file2") = 'test2' ]
   619  RUN [ $(cat "/test file3") = 'test3' ]
   620  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
   621  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
   622  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, command, command, command, command, command, command)),
   623  			withFile("test file1", "test1"),
   624  			withFile("test_file2", "test2"),
   625  			withFile("test file3", "test3"),
   626  			withFile("test dir/test_file4", "test4"),
   627  			withFile("test_dir/test_file5", "test5"),
   628  			withFile("test dir/test_file6", "test6"),
   629  		))
   630  
   631  		dockerCmd(c, "rmi", name)
   632  	}
   633  }
   634  
   635  func (s *DockerSuite) TestBuildCopyFileWithWhitespaceOnWindows(c *check.C) {
   636  	testRequires(c, DaemonIsWindows)
   637  	dockerfile := `FROM ` + testEnv.MinimalBaseImage() + `
   638  RUN mkdir "C:/test dir"
   639  RUN mkdir "C:/test_dir"
   640  COPY [ "test file1", "/test_file1" ]
   641  COPY [ "test_file2", "/test file2" ]
   642  COPY [ "test file3", "/test file3" ]
   643  COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
   644  COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
   645  COPY [ "test dir/test_file6", "/test dir/test_file6" ]
   646  RUN find "test1" "C:/test_file1"
   647  RUN find "test2" "C:/test file2"
   648  RUN find "test3" "C:/test file3"
   649  RUN find "test4" "C:/test_dir/test_file4"
   650  RUN find "test5" "C:/test dir/test_file5"
   651  RUN find "test6" "C:/test dir/test_file6"`
   652  
   653  	name := "testcopyfilewithwhitespace"
   654  	buildImageSuccessfully(c, name, withBuildContext(c,
   655  		withFile("Dockerfile", dockerfile),
   656  		withFile("test file1", "test1"),
   657  		withFile("test_file2", "test2"),
   658  		withFile("test file3", "test3"),
   659  		withFile("test dir/test_file4", "test4"),
   660  		withFile("test_dir/test_file5", "test5"),
   661  		withFile("test dir/test_file6", "test6"),
   662  	))
   663  }
   664  
   665  func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
   666  	name := "testcopywildcard"
   667  	server, err := fakeStorage(map[string]string{
   668  		"robots.txt": "hello",
   669  		"index.html": "world",
   670  	})
   671  	if err != nil {
   672  		c.Fatal(err)
   673  	}
   674  	defer server.Close()
   675  
   676  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   677  	COPY file*.txt /tmp/
   678  	RUN ls /tmp/file1.txt /tmp/file2.txt
   679  	RUN [ "mkdir",  "/tmp1" ]
   680  	COPY dir* /tmp1/
   681  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
   682  	RUN [ "mkdir",  "/tmp2" ]
   683          ADD dir/*dir %s/robots.txt /tmp2/
   684  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
   685  	`, server.URL()),
   686  		map[string]string{
   687  			"file1.txt":                     "test1",
   688  			"file2.txt":                     "test2",
   689  			"dir/nested_file":               "nested file",
   690  			"dir/nested_dir/nest_nest_file": "2 times nested",
   691  			"dirt": "dirty",
   692  		})
   693  	if err != nil {
   694  		c.Fatal(err)
   695  	}
   696  	defer ctx.Close()
   697  
   698  	id1, err := buildImageFromContext(name, ctx, true)
   699  	if err != nil {
   700  		c.Fatal(err)
   701  	}
   702  
   703  	// Now make sure we use a cache the 2nd time
   704  	id2, err := buildImageFromContext(name, ctx, true)
   705  	if err != nil {
   706  		c.Fatal(err)
   707  	}
   708  
   709  	if id1 != id2 {
   710  		c.Fatal("didn't use the cache")
   711  	}
   712  
   713  }
   714  
   715  func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) {
   716  	// Run this only on Linux
   717  	// Below is the original comment (that I don't agree with — vdemeester)
   718  	// Normally we would do c.Fatal(err) here but given that
   719  	// the odds of this failing are so rare, it must be because
   720  	// the OS we're running the client on doesn't support * in
   721  	// filenames (like windows).  So, instead of failing the test
   722  	// just let it pass. Then we don't need to explicitly
   723  	// say which OSs this works on or not.
   724  	testRequires(c, DaemonIsLinux)
   725  
   726  	buildImageSuccessfully(c, "testcopywildcardinname", withBuildContext(c,
   727  		withFile("Dockerfile", `FROM busybox
   728  	COPY *.txt /tmp/
   729  	RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ]
   730  	`),
   731  		withFile("*.txt", "hi there"),
   732  	))
   733  }
   734  
   735  func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
   736  	name := "testcopywildcardcache"
   737  	ctx, err := fakeContext(`FROM busybox
   738  	COPY file1.txt /tmp/`,
   739  		map[string]string{
   740  			"file1.txt": "test1",
   741  		})
   742  	if err != nil {
   743  		c.Fatal(err)
   744  	}
   745  	defer ctx.Close()
   746  
   747  	id1, err := buildImageFromContext(name, ctx, true)
   748  	if err != nil {
   749  		c.Fatal(err)
   750  	}
   751  
   752  	// Now make sure we use a cache the 2nd time even with wild cards.
   753  	// Use the same context so the file is the same and the checksum will match
   754  	ctx.Add("Dockerfile", `FROM busybox
   755  	COPY file*.txt /tmp/`)
   756  
   757  	id2, err := buildImageFromContext(name, ctx, true)
   758  	if err != nil {
   759  		c.Fatal(err)
   760  	}
   761  
   762  	if id1 != id2 {
   763  		c.Fatal("didn't use the cache")
   764  	}
   765  
   766  }
   767  
   768  func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) {
   769  	testRequires(c, DaemonIsLinux) // Linux specific test
   770  	buildImageSuccessfully(c, "testaddsinglefiletononexistingdir", withBuildContext(c,
   771  		withFile("Dockerfile", `FROM busybox
   772  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   773  RUN echo 'dockerio:x:1001:' >> /etc/group
   774  RUN touch /exists
   775  RUN chown dockerio.dockerio /exists
   776  ADD test_file /test_dir/
   777  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   778  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   779  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   780  		withFile("test_file", "test1")))
   781  }
   782  
   783  func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) {
   784  	testRequires(c, DaemonIsLinux) // Linux specific test
   785  	buildImageSuccessfully(c, "testadddircontenttoroot", withBuildContext(c,
   786  		withFile("Dockerfile", `FROM busybox
   787  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   788  RUN echo 'dockerio:x:1001:' >> /etc/group
   789  RUN touch /exists
   790  RUN chown dockerio.dockerio exists
   791  ADD test_dir /
   792  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   793  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   794  		withFile("test_dir/test_file", "test1")))
   795  }
   796  
   797  func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) {
   798  	testRequires(c, DaemonIsLinux) // Linux specific test
   799  	buildImageSuccessfully(c, "testadddircontenttoexistingdir", withBuildContext(c,
   800  		withFile("Dockerfile", `FROM busybox
   801  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   802  RUN echo 'dockerio:x:1001:' >> /etc/group
   803  RUN mkdir /exists
   804  RUN touch /exists/exists_file
   805  RUN chown -R dockerio.dockerio /exists
   806  ADD test_dir/ /exists/
   807  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   808  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   809  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`),
   810  		withFile("test_dir/test_file", "test1")))
   811  }
   812  
   813  func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) {
   814  	testRequires(c, DaemonIsLinux) // Linux specific test
   815  	buildImageSuccessfully(c, "testaddwholedirtoroot", withBuildContext(c,
   816  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   817  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   818  RUN echo 'dockerio:x:1001:' >> /etc/group
   819  RUN touch /exists
   820  RUN chown dockerio.dockerio exists
   821  ADD test_dir /test_dir
   822  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   823  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
   824  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   825  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
   826  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   827  		withFile("test_dir/test_file", "test1")))
   828  }
   829  
   830  // Testing #5941 : Having an etc directory in context conflicts with the /etc/mtab
   831  func (s *DockerSuite) TestBuildAddOrCopyEtcToRootShouldNotConflict(c *check.C) {
   832  	buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c,
   833  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
   834  ADD . /`),
   835  		withFile("etc/test_file", "test1")))
   836  	buildImageSuccessfully(c, "testcopyetctoroot", withBuildContext(c,
   837  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
   838  COPY . /`),
   839  		withFile("etc/test_file", "test1")))
   840  }
   841  
   842  // Testing #9401 : Losing setuid flag after a ADD
   843  func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) {
   844  	testRequires(c, DaemonIsLinux) // Linux specific test
   845  	buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c,
   846  		withFile("Dockerfile", `FROM busybox
   847  ADD suidbin /usr/bin/suidbin
   848  RUN chmod 4755 /usr/bin/suidbin
   849  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
   850  ADD ./data/ /
   851  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`),
   852  		withFile("suidbin", "suidbin"),
   853  		withFile("/data/usr/test_file", "test1")))
   854  }
   855  
   856  func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) {
   857  	testRequires(c, DaemonIsLinux) // Linux specific test
   858  	buildImageSuccessfully(c, "testcopysinglefiletoroot", withBuildContext(c,
   859  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   860  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   861  RUN echo 'dockerio:x:1001:' >> /etc/group
   862  RUN touch /exists
   863  RUN chown dockerio.dockerio /exists
   864  COPY test_file /
   865  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   866  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   867  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   868  		withFile("test_file", "test1")))
   869  }
   870  
   871  // Issue #3960: "ADD src ." hangs - adapted for COPY
   872  func (s *DockerSuite) TestBuildCopySingleFileToWorkdir(c *check.C) {
   873  	name := "testcopysinglefiletoworkdir"
   874  	ctx, err := fakeContext(`FROM busybox
   875  COPY test_file .`,
   876  		map[string]string{
   877  			"test_file": "test1",
   878  		})
   879  	if err != nil {
   880  		c.Fatal(err)
   881  	}
   882  	defer ctx.Close()
   883  
   884  	errChan := make(chan error)
   885  	go func() {
   886  		_, err := buildImageFromContext(name, ctx, true)
   887  		errChan <- err
   888  		close(errChan)
   889  	}()
   890  	select {
   891  	case <-time.After(15 * time.Second):
   892  		c.Fatal("Build with adding to workdir timed out")
   893  	case err := <-errChan:
   894  		c.Assert(err, check.IsNil)
   895  	}
   896  }
   897  
   898  func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) {
   899  	testRequires(c, DaemonIsLinux) // Linux specific test
   900  	buildImageSuccessfully(c, "testcopysinglefiletoexistdir", withBuildContext(c,
   901  		withFile("Dockerfile", `FROM busybox
   902  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   903  RUN echo 'dockerio:x:1001:' >> /etc/group
   904  RUN mkdir /exists
   905  RUN touch /exists/exists_file
   906  RUN chown -R dockerio.dockerio /exists
   907  COPY test_file /exists/
   908  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   909  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   910  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   911  		withFile("test_file", "test1")))
   912  }
   913  
   914  func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) {
   915  	testRequires(c, DaemonIsLinux) // Linux specific
   916  	buildImageSuccessfully(c, "testcopysinglefiletononexistdir", withBuildContext(c,
   917  		withFile("Dockerfile", `FROM busybox
   918  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   919  RUN echo 'dockerio:x:1001:' >> /etc/group
   920  RUN touch /exists
   921  RUN chown dockerio.dockerio /exists
   922  COPY test_file /test_dir/
   923  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   924  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   925  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   926  		withFile("test_file", "test1")))
   927  }
   928  
   929  func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) {
   930  	testRequires(c, DaemonIsLinux) // Linux specific test
   931  	buildImageSuccessfully(c, "testcopydircontenttoroot", withBuildContext(c,
   932  		withFile("Dockerfile", `FROM busybox
   933  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   934  RUN echo 'dockerio:x:1001:' >> /etc/group
   935  RUN touch /exists
   936  RUN chown dockerio.dockerio exists
   937  COPY test_dir /
   938  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   939  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`),
   940  		withFile("test_dir/test_file", "test1")))
   941  }
   942  
   943  func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) {
   944  	testRequires(c, DaemonIsLinux) // Linux specific test
   945  	buildImageSuccessfully(c, "testcopydircontenttoexistdir", withBuildContext(c,
   946  		withFile("Dockerfile", `FROM busybox
   947  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   948  RUN echo 'dockerio:x:1001:' >> /etc/group
   949  RUN mkdir /exists
   950  RUN touch /exists/exists_file
   951  RUN chown -R dockerio.dockerio /exists
   952  COPY test_dir/ /exists/
   953  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   954  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   955  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`),
   956  		withFile("test_dir/test_file", "test1")))
   957  }
   958  
   959  func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) {
   960  	testRequires(c, DaemonIsLinux) // Linux specific test
   961  	buildImageSuccessfully(c, "testcopywholedirtoroot", withBuildContext(c,
   962  		withFile("Dockerfile", fmt.Sprintf(`FROM busybox
   963  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   964  RUN echo 'dockerio:x:1001:' >> /etc/group
   965  RUN touch /exists
   966  RUN chown dockerio.dockerio exists
   967  COPY test_dir /test_dir
   968  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   969  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
   970  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   971  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
   972  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)),
   973  		withFile("test_dir/test_file", "test1")))
   974  }
   975  
   976  func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) {
   977  	testRequires(c, DaemonIsLinux) // Not currently working on Windows
   978  
   979  	dockerfile := `
   980  		FROM scratch
   981  		ADD links.tar /
   982  		ADD foo.txt /symlink/
   983  		`
   984  	targetFile := "foo.txt"
   985  	var (
   986  		name = "test-link-absolute"
   987  	)
   988  	ctx, err := fakeContext(dockerfile, nil)
   989  	if err != nil {
   990  		c.Fatal(err)
   991  	}
   992  	defer ctx.Close()
   993  
   994  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
   995  	if err != nil {
   996  		c.Fatalf("failed to create temporary directory: %s", tempDir)
   997  	}
   998  	defer os.RemoveAll(tempDir)
   999  
  1000  	var symlinkTarget string
  1001  	if runtime.GOOS == "windows" {
  1002  		var driveLetter string
  1003  		if abs, err := filepath.Abs(tempDir); err != nil {
  1004  			c.Fatal(err)
  1005  		} else {
  1006  			driveLetter = abs[:1]
  1007  		}
  1008  		tempDirWithoutDrive := tempDir[2:]
  1009  		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
  1010  	} else {
  1011  		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
  1012  	}
  1013  
  1014  	tarPath := filepath.Join(ctx.Dir, "links.tar")
  1015  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1016  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1017  
  1018  	tarOut, err := os.Create(tarPath)
  1019  	if err != nil {
  1020  		c.Fatal(err)
  1021  	}
  1022  
  1023  	tarWriter := tar.NewWriter(tarOut)
  1024  
  1025  	header := &tar.Header{
  1026  		Name:     "symlink",
  1027  		Typeflag: tar.TypeSymlink,
  1028  		Linkname: symlinkTarget,
  1029  		Mode:     0755,
  1030  		Uid:      0,
  1031  		Gid:      0,
  1032  	}
  1033  
  1034  	err = tarWriter.WriteHeader(header)
  1035  	if err != nil {
  1036  		c.Fatal(err)
  1037  	}
  1038  
  1039  	tarWriter.Close()
  1040  	tarOut.Close()
  1041  
  1042  	foo, err := os.Create(fooPath)
  1043  	if err != nil {
  1044  		c.Fatal(err)
  1045  	}
  1046  	defer foo.Close()
  1047  
  1048  	if _, err := foo.WriteString("test"); err != nil {
  1049  		c.Fatal(err)
  1050  	}
  1051  
  1052  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1053  		c.Fatal(err)
  1054  	}
  1055  
  1056  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1057  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1058  	}
  1059  
  1060  }
  1061  
  1062  func (s *DockerSuite) TestBuildAddBadLinksVolume(c *check.C) {
  1063  	testRequires(c, DaemonIsLinux) // ln not implemented on Windows busybox
  1064  	const (
  1065  		dockerfileTemplate = `
  1066  		FROM busybox
  1067  		RUN ln -s /../../../../../../../../%s /x
  1068  		VOLUME /x
  1069  		ADD foo.txt /x/`
  1070  		targetFile = "foo.txt"
  1071  	)
  1072  	var (
  1073  		name       = "test-link-absolute-volume"
  1074  		dockerfile = ""
  1075  	)
  1076  
  1077  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1078  	if err != nil {
  1079  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1080  	}
  1081  	defer os.RemoveAll(tempDir)
  1082  
  1083  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1084  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1085  
  1086  	ctx, err := fakeContext(dockerfile, nil)
  1087  	if err != nil {
  1088  		c.Fatal(err)
  1089  	}
  1090  	defer ctx.Close()
  1091  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1092  
  1093  	foo, err := os.Create(fooPath)
  1094  	if err != nil {
  1095  		c.Fatal(err)
  1096  	}
  1097  	defer foo.Close()
  1098  
  1099  	if _, err := foo.WriteString("test"); err != nil {
  1100  		c.Fatal(err)
  1101  	}
  1102  
  1103  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1104  		c.Fatal(err)
  1105  	}
  1106  
  1107  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1108  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1109  	}
  1110  
  1111  }
  1112  
  1113  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1114  // when we can't access files in the context.
  1115  func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) {
  1116  	testRequires(c, DaemonIsLinux, UnixCli) // test uses chown/chmod: not available on windows
  1117  
  1118  	{
  1119  		name := "testbuildinaccessiblefiles"
  1120  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1121  		if err != nil {
  1122  			c.Fatal(err)
  1123  		}
  1124  		defer ctx.Close()
  1125  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1126  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1127  
  1128  		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1129  			c.Fatalf("failed to chown file to root: %s", err)
  1130  		}
  1131  		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1132  			c.Fatalf("failed to chmod file to 700: %s", err)
  1133  		}
  1134  		result := icmd.RunCmd(icmd.Cmd{
  1135  			Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1136  			Dir:     ctx.Dir,
  1137  		})
  1138  		if result.Error == nil {
  1139  			c.Fatalf("build should have failed: %s %s", result.Error, result.Combined())
  1140  		}
  1141  
  1142  		// check if we've detected the failure before we started building
  1143  		if !strings.Contains(result.Combined(), "no permission to read from ") {
  1144  			c.Fatalf("output should've contained the string: no permission to read from but contained: %s", result.Combined())
  1145  		}
  1146  
  1147  		if !strings.Contains(result.Combined(), "Error checking context") {
  1148  			c.Fatalf("output should've contained the string: Error checking context")
  1149  		}
  1150  	}
  1151  	{
  1152  		name := "testbuildinaccessibledirectory"
  1153  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1154  		if err != nil {
  1155  			c.Fatal(err)
  1156  		}
  1157  		defer ctx.Close()
  1158  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1159  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1160  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1161  
  1162  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1163  			c.Fatalf("failed to chown directory to root: %s", err)
  1164  		}
  1165  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1166  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1167  		}
  1168  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1169  			c.Fatalf("failed to chmod file to 700: %s", err)
  1170  		}
  1171  
  1172  		result := icmd.RunCmd(icmd.Cmd{
  1173  			Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1174  			Dir:     ctx.Dir,
  1175  		})
  1176  		if result.Error == nil {
  1177  			c.Fatalf("build should have failed: %s %s", result.Error, result.Combined())
  1178  		}
  1179  
  1180  		// check if we've detected the failure before we started building
  1181  		if !strings.Contains(result.Combined(), "can't stat") {
  1182  			c.Fatalf("output should've contained the string: can't access %s", result.Combined())
  1183  		}
  1184  
  1185  		if !strings.Contains(result.Combined(), "Error checking context") {
  1186  			c.Fatalf("output should've contained the string: Error checking context\ngot:%s", result.Combined())
  1187  		}
  1188  
  1189  	}
  1190  	{
  1191  		name := "testlinksok"
  1192  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
  1193  		if err != nil {
  1194  			c.Fatal(err)
  1195  		}
  1196  		defer ctx.Close()
  1197  
  1198  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1199  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1200  			c.Fatal(err)
  1201  		}
  1202  		defer os.Remove(target)
  1203  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1204  		// This test doesn't require that we run commands as an unprivileged user
  1205  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1206  			c.Fatal(err)
  1207  		}
  1208  	}
  1209  	{
  1210  		name := "testbuildignoredinaccessible"
  1211  		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
  1212  			map[string]string{
  1213  				"directoryWeCantStat/bar": "foo",
  1214  				".dockerignore":           "directoryWeCantStat",
  1215  			})
  1216  		if err != nil {
  1217  			c.Fatal(err)
  1218  		}
  1219  		defer ctx.Close()
  1220  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1221  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1222  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1223  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1224  			c.Fatalf("failed to chown directory to root: %s", err)
  1225  		}
  1226  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1227  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1228  		}
  1229  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1230  			c.Fatalf("failed to chmod file to 700: %s", err)
  1231  		}
  1232  
  1233  		result := icmd.RunCmd(icmd.Cmd{
  1234  			Dir: ctx.Dir,
  1235  			Command: []string{"su", "unprivilegeduser", "-c",
  1236  				fmt.Sprintf("%s build -t %s .", dockerBinary, name)},
  1237  		})
  1238  		result.Assert(c, icmd.Expected{})
  1239  	}
  1240  }
  1241  
  1242  func (s *DockerSuite) TestBuildForceRm(c *check.C) {
  1243  	containerCountBefore, err := getContainerCount()
  1244  	if err != nil {
  1245  		c.Fatalf("failed to get the container count: %s", err)
  1246  	}
  1247  	name := "testbuildforcerm"
  1248  
  1249  	buildImageNew(name, withBuildFlags("--force-rm"), withBuildContext(c,
  1250  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
  1251  	RUN true
  1252  	RUN thiswillfail`))).Assert(c, icmd.Expected{
  1253  		ExitCode: 1,
  1254  	})
  1255  
  1256  	containerCountAfter, err := getContainerCount()
  1257  	if err != nil {
  1258  		c.Fatalf("failed to get the container count: %s", err)
  1259  	}
  1260  
  1261  	if containerCountBefore != containerCountAfter {
  1262  		c.Fatalf("--force-rm shouldn't have left containers behind")
  1263  	}
  1264  
  1265  }
  1266  
  1267  func (s *DockerSuite) TestBuildRm(c *check.C) {
  1268  	name := "testbuildrm"
  1269  
  1270  	testCases := []struct {
  1271  		buildflags                []string
  1272  		shouldLeftContainerBehind bool
  1273  	}{
  1274  		// Default case (i.e. --rm=true)
  1275  		{
  1276  			buildflags:                []string{},
  1277  			shouldLeftContainerBehind: false,
  1278  		},
  1279  		{
  1280  			buildflags:                []string{"--rm"},
  1281  			shouldLeftContainerBehind: false,
  1282  		},
  1283  		{
  1284  			buildflags:                []string{"--rm=false"},
  1285  			shouldLeftContainerBehind: true,
  1286  		},
  1287  	}
  1288  
  1289  	for _, tc := range testCases {
  1290  		containerCountBefore, err := getContainerCount()
  1291  		if err != nil {
  1292  			c.Fatalf("failed to get the container count: %s", err)
  1293  		}
  1294  
  1295  		buildImageSuccessfully(c, name, withBuildFlags(tc.buildflags...), withDockerfile(`FROM busybox
  1296  	RUN echo hello world`))
  1297  
  1298  		containerCountAfter, err := getContainerCount()
  1299  		if err != nil {
  1300  			c.Fatalf("failed to get the container count: %s", err)
  1301  		}
  1302  
  1303  		if tc.shouldLeftContainerBehind {
  1304  			if containerCountBefore == containerCountAfter {
  1305  				c.Fatalf("flags %v should have left containers behind", tc.buildflags)
  1306  			}
  1307  		} else {
  1308  			if containerCountBefore != containerCountAfter {
  1309  				c.Fatalf("flags %v shouldn't have left containers behind", tc.buildflags)
  1310  			}
  1311  		}
  1312  
  1313  		dockerCmd(c, "rmi", name)
  1314  	}
  1315  }
  1316  
  1317  func (s *DockerSuite) TestBuildWithVolumes(c *check.C) {
  1318  	testRequires(c, DaemonIsLinux) // Invalid volume paths on Windows
  1319  	var (
  1320  		result   map[string]map[string]struct{}
  1321  		name     = "testbuildvolumes"
  1322  		emptyMap = make(map[string]struct{})
  1323  		expected = map[string]map[string]struct{}{
  1324  			"/test1":  emptyMap,
  1325  			"/test2":  emptyMap,
  1326  			"/test3":  emptyMap,
  1327  			"/test4":  emptyMap,
  1328  			"/test5":  emptyMap,
  1329  			"/test6":  emptyMap,
  1330  			"[/test7": emptyMap,
  1331  			"/test8]": emptyMap,
  1332  		}
  1333  	)
  1334  
  1335  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1336  		VOLUME /test1
  1337  		VOLUME /test2
  1338      VOLUME /test3 /test4
  1339      VOLUME ["/test5", "/test6"]
  1340      VOLUME [/test7 /test8]
  1341      `))
  1342  
  1343  	inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result)
  1344  
  1345  	equal := reflect.DeepEqual(&result, &expected)
  1346  	if !equal {
  1347  		c.Fatalf("Volumes %s, expected %s", result, expected)
  1348  	}
  1349  
  1350  }
  1351  
  1352  func (s *DockerSuite) TestBuildMaintainer(c *check.C) {
  1353  	name := "testbuildmaintainer"
  1354  
  1355  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1356          MAINTAINER dockerio`))
  1357  
  1358  	expected := "dockerio"
  1359  	res := inspectField(c, name, "Author")
  1360  	if res != expected {
  1361  		c.Fatalf("Maintainer %s, expected %s", res, expected)
  1362  	}
  1363  }
  1364  
  1365  func (s *DockerSuite) TestBuildUser(c *check.C) {
  1366  	testRequires(c, DaemonIsLinux)
  1367  	name := "testbuilduser"
  1368  	expected := "dockerio"
  1369  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1370  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1371  		USER dockerio
  1372  		RUN [ $(whoami) = 'dockerio' ]`))
  1373  	res := inspectField(c, name, "Config.User")
  1374  	if res != expected {
  1375  		c.Fatalf("User %s, expected %s", res, expected)
  1376  	}
  1377  }
  1378  
  1379  func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
  1380  	name := "testbuildrelativeworkdir"
  1381  
  1382  	var (
  1383  		expected1     string
  1384  		expected2     string
  1385  		expected3     string
  1386  		expected4     string
  1387  		expectedFinal string
  1388  	)
  1389  
  1390  	if testEnv.DaemonPlatform() == "windows" {
  1391  		expected1 = `C:/`
  1392  		expected2 = `C:/test1`
  1393  		expected3 = `C:/test2`
  1394  		expected4 = `C:/test2/test3`
  1395  		expectedFinal = `C:\test2\test3` // Note inspect is going to return Windows paths, as it's not in busybox
  1396  	} else {
  1397  		expected1 = `/`
  1398  		expected2 = `/test1`
  1399  		expected3 = `/test2`
  1400  		expected4 = `/test2/test3`
  1401  		expectedFinal = `/test2/test3`
  1402  	}
  1403  
  1404  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1405  		RUN sh -c "[ "$PWD" = "`+expected1+`" ]"
  1406  		WORKDIR test1
  1407  		RUN sh -c "[ "$PWD" = "`+expected2+`" ]"
  1408  		WORKDIR /test2
  1409  		RUN sh -c "[ "$PWD" = "`+expected3+`" ]"
  1410  		WORKDIR test3
  1411  		RUN sh -c "[ "$PWD" = "`+expected4+`" ]"`))
  1412  
  1413  	res := inspectField(c, name, "Config.WorkingDir")
  1414  	if res != expectedFinal {
  1415  		c.Fatalf("Workdir %s, expected %s", res, expectedFinal)
  1416  	}
  1417  }
  1418  
  1419  // #22181 Regression test. Single end-to-end test of using
  1420  // Windows semantics. Most path handling verifications are in unit tests
  1421  func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) {
  1422  	testRequires(c, DaemonIsWindows)
  1423  	buildImageSuccessfully(c, "testbuildwindowsworkdirprocessing", withDockerfile(`FROM busybox
  1424  		WORKDIR C:\\foo
  1425  		WORKDIR bar
  1426  		RUN sh -c "[ "$PWD" = "C:/foo/bar" ]"
  1427  		`))
  1428  }
  1429  
  1430  // #22181 Regression test. Most paths handling verifications are in unit test.
  1431  // One functional test for end-to-end
  1432  func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) {
  1433  	testRequires(c, DaemonIsWindows)
  1434  	// TODO Windows (@jhowardmsft). Needs a follow-up PR to 22181 to
  1435  	// support backslash such as .\\ being equivalent to ./ and c:\\ being
  1436  	// equivalent to c:/. This is not currently (nor ever has been) supported
  1437  	// by docker on the Windows platform.
  1438  	buildImageSuccessfully(c, "testbuildwindowsaddcopypathprocessing", withBuildContext(c,
  1439  		withFile("Dockerfile", `FROM busybox
  1440  			# No trailing slash on COPY/ADD
  1441  			# Results in dir being changed to a file
  1442  			WORKDIR /wc1
  1443  			COPY wc1 c:/wc1
  1444  			WORKDIR /wc2
  1445  			ADD wc2 c:/wc2
  1446  			WORKDIR c:/
  1447  			RUN sh -c "[ $(cat c:/wc1/wc1) = 'hellowc1' ]"
  1448  			RUN sh -c "[ $(cat c:/wc2/wc2) = 'worldwc2' ]"
  1449  
  1450  			# Trailing slash on COPY/ADD, Windows-style path.
  1451  			WORKDIR /wd1
  1452  			COPY wd1 c:/wd1/
  1453  			WORKDIR /wd2
  1454  			ADD wd2 c:/wd2/
  1455  			RUN sh -c "[ $(cat c:/wd1/wd1) = 'hellowd1' ]"
  1456  			RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]"
  1457  			`),
  1458  		withFile("wc1", "hellowc1"),
  1459  		withFile("wc2", "worldwc2"),
  1460  		withFile("wd1", "hellowd1"),
  1461  		withFile("wd2", "worldwd2"),
  1462  	))
  1463  }
  1464  
  1465  func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
  1466  	name := "testbuildworkdirwithenvvariables"
  1467  
  1468  	var expected string
  1469  	if testEnv.DaemonPlatform() == "windows" {
  1470  		expected = `C:\test1\test2`
  1471  	} else {
  1472  		expected = `/test1/test2`
  1473  	}
  1474  
  1475  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1476  		ENV DIRPATH /test1
  1477  		ENV SUBDIRNAME test2
  1478  		WORKDIR $DIRPATH
  1479  		WORKDIR $SUBDIRNAME/$MISSING_VAR`))
  1480  	res := inspectField(c, name, "Config.WorkingDir")
  1481  	if res != expected {
  1482  		c.Fatalf("Workdir %s, expected %s", res, expected)
  1483  	}
  1484  }
  1485  
  1486  func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
  1487  	// cat /test1/test2/foo gets permission denied for the user
  1488  	testRequires(c, NotUserNamespace)
  1489  
  1490  	var expected string
  1491  	if testEnv.DaemonPlatform() == "windows" {
  1492  		expected = `C:/test1/test2`
  1493  	} else {
  1494  		expected = `/test1/test2`
  1495  	}
  1496  
  1497  	buildImageSuccessfully(c, "testbuildrelativecopy", withBuildContext(c,
  1498  		withFile("Dockerfile", `FROM busybox
  1499  			WORKDIR /test1
  1500  			WORKDIR test2
  1501  			RUN sh -c "[ "$PWD" = '`+expected+`' ]"
  1502  			COPY foo ./
  1503  			RUN sh -c "[ $(cat /test1/test2/foo) = 'hello' ]"
  1504  			ADD foo ./bar/baz
  1505  			RUN sh -c "[ $(cat /test1/test2/bar/baz) = 'hello' ]"
  1506  			COPY foo ./bar/baz2
  1507  			RUN sh -c "[ $(cat /test1/test2/bar/baz2) = 'hello' ]"
  1508  			WORKDIR ..
  1509  			COPY foo ./
  1510  			RUN sh -c "[ $(cat /test1/foo) = 'hello' ]"
  1511  			COPY foo /test3/
  1512  			RUN sh -c "[ $(cat /test3/foo) = 'hello' ]"
  1513  			WORKDIR /test4
  1514  			COPY . .
  1515  			RUN sh -c "[ $(cat /test4/foo) = 'hello' ]"
  1516  			WORKDIR /test5/test6
  1517  			COPY foo ../
  1518  			RUN sh -c "[ $(cat /test5/foo) = 'hello' ]"
  1519  			`),
  1520  		withFile("foo", "hello"),
  1521  	))
  1522  }
  1523  
  1524  func (s *DockerSuite) TestBuildBlankName(c *check.C) {
  1525  	name := "testbuildblankname"
  1526  	testCases := []struct {
  1527  		expression     string
  1528  		expectedStderr string
  1529  	}{
  1530  		{
  1531  			expression:     "ENV =",
  1532  			expectedStderr: "ENV names can not be blank",
  1533  		},
  1534  		{
  1535  			expression:     "LABEL =",
  1536  			expectedStderr: "LABEL names can not be blank",
  1537  		},
  1538  		{
  1539  			expression:     "ARG =foo",
  1540  			expectedStderr: "ARG names can not be blank",
  1541  		},
  1542  	}
  1543  
  1544  	for _, tc := range testCases {
  1545  		buildImageNew(name, withDockerfile(fmt.Sprintf(`FROM busybox
  1546  		%s`, tc.expression))).Assert(c, icmd.Expected{
  1547  			ExitCode: 1,
  1548  			Err:      tc.expectedStderr,
  1549  		})
  1550  	}
  1551  }
  1552  
  1553  func (s *DockerSuite) TestBuildEnv(c *check.C) {
  1554  	testRequires(c, DaemonIsLinux) // ENV expansion is different in Windows
  1555  	name := "testbuildenv"
  1556  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  1557  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1558  		ENV PATH /test:$PATH
  1559  		ENV PORT 2375
  1560  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`))
  1561  	res := inspectField(c, name, "Config.Env")
  1562  	if res != expected {
  1563  		c.Fatalf("Env %s, expected %s", res, expected)
  1564  	}
  1565  }
  1566  
  1567  func (s *DockerSuite) TestBuildPATH(c *check.C) {
  1568  	testRequires(c, DaemonIsLinux) // ENV expansion is different in Windows
  1569  
  1570  	defPath := "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
  1571  
  1572  	fn := func(dockerfile string, expected string) {
  1573  		buildImageSuccessfully(c, "testbldpath", withDockerfile(dockerfile))
  1574  		res := inspectField(c, "testbldpath", "Config.Env")
  1575  		if res != expected {
  1576  			c.Fatalf("Env %q, expected %q for dockerfile:%q", res, expected, dockerfile)
  1577  		}
  1578  	}
  1579  
  1580  	tests := []struct{ dockerfile, exp string }{
  1581  		{"FROM scratch\nMAINTAINER me", "[PATH=" + defPath + "]"},
  1582  		{"FROM busybox\nMAINTAINER me", "[PATH=" + defPath + "]"},
  1583  		{"FROM scratch\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
  1584  		{"FROM busybox\nENV FOO=bar", "[PATH=" + defPath + " FOO=bar]"},
  1585  		{"FROM scratch\nENV PATH=/test", "[PATH=/test]"},
  1586  		{"FROM busybox\nENV PATH=/test", "[PATH=/test]"},
  1587  		{"FROM scratch\nENV PATH=''", "[PATH=]"},
  1588  		{"FROM busybox\nENV PATH=''", "[PATH=]"},
  1589  	}
  1590  
  1591  	for _, test := range tests {
  1592  		fn(test.dockerfile, test.exp)
  1593  	}
  1594  }
  1595  
  1596  func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
  1597  	testRequires(c, SameHostDaemon)
  1598  
  1599  	name := "testbuildcontextcleanup"
  1600  	entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1601  	if err != nil {
  1602  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1603  	}
  1604  
  1605  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1606          ENTRYPOINT ["/bin/echo"]`))
  1607  
  1608  	entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1609  	if err != nil {
  1610  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1611  	}
  1612  	if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
  1613  		c.Fatalf("context should have been deleted, but wasn't")
  1614  	}
  1615  
  1616  }
  1617  
  1618  func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
  1619  	testRequires(c, SameHostDaemon)
  1620  
  1621  	name := "testbuildcontextcleanup"
  1622  	entries, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1623  	if err != nil {
  1624  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1625  	}
  1626  
  1627  	buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+`
  1628  	RUN /non/existing/command`)).Assert(c, icmd.Expected{
  1629  		ExitCode: 1,
  1630  	})
  1631  
  1632  	entriesFinal, err := ioutil.ReadDir(filepath.Join(testEnv.DockerBasePath(), "tmp"))
  1633  	if err != nil {
  1634  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  1635  	}
  1636  	if err = testutil.CompareDirectoryEntries(entries, entriesFinal); err != nil {
  1637  		c.Fatalf("context should have been deleted, but wasn't")
  1638  	}
  1639  
  1640  }
  1641  
  1642  func (s *DockerSuite) TestBuildCmd(c *check.C) {
  1643  	name := "testbuildcmd"
  1644  	expected := "[/bin/echo Hello World]"
  1645  
  1646  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1647          CMD ["/bin/echo", "Hello World"]`))
  1648  
  1649  	res := inspectField(c, name, "Config.Cmd")
  1650  	if res != expected {
  1651  		c.Fatalf("Cmd %s, expected %s", res, expected)
  1652  	}
  1653  }
  1654  
  1655  func (s *DockerSuite) TestBuildExpose(c *check.C) {
  1656  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1657  	name := "testbuildexpose"
  1658  	expected := "map[2375/tcp:{}]"
  1659  
  1660  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1661          EXPOSE 2375`))
  1662  
  1663  	res := inspectField(c, name, "Config.ExposedPorts")
  1664  	if res != expected {
  1665  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  1666  	}
  1667  }
  1668  
  1669  func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) {
  1670  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1671  	// start building docker file with a large number of ports
  1672  	portList := make([]string, 50)
  1673  	line := make([]string, 100)
  1674  	expectedPorts := make([]int, len(portList)*len(line))
  1675  	for i := 0; i < len(portList); i++ {
  1676  		for j := 0; j < len(line); j++ {
  1677  			p := i*len(line) + j + 1
  1678  			line[j] = strconv.Itoa(p)
  1679  			expectedPorts[p-1] = p
  1680  		}
  1681  		if i == len(portList)-1 {
  1682  			portList[i] = strings.Join(line, " ")
  1683  		} else {
  1684  			portList[i] = strings.Join(line, " ") + ` \`
  1685  		}
  1686  	}
  1687  
  1688  	dockerfile := `FROM scratch
  1689  	EXPOSE {{range .}} {{.}}
  1690  	{{end}}`
  1691  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  1692  	buf := bytes.NewBuffer(nil)
  1693  	tmpl.Execute(buf, portList)
  1694  
  1695  	name := "testbuildexpose"
  1696  	buildImageSuccessfully(c, name, withDockerfile(buf.String()))
  1697  
  1698  	// check if all the ports are saved inside Config.ExposedPorts
  1699  	res := inspectFieldJSON(c, name, "Config.ExposedPorts")
  1700  	var exposedPorts map[string]interface{}
  1701  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  1702  		c.Fatal(err)
  1703  	}
  1704  
  1705  	for _, p := range expectedPorts {
  1706  		ep := fmt.Sprintf("%d/tcp", p)
  1707  		if _, ok := exposedPorts[ep]; !ok {
  1708  			c.Errorf("Port(%s) is not exposed", ep)
  1709  		} else {
  1710  			delete(exposedPorts, ep)
  1711  		}
  1712  	}
  1713  	if len(exposedPorts) != 0 {
  1714  		c.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  1715  	}
  1716  }
  1717  
  1718  func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
  1719  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1720  	buildID := func(name, exposed string) string {
  1721  		buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM scratch
  1722  		EXPOSE %s`, exposed)))
  1723  		id := inspectField(c, name, "Id")
  1724  		return id
  1725  	}
  1726  
  1727  	id1 := buildID("testbuildexpose1", "80 2375")
  1728  	id2 := buildID("testbuildexpose2", "2375 80")
  1729  	if id1 != id2 {
  1730  		c.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  1731  	}
  1732  }
  1733  
  1734  func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
  1735  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1736  	name := "testbuildexposeuppercaseproto"
  1737  	expected := "map[5678/udp:{}]"
  1738  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  1739          EXPOSE 5678/UDP`))
  1740  	res := inspectField(c, name, "Config.ExposedPorts")
  1741  	if res != expected {
  1742  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  1743  	}
  1744  }
  1745  
  1746  func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
  1747  	name := "testbuildentrypointinheritance"
  1748  	name2 := "testbuildentrypointinheritance2"
  1749  
  1750  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1751          ENTRYPOINT ["/bin/echo"]`))
  1752  	res := inspectField(c, name, "Config.Entrypoint")
  1753  
  1754  	expected := "[/bin/echo]"
  1755  	if res != expected {
  1756  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1757  	}
  1758  
  1759  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s
  1760          ENTRYPOINT []`, name)))
  1761  	res = inspectField(c, name2, "Config.Entrypoint")
  1762  
  1763  	expected = "[]"
  1764  	if res != expected {
  1765  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1766  	}
  1767  }
  1768  
  1769  func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
  1770  	name := "testbuildentrypoint"
  1771  	expected := "[]"
  1772  
  1773  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  1774          ENTRYPOINT []`))
  1775  
  1776  	res := inspectField(c, name, "Config.Entrypoint")
  1777  	if res != expected {
  1778  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1779  	}
  1780  
  1781  }
  1782  
  1783  func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
  1784  	name := "testbuildentrypoint"
  1785  
  1786  	expected := "[/bin/echo]"
  1787  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  1788          ENTRYPOINT ["/bin/echo"]`))
  1789  
  1790  	res := inspectField(c, name, "Config.Entrypoint")
  1791  	if res != expected {
  1792  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  1793  	}
  1794  
  1795  }
  1796  
  1797  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  1798  func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) {
  1799  	buildImageSuccessfully(c, "testonbuildtrigger1", withDockerfile(`
  1800  		FROM busybox
  1801  		RUN echo "GRANDPARENT"
  1802  		ONBUILD RUN echo "ONBUILD PARENT"
  1803  		`))
  1804  	// ONBUILD should be run in second build.
  1805  	buildImageNew("testonbuildtrigger2", withDockerfile("FROM testonbuildtrigger1")).Assert(c, icmd.Expected{
  1806  		Out: "ONBUILD PARENT",
  1807  	})
  1808  	// ONBUILD should *not* be run in third build.
  1809  	result := buildImageNew("testonbuildtrigger3", withDockerfile("FROM testonbuildtrigger2"))
  1810  	result.Assert(c, icmd.Success)
  1811  	if strings.Contains(result.Combined(), "ONBUILD PARENT") {
  1812  		c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  1813  	}
  1814  }
  1815  
  1816  func (s *DockerSuite) TestBuildSameDockerfileWithAndWithoutCache(c *check.C) {
  1817  	testRequires(c, DaemonIsLinux) // Expose not implemented on Windows
  1818  	name := "testbuildwithcache"
  1819  	dockerfile := `FROM scratch
  1820  		MAINTAINER dockerio
  1821  		EXPOSE 5432
  1822          ENTRYPOINT ["/bin/echo"]`
  1823  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1824  	id1, err := getIDByName(name)
  1825  	c.Assert(err, checker.IsNil)
  1826  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  1827  	id2, err := getIDByName(name)
  1828  	c.Assert(err, checker.IsNil)
  1829  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
  1830  	id3, err := getIDByName(name)
  1831  	c.Assert(err, checker.IsNil)
  1832  	if id1 != id2 {
  1833  		c.Fatal("The cache should have been used but hasn't.")
  1834  	}
  1835  	if id1 == id3 {
  1836  		c.Fatal("The cache should have been invalided but hasn't.")
  1837  	}
  1838  }
  1839  
  1840  // Make sure that ADD/COPY still populate the cache even if they don't use it
  1841  func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
  1842  	name := "testbuildconditionalcache"
  1843  
  1844  	dockerfile := `
  1845  		FROM busybox
  1846          ADD foo /tmp/`
  1847  	ctx, err := fakeContext(dockerfile, map[string]string{
  1848  		"foo": "hello",
  1849  	})
  1850  	if err != nil {
  1851  		c.Fatal(err)
  1852  	}
  1853  	defer ctx.Close()
  1854  
  1855  	id1, err := buildImageFromContext(name, ctx, true)
  1856  	if err != nil {
  1857  		c.Fatalf("Error building #1: %s", err)
  1858  	}
  1859  
  1860  	if err := ctx.Add("foo", "bye"); err != nil {
  1861  		c.Fatalf("Error modifying foo: %s", err)
  1862  	}
  1863  
  1864  	// Updating a file should invalidate the cache
  1865  	id2, err := buildImageFromContext(name, ctx, true)
  1866  	if err != nil {
  1867  		c.Fatalf("Error building #2: %s", err)
  1868  	}
  1869  	if id2 == id1 {
  1870  		c.Fatal("Should not have used the cache")
  1871  	}
  1872  
  1873  	id3, err := buildImageFromContext(name, ctx, true)
  1874  	if err != nil {
  1875  		c.Fatalf("Error building #3: %s", err)
  1876  	}
  1877  	if id3 != id2 {
  1878  		c.Fatal("Should have used the cache")
  1879  	}
  1880  }
  1881  
  1882  // FIXME(vdemeester) this really seems to test the same thing as before
  1883  func (s *DockerSuite) TestBuildAddMultipleLocalFileWithAndWithoutCache(c *check.C) {
  1884  	name := "testbuildaddmultiplelocalfilewithcache"
  1885  	dockerfile := `
  1886  		FROM busybox
  1887          MAINTAINER dockerio
  1888          ADD foo Dockerfile /usr/lib/bla/
  1889  		RUN sh -c "[ $(cat /usr/lib/bla/foo) = "hello" ]"`
  1890  	ctx, err := fakeContext(dockerfile, map[string]string{
  1891  		"foo": "hello",
  1892  	})
  1893  	if err != nil {
  1894  		c.Fatal(err)
  1895  	}
  1896  	defer ctx.Close()
  1897  	id1, err := buildImageFromContext(name, ctx, true)
  1898  	if err != nil {
  1899  		c.Fatal(err)
  1900  	}
  1901  	id2, err := buildImageFromContext(name, ctx, true)
  1902  	if err != nil {
  1903  		c.Fatal(err)
  1904  	}
  1905  	id3, err := buildImageFromContext(name, ctx, false)
  1906  	if err != nil {
  1907  		c.Fatal(err)
  1908  	}
  1909  	if id1 != id2 {
  1910  		c.Fatal("The cache should have been used but hasn't.")
  1911  	}
  1912  	if id1 == id3 {
  1913  		c.Fatal("The cache should have been invalided but hasn't.")
  1914  	}
  1915  }
  1916  
  1917  func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
  1918  	name := "testbuildcopydirbutnotfile"
  1919  	name2 := "testbuildcopydirbutnotfile2"
  1920  
  1921  	dockerfile := `
  1922          FROM ` + minimalBaseImage() + `
  1923          COPY dir /tmp/`
  1924  	ctx, err := fakeContext(dockerfile, map[string]string{
  1925  		"dir/foo": "hello",
  1926  	})
  1927  	if err != nil {
  1928  		c.Fatal(err)
  1929  	}
  1930  	defer ctx.Close()
  1931  	id1, err := buildImageFromContext(name, ctx, true)
  1932  	if err != nil {
  1933  		c.Fatal(err)
  1934  	}
  1935  	// Check that adding file with similar name doesn't mess with cache
  1936  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  1937  		c.Fatal(err)
  1938  	}
  1939  	id2, err := buildImageFromContext(name2, ctx, true)
  1940  	if err != nil {
  1941  		c.Fatal(err)
  1942  	}
  1943  	if id1 != id2 {
  1944  		c.Fatal("The cache should have been used but wasn't")
  1945  	}
  1946  }
  1947  
  1948  func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) {
  1949  	name := "testbuildaddcurrentdirwithcache"
  1950  	name2 := name + "2"
  1951  	name3 := name + "3"
  1952  	name4 := name + "4"
  1953  	dockerfile := `
  1954          FROM ` + minimalBaseImage() + `
  1955          MAINTAINER dockerio
  1956          ADD . /usr/lib/bla`
  1957  	ctx, err := fakeContext(dockerfile, map[string]string{
  1958  		"foo": "hello",
  1959  	})
  1960  	if err != nil {
  1961  		c.Fatal(err)
  1962  	}
  1963  	defer ctx.Close()
  1964  	id1, err := buildImageFromContext(name, ctx, true)
  1965  	if err != nil {
  1966  		c.Fatal(err)
  1967  	}
  1968  	// Check that adding file invalidate cache of "ADD ."
  1969  	if err := ctx.Add("bar", "hello2"); err != nil {
  1970  		c.Fatal(err)
  1971  	}
  1972  	id2, err := buildImageFromContext(name2, ctx, true)
  1973  	if err != nil {
  1974  		c.Fatal(err)
  1975  	}
  1976  	if id1 == id2 {
  1977  		c.Fatal("The cache should have been invalided but hasn't.")
  1978  	}
  1979  	// Check that changing file invalidate cache of "ADD ."
  1980  	if err := ctx.Add("foo", "hello1"); err != nil {
  1981  		c.Fatal(err)
  1982  	}
  1983  	id3, err := buildImageFromContext(name3, ctx, true)
  1984  	if err != nil {
  1985  		c.Fatal(err)
  1986  	}
  1987  	if id2 == id3 {
  1988  		c.Fatal("The cache should have been invalided but hasn't.")
  1989  	}
  1990  	// Check that changing file to same content with different mtime does not
  1991  	// invalidate cache of "ADD ."
  1992  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  1993  	if err := ctx.Add("foo", "hello1"); err != nil {
  1994  		c.Fatal(err)
  1995  	}
  1996  	id4, err := buildImageFromContext(name4, ctx, true)
  1997  	if err != nil {
  1998  		c.Fatal(err)
  1999  	}
  2000  	if id3 != id4 {
  2001  		c.Fatal("The cache should have been used but hasn't.")
  2002  	}
  2003  }
  2004  
  2005  // FIXME(vdemeester) this really seems to test the same thing as before (TestBuildAddMultipleLocalFileWithAndWithoutCache)
  2006  func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) {
  2007  	name := "testbuildaddcurrentdirwithoutcache"
  2008  	dockerfile := `
  2009          FROM ` + minimalBaseImage() + `
  2010          MAINTAINER dockerio
  2011          ADD . /usr/lib/bla`
  2012  	ctx, err := fakeContext(dockerfile, map[string]string{
  2013  		"foo": "hello",
  2014  	})
  2015  	if err != nil {
  2016  		c.Fatal(err)
  2017  	}
  2018  	defer ctx.Close()
  2019  	id1, err := buildImageFromContext(name, ctx, true)
  2020  	if err != nil {
  2021  		c.Fatal(err)
  2022  	}
  2023  	id2, err := buildImageFromContext(name, ctx, false)
  2024  	if err != nil {
  2025  		c.Fatal(err)
  2026  	}
  2027  	if id1 == id2 {
  2028  		c.Fatal("The cache should have been invalided but hasn't.")
  2029  	}
  2030  }
  2031  
  2032  func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) {
  2033  	name := "testbuildaddremotefilewithcache"
  2034  	server, err := fakeStorage(map[string]string{
  2035  		"baz": "hello",
  2036  	})
  2037  	if err != nil {
  2038  		c.Fatal(err)
  2039  	}
  2040  	defer server.Close()
  2041  
  2042  	dockerfile := fmt.Sprintf(`FROM `+minimalBaseImage()+`
  2043          MAINTAINER dockerio
  2044          ADD %s/baz /usr/lib/baz/quux`, server.URL())
  2045  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  2046  	id1, err := getIDByName(name)
  2047  	c.Assert(err, checker.IsNil)
  2048  	buildImageSuccessfully(c, name, withDockerfile(dockerfile))
  2049  	id2, err := getIDByName(name)
  2050  	c.Assert(err, checker.IsNil)
  2051  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile))
  2052  	id3, err := getIDByName(name)
  2053  	c.Assert(err, checker.IsNil)
  2054  
  2055  	if id1 != id2 {
  2056  		c.Fatal("The cache should have been used but hasn't.")
  2057  	}
  2058  	if id1 == id3 {
  2059  		c.Fatal("The cache should have been invalided but hasn't.")
  2060  	}
  2061  }
  2062  
  2063  func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) {
  2064  	name := "testbuildaddremotefilemtime"
  2065  	name2 := name + "2"
  2066  	name3 := name + "3"
  2067  
  2068  	files := map[string]string{"baz": "hello"}
  2069  	server, err := fakeStorage(files)
  2070  	if err != nil {
  2071  		c.Fatal(err)
  2072  	}
  2073  	defer server.Close()
  2074  
  2075  	ctx, err := fakeContext(fmt.Sprintf(`FROM `+minimalBaseImage()+`
  2076          MAINTAINER dockerio
  2077          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  2078  	if err != nil {
  2079  		c.Fatal(err)
  2080  	}
  2081  	defer ctx.Close()
  2082  
  2083  	id1, err := buildImageFromContext(name, ctx, true)
  2084  	if err != nil {
  2085  		c.Fatal(err)
  2086  	}
  2087  
  2088  	id2, err := buildImageFromContext(name2, ctx, true)
  2089  	if err != nil {
  2090  		c.Fatal(err)
  2091  	}
  2092  	if id1 != id2 {
  2093  		c.Fatal("The cache should have been used but wasn't - #1")
  2094  	}
  2095  
  2096  	// Now create a different server with same contents (causes different mtime)
  2097  	// The cache should still be used
  2098  
  2099  	// allow some time for clock to pass as mtime precision is only 1s
  2100  	time.Sleep(2 * time.Second)
  2101  
  2102  	server2, err := fakeStorage(files)
  2103  	if err != nil {
  2104  		c.Fatal(err)
  2105  	}
  2106  	defer server2.Close()
  2107  
  2108  	ctx2, err := fakeContext(fmt.Sprintf(`FROM `+minimalBaseImage()+`
  2109          MAINTAINER dockerio
  2110          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  2111  	if err != nil {
  2112  		c.Fatal(err)
  2113  	}
  2114  	defer ctx2.Close()
  2115  	id3, err := buildImageFromContext(name3, ctx2, true)
  2116  	if err != nil {
  2117  		c.Fatal(err)
  2118  	}
  2119  	if id1 != id3 {
  2120  		c.Fatal("The cache should have been used but wasn't")
  2121  	}
  2122  }
  2123  
  2124  // FIXME(vdemeester) this really seems to test the same thing as before (combined)
  2125  func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache(c *check.C) {
  2126  	name := "testbuildaddlocalandremotefilewithcache"
  2127  	server, err := fakeStorage(map[string]string{
  2128  		"baz": "hello",
  2129  	})
  2130  	if err != nil {
  2131  		c.Fatal(err)
  2132  	}
  2133  	defer server.Close()
  2134  
  2135  	ctx, err := fakeContext(fmt.Sprintf(`FROM `+minimalBaseImage()+`
  2136          MAINTAINER dockerio
  2137          ADD foo /usr/lib/bla/bar
  2138          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2139  		map[string]string{
  2140  			"foo": "hello world",
  2141  		})
  2142  	if err != nil {
  2143  		c.Fatal(err)
  2144  	}
  2145  	defer ctx.Close()
  2146  	id1, err := buildImageFromContext(name, ctx, true)
  2147  	if err != nil {
  2148  		c.Fatal(err)
  2149  	}
  2150  	id2, err := buildImageFromContext(name, ctx, true)
  2151  	if err != nil {
  2152  		c.Fatal(err)
  2153  	}
  2154  	id3, err := buildImageFromContext(name, ctx, false)
  2155  	if err != nil {
  2156  		c.Fatal(err)
  2157  	}
  2158  	if id1 != id2 {
  2159  		c.Fatal("The cache should have been used but hasn't.")
  2160  	}
  2161  	if id1 == id3 {
  2162  		c.Fatal("The cache should have been invalidated but hasn't.")
  2163  	}
  2164  }
  2165  
  2166  func testContextTar(c *check.C, compression archive.Compression) {
  2167  	ctx, err := fakeContext(
  2168  		`FROM busybox
  2169  ADD foo /foo
  2170  CMD ["cat", "/foo"]`,
  2171  		map[string]string{
  2172  			"foo": "bar",
  2173  		},
  2174  	)
  2175  	if err != nil {
  2176  		c.Fatal(err)
  2177  	}
  2178  	defer ctx.Close()
  2179  	context, err := archive.Tar(ctx.Dir, compression)
  2180  	if err != nil {
  2181  		c.Fatalf("failed to build context tar: %v", err)
  2182  	}
  2183  	name := "contexttar"
  2184  
  2185  	icmd.RunCmd(icmd.Cmd{
  2186  		Command: []string{dockerBinary, "build", "-t", name, "-"},
  2187  		Stdin:   context,
  2188  	}).Assert(c, icmd.Success)
  2189  }
  2190  
  2191  func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) {
  2192  	testContextTar(c, archive.Gzip)
  2193  }
  2194  
  2195  func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) {
  2196  	testContextTar(c, archive.Uncompressed)
  2197  }
  2198  
  2199  func (s *DockerSuite) TestBuildNoContext(c *check.C) {
  2200  	name := "nocontext"
  2201  	icmd.RunCmd(icmd.Cmd{
  2202  		Command: []string{dockerBinary, "build", "-t", name, "-"},
  2203  		Stdin: strings.NewReader(
  2204  			`FROM busybox
  2205  			CMD ["echo", "ok"]`),
  2206  	}).Assert(c, icmd.Success)
  2207  
  2208  	if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" {
  2209  		c.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  2210  	}
  2211  }
  2212  
  2213  func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) {
  2214  	testRequires(c, DaemonIsLinux)
  2215  	name := "testbuildimg"
  2216  
  2217  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox:latest
  2218          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  2219          VOLUME /test`))
  2220  
  2221  	out, _ := dockerCmd(c, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  2222  	if expected := "drw-------"; !strings.Contains(out, expected) {
  2223  		c.Fatalf("expected %s received %s", expected, out)
  2224  	}
  2225  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  2226  		c.Fatalf("expected %s received %s", expected, out)
  2227  	}
  2228  
  2229  }
  2230  
  2231  // testing #1405 - config.Cmd does not get cleaned up if
  2232  // utilizing cache
  2233  func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
  2234  	name := "testbuildcmdcleanup"
  2235  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2236          RUN echo "hello"`))
  2237  
  2238  	buildImageSuccessfully(c, name, withBuildContext(c,
  2239  		withFile("Dockerfile", `FROM busybox
  2240          RUN echo "hello"
  2241          ADD foo /foo
  2242          ENTRYPOINT ["/bin/echo"]`),
  2243  		withFile("foo", "hello")))
  2244  
  2245  	res := inspectField(c, name, "Config.Cmd")
  2246  	// Cmd must be cleaned up
  2247  	if res != "[]" {
  2248  		c.Fatalf("Cmd %s, expected nil", res)
  2249  	}
  2250  }
  2251  
  2252  func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) {
  2253  	name := "testbuildaddnotfound"
  2254  	expected := "foo: no such file or directory"
  2255  
  2256  	if testEnv.DaemonPlatform() == "windows" {
  2257  		expected = "foo: The system cannot find the file specified"
  2258  	}
  2259  
  2260  	buildImageNew(name, withBuildContext(c,
  2261  		withFile("Dockerfile", `FROM `+minimalBaseImage()+`
  2262          ADD foo /usr/local/bar`),
  2263  		withFile("bar", "hello"))).Assert(c, icmd.Expected{
  2264  		ExitCode: 1,
  2265  		Err:      expected,
  2266  	})
  2267  }
  2268  
  2269  func (s *DockerSuite) TestBuildInheritance(c *check.C) {
  2270  	testRequires(c, DaemonIsLinux)
  2271  	name := "testbuildinheritance"
  2272  
  2273  	buildImageSuccessfully(c, name, withDockerfile(`FROM scratch
  2274  		EXPOSE 2375`))
  2275  	ports1 := inspectField(c, name, "Config.ExposedPorts")
  2276  
  2277  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  2278  		ENTRYPOINT ["/bin/echo"]`, name)))
  2279  
  2280  	res := inspectField(c, name, "Config.Entrypoint")
  2281  	if expected := "[/bin/echo]"; res != expected {
  2282  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2283  	}
  2284  	ports2 := inspectField(c, name, "Config.ExposedPorts")
  2285  	if ports1 != ports2 {
  2286  		c.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  2287  	}
  2288  }
  2289  
  2290  func (s *DockerSuite) TestBuildFails(c *check.C) {
  2291  	name := "testbuildfails"
  2292  	buildImageNew(name, withDockerfile(`FROM busybox
  2293  		RUN sh -c "exit 23"`)).Assert(c, icmd.Expected{
  2294  		ExitCode: 23,
  2295  		Err:      "returned a non-zero code: 23",
  2296  	})
  2297  }
  2298  
  2299  func (s *DockerSuite) TestBuildOnBuild(c *check.C) {
  2300  	name := "testbuildonbuild"
  2301  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2302  		ONBUILD RUN touch foobar`))
  2303  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  2304  		RUN [ -f foobar ]`, name)))
  2305  }
  2306  
  2307  // gh #2446
  2308  func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
  2309  	makeLink := `ln -s /foo /bar`
  2310  	if testEnv.DaemonPlatform() == "windows" {
  2311  		makeLink = `mklink /D C:\bar C:\foo`
  2312  	}
  2313  	name := "testbuildaddtosymlinkdest"
  2314  	buildImageSuccessfully(c, name, withBuildContext(c,
  2315  		withFile("Dockerfile", `
  2316  		FROM busybox
  2317  		RUN sh -c "mkdir /foo"
  2318  		RUN `+makeLink+`
  2319  		ADD foo /bar/
  2320  		RUN sh -c "[ -f /bar/foo ]"
  2321  		RUN sh -c "[ -f /foo/foo ]"`),
  2322  		withFile("foo", "hello"),
  2323  	))
  2324  }
  2325  
  2326  func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) {
  2327  	name := "testbuildescapewhitespace"
  2328  
  2329  	buildImageSuccessfully(c, name, withDockerfile(`
  2330    # ESCAPE=\
  2331    FROM busybox
  2332    MAINTAINER "Docker \
  2333  IO <io@\
  2334  docker.com>"
  2335    `))
  2336  
  2337  	res := inspectField(c, name, "Author")
  2338  	if res != "\"Docker IO <io@docker.com>\"" {
  2339  		c.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  2340  	}
  2341  
  2342  }
  2343  
  2344  func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) {
  2345  	// Verify that strings that look like ints are still passed as strings
  2346  	name := "testbuildstringing"
  2347  
  2348  	buildImageSuccessfully(c, name, withDockerfile(`
  2349  	FROM busybox
  2350  	MAINTAINER 123`))
  2351  
  2352  	out, _ := dockerCmd(c, "inspect", name)
  2353  	if !strings.Contains(out, "\"123\"") {
  2354  		c.Fatalf("Output does not contain the int as a string:\n%s", out)
  2355  	}
  2356  
  2357  }
  2358  
  2359  func (s *DockerSuite) TestBuildDockerignore(c *check.C) {
  2360  	name := "testbuilddockerignore"
  2361  	buildImageSuccessfully(c, name, withBuildContext(c,
  2362  		withFile("Dockerfile", `
  2363  		FROM busybox
  2364  		 ADD . /bla
  2365  		RUN sh -c "[[ -f /bla/src/x.go ]]"
  2366  		RUN sh -c "[[ -f /bla/Makefile ]]"
  2367  		RUN sh -c "[[ ! -e /bla/src/_vendor ]]"
  2368  		RUN sh -c "[[ ! -e /bla/.gitignore ]]"
  2369  		RUN sh -c "[[ ! -e /bla/README.md ]]"
  2370  		RUN sh -c "[[ ! -e /bla/dir/foo ]]"
  2371  		RUN sh -c "[[ ! -e /bla/foo ]]"
  2372  		RUN sh -c "[[ ! -e /bla/.git ]]"
  2373  		RUN sh -c "[[ ! -e v.cc ]]"
  2374  		RUN sh -c "[[ ! -e src/v.cc ]]"
  2375  		RUN sh -c "[[ ! -e src/_vendor/v.cc ]]"`),
  2376  		withFile("Makefile", "all:"),
  2377  		withFile(".git/HEAD", "ref: foo"),
  2378  		withFile("src/x.go", "package main"),
  2379  		withFile("src/_vendor/v.go", "package main"),
  2380  		withFile("src/_vendor/v.cc", "package main"),
  2381  		withFile("src/v.cc", "package main"),
  2382  		withFile("v.cc", "package main"),
  2383  		withFile("dir/foo", ""),
  2384  		withFile(".gitignore", ""),
  2385  		withFile("README.md", "readme"),
  2386  		withFile(".dockerignore", `
  2387  .git
  2388  pkg
  2389  .gitignore
  2390  src/_vendor
  2391  *.md
  2392  **/*.cc
  2393  dir`),
  2394  	))
  2395  }
  2396  
  2397  func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) {
  2398  	name := "testbuilddockerignorecleanpaths"
  2399  	buildImageSuccessfully(c, name, withBuildContext(c,
  2400  		withFile("Dockerfile", `
  2401          FROM busybox
  2402          ADD . /tmp/
  2403          RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)"`),
  2404  		withFile("foo", "foo"),
  2405  		withFile("foo2", "foo2"),
  2406  		withFile("dir1/foo", "foo in dir1"),
  2407  		withFile(".dockerignore", "./foo\ndir1//foo\n./dir1/../foo2"),
  2408  	))
  2409  }
  2410  
  2411  func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) {
  2412  	name := "testbuilddockerignoreexceptions"
  2413  	buildImageSuccessfully(c, name, withBuildContext(c,
  2414  		withFile("Dockerfile", `
  2415  		FROM busybox
  2416  		ADD . /bla
  2417  		RUN sh -c "[[ -f /bla/src/x.go ]]"
  2418  		RUN sh -c "[[ -f /bla/Makefile ]]"
  2419  		RUN sh -c "[[ ! -e /bla/src/_vendor ]]"
  2420  		RUN sh -c "[[ ! -e /bla/.gitignore ]]"
  2421  		RUN sh -c "[[ ! -e /bla/README.md ]]"
  2422  		RUN sh -c "[[  -e /bla/dir/dir/foo ]]"
  2423  		RUN sh -c "[[ ! -e /bla/dir/foo1 ]]"
  2424  		RUN sh -c "[[ -f /bla/dir/e ]]"
  2425  		RUN sh -c "[[ -f /bla/dir/e-dir/foo ]]"
  2426  		RUN sh -c "[[ ! -e /bla/foo ]]"
  2427  		RUN sh -c "[[ ! -e /bla/.git ]]"
  2428  		RUN sh -c "[[ -e /bla/dir/a.cc ]]"`),
  2429  		withFile("Makefile", "all:"),
  2430  		withFile(".git/HEAD", "ref: foo"),
  2431  		withFile("src/x.go", "package main"),
  2432  		withFile("src/_vendor/v.go", "package main"),
  2433  		withFile("dir/foo", ""),
  2434  		withFile("dir/foo1", ""),
  2435  		withFile("dir/dir/f1", ""),
  2436  		withFile("dir/dir/foo", ""),
  2437  		withFile("dir/e", ""),
  2438  		withFile("dir/e-dir/foo", ""),
  2439  		withFile(".gitignore", ""),
  2440  		withFile("README.md", "readme"),
  2441  		withFile("dir/a.cc", "hello"),
  2442  		withFile(".dockerignore", `
  2443  .git
  2444  pkg
  2445  .gitignore
  2446  src/_vendor
  2447  *.md
  2448  dir
  2449  !dir/e*
  2450  !dir/dir/foo
  2451  **/*.cc
  2452  !**/*.cc`),
  2453  	))
  2454  }
  2455  
  2456  func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) {
  2457  	name := "testbuilddockerignoredockerfile"
  2458  	dockerfile := `
  2459  		FROM busybox
  2460  		ADD . /tmp/
  2461  		RUN sh -c "! ls /tmp/Dockerfile"
  2462  		RUN ls /tmp/.dockerignore`
  2463  	buildImageSuccessfully(c, name, withBuildContext(c,
  2464  		withFile("Dockerfile", dockerfile),
  2465  		withFile(".dockerignore", "Dockerfile\n"),
  2466  	))
  2467  	buildImageSuccessfully(c, name, withBuildContext(c,
  2468  		withFile("Dockerfile", dockerfile),
  2469  		withFile(".dockerignore", "./Dockerfile\n"),
  2470  	))
  2471  }
  2472  
  2473  func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) {
  2474  	name := "testbuilddockerignoredockerfile"
  2475  	dockerfile := `
  2476  		FROM busybox
  2477  		ADD . /tmp/
  2478  		RUN ls /tmp/Dockerfile
  2479  		RUN sh -c "! ls /tmp/MyDockerfile"
  2480  		RUN ls /tmp/.dockerignore`
  2481  	buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c,
  2482  		withFile("Dockerfile", "Should not use me"),
  2483  		withFile("MyDockerfile", dockerfile),
  2484  		withFile(".dockerignore", "MyDockerfile\n"),
  2485  	))
  2486  	buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c,
  2487  		withFile("Dockerfile", "Should not use me"),
  2488  		withFile("MyDockerfile", dockerfile),
  2489  		withFile(".dockerignore", "./MyDockerfile\n"),
  2490  	))
  2491  }
  2492  
  2493  func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) {
  2494  	name := "testbuilddockerignoredockerignore"
  2495  	dockerfile := `
  2496  		FROM busybox
  2497  		ADD . /tmp/
  2498  		RUN sh -c "! ls /tmp/.dockerignore"
  2499  		RUN ls /tmp/Dockerfile`
  2500  	buildImageSuccessfully(c, name, withBuildContext(c,
  2501  		withFile("Dockerfile", dockerfile),
  2502  		withFile(".dockerignore", ".dockerignore\n"),
  2503  	))
  2504  }
  2505  
  2506  func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) {
  2507  	var id1 string
  2508  	var id2 string
  2509  
  2510  	name := "testbuilddockerignoretouchdockerfile"
  2511  	dockerfile := `
  2512          FROM busybox
  2513  		ADD . /tmp/`
  2514  	ctx, err := fakeContext(dockerfile, map[string]string{
  2515  		"Dockerfile":    dockerfile,
  2516  		".dockerignore": "Dockerfile\n",
  2517  	})
  2518  	if err != nil {
  2519  		c.Fatal(err)
  2520  	}
  2521  	defer ctx.Close()
  2522  
  2523  	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
  2524  		c.Fatalf("Didn't build it correctly:%s", err)
  2525  	}
  2526  
  2527  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  2528  		c.Fatalf("Didn't build it correctly:%s", err)
  2529  	}
  2530  	if id1 != id2 {
  2531  		c.Fatalf("Didn't use the cache - 1")
  2532  	}
  2533  
  2534  	// Now make sure touching Dockerfile doesn't invalidate the cache
  2535  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  2536  		c.Fatalf("Didn't add Dockerfile: %s", err)
  2537  	}
  2538  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  2539  		c.Fatalf("Didn't build it correctly:%s", err)
  2540  	}
  2541  	if id1 != id2 {
  2542  		c.Fatalf("Didn't use the cache - 2")
  2543  	}
  2544  
  2545  	// One more time but just 'touch' it instead of changing the content
  2546  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  2547  		c.Fatalf("Didn't add Dockerfile: %s", err)
  2548  	}
  2549  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  2550  		c.Fatalf("Didn't build it correctly:%s", err)
  2551  	}
  2552  	if id1 != id2 {
  2553  		c.Fatalf("Didn't use the cache - 3")
  2554  	}
  2555  }
  2556  
  2557  func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) {
  2558  	name := "testbuilddockerignorewholedir"
  2559  
  2560  	dockerfile := `
  2561  		FROM busybox
  2562  		COPY . /
  2563  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2564  		RUN sh -c "[[ ! -e /Makefile ]]"`
  2565  
  2566  	buildImageSuccessfully(c, name, withBuildContext(c,
  2567  		withFile("Dockerfile", dockerfile),
  2568  		withFile(".dockerignore", "*\n"),
  2569  		withFile("Makefile", "all:"),
  2570  		withFile(".gitignore", ""),
  2571  	))
  2572  }
  2573  
  2574  func (s *DockerSuite) TestBuildDockerignoringOnlyDotfiles(c *check.C) {
  2575  	name := "testbuilddockerignorewholedir"
  2576  
  2577  	dockerfile := `
  2578  		FROM busybox
  2579  		COPY . /
  2580  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2581  		RUN sh -c "[[ -f /Makefile ]]"`
  2582  
  2583  	buildImageSuccessfully(c, name, withBuildContext(c,
  2584  		withFile("Dockerfile", dockerfile),
  2585  		withFile(".dockerignore", ".*"),
  2586  		withFile("Makefile", "all:"),
  2587  		withFile(".gitignore", ""),
  2588  	))
  2589  }
  2590  
  2591  func (s *DockerSuite) TestBuildDockerignoringBadExclusion(c *check.C) {
  2592  	name := "testbuilddockerignorebadexclusion"
  2593  	buildImageNew(name, withBuildContext(c,
  2594  		withFile("Dockerfile", `
  2595  		FROM busybox
  2596  		COPY . /
  2597  		RUN sh -c "[[ ! -e /.gitignore ]]"
  2598  		RUN sh -c "[[ -f /Makefile ]]"`),
  2599  		withFile("Makefile", "all:"),
  2600  		withFile(".gitignore", ""),
  2601  		withFile(".dockerignore", "!\n"),
  2602  	)).Assert(c, icmd.Expected{
  2603  		ExitCode: 1,
  2604  		Err:      "Error checking context: 'Illegal exclusion pattern: !",
  2605  	})
  2606  }
  2607  
  2608  func (s *DockerSuite) TestBuildDockerignoringWildTopDir(c *check.C) {
  2609  	dockerfile := `
  2610  		FROM busybox
  2611  		COPY . /
  2612  		RUN sh -c "[[ ! -e /.dockerignore ]]"
  2613  		RUN sh -c "[[ ! -e /Dockerfile ]]"
  2614  		RUN sh -c "[[ ! -e /file1 ]]"
  2615  		RUN sh -c "[[ ! -e /dir ]]"`
  2616  
  2617  	// All of these should result in ignoring all files
  2618  	for _, variant := range []string{"**", "**/", "**/**", "*"} {
  2619  		buildImageSuccessfully(c, "noname", withBuildContext(c,
  2620  			withFile("Dockerfile", dockerfile),
  2621  			withFile("file1", ""),
  2622  			withFile("dir/file1", ""),
  2623  			withFile(".dockerignore", variant),
  2624  		))
  2625  
  2626  		dockerCmd(c, "rmi", "noname")
  2627  	}
  2628  }
  2629  
  2630  func (s *DockerSuite) TestBuildDockerignoringWildDirs(c *check.C) {
  2631  	dockerfile := `
  2632          FROM busybox
  2633  		COPY . /
  2634  		#RUN sh -c "[[ -e /.dockerignore ]]"
  2635  		RUN sh -c "[[ -e /Dockerfile ]]           && \
  2636  		           [[ ! -e /file0 ]]              && \
  2637  		           [[ ! -e /dir1/file0 ]]         && \
  2638  		           [[ ! -e /dir2/file0 ]]         && \
  2639  		           [[ ! -e /file1 ]]              && \
  2640  		           [[ ! -e /dir1/file1 ]]         && \
  2641  		           [[ ! -e /dir1/dir2/file1 ]]    && \
  2642  		           [[ ! -e /dir1/file2 ]]         && \
  2643  		           [[   -e /dir1/dir2/file2 ]]    && \
  2644  		           [[ ! -e /dir1/dir2/file4 ]]    && \
  2645  		           [[ ! -e /dir1/dir2/file5 ]]    && \
  2646  		           [[ ! -e /dir1/dir2/file6 ]]    && \
  2647  		           [[ ! -e /dir1/dir3/file7 ]]    && \
  2648  		           [[ ! -e /dir1/dir3/file8 ]]    && \
  2649  		           [[   -e /dir1/dir3 ]]          && \
  2650  		           [[   -e /dir1/dir4 ]]          && \
  2651  		           [[ ! -e 'dir1/dir5/fileAA' ]]  && \
  2652  		           [[   -e 'dir1/dir5/fileAB' ]]  && \
  2653  		           [[   -e 'dir1/dir5/fileB' ]]"   # "." in pattern means nothing
  2654  
  2655  		RUN echo all done!`
  2656  
  2657  	dockerignore := `
  2658  **/file0
  2659  **/*file1
  2660  **/dir1/file2
  2661  dir1/**/file4
  2662  **/dir2/file5
  2663  **/dir1/dir2/file6
  2664  dir1/dir3/**
  2665  **/dir4/**
  2666  **/file?A
  2667  **/file\?B
  2668  **/dir5/file.
  2669  `
  2670  
  2671  	buildImageSuccessfully(c, "noname", withBuildContext(c,
  2672  		withFile("Dockerfile", dockerfile),
  2673  		withFile(".dockerignore", dockerignore),
  2674  		withFile("dir1/file0", ""),
  2675  		withFile("dir1/dir2/file0", ""),
  2676  		withFile("file1", ""),
  2677  		withFile("dir1/file1", ""),
  2678  		withFile("dir1/dir2/file1", ""),
  2679  		withFile("dir1/file2", ""),
  2680  		withFile("dir1/dir2/file2", ""), // remains
  2681  		withFile("dir1/dir2/file4", ""),
  2682  		withFile("dir1/dir2/file5", ""),
  2683  		withFile("dir1/dir2/file6", ""),
  2684  		withFile("dir1/dir3/file7", ""),
  2685  		withFile("dir1/dir3/file8", ""),
  2686  		withFile("dir1/dir4/file9", ""),
  2687  		withFile("dir1/dir5/fileAA", ""),
  2688  		withFile("dir1/dir5/fileAB", ""),
  2689  		withFile("dir1/dir5/fileB", ""),
  2690  	))
  2691  }
  2692  
  2693  func (s *DockerSuite) TestBuildLineBreak(c *check.C) {
  2694  	testRequires(c, DaemonIsLinux)
  2695  	name := "testbuildlinebreak"
  2696  	buildImageSuccessfully(c, name, withDockerfile(`FROM  busybox
  2697  RUN    sh -c 'echo root:testpass \
  2698  	> /tmp/passwd'
  2699  RUN    mkdir -p /var/run/sshd
  2700  RUN    sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]"
  2701  RUN    sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`))
  2702  }
  2703  
  2704  func (s *DockerSuite) TestBuildEOLInLine(c *check.C) {
  2705  	testRequires(c, DaemonIsLinux)
  2706  	name := "testbuildeolinline"
  2707  	buildImageSuccessfully(c, name, withDockerfile(`FROM   busybox
  2708  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  2709  RUN    echo "foo \n bar"; echo "baz"
  2710  RUN    mkdir -p /var/run/sshd
  2711  RUN    sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]"
  2712  RUN    sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`))
  2713  }
  2714  
  2715  func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) {
  2716  	testRequires(c, DaemonIsLinux)
  2717  	name := "testbuildcomments"
  2718  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2719  # This is an ordinary comment.
  2720  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  2721  RUN [ ! -x /hello.sh ]
  2722  # comment with line break \
  2723  RUN chmod +x /hello.sh
  2724  RUN [ -x /hello.sh ]
  2725  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  2726  RUN [ "$(/hello.sh)" = "hello world" ]`))
  2727  }
  2728  
  2729  func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) {
  2730  	testRequires(c, DaemonIsLinux)
  2731  	name := "testbuildusers"
  2732  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  2733  
  2734  # Make sure our defaults work
  2735  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  2736  
  2737  # 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)
  2738  USER root
  2739  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  2740  
  2741  # Setup dockerio user and group
  2742  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd && \
  2743  	echo 'dockerio:x:1001:' >> /etc/group
  2744  
  2745  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  2746  USER dockerio
  2747  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2748  
  2749  # Switch back to root and double check that worked exactly as we might expect it to
  2750  USER root
  2751  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ] && \
  2752          # Add a "supplementary" group for our dockerio user
  2753  	echo 'supplementary:x:1002:dockerio' >> /etc/group
  2754  
  2755  # ... and then go verify that we get it like we expect
  2756  USER dockerio
  2757  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  2758  USER 1001
  2759  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  2760  
  2761  # super test the new "user:group" syntax
  2762  USER dockerio:dockerio
  2763  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2764  USER 1001:dockerio
  2765  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2766  USER dockerio:1001
  2767  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2768  USER 1001:1001
  2769  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  2770  USER dockerio:supplementary
  2771  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2772  USER dockerio:1002
  2773  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2774  USER 1001:supplementary
  2775  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2776  USER 1001:1002
  2777  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  2778  
  2779  # make sure unknown uid/gid still works properly
  2780  USER 1042:1043
  2781  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`))
  2782  }
  2783  
  2784  // FIXME(vdemeester) rename this test (and probably "merge" it with the one below TestBuildEnvUsage2)
  2785  func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
  2786  	// /docker/world/hello is not owned by the correct user
  2787  	testRequires(c, NotUserNamespace)
  2788  	testRequires(c, DaemonIsLinux)
  2789  	name := "testbuildenvusage"
  2790  	dockerfile := `FROM busybox
  2791  ENV    HOME /root
  2792  ENV    PATH $HOME/bin:$PATH
  2793  ENV    PATH /tmp:$PATH
  2794  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  2795  ENV    FOO /foo/baz
  2796  ENV    BAR /bar
  2797  ENV    BAZ $BAR
  2798  ENV    FOOPATH $PATH:$FOO
  2799  RUN    [ "$BAR" = "$BAZ" ]
  2800  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  2801  ENV    FROM hello/docker/world
  2802  ENV    TO /docker/world/hello
  2803  ADD    $FROM $TO
  2804  RUN    [ "$(cat $TO)" = "hello" ]
  2805  ENV    abc=def
  2806  ENV    ghi=$abc
  2807  RUN    [ "$ghi" = "def" ]
  2808  `
  2809  	buildImageSuccessfully(c, name, withBuildContext(c,
  2810  		withFile("Dockerfile", dockerfile),
  2811  		withFile("hello/docker/world", "hello"),
  2812  	))
  2813  }
  2814  
  2815  // FIXME(vdemeester) rename this test (and probably "merge" it with the one above TestBuildEnvUsage)
  2816  func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
  2817  	// /docker/world/hello is not owned by the correct user
  2818  	testRequires(c, NotUserNamespace)
  2819  	testRequires(c, DaemonIsLinux)
  2820  	name := "testbuildenvusage2"
  2821  	dockerfile := `FROM busybox
  2822  ENV    abc=def def="hello world"
  2823  RUN    [ "$abc,$def" = "def,hello world" ]
  2824  ENV    def=hello\ world v1=abc v2="hi there" v3='boogie nights' v4="with'quotes too"
  2825  RUN    [ "$def,$v1,$v2,$v3,$v4" = "hello world,abc,hi there,boogie nights,with'quotes too" ]
  2826  ENV    abc=zzz FROM=hello/docker/world
  2827  ENV    abc=zzz TO=/docker/world/hello
  2828  ADD    $FROM $TO
  2829  RUN    [ "$abc,$(cat $TO)" = "zzz,hello" ]
  2830  ENV    abc 'yyy'
  2831  RUN    [ $abc = 'yyy' ]
  2832  ENV    abc=
  2833  RUN    [ "$abc" = "" ]
  2834  
  2835  # use grep to make sure if the builder substitutes \$foo by mistake
  2836  # we don't get a false positive
  2837  ENV    abc=\$foo
  2838  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  2839  ENV    abc \$foo
  2840  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  2841  
  2842  ENV    abc=\'foo\' abc2=\"foo\"
  2843  RUN    [ "$abc,$abc2" = "'foo',\"foo\"" ]
  2844  ENV    abc "foo"
  2845  RUN    [ "$abc" = "foo" ]
  2846  ENV    abc 'foo'
  2847  RUN    [ "$abc" = 'foo' ]
  2848  ENV    abc \'foo\'
  2849  RUN    [ "$abc" = "'foo'" ]
  2850  ENV    abc \"foo\"
  2851  RUN    [ "$abc" = '"foo"' ]
  2852  
  2853  ENV    abc=ABC
  2854  RUN    [ "$abc" = "ABC" ]
  2855  ENV    def1=${abc:-DEF} def2=${ccc:-DEF}
  2856  ENV    def3=${ccc:-${def2}xx} def4=${abc:+ALT} def5=${def2:+${abc}:} def6=${ccc:-\$abc:} def7=${ccc:-\${abc}:}
  2857  RUN    [ "$def1,$def2,$def3,$def4,$def5,$def6,$def7" = 'ABC,DEF,DEFxx,ALT,ABC:,$abc:,${abc:}' ]
  2858  ENV    mypath=${mypath:+$mypath:}/home
  2859  ENV    mypath=${mypath:+$mypath:}/away
  2860  RUN    [ "$mypath" = '/home:/away' ]
  2861  
  2862  ENV    e1=bar
  2863  ENV    e2=$e1 e3=$e11 e4=\$e1 e5=\$e11
  2864  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  2865  
  2866  ENV    ee1 bar
  2867  ENV    ee2 $ee1
  2868  ENV    ee3 $ee11
  2869  ENV    ee4 \$ee1
  2870  ENV    ee5 \$ee11
  2871  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  2872  
  2873  ENV    eee1="foo" eee2='foo'
  2874  ENV    eee3 "foo"
  2875  ENV    eee4 'foo'
  2876  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  2877  
  2878  `
  2879  	buildImageSuccessfully(c, name, withBuildContext(c,
  2880  		withFile("Dockerfile", dockerfile),
  2881  		withFile("hello/docker/world", "hello"),
  2882  	))
  2883  }
  2884  
  2885  func (s *DockerSuite) TestBuildAddScript(c *check.C) {
  2886  	testRequires(c, DaemonIsLinux)
  2887  	name := "testbuildaddscript"
  2888  	dockerfile := `
  2889  FROM busybox
  2890  ADD test /test
  2891  RUN ["chmod","+x","/test"]
  2892  RUN ["/test"]
  2893  RUN [ "$(cat /testfile)" = 'test!' ]`
  2894  
  2895  	buildImageSuccessfully(c, name, withBuildContext(c,
  2896  		withFile("Dockerfile", dockerfile),
  2897  		withFile("test", "#!/bin/sh\necho 'test!' > /testfile"),
  2898  	))
  2899  }
  2900  
  2901  func (s *DockerSuite) TestBuildAddTar(c *check.C) {
  2902  	// /test/foo is not owned by the correct user
  2903  	testRequires(c, NotUserNamespace)
  2904  	name := "testbuildaddtar"
  2905  
  2906  	ctx := func() *FakeContext {
  2907  		dockerfile := `
  2908  FROM busybox
  2909  ADD test.tar /
  2910  RUN cat /test/foo | grep Hi
  2911  ADD test.tar /test.tar
  2912  RUN cat /test.tar/test/foo | grep Hi
  2913  ADD test.tar /unlikely-to-exist
  2914  RUN cat /unlikely-to-exist/test/foo | grep Hi
  2915  ADD test.tar /unlikely-to-exist-trailing-slash/
  2916  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  2917  RUN sh -c "mkdir /existing-directory" #sh -c is needed on Windows to use the correct mkdir
  2918  ADD test.tar /existing-directory
  2919  RUN cat /existing-directory/test/foo | grep Hi
  2920  ADD test.tar /existing-directory-trailing-slash/
  2921  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  2922  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2923  		c.Assert(err, check.IsNil)
  2924  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2925  		if err != nil {
  2926  			c.Fatalf("failed to create test.tar archive: %v", err)
  2927  		}
  2928  		defer testTar.Close()
  2929  
  2930  		tw := tar.NewWriter(testTar)
  2931  
  2932  		if err := tw.WriteHeader(&tar.Header{
  2933  			Name: "test/foo",
  2934  			Size: 2,
  2935  		}); err != nil {
  2936  			c.Fatalf("failed to write tar file header: %v", err)
  2937  		}
  2938  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2939  			c.Fatalf("failed to write tar file content: %v", err)
  2940  		}
  2941  		if err := tw.Close(); err != nil {
  2942  			c.Fatalf("failed to close tar archive: %v", err)
  2943  		}
  2944  
  2945  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2946  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2947  		}
  2948  		return fakeContextFromDir(tmpDir)
  2949  	}()
  2950  	defer ctx.Close()
  2951  
  2952  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2953  		c.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  2954  	}
  2955  
  2956  }
  2957  
  2958  func (s *DockerSuite) TestBuildAddBrokenTar(c *check.C) {
  2959  	name := "testbuildaddbrokentar"
  2960  
  2961  	ctx := func() *FakeContext {
  2962  		dockerfile := `
  2963  FROM busybox
  2964  ADD test.tar /`
  2965  		tmpDir, err := ioutil.TempDir("", "fake-context")
  2966  		c.Assert(err, check.IsNil)
  2967  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  2968  		if err != nil {
  2969  			c.Fatalf("failed to create test.tar archive: %v", err)
  2970  		}
  2971  		defer testTar.Close()
  2972  
  2973  		tw := tar.NewWriter(testTar)
  2974  
  2975  		if err := tw.WriteHeader(&tar.Header{
  2976  			Name: "test/foo",
  2977  			Size: 2,
  2978  		}); err != nil {
  2979  			c.Fatalf("failed to write tar file header: %v", err)
  2980  		}
  2981  		if _, err := tw.Write([]byte("Hi")); err != nil {
  2982  			c.Fatalf("failed to write tar file content: %v", err)
  2983  		}
  2984  		if err := tw.Close(); err != nil {
  2985  			c.Fatalf("failed to close tar archive: %v", err)
  2986  		}
  2987  
  2988  		// Corrupt the tar by removing one byte off the end
  2989  		stat, err := testTar.Stat()
  2990  		if err != nil {
  2991  			c.Fatalf("failed to stat tar archive: %v", err)
  2992  		}
  2993  		if err := testTar.Truncate(stat.Size() - 1); err != nil {
  2994  			c.Fatalf("failed to truncate tar archive: %v", err)
  2995  		}
  2996  
  2997  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  2998  			c.Fatalf("failed to open destination dockerfile: %v", err)
  2999  		}
  3000  		return fakeContextFromDir(tmpDir)
  3001  	}()
  3002  	defer ctx.Close()
  3003  
  3004  	if _, err := buildImageFromContext(name, ctx, true); err == nil {
  3005  		c.Fatalf("build should have failed for TestBuildAddBrokenTar")
  3006  	}
  3007  }
  3008  
  3009  func (s *DockerSuite) TestBuildAddNonTar(c *check.C) {
  3010  	name := "testbuildaddnontar"
  3011  
  3012  	// Should not try to extract test.tar
  3013  	buildImageSuccessfully(c, name, withBuildContext(c,
  3014  		withFile("Dockerfile", `
  3015  		FROM busybox
  3016  		ADD test.tar /
  3017  		RUN test -f /test.tar`),
  3018  		withFile("test.tar", "not_a_tar_file"),
  3019  	))
  3020  }
  3021  
  3022  func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
  3023  	// /test/foo is not owned by the correct user
  3024  	testRequires(c, NotUserNamespace)
  3025  	testRequires(c, DaemonIsLinux)
  3026  	name := "testbuildaddtarxz"
  3027  
  3028  	ctx := func() *FakeContext {
  3029  		dockerfile := `
  3030  			FROM busybox
  3031  			ADD test.tar.xz /
  3032  			RUN cat /test/foo | grep Hi`
  3033  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3034  		c.Assert(err, check.IsNil)
  3035  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3036  		if err != nil {
  3037  			c.Fatalf("failed to create test.tar archive: %v", err)
  3038  		}
  3039  		defer testTar.Close()
  3040  
  3041  		tw := tar.NewWriter(testTar)
  3042  
  3043  		if err := tw.WriteHeader(&tar.Header{
  3044  			Name: "test/foo",
  3045  			Size: 2,
  3046  		}); err != nil {
  3047  			c.Fatalf("failed to write tar file header: %v", err)
  3048  		}
  3049  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3050  			c.Fatalf("failed to write tar file content: %v", err)
  3051  		}
  3052  		if err := tw.Close(); err != nil {
  3053  			c.Fatalf("failed to close tar archive: %v", err)
  3054  		}
  3055  
  3056  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  3057  		xzCompressCmd.Dir = tmpDir
  3058  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3059  		if err != nil {
  3060  			c.Fatal(err, out)
  3061  		}
  3062  
  3063  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3064  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3065  		}
  3066  		return fakeContextFromDir(tmpDir)
  3067  	}()
  3068  
  3069  	defer ctx.Close()
  3070  
  3071  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3072  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  3073  	}
  3074  
  3075  }
  3076  
  3077  func (s *DockerSuite) TestBuildAddTarXzGz(c *check.C) {
  3078  	testRequires(c, DaemonIsLinux)
  3079  	name := "testbuildaddtarxzgz"
  3080  
  3081  	ctx := func() *FakeContext {
  3082  		dockerfile := `
  3083  			FROM busybox
  3084  			ADD test.tar.xz.gz /
  3085  			RUN ls /test.tar.xz.gz`
  3086  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3087  		c.Assert(err, check.IsNil)
  3088  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3089  		if err != nil {
  3090  			c.Fatalf("failed to create test.tar archive: %v", err)
  3091  		}
  3092  		defer testTar.Close()
  3093  
  3094  		tw := tar.NewWriter(testTar)
  3095  
  3096  		if err := tw.WriteHeader(&tar.Header{
  3097  			Name: "test/foo",
  3098  			Size: 2,
  3099  		}); err != nil {
  3100  			c.Fatalf("failed to write tar file header: %v", err)
  3101  		}
  3102  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3103  			c.Fatalf("failed to write tar file content: %v", err)
  3104  		}
  3105  		if err := tw.Close(); err != nil {
  3106  			c.Fatalf("failed to close tar archive: %v", err)
  3107  		}
  3108  
  3109  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  3110  		xzCompressCmd.Dir = tmpDir
  3111  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3112  		if err != nil {
  3113  			c.Fatal(err, out)
  3114  		}
  3115  
  3116  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  3117  		gzipCompressCmd.Dir = tmpDir
  3118  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  3119  		if err != nil {
  3120  			c.Fatal(err, out)
  3121  		}
  3122  
  3123  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3124  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3125  		}
  3126  		return fakeContextFromDir(tmpDir)
  3127  	}()
  3128  
  3129  	defer ctx.Close()
  3130  
  3131  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3132  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  3133  	}
  3134  
  3135  }
  3136  
  3137  func (s *DockerSuite) TestBuildFromGit(c *check.C) {
  3138  	name := "testbuildfromgit"
  3139  	git, err := newFakeGit("repo", map[string]string{
  3140  		"Dockerfile": `FROM busybox
  3141  		ADD first /first
  3142  		RUN [ -f /first ]
  3143  		MAINTAINER docker`,
  3144  		"first": "test git data",
  3145  	}, true)
  3146  	if err != nil {
  3147  		c.Fatal(err)
  3148  	}
  3149  	defer git.Close()
  3150  
  3151  	buildImageSuccessfully(c, name, withBuildContextPath(git.RepoURL))
  3152  
  3153  	res := inspectField(c, name, "Author")
  3154  	if res != "docker" {
  3155  		c.Fatalf("Maintainer should be docker, got %s", res)
  3156  	}
  3157  }
  3158  
  3159  func (s *DockerSuite) TestBuildFromGitWithContext(c *check.C) {
  3160  	name := "testbuildfromgit"
  3161  	git, err := newFakeGit("repo", map[string]string{
  3162  		"docker/Dockerfile": `FROM busybox
  3163  					ADD first /first
  3164  					RUN [ -f /first ]
  3165  					MAINTAINER docker`,
  3166  		"docker/first": "test git data",
  3167  	}, true)
  3168  	if err != nil {
  3169  		c.Fatal(err)
  3170  	}
  3171  	defer git.Close()
  3172  
  3173  	buildImageSuccessfully(c, name, withBuildContextPath(fmt.Sprintf("%s#master:docker", git.RepoURL)))
  3174  
  3175  	res := inspectField(c, name, "Author")
  3176  	if res != "docker" {
  3177  		c.Fatalf("Maintainer should be docker, got %s", res)
  3178  	}
  3179  }
  3180  
  3181  func (s *DockerSuite) TestBuildFromGitwithF(c *check.C) {
  3182  	name := "testbuildfromgitwithf"
  3183  	git, err := newFakeGit("repo", map[string]string{
  3184  		"myApp/myDockerfile": `FROM busybox
  3185  					RUN echo hi from Dockerfile`,
  3186  	}, true)
  3187  	if err != nil {
  3188  		c.Fatal(err)
  3189  	}
  3190  	defer git.Close()
  3191  
  3192  	buildImageNew(name, withBuildFlags("-f", "myApp/myDockerfile"), withBuildContextPath(git.RepoURL)).Assert(c, icmd.Expected{
  3193  		Out: "hi from Dockerfile",
  3194  	})
  3195  }
  3196  
  3197  func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) {
  3198  	name := "testbuildfromremotetarball"
  3199  
  3200  	buffer := new(bytes.Buffer)
  3201  	tw := tar.NewWriter(buffer)
  3202  	defer tw.Close()
  3203  
  3204  	dockerfile := []byte(`FROM busybox
  3205  					MAINTAINER docker`)
  3206  	if err := tw.WriteHeader(&tar.Header{
  3207  		Name: "Dockerfile",
  3208  		Size: int64(len(dockerfile)),
  3209  	}); err != nil {
  3210  		c.Fatalf("failed to write tar file header: %v", err)
  3211  	}
  3212  	if _, err := tw.Write(dockerfile); err != nil {
  3213  		c.Fatalf("failed to write tar file content: %v", err)
  3214  	}
  3215  	if err := tw.Close(); err != nil {
  3216  		c.Fatalf("failed to close tar archive: %v", err)
  3217  	}
  3218  
  3219  	server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
  3220  		"testT.tar": buffer,
  3221  	})
  3222  	c.Assert(err, check.IsNil)
  3223  
  3224  	defer server.Close()
  3225  
  3226  	buildImageSuccessfully(c, name, withBuildContextPath(server.URL()+"/testT.tar"))
  3227  
  3228  	res := inspectField(c, name, "Author")
  3229  	if res != "docker" {
  3230  		c.Fatalf("Maintainer should be docker, got %s", res)
  3231  	}
  3232  }
  3233  
  3234  func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
  3235  	name := "testbuildcmdcleanuponentrypoint"
  3236  
  3237  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  3238  		CMD ["test"]
  3239  		ENTRYPOINT ["echo"]`))
  3240  	buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s
  3241  		ENTRYPOINT ["cat"]`, name)))
  3242  
  3243  	res := inspectField(c, name, "Config.Cmd")
  3244  	if res != "[]" {
  3245  		c.Fatalf("Cmd %s, expected nil", res)
  3246  	}
  3247  	res = inspectField(c, name, "Config.Entrypoint")
  3248  	if expected := "[cat]"; res != expected {
  3249  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  3250  	}
  3251  }
  3252  
  3253  func (s *DockerSuite) TestBuildClearCmd(c *check.C) {
  3254  	name := "testbuildclearcmd"
  3255  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  3256     ENTRYPOINT ["/bin/bash"]
  3257     CMD []`))
  3258  
  3259  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3260  	if res != "[]" {
  3261  		c.Fatalf("Cmd %s, expected %s", res, "[]")
  3262  	}
  3263  }
  3264  
  3265  func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) {
  3266  	// Skip on Windows. Base image on Windows has a CMD set in the image.
  3267  	testRequires(c, DaemonIsLinux)
  3268  
  3269  	name := "testbuildemptycmd"
  3270  	buildImageSuccessfully(c, name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n"))
  3271  
  3272  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3273  	if res != "null" {
  3274  		c.Fatalf("Cmd %s, expected %s", res, "null")
  3275  	}
  3276  }
  3277  
  3278  func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) {
  3279  	name := "testbuildonbuildparent"
  3280  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nONBUILD RUN echo foo\n"))
  3281  
  3282  	buildImageNew(name, withDockerfile("FROM "+name+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{
  3283  		Out: "# Executing 1 build trigger",
  3284  	})
  3285  }
  3286  
  3287  // FIXME(vdemeester) should be a unit test
  3288  func (s *DockerSuite) TestBuildInvalidTag(c *check.C) {
  3289  	name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200)
  3290  	buildImageNew(name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{
  3291  		ExitCode: 125,
  3292  		Err:      "Error parsing reference",
  3293  	})
  3294  }
  3295  
  3296  func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) {
  3297  	name := "testbuildcmdshc"
  3298  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD echo cmd\n"))
  3299  
  3300  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3301  	expected := `["/bin/sh","-c","echo cmd"]`
  3302  	if testEnv.DaemonPlatform() == "windows" {
  3303  		expected = `["cmd","/S","/C","echo cmd"]`
  3304  	}
  3305  	if res != expected {
  3306  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3307  	}
  3308  
  3309  }
  3310  
  3311  func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) {
  3312  	// Test to make sure that when we strcat arrays we take into account
  3313  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  3314  	// look the same
  3315  	name := "testbuildcmdspaces"
  3316  
  3317  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo hi\"]\n"))
  3318  	id1, err := getIDByName(name)
  3319  	c.Assert(err, checker.IsNil)
  3320  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"hi\"]\n"))
  3321  	id2, err := getIDByName(name)
  3322  
  3323  	if id1 == id2 {
  3324  		c.Fatal("Should not have resulted in the same CMD")
  3325  	}
  3326  
  3327  	// Now do the same with ENTRYPOINT
  3328  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo hi\"]\n"))
  3329  	id1, err = getIDByName(name)
  3330  	c.Assert(err, checker.IsNil)
  3331  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n"))
  3332  	id2, err = getIDByName(name)
  3333  
  3334  	if id1 == id2 {
  3335  		c.Fatal("Should not have resulted in the same ENTRYPOINT")
  3336  	}
  3337  }
  3338  
  3339  func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) {
  3340  	name := "testbuildcmdjson"
  3341  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"cmd\"]"))
  3342  
  3343  	res := inspectFieldJSON(c, name, "Config.Cmd")
  3344  	expected := `["echo","cmd"]`
  3345  	if res != expected {
  3346  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3347  	}
  3348  }
  3349  
  3350  func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChild(c *check.C) {
  3351  	buildImageSuccessfully(c, "parent", withDockerfile(`
  3352      FROM busybox
  3353      ENTRYPOINT exit 130
  3354      `))
  3355  
  3356  	icmd.RunCommand(dockerBinary, "run", "parent").Assert(c, icmd.Expected{
  3357  		ExitCode: 130,
  3358  	})
  3359  
  3360  	buildImageSuccessfully(c, "child", withDockerfile(`
  3361      FROM parent
  3362      ENTRYPOINT exit 5
  3363      `))
  3364  
  3365  	icmd.RunCommand(dockerBinary, "run", "child").Assert(c, icmd.Expected{
  3366  		ExitCode: 5,
  3367  	})
  3368  }
  3369  
  3370  func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChildInspect(c *check.C) {
  3371  	var (
  3372  		name     = "testbuildepinherit"
  3373  		name2    = "testbuildepinherit2"
  3374  		expected = `["/bin/sh","-c","echo quux"]`
  3375  	)
  3376  
  3377  	if testEnv.DaemonPlatform() == "windows" {
  3378  		expected = `["cmd","/S","/C","echo quux"]`
  3379  	}
  3380  
  3381  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT /foo/bar"))
  3382  	buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name)))
  3383  
  3384  	res := inspectFieldJSON(c, name2, "Config.Entrypoint")
  3385  	if res != expected {
  3386  		c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  3387  	}
  3388  
  3389  	icmd.RunCommand(dockerBinary, "run", name2).Assert(c, icmd.Expected{
  3390  		Out: "quux",
  3391  	})
  3392  }
  3393  
  3394  func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) {
  3395  	name := "testbuildentrypoint"
  3396  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3397                                  ENTRYPOINT echo`))
  3398  	dockerCmd(c, "run", "--rm", name)
  3399  }
  3400  
  3401  func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) {
  3402  	testRequires(c, DaemonIsLinux)
  3403  	name := "testbuildexoticshellinterpolation"
  3404  
  3405  	buildImageSuccessfully(c, name, withDockerfile(`
  3406  		FROM busybox
  3407  
  3408  		ENV SOME_VAR a.b.c
  3409  
  3410  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  3411  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  3412  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  3413  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  3414  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  3415  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  3416  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  3417  		RUN [ "${#SOME_VAR}"    = '5'     ]
  3418  
  3419  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  3420  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  3421  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  3422  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  3423  	`))
  3424  }
  3425  
  3426  func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) {
  3427  	// This testcase is supposed to generate an error because the
  3428  	// JSON array we're passing in on the CMD uses single quotes instead
  3429  	// of double quotes (per the JSON spec). This means we interpret it
  3430  	// as a "string" instead of "JSON array" and pass it on to "sh -c" and
  3431  	// it should barf on it.
  3432  	name := "testbuildsinglequotefails"
  3433  	expectedExitCode := 2
  3434  	if testEnv.DaemonPlatform() == "windows" {
  3435  		expectedExitCode = 127
  3436  	}
  3437  
  3438  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3439  		CMD [ '/bin/sh', '-c', 'echo hi' ]`))
  3440  
  3441  	icmd.RunCommand(dockerBinary, "run", "--rm", name).Assert(c, icmd.Expected{
  3442  		ExitCode: expectedExitCode,
  3443  	})
  3444  }
  3445  
  3446  func (s *DockerSuite) TestBuildVerboseOut(c *check.C) {
  3447  	name := "testbuildverboseout"
  3448  	expected := "\n123\n"
  3449  
  3450  	if testEnv.DaemonPlatform() == "windows" {
  3451  		expected = "\n123\r\n"
  3452  	}
  3453  
  3454  	buildImageNew(name, withDockerfile(`FROM busybox
  3455  RUN echo 123`)).Assert(c, icmd.Expected{
  3456  		Out: expected,
  3457  	})
  3458  }
  3459  
  3460  func (s *DockerSuite) TestBuildWithTabs(c *check.C) {
  3461  	name := "testbuildwithtabs"
  3462  	buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nRUN echo\tone\t\ttwo"))
  3463  	res := inspectFieldJSON(c, name, "ContainerConfig.Cmd")
  3464  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  3465  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  3466  	if testEnv.DaemonPlatform() == "windows" {
  3467  		expected1 = `["cmd","/S","/C","echo\tone\t\ttwo"]`
  3468  		expected2 = `["cmd","/S","/C","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  3469  	}
  3470  	if res != expected1 && res != expected2 {
  3471  		c.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  3472  	}
  3473  }
  3474  
  3475  func (s *DockerSuite) TestBuildLabels(c *check.C) {
  3476  	name := "testbuildlabel"
  3477  	expected := `{"License":"GPL","Vendor":"Acme"}`
  3478  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3479  		LABEL Vendor=Acme
  3480                  LABEL License GPL`))
  3481  	res := inspectFieldJSON(c, name, "Config.Labels")
  3482  	if res != expected {
  3483  		c.Fatalf("Labels %s, expected %s", res, expected)
  3484  	}
  3485  }
  3486  
  3487  func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
  3488  	name := "testbuildlabelcache"
  3489  
  3490  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3491  		LABEL Vendor=Acme`))
  3492  	id1, err := getIDByName(name)
  3493  	c.Assert(err, checker.IsNil)
  3494  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3495  		LABEL Vendor=Acme`))
  3496  	id2, err := getIDByName(name)
  3497  	c.Assert(err, checker.IsNil)
  3498  	if id1 != id2 {
  3499  		c.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
  3500  	}
  3501  
  3502  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3503  		LABEL Vendor=Acme1`))
  3504  	id2, err = getIDByName(name)
  3505  	c.Assert(err, checker.IsNil)
  3506  	if id1 == id2 {
  3507  		c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
  3508  	}
  3509  
  3510  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3511  		LABEL Vendor Acme`))
  3512  	id2, err = getIDByName(name)
  3513  	c.Assert(err, checker.IsNil)
  3514  	if id1 != id2 {
  3515  		c.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
  3516  	}
  3517  
  3518  	// Now make sure the cache isn't used by mistake
  3519  	buildImageSuccessfully(c, name, withoutCache, withDockerfile(`FROM busybox
  3520         LABEL f1=b1 f2=b2`))
  3521  	_, err = getIDByName(name)
  3522  	c.Assert(err, checker.IsNil)
  3523  
  3524  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  3525         LABEL f1=b1 f2=b2`))
  3526  	id2, err = getIDByName(name)
  3527  	c.Assert(err, checker.IsNil)
  3528  	if id1 == id2 {
  3529  		c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
  3530  	}
  3531  
  3532  }
  3533  
  3534  func (s *DockerSuite) TestBuildNotVerboseSuccess(c *check.C) {
  3535  	// This test makes sure that -q works correctly when build is successful:
  3536  	// stdout has only the image ID (long image ID) and stderr is empty.
  3537  	outRegexp := regexp.MustCompile("^(sha256:|)[a-z0-9]{64}\\n$")
  3538  	buildFlags := withBuildFlags("-q")
  3539  
  3540  	tt := []struct {
  3541  		Name      string
  3542  		BuildFunc func(string) *icmd.Result
  3543  	}{
  3544  		{
  3545  			Name: "quiet_build_stdin_success",
  3546  			BuildFunc: func(name string) *icmd.Result {
  3547  				return buildImageNew(name, buildFlags, withDockerfile("FROM busybox"))
  3548  			},
  3549  		},
  3550  		{
  3551  			Name: "quiet_build_ctx_success",
  3552  			BuildFunc: func(name string) *icmd.Result {
  3553  				return buildImageNew(name, buildFlags, withBuildContext(c,
  3554  					withFile("Dockerfile", "FROM busybox"),
  3555  					withFile("quiet_build_success_fctx", "test"),
  3556  				))
  3557  			},
  3558  		},
  3559  		{
  3560  			Name: "quiet_build_git_success",
  3561  			BuildFunc: func(name string) *icmd.Result {
  3562  				git, err := newFakeGit("repo", map[string]string{
  3563  					"Dockerfile": "FROM busybox",
  3564  				}, true)
  3565  				c.Assert(err, checker.IsNil)
  3566  				return buildImageNew(name, buildFlags, withBuildContextPath(git.RepoURL))
  3567  			},
  3568  		},
  3569  	}
  3570  
  3571  	for _, te := range tt {
  3572  		result := te.BuildFunc(te.Name)
  3573  		result.Assert(c, icmd.Success)
  3574  		if outRegexp.Find([]byte(result.Stdout())) == nil {
  3575  			c.Fatalf("Test %s expected stdout to match the [%v] regexp, but it is [%v]", te.Name, outRegexp, result.Stdout())
  3576  		}
  3577  
  3578  		if result.Stderr() != "" {
  3579  			c.Fatalf("Test %s expected stderr to be empty, but it is [%#v]", te.Name, result.Stderr())
  3580  		}
  3581  	}
  3582  
  3583  }
  3584  
  3585  func (s *DockerSuite) TestBuildNotVerboseFailureWithNonExistImage(c *check.C) {
  3586  	// This test makes sure that -q works correctly when build fails by
  3587  	// comparing between the stderr output in quiet mode and in stdout
  3588  	// and stderr output in verbose mode
  3589  	testRequires(c, Network)
  3590  	testName := "quiet_build_not_exists_image"
  3591  	dockerfile := "FROM busybox11"
  3592  	quietResult := buildImageNew(testName, withBuildFlags("-q"), withDockerfile(dockerfile))
  3593  	quietResult.Assert(c, icmd.Expected{
  3594  		ExitCode: 1,
  3595  	})
  3596  	result := buildImageNew(testName, withDockerfile(dockerfile))
  3597  	result.Assert(c, icmd.Expected{
  3598  		ExitCode: 1,
  3599  	})
  3600  	if quietResult.Stderr() != result.Combined() {
  3601  		c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", testName, quietResult.Stderr(), result.Combined()))
  3602  	}
  3603  }
  3604  
  3605  func (s *DockerSuite) TestBuildNotVerboseFailure(c *check.C) {
  3606  	// This test makes sure that -q works correctly when build fails by
  3607  	// comparing between the stderr output in quiet mode and in stdout
  3608  	// and stderr output in verbose mode
  3609  	testCases := []struct {
  3610  		testName   string
  3611  		dockerfile string
  3612  	}{
  3613  		{"quiet_build_no_from_at_the_beginning", "RUN whoami"},
  3614  		{"quiet_build_unknown_instr", "FROMD busybox"},
  3615  	}
  3616  
  3617  	for _, tc := range testCases {
  3618  		quietResult := buildImageNew(tc.testName, withBuildFlags("-q"), withDockerfile(tc.dockerfile))
  3619  		quietResult.Assert(c, icmd.Expected{
  3620  			ExitCode: 1,
  3621  		})
  3622  		result := buildImageNew(tc.testName, withDockerfile(tc.dockerfile))
  3623  		result.Assert(c, icmd.Expected{
  3624  			ExitCode: 1,
  3625  		})
  3626  		if quietResult.Stderr() != result.Combined() {
  3627  			c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", tc.testName, quietResult.Stderr(), result.Combined()))
  3628  		}
  3629  	}
  3630  }
  3631  
  3632  func (s *DockerSuite) TestBuildNotVerboseFailureRemote(c *check.C) {
  3633  	// This test ensures that when given a wrong URL, stderr in quiet mode and
  3634  	// stderr in verbose mode are identical.
  3635  	// TODO(vdemeester) with cobra, stdout has a carriage return too much so this test should not check stdout
  3636  	URL := "http://something.invalid"
  3637  	name := "quiet_build_wrong_remote"
  3638  	quietResult := buildImageNew(name, withBuildFlags("-q"), withBuildContextPath(URL))
  3639  	quietResult.Assert(c, icmd.Expected{
  3640  		ExitCode: 1,
  3641  	})
  3642  	result := buildImageNew(name, withBuildContextPath(URL))
  3643  	result.Assert(c, icmd.Expected{
  3644  		ExitCode: 1,
  3645  	})
  3646  	if strings.TrimSpace(quietResult.Stderr()) != strings.TrimSpace(result.Combined()) {
  3647  		c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", name, quietResult.Stderr(), result.Combined()))
  3648  	}
  3649  }
  3650  
  3651  func (s *DockerSuite) TestBuildStderr(c *check.C) {
  3652  	// This test just makes sure that no non-error output goes
  3653  	// to stderr
  3654  	name := "testbuildstderr"
  3655  	result := buildImageNew(name, withDockerfile("FROM busybox\nRUN echo one"))
  3656  	result.Assert(c, icmd.Success)
  3657  
  3658  	// Windows to non-Windows should have a security warning
  3659  	if runtime.GOOS == "windows" && testEnv.DaemonPlatform() != "windows" && !strings.Contains(result.Stdout(), "SECURITY WARNING:") {
  3660  		c.Fatalf("Stdout contains unexpected output: %q", result.Stdout())
  3661  	}
  3662  
  3663  	// Stderr should always be empty
  3664  	if result.Stderr() != "" {
  3665  		c.Fatalf("Stderr should have been empty, instead it's: %q", result.Stderr())
  3666  	}
  3667  }
  3668  
  3669  func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) {
  3670  	testRequires(c, UnixCli, DaemonIsLinux) // test uses chown: not available on windows
  3671  
  3672  	name := "testbuildchownsinglefile"
  3673  
  3674  	ctx, err := fakeContext(`
  3675  FROM busybox
  3676  COPY test /
  3677  RUN ls -l /test
  3678  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  3679  `, map[string]string{
  3680  		"test": "test",
  3681  	})
  3682  	if err != nil {
  3683  		c.Fatal(err)
  3684  	}
  3685  	defer ctx.Close()
  3686  
  3687  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  3688  		c.Fatal(err)
  3689  	}
  3690  
  3691  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3692  		c.Fatal(err)
  3693  	}
  3694  
  3695  }
  3696  
  3697  func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
  3698  	name := "testbuildsymlinkbreakout"
  3699  	tmpdir, err := ioutil.TempDir("", name)
  3700  	c.Assert(err, check.IsNil)
  3701  	defer os.RemoveAll(tmpdir)
  3702  	ctx := filepath.Join(tmpdir, "context")
  3703  	if err := os.MkdirAll(ctx, 0755); err != nil {
  3704  		c.Fatal(err)
  3705  	}
  3706  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  3707  	from busybox
  3708  	add symlink.tar /
  3709  	add inject /symlink/
  3710  	`), 0644); err != nil {
  3711  		c.Fatal(err)
  3712  	}
  3713  	inject := filepath.Join(ctx, "inject")
  3714  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  3715  		c.Fatal(err)
  3716  	}
  3717  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  3718  	if err != nil {
  3719  		c.Fatal(err)
  3720  	}
  3721  	w := tar.NewWriter(f)
  3722  	w.WriteHeader(&tar.Header{
  3723  		Name:     "symlink2",
  3724  		Typeflag: tar.TypeSymlink,
  3725  		Linkname: "/../../../../../../../../../../../../../../",
  3726  		Uid:      os.Getuid(),
  3727  		Gid:      os.Getgid(),
  3728  	})
  3729  	w.WriteHeader(&tar.Header{
  3730  		Name:     "symlink",
  3731  		Typeflag: tar.TypeSymlink,
  3732  		Linkname: filepath.Join("symlink2", tmpdir),
  3733  		Uid:      os.Getuid(),
  3734  		Gid:      os.Getgid(),
  3735  	})
  3736  	w.Close()
  3737  	f.Close()
  3738  	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
  3739  		c.Fatal(err)
  3740  	}
  3741  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  3742  		c.Fatal("symlink breakout - inject")
  3743  	} else if !os.IsNotExist(err) {
  3744  		c.Fatalf("unexpected error: %v", err)
  3745  	}
  3746  }
  3747  
  3748  func (s *DockerSuite) TestBuildXZHost(c *check.C) {
  3749  	// /usr/local/sbin/xz gets permission denied for the user
  3750  	testRequires(c, NotUserNamespace)
  3751  	testRequires(c, DaemonIsLinux)
  3752  	name := "testbuildxzhost"
  3753  
  3754  	buildImageSuccessfully(c, name, withBuildContext(c,
  3755  		withFile("Dockerfile", `
  3756  FROM busybox
  3757  ADD xz /usr/local/sbin/
  3758  RUN chmod 755 /usr/local/sbin/xz
  3759  ADD test.xz /
  3760  RUN [ ! -e /injected ]`),
  3761  		withFile("test.xz", "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00"+
  3762  			"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd"+
  3763  			"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21"),
  3764  		withFile("xz", "#!/bin/sh\ntouch /injected"),
  3765  	))
  3766  }
  3767  
  3768  func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
  3769  	// /foo/file gets permission denied for the user
  3770  	testRequires(c, NotUserNamespace)
  3771  	testRequires(c, DaemonIsLinux) // TODO Windows: Issue #20127
  3772  	var (
  3773  		name     = "testbuildvolumescontent"
  3774  		expected = "some text"
  3775  		volName  = "/foo"
  3776  	)
  3777  
  3778  	if testEnv.DaemonPlatform() == "windows" {
  3779  		volName = "C:/foo"
  3780  	}
  3781  
  3782  	buildImageSuccessfully(c, name, withBuildContext(c,
  3783  		withFile("Dockerfile", `
  3784  FROM busybox
  3785  COPY content /foo/file
  3786  VOLUME `+volName+`
  3787  CMD cat /foo/file`),
  3788  		withFile("content", expected),
  3789  	))
  3790  
  3791  	out, _ := dockerCmd(c, "run", "--rm", name)
  3792  	if out != expected {
  3793  		c.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  3794  	}
  3795  
  3796  }
  3797  
  3798  // FIXME(vdemeester) part of this should be unit test, other part should be clearer
  3799  func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
  3800  	ctx, err := fakeContext(`FROM busybox
  3801  	RUN echo from Dockerfile`,
  3802  		map[string]string{
  3803  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  3804  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  3805  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  3806  			"dFile":            "FROM busybox\nRUN echo from dFile",
  3807  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  3808  		})
  3809  	if err != nil {
  3810  		c.Fatal(err)
  3811  	}
  3812  	defer ctx.Close()
  3813  
  3814  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  3815  	if err != nil {
  3816  		c.Fatalf("Failed to build: %s\n%s", out, err)
  3817  	}
  3818  	if !strings.Contains(out, "from Dockerfile") {
  3819  		c.Fatalf("test1 should have used Dockerfile, output:%s", out)
  3820  	}
  3821  
  3822  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  3823  	if err != nil {
  3824  		c.Fatal(err)
  3825  	}
  3826  	if !strings.Contains(out, "from files/Dockerfile") {
  3827  		c.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  3828  	}
  3829  
  3830  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  3831  	if err != nil {
  3832  		c.Fatal(err)
  3833  	}
  3834  	if !strings.Contains(out, "from files/dFile") {
  3835  		c.Fatalf("test3 should have used files/dFile, output:%s", out)
  3836  	}
  3837  
  3838  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  3839  	if err != nil {
  3840  		c.Fatal(err)
  3841  	}
  3842  	if !strings.Contains(out, "from dFile") {
  3843  		c.Fatalf("test4 should have used dFile, output:%s", out)
  3844  	}
  3845  
  3846  	dirWithNoDockerfile, err := ioutil.TempDir(os.TempDir(), "test5")
  3847  	c.Assert(err, check.IsNil)
  3848  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  3849  	if _, err = os.Create(nonDockerfileFile); err != nil {
  3850  		c.Fatal(err)
  3851  	}
  3852  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  3853  
  3854  	if err == nil {
  3855  		c.Fatalf("test5 was supposed to fail to find passwd")
  3856  	}
  3857  
  3858  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) {
  3859  		c.Fatalf("wrong error message:%v\nexpected to contain=%v", out, expected)
  3860  	}
  3861  
  3862  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  3863  	if err != nil {
  3864  		c.Fatalf("test6 failed: %s", err)
  3865  	}
  3866  	if !strings.Contains(out, "from Dockerfile") {
  3867  		c.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  3868  	}
  3869  
  3870  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  3871  	if err != nil {
  3872  		c.Fatalf("test7 failed: %s", err)
  3873  	}
  3874  	if !strings.Contains(out, "from files/Dockerfile") {
  3875  		c.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  3876  	}
  3877  
  3878  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  3879  	if err == nil || !strings.Contains(out, "must be within the build context") {
  3880  		c.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  3881  	}
  3882  
  3883  	tmpDir := os.TempDir()
  3884  	out, _, err = dockerCmdInDir(c, tmpDir, "build", "-t", "test9", ctx.Dir)
  3885  	if err != nil {
  3886  		c.Fatalf("test9 - failed: %s", err)
  3887  	}
  3888  	if !strings.Contains(out, "from Dockerfile") {
  3889  		c.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  3890  	}
  3891  
  3892  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  3893  	if err != nil {
  3894  		c.Fatalf("test10 should have worked: %s", err)
  3895  	}
  3896  	if !strings.Contains(out, "from files/dFile2") {
  3897  		c.Fatalf("test10 should have used files/dFile2, output:%s", out)
  3898  	}
  3899  
  3900  }
  3901  
  3902  func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) {
  3903  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  3904  	testRequires(c, DaemonIsLinux)
  3905  
  3906  	// If Dockerfile is not present, use dockerfile
  3907  	buildImageNew("test1", withBuildContext(c,
  3908  		withFile("dockerfile", `FROM busybox
  3909  	RUN echo from dockerfile`),
  3910  	)).Assert(c, icmd.Expected{
  3911  		Out: "from dockerfile",
  3912  	})
  3913  
  3914  	// Prefer Dockerfile in place of dockerfile
  3915  	buildImageNew("test1", withBuildContext(c,
  3916  		withFile("dockerfile", `FROM busybox
  3917  	RUN echo from dockerfile`),
  3918  		withFile("Dockerfile", `FROM busybox
  3919  	RUN echo from Dockerfile`),
  3920  	)).Assert(c, icmd.Expected{
  3921  		Out: "from Dockerfile",
  3922  	})
  3923  }
  3924  
  3925  func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) {
  3926  	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
  3927  RUN echo from baz
  3928  COPY * /tmp/
  3929  RUN find /tmp/`})
  3930  	if err != nil {
  3931  		c.Fatal(err)
  3932  	}
  3933  	defer server.Close()
  3934  
  3935  	ctx, err := fakeContext(`FROM busybox
  3936  RUN echo from Dockerfile`,
  3937  		map[string]string{})
  3938  	if err != nil {
  3939  		c.Fatal(err)
  3940  	}
  3941  	defer ctx.Close()
  3942  
  3943  	// Make sure that -f is ignored and that we don't use the Dockerfile
  3944  	// that's in the current dir
  3945  	result := buildImageNew("test1", withBuildFlags("-f", "baz", server.URL()+"/baz"), func(cmd *icmd.Cmd) func() {
  3946  		cmd.Dir = ctx.Dir
  3947  		return nil
  3948  	})
  3949  	result.Assert(c, icmd.Success)
  3950  
  3951  	if !strings.Contains(result.Combined(), "from baz") ||
  3952  		strings.Contains(result.Combined(), "/tmp/baz") ||
  3953  		!strings.Contains(result.Combined(), "/tmp/Dockerfile") {
  3954  		c.Fatalf("Missing proper output: %s", result.Combined())
  3955  	}
  3956  
  3957  }
  3958  
  3959  func (s *DockerSuite) TestBuildFromStdinWithF(c *check.C) {
  3960  	testRequires(c, DaemonIsLinux) // TODO Windows: This test is flaky; no idea why
  3961  	ctx, err := fakeContext(`FROM busybox
  3962  RUN echo "from Dockerfile"`,
  3963  		map[string]string{})
  3964  	if err != nil {
  3965  		c.Fatal(err)
  3966  	}
  3967  	defer ctx.Close()
  3968  
  3969  	// Make sure that -f is ignored and that we don't use the Dockerfile
  3970  	// that's in the current dir
  3971  	result := buildImageNew("test1", withBuildFlags("-f", "baz", "-"), func(cmd *icmd.Cmd) func() {
  3972  		cmd.Dir = ctx.Dir
  3973  		cmd.Stdin = strings.NewReader(`FROM busybox
  3974  RUN echo "from baz"
  3975  COPY * /tmp/
  3976  RUN sh -c "find /tmp/" # sh -c is needed on Windows to use the correct find`)
  3977  		return nil
  3978  	})
  3979  	result.Assert(c, icmd.Success)
  3980  
  3981  	if !strings.Contains(result.Combined(), "from baz") ||
  3982  		strings.Contains(result.Combined(), "/tmp/baz") ||
  3983  		!strings.Contains(result.Combined(), "/tmp/Dockerfile") {
  3984  		c.Fatalf("Missing proper output: %s", result.Combined())
  3985  	}
  3986  
  3987  }
  3988  
  3989  func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) {
  3990  	name := "testbuildfromofficial"
  3991  	fromNames := []string{
  3992  		"busybox",
  3993  		"docker.io/busybox",
  3994  		"index.docker.io/busybox",
  3995  		"library/busybox",
  3996  		"docker.io/library/busybox",
  3997  		"index.docker.io/library/busybox",
  3998  	}
  3999  	for idx, fromName := range fromNames {
  4000  		imgName := fmt.Sprintf("%s%d", name, idx)
  4001  		buildImageSuccessfully(c, imgName, withDockerfile("FROM "+fromName))
  4002  		dockerCmd(c, "rmi", imgName)
  4003  	}
  4004  }
  4005  
  4006  func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) {
  4007  	testRequires(c, UnixCli, DaemonIsLinux) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  4008  
  4009  	name := "testbuilddockerfileoutsidecontext"
  4010  	tmpdir, err := ioutil.TempDir("", name)
  4011  	c.Assert(err, check.IsNil)
  4012  	defer os.RemoveAll(tmpdir)
  4013  	ctx := filepath.Join(tmpdir, "context")
  4014  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4015  		c.Fatal(err)
  4016  	}
  4017  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  4018  		c.Fatal(err)
  4019  	}
  4020  	wd, err := os.Getwd()
  4021  	if err != nil {
  4022  		c.Fatal(err)
  4023  	}
  4024  	defer os.Chdir(wd)
  4025  	if err := os.Chdir(ctx); err != nil {
  4026  		c.Fatal(err)
  4027  	}
  4028  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  4029  		c.Fatal(err)
  4030  	}
  4031  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  4032  		c.Fatal(err)
  4033  	}
  4034  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  4035  		c.Fatal(err)
  4036  	}
  4037  
  4038  	for _, dockerfilePath := range []string{
  4039  		filepath.Join("..", "outsideDockerfile"),
  4040  		filepath.Join(ctx, "dockerfile1"),
  4041  		filepath.Join(ctx, "dockerfile2"),
  4042  	} {
  4043  		result := dockerCmdWithResult("build", "-t", name, "--no-cache", "-f", dockerfilePath, ".")
  4044  		c.Assert(result, icmd.Matches, icmd.Expected{
  4045  			Err:      "must be within the build context",
  4046  			ExitCode: 1,
  4047  		})
  4048  		deleteImages(name)
  4049  	}
  4050  
  4051  	os.Chdir(tmpdir)
  4052  
  4053  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  4054  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  4055  	out, _, err := dockerCmdWithError("build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx)
  4056  	if err == nil {
  4057  		c.Fatalf("Expected error. Out: %s", out)
  4058  	}
  4059  }
  4060  
  4061  // FIXME(vdemeester) should be a unit test
  4062  func (s *DockerSuite) TestBuildSpaces(c *check.C) {
  4063  	// Test to make sure that leading/trailing spaces on a command
  4064  	// doesn't change the error msg we get
  4065  	var (
  4066  		err1 error
  4067  		err2 error
  4068  	)
  4069  
  4070  	name := "testspaces"
  4071  	ctx, err := fakeContext("FROM busybox\nCOPY\n",
  4072  		map[string]string{
  4073  			"Dockerfile": "FROM busybox\nCOPY\n",
  4074  		})
  4075  	if err != nil {
  4076  		c.Fatal(err)
  4077  	}
  4078  	defer ctx.Close()
  4079  
  4080  	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
  4081  		c.Fatal("Build 1 was supposed to fail, but didn't")
  4082  	}
  4083  
  4084  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  4085  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  4086  		c.Fatal("Build 2 was supposed to fail, but didn't")
  4087  	}
  4088  
  4089  	removeLogTimestamps := func(s string) string {
  4090  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  4091  	}
  4092  
  4093  	// Skip over the times
  4094  	e1 := removeLogTimestamps(err1.Error())
  4095  	e2 := removeLogTimestamps(err2.Error())
  4096  
  4097  	// Ignore whitespace since that's what were verifying doesn't change stuff
  4098  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  4099  		c.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
  4100  	}
  4101  
  4102  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  4103  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  4104  		c.Fatal("Build 3 was supposed to fail, but didn't")
  4105  	}
  4106  
  4107  	// Skip over the times
  4108  	e1 = removeLogTimestamps(err1.Error())
  4109  	e2 = removeLogTimestamps(err2.Error())
  4110  
  4111  	// Ignore whitespace since that's what were verifying doesn't change stuff
  4112  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  4113  		c.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
  4114  	}
  4115  
  4116  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  4117  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  4118  		c.Fatal("Build 4 was supposed to fail, but didn't")
  4119  	}
  4120  
  4121  	// Skip over the times
  4122  	e1 = removeLogTimestamps(err1.Error())
  4123  	e2 = removeLogTimestamps(err2.Error())
  4124  
  4125  	// Ignore whitespace since that's what were verifying doesn't change stuff
  4126  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  4127  		c.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
  4128  	}
  4129  
  4130  }
  4131  
  4132  func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) {
  4133  	// Test to make sure that spaces in quotes aren't lost
  4134  	name := "testspacesquotes"
  4135  
  4136  	dockerfile := `FROM busybox
  4137  RUN echo "  \
  4138    foo  "`
  4139  
  4140  	expected := "\n    foo  \n"
  4141  	// Windows uses the builtin echo, which preserves quotes
  4142  	if testEnv.DaemonPlatform() == "windows" {
  4143  		expected = "\"    foo  \""
  4144  	}
  4145  
  4146  	buildImageNew(name, withDockerfile(dockerfile)).Assert(c, icmd.Expected{
  4147  		Out: expected,
  4148  	})
  4149  }
  4150  
  4151  // #4393
  4152  func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) {
  4153  	testRequires(c, DaemonIsLinux) // TODO Windows: This should error out
  4154  	buildImageNew("docker-test-errcreatevolumewithfile", withDockerfile(`
  4155  	FROM busybox
  4156  	RUN touch /foo
  4157  	VOLUME /foo
  4158  	`)).Assert(c, icmd.Expected{
  4159  		ExitCode: 1,
  4160  		Err:      "file exists",
  4161  	})
  4162  }
  4163  
  4164  // FIXME(vdemeester) should be a unit test
  4165  func (s *DockerSuite) TestBuildMissingArgs(c *check.C) {
  4166  	// Test to make sure that all Dockerfile commands (except the ones listed
  4167  	// in skipCmds) will generate an error if no args are provided.
  4168  	// Note: INSERT is deprecated so we exclude it because of that.
  4169  	skipCmds := map[string]struct{}{
  4170  		"CMD":        {},
  4171  		"RUN":        {},
  4172  		"ENTRYPOINT": {},
  4173  		"INSERT":     {},
  4174  	}
  4175  
  4176  	if testEnv.DaemonPlatform() == "windows" {
  4177  		skipCmds = map[string]struct{}{
  4178  			"CMD":        {},
  4179  			"RUN":        {},
  4180  			"ENTRYPOINT": {},
  4181  			"INSERT":     {},
  4182  			"STOPSIGNAL": {},
  4183  			"ARG":        {},
  4184  			"USER":       {},
  4185  			"EXPOSE":     {},
  4186  		}
  4187  	}
  4188  
  4189  	for cmd := range command.Commands {
  4190  		cmd = strings.ToUpper(cmd)
  4191  		if _, ok := skipCmds[cmd]; ok {
  4192  			continue
  4193  		}
  4194  		var dockerfile string
  4195  		if cmd == "FROM" {
  4196  			dockerfile = cmd
  4197  		} else {
  4198  			// Add FROM to make sure we don't complain about it missing
  4199  			dockerfile = "FROM busybox\n" + cmd
  4200  		}
  4201  
  4202  		buildImageNew("args", withDockerfile(dockerfile)).Assert(c, icmd.Expected{
  4203  			ExitCode: 1,
  4204  			Err:      cmd + " requires",
  4205  		})
  4206  	}
  4207  
  4208  }
  4209  
  4210  func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) {
  4211  	testRequires(c, DaemonIsLinux)
  4212  	buildImageNew("sc", withDockerfile("FROM scratch")).Assert(c, icmd.Expected{
  4213  		ExitCode: 1,
  4214  		Err:      "No image was generated",
  4215  	})
  4216  }
  4217  
  4218  func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
  4219  	buildImageSuccessfully(c, "sc", withBuildContext(c,
  4220  		withFile("Dockerfile", "FROM busybox\n"),
  4221  		withFile("..gitme", ""),
  4222  	))
  4223  }
  4224  
  4225  func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
  4226  	testRequires(c, DaemonIsLinux) // No hello-world Windows image
  4227  	name := "testbuildrunonejson"
  4228  
  4229  	buildImageNew(name, withDockerfile(`FROM hello-world:frozen
  4230  RUN [ "/hello" ]`)).Assert(c, icmd.Expected{
  4231  		Out: "Hello from Docker",
  4232  	})
  4233  }
  4234  
  4235  func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
  4236  	name := "testbuildemptystringvolume"
  4237  
  4238  	buildImageNew(name, withDockerfile(`
  4239    FROM busybox
  4240    ENV foo=""
  4241    VOLUME $foo
  4242    `)).Assert(c, icmd.Expected{
  4243  		ExitCode: 1,
  4244  	})
  4245  }
  4246  
  4247  func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
  4248  	testRequires(c, SameHostDaemon, DaemonIsLinux)
  4249  
  4250  	cgroupParent := "test"
  4251  	data, err := ioutil.ReadFile("/proc/self/cgroup")
  4252  	if err != nil {
  4253  		c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
  4254  	}
  4255  	selfCgroupPaths := testutil.ParseCgroupPaths(string(data))
  4256  	_, found := selfCgroupPaths["memory"]
  4257  	if !found {
  4258  		c.Fatalf("unable to find self memory cgroup path. CgroupsPath: %v", selfCgroupPaths)
  4259  	}
  4260  	result := buildImageNew("buildcgroupparent",
  4261  		withBuildFlags("--cgroup-parent", cgroupParent),
  4262  		withDockerfile(`
  4263  FROM busybox
  4264  RUN cat /proc/self/cgroup
  4265  `))
  4266  	result.Assert(c, icmd.Success)
  4267  	m, err := regexp.MatchString(fmt.Sprintf("memory:.*/%s/.*", cgroupParent), result.Combined())
  4268  	c.Assert(err, check.IsNil)
  4269  	if !m {
  4270  		c.Fatalf("There is no expected memory cgroup with parent /%s/: %s", cgroupParent, result.Combined())
  4271  	}
  4272  }
  4273  
  4274  // FIXME(vdemeester) could be a unit test
  4275  func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
  4276  	// Check to make sure our build output prints the Dockerfile cmd
  4277  	// property - there was a bug that caused it to be duplicated on the
  4278  	// Step X  line
  4279  	name := "testbuildnodupoutput"
  4280  	result := buildImageNew(name, withDockerfile(`
  4281    FROM busybox
  4282    RUN env`))
  4283  	result.Assert(c, icmd.Success)
  4284  	exp := "\nStep 2/2 : RUN env\n"
  4285  	if !strings.Contains(result.Combined(), exp) {
  4286  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp)
  4287  	}
  4288  }
  4289  
  4290  // GH15826
  4291  // FIXME(vdemeester) could be a unit test
  4292  func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) {
  4293  	// Explicit check to ensure that build starts from step 1 rather than 0
  4294  	name := "testbuildstartsfromone"
  4295  	result := buildImageNew(name, withDockerfile(`FROM busybox`))
  4296  	result.Assert(c, icmd.Success)
  4297  	exp := "\nStep 1/1 : FROM busybox\n"
  4298  	if !strings.Contains(result.Combined(), exp) {
  4299  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp)
  4300  	}
  4301  }
  4302  
  4303  func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
  4304  	// Test to make sure the bad command is quoted with just "s and
  4305  	// not as a Go []string
  4306  	name := "testbuildbadrunerrmsg"
  4307  	shell := "/bin/sh -c"
  4308  	exitCode := 127
  4309  	if testEnv.DaemonPlatform() == "windows" {
  4310  		shell = "cmd /S /C"
  4311  		// architectural - Windows has to start the container to determine the exe is bad, Linux does not
  4312  		exitCode = 1
  4313  	}
  4314  	exp := fmt.Sprintf(`The command '%s badEXE a1 \& a2	a3' returned a non-zero code: %d`, shell, exitCode)
  4315  
  4316  	buildImageNew(name, withDockerfile(`
  4317    FROM busybox
  4318    RUN badEXE a1 \& a2	a3`)).Assert(c, icmd.Expected{
  4319  		ExitCode: exitCode,
  4320  		Err:      exp,
  4321  	})
  4322  }
  4323  
  4324  func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) {
  4325  	repoName := s.setupTrustedImage(c, "trusted-build")
  4326  	dockerFile := fmt.Sprintf(`
  4327    FROM %s
  4328    RUN []
  4329      `, repoName)
  4330  
  4331  	name := "testtrustedbuild"
  4332  
  4333  	buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4334  		Out: fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7]),
  4335  	})
  4336  
  4337  	// We should also have a tag reference for the image.
  4338  	dockerCmd(c, "inspect", repoName)
  4339  
  4340  	// We should now be able to remove the tag reference.
  4341  	dockerCmd(c, "rmi", repoName)
  4342  }
  4343  
  4344  func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
  4345  	repoName := fmt.Sprintf("%v/dockercli/build-untrusted-tag:latest", privateRegistryURL)
  4346  	dockerFile := fmt.Sprintf(`
  4347    FROM %s
  4348    RUN []
  4349      `, repoName)
  4350  
  4351  	name := "testtrustedbuilduntrustedtag"
  4352  
  4353  	buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4354  		ExitCode: 1,
  4355  		Err:      "does not have trust data for",
  4356  	})
  4357  }
  4358  
  4359  func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) {
  4360  	testRequires(c, DaemonIsLinux)
  4361  	tempDir, err := ioutil.TempDir("", "test-build-dir-is-symlink-")
  4362  	c.Assert(err, check.IsNil)
  4363  	defer os.RemoveAll(tempDir)
  4364  
  4365  	// Make a real context directory in this temp directory with a simple
  4366  	// Dockerfile.
  4367  	realContextDirname := filepath.Join(tempDir, "context")
  4368  	if err := os.Mkdir(realContextDirname, os.FileMode(0755)); err != nil {
  4369  		c.Fatal(err)
  4370  	}
  4371  
  4372  	if err = ioutil.WriteFile(
  4373  		filepath.Join(realContextDirname, "Dockerfile"),
  4374  		[]byte(`
  4375  			FROM busybox
  4376  			RUN echo hello world
  4377  		`),
  4378  		os.FileMode(0644),
  4379  	); err != nil {
  4380  		c.Fatal(err)
  4381  	}
  4382  
  4383  	// Make a symlink to the real context directory.
  4384  	contextSymlinkName := filepath.Join(tempDir, "context_link")
  4385  	if err := os.Symlink(realContextDirname, contextSymlinkName); err != nil {
  4386  		c.Fatal(err)
  4387  	}
  4388  
  4389  	// Executing the build with the symlink as the specified context should
  4390  	// *not* fail.
  4391  	dockerCmd(c, "build", contextSymlinkName)
  4392  }
  4393  
  4394  func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) {
  4395  	testRequires(c, NotaryHosting)
  4396  
  4397  	latestTag := s.setupTrustedImage(c, "trusted-build-releases-role")
  4398  	repoName := strings.TrimSuffix(latestTag, ":latest")
  4399  
  4400  	// Now create the releases role
  4401  	s.notaryCreateDelegation(c, repoName, "targets/releases", s.not.keys[0].Public)
  4402  	s.notaryImportKey(c, repoName, "targets/releases", s.not.keys[0].Private)
  4403  	s.notaryPublish(c, repoName)
  4404  
  4405  	// push a different tag to the releases role
  4406  	otherTag := fmt.Sprintf("%s:other", repoName)
  4407  	dockerCmd(c, "tag", "busybox", otherTag)
  4408  
  4409  	icmd.RunCmd(icmd.Command(dockerBinary, "push", otherTag), trustedCmd).Assert(c, icmd.Success)
  4410  	s.assertTargetInRoles(c, repoName, "other", "targets/releases")
  4411  	s.assertTargetNotInRoles(c, repoName, "other", "targets")
  4412  
  4413  	out, status := dockerCmd(c, "rmi", otherTag)
  4414  	c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
  4415  
  4416  	dockerFile := fmt.Sprintf(`
  4417    FROM %s
  4418    RUN []
  4419      `, otherTag)
  4420  	name := "testtrustedbuildreleasesrole"
  4421  	buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4422  		Out: fmt.Sprintf("FROM %s@sha", repoName),
  4423  	})
  4424  }
  4425  
  4426  func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) {
  4427  	testRequires(c, NotaryHosting)
  4428  
  4429  	latestTag := s.setupTrustedImage(c, "trusted-build-releases-role")
  4430  	repoName := strings.TrimSuffix(latestTag, ":latest")
  4431  
  4432  	// Now create a non-releases delegation role
  4433  	s.notaryCreateDelegation(c, repoName, "targets/other", s.not.keys[0].Public)
  4434  	s.notaryImportKey(c, repoName, "targets/other", s.not.keys[0].Private)
  4435  	s.notaryPublish(c, repoName)
  4436  
  4437  	// push a different tag to the other role
  4438  	otherTag := fmt.Sprintf("%s:other", repoName)
  4439  	dockerCmd(c, "tag", "busybox", otherTag)
  4440  
  4441  	icmd.RunCmd(icmd.Command(dockerBinary, "push", otherTag), trustedCmd).Assert(c, icmd.Success)
  4442  	s.assertTargetInRoles(c, repoName, "other", "targets/other")
  4443  	s.assertTargetNotInRoles(c, repoName, "other", "targets")
  4444  
  4445  	out, status := dockerCmd(c, "rmi", otherTag)
  4446  	c.Assert(status, check.Equals, 0, check.Commentf("docker rmi failed: %s", out))
  4447  
  4448  	dockerFile := fmt.Sprintf(`
  4449    FROM %s
  4450    RUN []
  4451      `, otherTag)
  4452  
  4453  	name := "testtrustedbuildotherrole"
  4454  	buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  4455  		ExitCode: 1,
  4456  	})
  4457  }
  4458  
  4459  // Issue #15634: COPY fails when path starts with "null"
  4460  func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) {
  4461  	name := "testbuildnullstringinaddcopyvolume"
  4462  	volName := "nullvolume"
  4463  	if testEnv.DaemonPlatform() == "windows" {
  4464  		volName = `C:\\nullvolume`
  4465  	}
  4466  
  4467  	buildImageSuccessfully(c, name, withBuildContext(c,
  4468  		withFile("Dockerfile", `
  4469  		FROM busybox
  4470  
  4471  		ADD null /
  4472  		COPY nullfile /
  4473  		VOLUME `+volName+`
  4474  		`),
  4475  		withFile("null", "test1"),
  4476  		withFile("nullfile", "test2"),
  4477  	))
  4478  }
  4479  
  4480  func (s *DockerSuite) TestBuildStopSignal(c *check.C) {
  4481  	testRequires(c, DaemonIsLinux) // Windows does not support STOPSIGNAL yet
  4482  	imgName := "test_build_stop_signal"
  4483  	buildImageSuccessfully(c, imgName, withDockerfile(`FROM busybox
  4484  		 STOPSIGNAL SIGKILL`))
  4485  	res := inspectFieldJSON(c, imgName, "Config.StopSignal")
  4486  	if res != `"SIGKILL"` {
  4487  		c.Fatalf("Signal %s, expected SIGKILL", res)
  4488  	}
  4489  
  4490  	containerName := "test-container-stop-signal"
  4491  	dockerCmd(c, "run", "-d", "--name", containerName, imgName, "top")
  4492  	res = inspectFieldJSON(c, containerName, "Config.StopSignal")
  4493  	if res != `"SIGKILL"` {
  4494  		c.Fatalf("Signal %s, expected SIGKILL", res)
  4495  	}
  4496  }
  4497  
  4498  func (s *DockerSuite) TestBuildBuildTimeArg(c *check.C) {
  4499  	imgName := "bldargtest"
  4500  	envKey := "foo"
  4501  	envVal := "bar"
  4502  	var dockerfile string
  4503  	if testEnv.DaemonPlatform() == "windows" {
  4504  		// Bugs in Windows busybox port - use the default base image and native cmd stuff
  4505  		dockerfile = fmt.Sprintf(`FROM `+minimalBaseImage()+`
  4506  			ARG %s
  4507  			RUN echo %%%s%%
  4508  			CMD setlocal enableextensions && if defined %s (echo %%%s%%)`, envKey, envKey, envKey, envKey)
  4509  	} else {
  4510  		dockerfile = fmt.Sprintf(`FROM busybox
  4511  			ARG %s
  4512  			RUN echo $%s
  4513  			CMD echo $%s`, envKey, envKey, envKey)
  4514  
  4515  	}
  4516  	buildImageNew(imgName,
  4517  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4518  		withDockerfile(dockerfile),
  4519  	).Assert(c, icmd.Expected{
  4520  		Out: envVal,
  4521  	})
  4522  
  4523  	containerName := "bldargCont"
  4524  	out, _ := dockerCmd(c, "run", "--name", containerName, imgName)
  4525  	out = strings.Trim(out, " \r\n'")
  4526  	if out != "" {
  4527  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4528  	}
  4529  }
  4530  
  4531  func (s *DockerSuite) TestBuildBuildTimeArgHistory(c *check.C) {
  4532  	imgName := "bldargtest"
  4533  	envKey := "foo"
  4534  	envVal := "bar"
  4535  	envDef := "bar1"
  4536  	dockerfile := fmt.Sprintf(`FROM busybox
  4537  		ARG %s=%s`, envKey, envDef)
  4538  	buildImageNew(imgName,
  4539  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4540  		withDockerfile(dockerfile),
  4541  	).Assert(c, icmd.Expected{
  4542  		Out: envVal,
  4543  	})
  4544  
  4545  	out, _ := dockerCmd(c, "history", "--no-trunc", imgName)
  4546  	outputTabs := strings.Split(out, "\n")[1]
  4547  	if !strings.Contains(outputTabs, envDef) {
  4548  		c.Fatalf("failed to find arg default in image history output: %q expected: %q", outputTabs, envDef)
  4549  	}
  4550  }
  4551  
  4552  func (s *DockerSuite) TestBuildBuildTimeArgCacheHit(c *check.C) {
  4553  	imgName := "bldargtest"
  4554  	envKey := "foo"
  4555  	envVal := "bar"
  4556  	dockerfile := fmt.Sprintf(`FROM busybox
  4557  		ARG %s
  4558  		RUN echo $%s`, envKey, envKey)
  4559  	buildImageSuccessfully(c, imgName,
  4560  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4561  		withDockerfile(dockerfile),
  4562  	)
  4563  	origImgID, err := getIDByName(imgName)
  4564  	c.Assert(err, checker.IsNil)
  4565  
  4566  	imgNameCache := "bldargtestcachehit"
  4567  	buildImageSuccessfully(c, imgNameCache,
  4568  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4569  		withDockerfile(dockerfile),
  4570  	)
  4571  	newImgID, err := getIDByName(imgName)
  4572  	c.Assert(err, checker.IsNil)
  4573  	if newImgID != origImgID {
  4574  		c.Fatalf("build didn't use cache! expected image id: %q built image id: %q", origImgID, newImgID)
  4575  	}
  4576  }
  4577  
  4578  func (s *DockerSuite) TestBuildBuildTimeArgCacheMissExtraArg(c *check.C) {
  4579  	imgName := "bldargtest"
  4580  	envKey := "foo"
  4581  	envVal := "bar"
  4582  	extraEnvKey := "foo1"
  4583  	extraEnvVal := "bar1"
  4584  	dockerfile := fmt.Sprintf(`FROM busybox
  4585  		ARG %s
  4586  		ARG %s
  4587  		RUN echo $%s`, envKey, extraEnvKey, envKey)
  4588  	buildImageSuccessfully(c, imgName,
  4589  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4590  		withDockerfile(dockerfile),
  4591  	)
  4592  	origImgID, err := getIDByName(imgName)
  4593  	c.Assert(err, checker.IsNil)
  4594  
  4595  	imgNameCache := "bldargtestcachemiss"
  4596  	buildImageSuccessfully(c, imgNameCache,
  4597  		withBuildFlags(
  4598  			"--build-arg", fmt.Sprintf("%s=%s", envKey, envVal),
  4599  			"--build-arg", fmt.Sprintf("%s=%s", extraEnvKey, extraEnvVal),
  4600  		),
  4601  		withDockerfile(dockerfile),
  4602  	)
  4603  	newImgID, err := getIDByName(imgNameCache)
  4604  	c.Assert(err, checker.IsNil)
  4605  
  4606  	if newImgID == origImgID {
  4607  		c.Fatalf("build used cache, expected a miss!")
  4608  	}
  4609  }
  4610  
  4611  func (s *DockerSuite) TestBuildBuildTimeArgCacheMissSameArgDiffVal(c *check.C) {
  4612  	imgName := "bldargtest"
  4613  	envKey := "foo"
  4614  	envVal := "bar"
  4615  	newEnvVal := "bar1"
  4616  	dockerfile := fmt.Sprintf(`FROM busybox
  4617  		ARG %s
  4618  		RUN echo $%s`, envKey, envKey)
  4619  	buildImageSuccessfully(c, imgName,
  4620  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4621  		withDockerfile(dockerfile),
  4622  	)
  4623  	origImgID, err := getIDByName(imgName)
  4624  	c.Assert(err, checker.IsNil)
  4625  
  4626  	imgNameCache := "bldargtestcachemiss"
  4627  	buildImageSuccessfully(c, imgNameCache,
  4628  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, newEnvVal)),
  4629  		withDockerfile(dockerfile),
  4630  	)
  4631  	newImgID, err := getIDByName(imgNameCache)
  4632  	c.Assert(err, checker.IsNil)
  4633  	if newImgID == origImgID {
  4634  		c.Fatalf("build used cache, expected a miss!")
  4635  	}
  4636  }
  4637  
  4638  func (s *DockerSuite) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv(c *check.C) {
  4639  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4640  	imgName := "bldargtest"
  4641  	envKey := "foo"
  4642  	envVal := "bar"
  4643  	envValOveride := "barOverride"
  4644  	dockerfile := fmt.Sprintf(`FROM busybox
  4645  		ARG %s
  4646  		ENV %s %s
  4647  		RUN echo $%s
  4648  		CMD echo $%s
  4649          `, envKey, envKey, envValOveride, envKey, envKey)
  4650  
  4651  	result := buildImageNew(imgName,
  4652  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4653  		withDockerfile(dockerfile),
  4654  	)
  4655  	result.Assert(c, icmd.Success)
  4656  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4657  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4658  	}
  4659  
  4660  	containerName := "bldargCont"
  4661  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4662  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4663  	}
  4664  }
  4665  
  4666  // FIXME(vdemeester) might be useful to merge with the one above ?
  4667  func (s *DockerSuite) TestBuildBuildTimeArgOverrideEnvDefinedBeforeArg(c *check.C) {
  4668  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4669  	imgName := "bldargtest"
  4670  	envKey := "foo"
  4671  	envVal := "bar"
  4672  	envValOveride := "barOverride"
  4673  	dockerfile := fmt.Sprintf(`FROM busybox
  4674  		ENV %s %s
  4675  		ARG %s
  4676  		RUN echo $%s
  4677  		CMD echo $%s
  4678          `, envKey, envValOveride, envKey, envKey, envKey)
  4679  	result := buildImageNew(imgName,
  4680  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4681  		withDockerfile(dockerfile),
  4682  	)
  4683  	result.Assert(c, icmd.Success)
  4684  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4685  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4686  	}
  4687  
  4688  	containerName := "bldargCont"
  4689  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4690  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4691  	}
  4692  }
  4693  
  4694  func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) {
  4695  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4696  	imgName := "bldvarstest"
  4697  
  4698  	wdVar := "WDIR"
  4699  	wdVal := "/tmp/"
  4700  	addVar := "AFILE"
  4701  	addVal := "addFile"
  4702  	copyVar := "CFILE"
  4703  	copyVal := "copyFile"
  4704  	envVar := "foo"
  4705  	envVal := "bar"
  4706  	exposeVar := "EPORT"
  4707  	exposeVal := "9999"
  4708  	userVar := "USER"
  4709  	userVal := "testUser"
  4710  	volVar := "VOL"
  4711  	volVal := "/testVol/"
  4712  
  4713  	buildImageSuccessfully(c, imgName,
  4714  		withBuildFlags(
  4715  			"--build-arg", fmt.Sprintf("%s=%s", wdVar, wdVal),
  4716  			"--build-arg", fmt.Sprintf("%s=%s", addVar, addVal),
  4717  			"--build-arg", fmt.Sprintf("%s=%s", copyVar, copyVal),
  4718  			"--build-arg", fmt.Sprintf("%s=%s", envVar, envVal),
  4719  			"--build-arg", fmt.Sprintf("%s=%s", exposeVar, exposeVal),
  4720  			"--build-arg", fmt.Sprintf("%s=%s", userVar, userVal),
  4721  			"--build-arg", fmt.Sprintf("%s=%s", volVar, volVal),
  4722  		),
  4723  		withBuildContext(c,
  4724  			withFile("Dockerfile", fmt.Sprintf(`FROM busybox
  4725  		ARG %s
  4726  		WORKDIR ${%s}
  4727  		ARG %s
  4728  		ADD ${%s} testDir/
  4729  		ARG %s
  4730  		COPY $%s testDir/
  4731  		ARG %s
  4732  		ENV %s=${%s}
  4733  		ARG %s
  4734  		EXPOSE $%s
  4735  		ARG %s
  4736  		USER $%s
  4737  		ARG %s
  4738  		VOLUME ${%s}`,
  4739  				wdVar, wdVar, addVar, addVar, copyVar, copyVar, envVar, envVar,
  4740  				envVar, exposeVar, exposeVar, userVar, userVar, volVar, volVar)),
  4741  			withFile(addVal, "some stuff"),
  4742  			withFile(copyVal, "some stuff"),
  4743  		),
  4744  	)
  4745  
  4746  	res := inspectField(c, imgName, "Config.WorkingDir")
  4747  	if res != filepath.ToSlash(filepath.Clean(wdVal)) {
  4748  		c.Fatalf("Config.WorkingDir value mismatch. Expected: %s, got: %s", filepath.ToSlash(filepath.Clean(wdVal)), res)
  4749  	}
  4750  
  4751  	var resArr []string
  4752  	inspectFieldAndUnmarshall(c, imgName, "Config.Env", &resArr)
  4753  
  4754  	found := false
  4755  	for _, v := range resArr {
  4756  		if fmt.Sprintf("%s=%s", envVar, envVal) == v {
  4757  			found = true
  4758  			break
  4759  		}
  4760  	}
  4761  	if !found {
  4762  		c.Fatalf("Config.Env value mismatch. Expected <key=value> to exist: %s=%s, got: %v",
  4763  			envVar, envVal, resArr)
  4764  	}
  4765  
  4766  	var resMap map[string]interface{}
  4767  	inspectFieldAndUnmarshall(c, imgName, "Config.ExposedPorts", &resMap)
  4768  	if _, ok := resMap[fmt.Sprintf("%s/tcp", exposeVal)]; !ok {
  4769  		c.Fatalf("Config.ExposedPorts value mismatch. Expected exposed port: %s/tcp, got: %v", exposeVal, resMap)
  4770  	}
  4771  
  4772  	res = inspectField(c, imgName, "Config.User")
  4773  	if res != userVal {
  4774  		c.Fatalf("Config.User value mismatch. Expected: %s, got: %s", userVal, res)
  4775  	}
  4776  
  4777  	inspectFieldAndUnmarshall(c, imgName, "Config.Volumes", &resMap)
  4778  	if _, ok := resMap[volVal]; !ok {
  4779  		c.Fatalf("Config.Volumes value mismatch. Expected volume: %s, got: %v", volVal, resMap)
  4780  	}
  4781  }
  4782  
  4783  func (s *DockerSuite) TestBuildBuildTimeArgExpansionOverride(c *check.C) {
  4784  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4785  	imgName := "bldvarstest"
  4786  	envKey := "foo"
  4787  	envVal := "bar"
  4788  	envKey1 := "foo1"
  4789  	envValOveride := "barOverride"
  4790  	dockerfile := fmt.Sprintf(`FROM busybox
  4791  		ARG %s
  4792  		ENV %s %s
  4793  		ENV %s ${%s}
  4794  		RUN echo $%s
  4795  		CMD echo $%s`, envKey, envKey, envValOveride, envKey1, envKey, envKey1, envKey1)
  4796  	result := buildImageNew(imgName,
  4797  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4798  		withDockerfile(dockerfile),
  4799  	)
  4800  	result.Assert(c, icmd.Success)
  4801  	if strings.Count(result.Combined(), envValOveride) != 2 {
  4802  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4803  	}
  4804  
  4805  	containerName := "bldargCont"
  4806  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4807  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4808  	}
  4809  }
  4810  
  4811  func (s *DockerSuite) TestBuildBuildTimeArgUntrustedDefinedAfterUse(c *check.C) {
  4812  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4813  	imgName := "bldargtest"
  4814  	envKey := "foo"
  4815  	envVal := "bar"
  4816  	dockerfile := fmt.Sprintf(`FROM busybox
  4817  		RUN echo $%s
  4818  		ARG %s
  4819  		CMD echo $%s`, envKey, envKey, envKey)
  4820  	result := buildImageNew(imgName,
  4821  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4822  		withDockerfile(dockerfile),
  4823  	)
  4824  	result.Assert(c, icmd.Success)
  4825  	if strings.Contains(result.Combined(), envVal) {
  4826  		c.Fatalf("able to access environment variable in output: %q expected to be missing", result.Combined())
  4827  	}
  4828  
  4829  	containerName := "bldargCont"
  4830  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); out != "\n" {
  4831  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4832  	}
  4833  }
  4834  
  4835  func (s *DockerSuite) TestBuildBuildTimeArgBuiltinArg(c *check.C) {
  4836  	testRequires(c, DaemonIsLinux) // Windows does not support --build-arg
  4837  	imgName := "bldargtest"
  4838  	envKey := "HTTP_PROXY"
  4839  	envVal := "bar"
  4840  	dockerfile := fmt.Sprintf(`FROM busybox
  4841  		RUN echo $%s
  4842  		CMD echo $%s`, envKey, envKey)
  4843  
  4844  	result := buildImageNew(imgName,
  4845  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4846  		withDockerfile(dockerfile),
  4847  	)
  4848  	result.Assert(c, icmd.Success)
  4849  	if !strings.Contains(result.Combined(), envVal) {
  4850  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envVal)
  4851  	}
  4852  	containerName := "bldargCont"
  4853  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); out != "\n" {
  4854  		c.Fatalf("run produced invalid output: %q, expected empty string", out)
  4855  	}
  4856  }
  4857  
  4858  func (s *DockerSuite) TestBuildBuildTimeArgDefaultOverride(c *check.C) {
  4859  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4860  	imgName := "bldargtest"
  4861  	envKey := "foo"
  4862  	envVal := "bar"
  4863  	envValOveride := "barOverride"
  4864  	dockerfile := fmt.Sprintf(`FROM busybox
  4865  		ARG %s=%s
  4866  		ENV %s $%s
  4867  		RUN echo $%s
  4868  		CMD echo $%s`, envKey, envVal, envKey, envKey, envKey, envKey)
  4869  	result := buildImageNew(imgName,
  4870  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envValOveride)),
  4871  		withDockerfile(dockerfile),
  4872  	)
  4873  	result.Assert(c, icmd.Success)
  4874  	if strings.Count(result.Combined(), envValOveride) != 1 {
  4875  		c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride)
  4876  	}
  4877  
  4878  	containerName := "bldargCont"
  4879  	if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); !strings.Contains(out, envValOveride) {
  4880  		c.Fatalf("run produced invalid output: %q, expected %q", out, envValOveride)
  4881  	}
  4882  }
  4883  
  4884  func (s *DockerSuite) TestBuildBuildTimeArgUnconsumedArg(c *check.C) {
  4885  	imgName := "bldargtest"
  4886  	envKey := "foo"
  4887  	envVal := "bar"
  4888  	dockerfile := fmt.Sprintf(`FROM busybox
  4889  		RUN echo $%s
  4890  		CMD echo $%s`, envKey, envKey)
  4891  	warnStr := "[Warning] One or more build-args"
  4892  	buildImageNew(imgName,
  4893  		withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)),
  4894  		withDockerfile(dockerfile),
  4895  	).Assert(c, icmd.Expected{
  4896  		Out: warnStr,
  4897  	})
  4898  }
  4899  
  4900  func (s *DockerSuite) TestBuildBuildTimeArgEnv(c *check.C) {
  4901  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4902  	dockerfile := `FROM busybox
  4903  		ARG FOO1=fromfile
  4904  		ARG FOO2=fromfile
  4905  		ARG FOO3=fromfile
  4906  		ARG FOO4=fromfile
  4907  		ARG FOO5
  4908  		ARG FOO6
  4909  		RUN env
  4910  		RUN [ "$FOO1" == "fromcmd" ]
  4911  		RUN [ "$FOO2" == "" ]
  4912  		RUN [ "$FOO3" == "fromenv" ]
  4913  		RUN [ "$FOO4" == "fromfile" ]
  4914  		RUN [ "$FOO5" == "fromcmd" ]
  4915  		# The following should not exist at all in the env
  4916  		RUN [ "$(env | grep FOO6)" == "" ]
  4917  		RUN [ "$(env | grep FOO7)" == "" ]
  4918  		RUN [ "$(env | grep FOO8)" == "" ]
  4919  		RUN [ "$(env | grep FOO9)" == "" ]
  4920  	    `
  4921  	result := buildImageNew("testbuildtimeargenv",
  4922  		withBuildFlags(
  4923  			"--build-arg", fmt.Sprintf("FOO1=fromcmd"),
  4924  			"--build-arg", fmt.Sprintf("FOO2="),
  4925  			"--build-arg", fmt.Sprintf("FOO3"), // set in env
  4926  			"--build-arg", fmt.Sprintf("FOO4"), // not set in env
  4927  			"--build-arg", fmt.Sprintf("FOO5=fromcmd"),
  4928  			// FOO6 is not set at all
  4929  			"--build-arg", fmt.Sprintf("FOO7=fromcmd"), // should produce a warning
  4930  			"--build-arg", fmt.Sprintf("FOO8="), // should produce a warning
  4931  			"--build-arg", fmt.Sprintf("FOO9"), // should produce a warning
  4932  		),
  4933  		withEnvironmentVariales(append(os.Environ(),
  4934  			"FOO1=fromenv",
  4935  			"FOO2=fromenv",
  4936  			"FOO3=fromenv")...),
  4937  		withBuildContext(c,
  4938  			withFile("Dockerfile", dockerfile),
  4939  		),
  4940  	)
  4941  	result.Assert(c, icmd.Success)
  4942  
  4943  	// Now check to make sure we got a warning msg about unused build-args
  4944  	i := strings.Index(result.Combined(), "[Warning]")
  4945  	if i < 0 {
  4946  		c.Fatalf("Missing the build-arg warning in %q", result.Combined())
  4947  	}
  4948  
  4949  	out := result.Combined()[i:] // "out" should contain just the warning message now
  4950  
  4951  	// These were specified on a --build-arg but no ARG was in the Dockerfile
  4952  	c.Assert(out, checker.Contains, "FOO7")
  4953  	c.Assert(out, checker.Contains, "FOO8")
  4954  	c.Assert(out, checker.Contains, "FOO9")
  4955  }
  4956  
  4957  func (s *DockerSuite) TestBuildBuildTimeArgQuotedValVariants(c *check.C) {
  4958  	imgName := "bldargtest"
  4959  	envKey := "foo"
  4960  	envKey1 := "foo1"
  4961  	envKey2 := "foo2"
  4962  	envKey3 := "foo3"
  4963  	dockerfile := fmt.Sprintf(`FROM busybox
  4964  		ARG %s=""
  4965  		ARG %s=''
  4966  		ARG %s="''"
  4967  		ARG %s='""'
  4968  		RUN [ "$%s" != "$%s" ]
  4969  		RUN [ "$%s" != "$%s" ]
  4970  		RUN [ "$%s" != "$%s" ]
  4971  		RUN [ "$%s" != "$%s" ]
  4972  		RUN [ "$%s" != "$%s" ]`, envKey, envKey1, envKey2, envKey3,
  4973  		envKey, envKey2, envKey, envKey3, envKey1, envKey2, envKey1, envKey3,
  4974  		envKey2, envKey3)
  4975  	buildImageSuccessfully(c, imgName, withDockerfile(dockerfile))
  4976  }
  4977  
  4978  func (s *DockerSuite) TestBuildBuildTimeArgEmptyValVariants(c *check.C) {
  4979  	testRequires(c, DaemonIsLinux) // Windows does not support ARG
  4980  	imgName := "bldargtest"
  4981  	envKey := "foo"
  4982  	envKey1 := "foo1"
  4983  	envKey2 := "foo2"
  4984  	dockerfile := fmt.Sprintf(`FROM busybox
  4985  		ARG %s=
  4986  		ARG %s=""
  4987  		ARG %s=''
  4988  		RUN [ "$%s" == "$%s" ]
  4989  		RUN [ "$%s" == "$%s" ]
  4990  		RUN [ "$%s" == "$%s" ]`, envKey, envKey1, envKey2, envKey, envKey1, envKey1, envKey2, envKey, envKey2)
  4991  	buildImageSuccessfully(c, imgName, withDockerfile(dockerfile))
  4992  }
  4993  
  4994  func (s *DockerSuite) TestBuildBuildTimeArgDefintionWithNoEnvInjection(c *check.C) {
  4995  	imgName := "bldargtest"
  4996  	envKey := "foo"
  4997  	dockerfile := fmt.Sprintf(`FROM busybox
  4998  		ARG %s
  4999  		RUN env`, envKey)
  5000  
  5001  	result := buildImageNew(imgName, withDockerfile(dockerfile))
  5002  	result.Assert(c, icmd.Success)
  5003  	if strings.Count(result.Combined(), envKey) != 1 {
  5004  		c.Fatalf("unexpected number of occurrences of the arg in output: %q expected: 1", result.Combined())
  5005  	}
  5006  }
  5007  
  5008  func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) {
  5009  	volName := "testname:/foo"
  5010  
  5011  	if testEnv.DaemonPlatform() == "windows" {
  5012  		volName = "testname:C:\\foo"
  5013  	}
  5014  	dockerCmd(c, "run", "-v", volName, "busybox", "sh", "-c", "touch /foo/oops")
  5015  
  5016  	dockerFile := `FROM busybox
  5017  	VOLUME ` + volName + `
  5018  	RUN ls /foo/oops
  5019  	`
  5020  	buildImageNew("test", withDockerfile(dockerFile)).Assert(c, icmd.Expected{
  5021  		ExitCode: 1,
  5022  	})
  5023  }
  5024  
  5025  func (s *DockerSuite) TestBuildTagEvent(c *check.C) {
  5026  	since := daemonUnixTime(c)
  5027  
  5028  	dockerFile := `FROM busybox
  5029  	RUN echo events
  5030  	`
  5031  	buildImageSuccessfully(c, "test", withDockerfile(dockerFile))
  5032  
  5033  	until := daemonUnixTime(c)
  5034  	out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "type=image")
  5035  	events := strings.Split(strings.TrimSpace(out), "\n")
  5036  	actions := eventActionsByIDAndType(c, events, "test:latest", "image")
  5037  	var foundTag bool
  5038  	for _, a := range actions {
  5039  		if a == "tag" {
  5040  			foundTag = true
  5041  			break
  5042  		}
  5043  	}
  5044  
  5045  	c.Assert(foundTag, checker.True, check.Commentf("No tag event found:\n%s", out))
  5046  }
  5047  
  5048  // #15780
  5049  func (s *DockerSuite) TestBuildMultipleTags(c *check.C) {
  5050  	dockerfile := `
  5051  	FROM busybox
  5052  	MAINTAINER test-15780
  5053  	`
  5054  	buildImageSuccessfully(c, "tag1", withBuildFlags("-t", "tag2:v2", "-t", "tag1:latest", "-t", "tag1"), withDockerfile(dockerfile))
  5055  
  5056  	id1, err := getIDByName("tag1")
  5057  	c.Assert(err, check.IsNil)
  5058  	id2, err := getIDByName("tag2:v2")
  5059  	c.Assert(err, check.IsNil)
  5060  	c.Assert(id1, check.Equals, id2)
  5061  }
  5062  
  5063  // #17290
  5064  func (s *DockerSuite) TestBuildCacheBrokenSymlink(c *check.C) {
  5065  	name := "testbuildbrokensymlink"
  5066  	ctx, err := fakeContext(`
  5067  	FROM busybox
  5068  	COPY . ./`,
  5069  		map[string]string{
  5070  			"foo": "bar",
  5071  		})
  5072  	c.Assert(err, checker.IsNil)
  5073  	defer ctx.Close()
  5074  
  5075  	err = os.Symlink(filepath.Join(ctx.Dir, "nosuchfile"), filepath.Join(ctx.Dir, "asymlink"))
  5076  	c.Assert(err, checker.IsNil)
  5077  
  5078  	// warm up cache
  5079  	_, err = buildImageFromContext(name, ctx, true)
  5080  	c.Assert(err, checker.IsNil)
  5081  
  5082  	// add new file to context, should invalidate cache
  5083  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "newfile"), []byte("foo"), 0644)
  5084  	c.Assert(err, checker.IsNil)
  5085  
  5086  	_, out, err := buildImageFromContextWithOut(name, ctx, true)
  5087  	c.Assert(err, checker.IsNil)
  5088  
  5089  	c.Assert(out, checker.Not(checker.Contains), "Using cache")
  5090  
  5091  }
  5092  
  5093  func (s *DockerSuite) TestBuildFollowSymlinkToFile(c *check.C) {
  5094  	name := "testbuildbrokensymlink"
  5095  	ctx, err := fakeContext(`
  5096  	FROM busybox
  5097  	COPY asymlink target`,
  5098  		map[string]string{
  5099  			"foo": "bar",
  5100  		})
  5101  	c.Assert(err, checker.IsNil)
  5102  	defer ctx.Close()
  5103  
  5104  	err = os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  5105  	c.Assert(err, checker.IsNil)
  5106  
  5107  	id, err := buildImageFromContext(name, ctx, true)
  5108  	c.Assert(err, checker.IsNil)
  5109  
  5110  	out, _ := dockerCmd(c, "run", "--rm", id, "cat", "target")
  5111  	c.Assert(out, checker.Matches, "bar")
  5112  
  5113  	// change target file should invalidate cache
  5114  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "foo"), []byte("baz"), 0644)
  5115  	c.Assert(err, checker.IsNil)
  5116  
  5117  	id, out, err = buildImageFromContextWithOut(name, ctx, true)
  5118  	c.Assert(err, checker.IsNil)
  5119  	c.Assert(out, checker.Not(checker.Contains), "Using cache")
  5120  
  5121  	out, _ = dockerCmd(c, "run", "--rm", id, "cat", "target")
  5122  	c.Assert(out, checker.Matches, "baz")
  5123  }
  5124  
  5125  func (s *DockerSuite) TestBuildFollowSymlinkToDir(c *check.C) {
  5126  	name := "testbuildbrokensymlink"
  5127  	ctx, err := fakeContext(`
  5128  	FROM busybox
  5129  	COPY asymlink /`,
  5130  		map[string]string{
  5131  			"foo/abc": "bar",
  5132  			"foo/def": "baz",
  5133  		})
  5134  	c.Assert(err, checker.IsNil)
  5135  	defer ctx.Close()
  5136  
  5137  	err = os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  5138  	c.Assert(err, checker.IsNil)
  5139  
  5140  	id, err := buildImageFromContext(name, ctx, true)
  5141  	c.Assert(err, checker.IsNil)
  5142  
  5143  	out, _ := dockerCmd(c, "run", "--rm", id, "cat", "abc", "def")
  5144  	c.Assert(out, checker.Matches, "barbaz")
  5145  
  5146  	// change target file should invalidate cache
  5147  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "foo/def"), []byte("bax"), 0644)
  5148  	c.Assert(err, checker.IsNil)
  5149  
  5150  	id, out, err = buildImageFromContextWithOut(name, ctx, true)
  5151  	c.Assert(err, checker.IsNil)
  5152  	c.Assert(out, checker.Not(checker.Contains), "Using cache")
  5153  
  5154  	out, _ = dockerCmd(c, "run", "--rm", id, "cat", "abc", "def")
  5155  	c.Assert(out, checker.Matches, "barbax")
  5156  
  5157  }
  5158  
  5159  // TestBuildSymlinkBasename tests that target file gets basename from symlink,
  5160  // not from the target file.
  5161  func (s *DockerSuite) TestBuildSymlinkBasename(c *check.C) {
  5162  	name := "testbuildbrokensymlink"
  5163  	ctx, err := fakeContext(`
  5164  	FROM busybox
  5165  	COPY asymlink /`,
  5166  		map[string]string{
  5167  			"foo": "bar",
  5168  		})
  5169  	c.Assert(err, checker.IsNil)
  5170  	defer ctx.Close()
  5171  
  5172  	err = os.Symlink("foo", filepath.Join(ctx.Dir, "asymlink"))
  5173  	c.Assert(err, checker.IsNil)
  5174  
  5175  	id, err := buildImageFromContext(name, ctx, true)
  5176  	c.Assert(err, checker.IsNil)
  5177  
  5178  	out, _ := dockerCmd(c, "run", "--rm", id, "cat", "asymlink")
  5179  	c.Assert(out, checker.Matches, "bar")
  5180  
  5181  }
  5182  
  5183  // #17827
  5184  func (s *DockerSuite) TestBuildCacheRootSource(c *check.C) {
  5185  	name := "testbuildrootsource"
  5186  	ctx, err := fakeContext(`
  5187  	FROM busybox
  5188  	COPY / /data`,
  5189  		map[string]string{
  5190  			"foo": "bar",
  5191  		})
  5192  	c.Assert(err, checker.IsNil)
  5193  	defer ctx.Close()
  5194  
  5195  	// warm up cache
  5196  	_, err = buildImageFromContext(name, ctx, true)
  5197  	c.Assert(err, checker.IsNil)
  5198  
  5199  	// change file, should invalidate cache
  5200  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "foo"), []byte("baz"), 0644)
  5201  	c.Assert(err, checker.IsNil)
  5202  
  5203  	_, out, err := buildImageFromContextWithOut(name, ctx, true)
  5204  	c.Assert(err, checker.IsNil)
  5205  
  5206  	c.Assert(out, checker.Not(checker.Contains), "Using cache")
  5207  }
  5208  
  5209  // #19375
  5210  func (s *DockerSuite) TestBuildFailsGitNotCallable(c *check.C) {
  5211  	buildImageNew("gitnotcallable", withEnvironmentVariales("PATH="),
  5212  		withBuildContextPath("github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{
  5213  		ExitCode: 1,
  5214  		Err:      "unable to prepare context: unable to find 'git': ",
  5215  	})
  5216  
  5217  	buildImageNew("gitnotcallable", withEnvironmentVariales("PATH="),
  5218  		withBuildContextPath("https://github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{
  5219  		ExitCode: 1,
  5220  		Err:      "unable to prepare context: unable to find 'git': ",
  5221  	})
  5222  }
  5223  
  5224  // TestBuildWorkdirWindowsPath tests that a Windows style path works as a workdir
  5225  func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) {
  5226  	testRequires(c, DaemonIsWindows)
  5227  	name := "testbuildworkdirwindowspath"
  5228  	buildImageSuccessfully(c, name, withDockerfile(`
  5229  	FROM `+testEnv.MinimalBaseImage()+`
  5230  	RUN mkdir C:\\work
  5231  	WORKDIR C:\\work
  5232  	RUN if "%CD%" NEQ "C:\work" exit -1
  5233  	`))
  5234  }
  5235  
  5236  func (s *DockerSuite) TestBuildLabel(c *check.C) {
  5237  	name := "testbuildlabel"
  5238  	testLabel := "foo"
  5239  
  5240  	buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel),
  5241  		withDockerfile(`
  5242    FROM `+minimalBaseImage()+`
  5243    LABEL default foo
  5244  `))
  5245  
  5246  	var labels map[string]string
  5247  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5248  	if _, ok := labels[testLabel]; !ok {
  5249  		c.Fatal("label not found in image")
  5250  	}
  5251  }
  5252  
  5253  func (s *DockerSuite) TestBuildLabelOneNode(c *check.C) {
  5254  	name := "testbuildlabel"
  5255  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=bar"),
  5256  		withDockerfile("FROM busybox"))
  5257  
  5258  	var labels map[string]string
  5259  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5260  	v, ok := labels["foo"]
  5261  	if !ok {
  5262  		c.Fatal("label `foo` not found in image")
  5263  	}
  5264  	c.Assert(v, checker.Equals, "bar")
  5265  }
  5266  
  5267  func (s *DockerSuite) TestBuildLabelCacheCommit(c *check.C) {
  5268  	name := "testbuildlabelcachecommit"
  5269  	testLabel := "foo"
  5270  
  5271  	buildImageSuccessfully(c, name, withDockerfile(`
  5272    FROM `+minimalBaseImage()+`
  5273    LABEL default foo
  5274    `))
  5275  	buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel),
  5276  		withDockerfile(`
  5277    FROM `+minimalBaseImage()+`
  5278    LABEL default foo
  5279    `))
  5280  
  5281  	var labels map[string]string
  5282  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5283  	if _, ok := labels[testLabel]; !ok {
  5284  		c.Fatal("label not found in image")
  5285  	}
  5286  }
  5287  
  5288  func (s *DockerSuite) TestBuildLabelMultiple(c *check.C) {
  5289  	name := "testbuildlabelmultiple"
  5290  	testLabels := map[string]string{
  5291  		"foo": "bar",
  5292  		"123": "456",
  5293  	}
  5294  	labelArgs := []string{}
  5295  	for k, v := range testLabels {
  5296  		labelArgs = append(labelArgs, "--label", k+"="+v)
  5297  	}
  5298  
  5299  	buildImageSuccessfully(c, name, withBuildFlags(labelArgs...),
  5300  		withDockerfile(`
  5301    FROM `+minimalBaseImage()+`
  5302    LABEL default foo
  5303  `))
  5304  
  5305  	var labels map[string]string
  5306  	inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels)
  5307  	for k, v := range testLabels {
  5308  		if x, ok := labels[k]; !ok || x != v {
  5309  			c.Fatalf("label %s=%s not found in image", k, v)
  5310  		}
  5311  	}
  5312  }
  5313  
  5314  func (s *DockerRegistryAuthHtpasswdSuite) TestBuildFromAuthenticatedRegistry(c *check.C) {
  5315  	dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
  5316  	baseImage := privateRegistryURL + "/baseimage"
  5317  
  5318  	buildImageSuccessfully(c, baseImage, withDockerfile(`
  5319  	FROM busybox
  5320  	ENV env1 val1
  5321  	`))
  5322  
  5323  	dockerCmd(c, "push", baseImage)
  5324  	dockerCmd(c, "rmi", baseImage)
  5325  
  5326  	buildImageSuccessfully(c, baseImage, withDockerfile(fmt.Sprintf(`
  5327  	FROM %s
  5328  	ENV env2 val2
  5329  	`, baseImage)))
  5330  }
  5331  
  5332  func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C) {
  5333  	osPath := os.Getenv("PATH")
  5334  	defer os.Setenv("PATH", osPath)
  5335  
  5336  	workingDir, err := os.Getwd()
  5337  	c.Assert(err, checker.IsNil)
  5338  	absolute, err := filepath.Abs(filepath.Join(workingDir, "fixtures", "auth"))
  5339  	c.Assert(err, checker.IsNil)
  5340  	testPath := fmt.Sprintf("%s%c%s", osPath, filepath.ListSeparator, absolute)
  5341  
  5342  	os.Setenv("PATH", testPath)
  5343  
  5344  	repoName := fmt.Sprintf("%v/dockercli/busybox:authtest", privateRegistryURL)
  5345  
  5346  	tmp, err := ioutil.TempDir("", "integration-cli-")
  5347  	c.Assert(err, checker.IsNil)
  5348  
  5349  	externalAuthConfig := `{ "credsStore": "shell-test" }`
  5350  
  5351  	configPath := filepath.Join(tmp, "config.json")
  5352  	err = ioutil.WriteFile(configPath, []byte(externalAuthConfig), 0644)
  5353  	c.Assert(err, checker.IsNil)
  5354  
  5355  	dockerCmd(c, "--config", tmp, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL)
  5356  
  5357  	b, err := ioutil.ReadFile(configPath)
  5358  	c.Assert(err, checker.IsNil)
  5359  	c.Assert(string(b), checker.Not(checker.Contains), "\"auth\":")
  5360  
  5361  	dockerCmd(c, "--config", tmp, "tag", "busybox", repoName)
  5362  	dockerCmd(c, "--config", tmp, "push", repoName)
  5363  
  5364  	// make sure the image is pulled when building
  5365  	dockerCmd(c, "rmi", repoName)
  5366  
  5367  	icmd.RunCmd(icmd.Cmd{
  5368  		Command: []string{dockerBinary, "--config", tmp, "build", "-"},
  5369  		Stdin:   strings.NewReader(fmt.Sprintf("FROM %s", repoName)),
  5370  	}).Assert(c, icmd.Success)
  5371  }
  5372  
  5373  // Test cases in #22036
  5374  func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) {
  5375  	// Command line option labels will always override
  5376  	name := "scratchy"
  5377  	expected := `{"bar":"from-flag","foo":"from-flag"}`
  5378  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"),
  5379  		withDockerfile(`FROM `+minimalBaseImage()+`
  5380                  LABEL foo=from-dockerfile`))
  5381  	res := inspectFieldJSON(c, name, "Config.Labels")
  5382  	if res != expected {
  5383  		c.Fatalf("Labels %s, expected %s", res, expected)
  5384  	}
  5385  
  5386  	name = "from"
  5387  	expected = `{"foo":"from-dockerfile"}`
  5388  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  5389                  LABEL foo from-dockerfile`))
  5390  	res = inspectFieldJSON(c, name, "Config.Labels")
  5391  	if res != expected {
  5392  		c.Fatalf("Labels %s, expected %s", res, expected)
  5393  	}
  5394  
  5395  	// Command line option label will override even via `FROM`
  5396  	name = "new"
  5397  	expected = `{"bar":"from-dockerfile2","foo":"new"}`
  5398  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=new"),
  5399  		withDockerfile(`FROM from
  5400                  LABEL bar from-dockerfile2`))
  5401  	res = inspectFieldJSON(c, name, "Config.Labels")
  5402  	if res != expected {
  5403  		c.Fatalf("Labels %s, expected %s", res, expected)
  5404  	}
  5405  
  5406  	// Command line option without a value set (--label foo, --label bar=)
  5407  	// will be treated as --label foo="", --label bar=""
  5408  	name = "scratchy2"
  5409  	expected = `{"bar":"","foo":""}`
  5410  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo", "--label", "bar="),
  5411  		withDockerfile(`FROM `+minimalBaseImage()+`
  5412                  LABEL foo=from-dockerfile`))
  5413  	res = inspectFieldJSON(c, name, "Config.Labels")
  5414  	if res != expected {
  5415  		c.Fatalf("Labels %s, expected %s", res, expected)
  5416  	}
  5417  
  5418  	// Command line option without a value set (--label foo, --label bar=)
  5419  	// will be treated as --label foo="", --label bar=""
  5420  	// This time is for inherited images
  5421  	name = "new2"
  5422  	expected = `{"bar":"","foo":""}`
  5423  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=", "--label", "bar"),
  5424  		withDockerfile(`FROM from
  5425                  LABEL bar from-dockerfile2`))
  5426  	res = inspectFieldJSON(c, name, "Config.Labels")
  5427  	if res != expected {
  5428  		c.Fatalf("Labels %s, expected %s", res, expected)
  5429  	}
  5430  
  5431  	// Command line option labels with only `FROM`
  5432  	name = "scratchy"
  5433  	expected = `{"bar":"from-flag","foo":"from-flag"}`
  5434  	buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"),
  5435  		withDockerfile(`FROM `+minimalBaseImage()))
  5436  	res = inspectFieldJSON(c, name, "Config.Labels")
  5437  	if res != expected {
  5438  		c.Fatalf("Labels %s, expected %s", res, expected)
  5439  	}
  5440  
  5441  	// Command line option labels with env var
  5442  	name = "scratchz"
  5443  	expected = `{"bar":"$PATH"}`
  5444  	buildImageSuccessfully(c, name, withBuildFlags("--label", "bar=$PATH"),
  5445  		withDockerfile(`FROM `+minimalBaseImage()))
  5446  	res = inspectFieldJSON(c, name, "Config.Labels")
  5447  	if res != expected {
  5448  		c.Fatalf("Labels %s, expected %s", res, expected)
  5449  	}
  5450  }
  5451  
  5452  // Test case for #22855
  5453  func (s *DockerSuite) TestBuildDeleteCommittedFile(c *check.C) {
  5454  	name := "test-delete-committed-file"
  5455  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  5456  		RUN echo test > file
  5457  		RUN test -e file
  5458  		RUN rm file
  5459  		RUN sh -c "! test -e file"`))
  5460  }
  5461  
  5462  // #20083
  5463  func (s *DockerSuite) TestBuildDockerignoreComment(c *check.C) {
  5464  	// TODO Windows: Figure out why this test is flakey on TP5. If you add
  5465  	// something like RUN sleep 5, or even RUN ls /tmp after the ADD line,
  5466  	// it is more reliable, but that's not a good fix.
  5467  	testRequires(c, DaemonIsLinux)
  5468  
  5469  	name := "testbuilddockerignorecleanpaths"
  5470  	dockerfile := `
  5471          FROM busybox
  5472          ADD . /tmp/
  5473          RUN sh -c "(ls -la /tmp/#1)"
  5474          RUN sh -c "(! ls -la /tmp/#2)"
  5475          RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (ls /tmp/dir1/foo)"`
  5476  	buildImageSuccessfully(c, name, withBuildContext(c,
  5477  		withFile("Dockerfile", dockerfile),
  5478  		withFile("foo", "foo"),
  5479  		withFile("foo2", "foo2"),
  5480  		withFile("dir1/foo", "foo in dir1"),
  5481  		withFile("#1", "# file 1"),
  5482  		withFile("#2", "# file 2"),
  5483  		withFile(".dockerignore", `# Visual C++ cache files
  5484  # because we have git ;-)
  5485  # The above comment is from #20083
  5486  foo
  5487  #dir1/foo
  5488  foo2
  5489  # The following is considered as comment as # is at the beginning
  5490  #1
  5491  # The following is not considered as comment as # is not at the beginning
  5492    #2
  5493  `)))
  5494  }
  5495  
  5496  // Test case for #23221
  5497  func (s *DockerSuite) TestBuildWithUTF8BOM(c *check.C) {
  5498  	name := "test-with-utf8-bom"
  5499  	dockerfile := []byte(`FROM busybox`)
  5500  	bomDockerfile := append([]byte{0xEF, 0xBB, 0xBF}, dockerfile...)
  5501  	buildImageSuccessfully(c, name, withBuildContext(c,
  5502  		withFile("Dockerfile", string(bomDockerfile)),
  5503  	))
  5504  }
  5505  
  5506  // Test case for UTF-8 BOM in .dockerignore, related to #23221
  5507  func (s *DockerSuite) TestBuildWithUTF8BOMDockerignore(c *check.C) {
  5508  	name := "test-with-utf8-bom-dockerignore"
  5509  	dockerfile := `
  5510          FROM busybox
  5511  		ADD . /tmp/
  5512  		RUN ls -la /tmp
  5513  		RUN sh -c "! ls /tmp/Dockerfile"
  5514  		RUN ls /tmp/.dockerignore`
  5515  	dockerignore := []byte("./Dockerfile\n")
  5516  	bomDockerignore := append([]byte{0xEF, 0xBB, 0xBF}, dockerignore...)
  5517  	buildImageSuccessfully(c, name, withBuildContext(c,
  5518  		withFile("Dockerfile", dockerfile),
  5519  		withFile(".dockerignore", string(bomDockerignore)),
  5520  	))
  5521  }
  5522  
  5523  // #22489 Shell test to confirm config gets updated correctly
  5524  func (s *DockerSuite) TestBuildShellUpdatesConfig(c *check.C) {
  5525  	name := "testbuildshellupdatesconfig"
  5526  
  5527  	buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+`
  5528          SHELL ["foo", "-bar"]`))
  5529  	expected := `["foo","-bar","#(nop) ","SHELL [foo -bar]"]`
  5530  	res := inspectFieldJSON(c, name, "ContainerConfig.Cmd")
  5531  	if res != expected {
  5532  		c.Fatalf("%s, expected %s", res, expected)
  5533  	}
  5534  	res = inspectFieldJSON(c, name, "ContainerConfig.Shell")
  5535  	if res != `["foo","-bar"]` {
  5536  		c.Fatalf(`%s, expected ["foo","-bar"]`, res)
  5537  	}
  5538  }
  5539  
  5540  // #22489 Changing the shell multiple times and CMD after.
  5541  func (s *DockerSuite) TestBuildShellMultiple(c *check.C) {
  5542  	name := "testbuildshellmultiple"
  5543  
  5544  	result := buildImageNew(name, withDockerfile(`FROM busybox
  5545  		RUN echo defaultshell
  5546  		SHELL ["echo"]
  5547  		RUN echoshell
  5548  		SHELL ["ls"]
  5549  		RUN -l
  5550  		CMD -l`))
  5551  	result.Assert(c, icmd.Success)
  5552  
  5553  	// Must contain 'defaultshell' twice
  5554  	if len(strings.Split(result.Combined(), "defaultshell")) != 3 {
  5555  		c.Fatalf("defaultshell should have appeared twice in %s", result.Combined())
  5556  	}
  5557  
  5558  	// Must contain 'echoshell' twice
  5559  	if len(strings.Split(result.Combined(), "echoshell")) != 3 {
  5560  		c.Fatalf("echoshell should have appeared twice in %s", result.Combined())
  5561  	}
  5562  
  5563  	// Must contain "total " (part of ls -l)
  5564  	if !strings.Contains(result.Combined(), "total ") {
  5565  		c.Fatalf("%s should have contained 'total '", result.Combined())
  5566  	}
  5567  
  5568  	// A container started from the image uses the shell-form CMD.
  5569  	// Last shell is ls. CMD is -l. So should contain 'total '.
  5570  	outrun, _ := dockerCmd(c, "run", "--rm", name)
  5571  	if !strings.Contains(outrun, "total ") {
  5572  		c.Fatalf("Expected started container to run ls -l. %s", outrun)
  5573  	}
  5574  }
  5575  
  5576  // #22489. Changed SHELL with ENTRYPOINT
  5577  func (s *DockerSuite) TestBuildShellEntrypoint(c *check.C) {
  5578  	name := "testbuildshellentrypoint"
  5579  
  5580  	buildImageSuccessfully(c, name, withDockerfile(`FROM busybox
  5581  		SHELL ["ls"]
  5582  		ENTRYPOINT -l`))
  5583  	// A container started from the image uses the shell-form ENTRYPOINT.
  5584  	// Shell is ls. ENTRYPOINT is -l. So should contain 'total '.
  5585  	outrun, _ := dockerCmd(c, "run", "--rm", name)
  5586  	if !strings.Contains(outrun, "total ") {
  5587  		c.Fatalf("Expected started container to run ls -l. %s", outrun)
  5588  	}
  5589  }
  5590  
  5591  // #22489 Shell test to confirm shell is inherited in a subsequent build
  5592  func (s *DockerSuite) TestBuildShellInherited(c *check.C) {
  5593  	name1 := "testbuildshellinherited1"
  5594  	buildImageSuccessfully(c, name1, withDockerfile(`FROM busybox
  5595          SHELL ["ls"]`))
  5596  	name2 := "testbuildshellinherited2"
  5597  	buildImageNew(name2, withDockerfile(`FROM `+name1+`
  5598          RUN -l`)).Assert(c, icmd.Expected{
  5599  		// ls -l has "total " followed by some number in it, ls without -l does not.
  5600  		Out: "total ",
  5601  	})
  5602  }
  5603  
  5604  // #22489 Shell test to confirm non-JSON doesn't work
  5605  func (s *DockerSuite) TestBuildShellNotJSON(c *check.C) {
  5606  	name := "testbuildshellnotjson"
  5607  
  5608  	buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+`
  5609          sHeLl exec -form`, // Casing explicit to ensure error is upper-cased.
  5610  	)).Assert(c, icmd.Expected{
  5611  		ExitCode: 1,
  5612  		Err:      "SHELL requires the arguments to be in JSON form",
  5613  	})
  5614  }
  5615  
  5616  // #22489 Windows shell test to confirm native is powershell if executing a PS command
  5617  // This would error if the default shell were still cmd.
  5618  func (s *DockerSuite) TestBuildShellWindowsPowershell(c *check.C) {
  5619  	testRequires(c, DaemonIsWindows)
  5620  	name := "testbuildshellpowershell"
  5621  	buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+`
  5622          SHELL ["powershell", "-command"]
  5623  		RUN Write-Host John`)).Assert(c, icmd.Expected{
  5624  		Out: "\nJohn\n",
  5625  	})
  5626  }
  5627  
  5628  // Verify that escape is being correctly applied to words when escape directive is not \.
  5629  // Tests WORKDIR, ADD
  5630  func (s *DockerSuite) TestBuildEscapeNotBackslashWordTest(c *check.C) {
  5631  	testRequires(c, DaemonIsWindows)
  5632  	name := "testbuildescapenotbackslashwordtesta"
  5633  	buildImageNew(name, withDockerfile(`# escape= `+"`"+`
  5634  		FROM `+minimalBaseImage()+`
  5635          WORKDIR c:\windows
  5636  		RUN dir /w`)).Assert(c, icmd.Expected{
  5637  		Out: "[System32]",
  5638  	})
  5639  
  5640  	name = "testbuildescapenotbackslashwordtestb"
  5641  	buildImageNew(name, withDockerfile(`# escape= `+"`"+`
  5642  		FROM `+minimalBaseImage()+`
  5643  		SHELL ["powershell.exe"]
  5644          WORKDIR c:\foo
  5645  		ADD Dockerfile c:\foo\
  5646  		RUN dir Dockerfile`)).Assert(c, icmd.Expected{
  5647  		Out: "-a----",
  5648  	})
  5649  }
  5650  
  5651  // #22868. Make sure shell-form CMD is marked as escaped in the config of the image
  5652  func (s *DockerSuite) TestBuildCmdShellArgsEscaped(c *check.C) {
  5653  	testRequires(c, DaemonIsWindows)
  5654  	name := "testbuildcmdshellescaped"
  5655  	buildImageSuccessfully(c, name, withDockerfile(`
  5656    FROM `+minimalBaseImage()+`
  5657    CMD "ipconfig"
  5658    `))
  5659  	res := inspectFieldJSON(c, name, "Config.ArgsEscaped")
  5660  	if res != "true" {
  5661  		c.Fatalf("CMD did not update Config.ArgsEscaped on image: %v", res)
  5662  	}
  5663  	dockerCmd(c, "run", "--name", "inspectme", name)
  5664  	dockerCmd(c, "wait", "inspectme")
  5665  	res = inspectFieldJSON(c, name, "Config.Cmd")
  5666  
  5667  	if res != `["cmd","/S","/C","\"ipconfig\""]` {
  5668  		c.Fatalf("CMD was not escaped Config.Cmd: got %v", res)
  5669  	}
  5670  }
  5671  
  5672  // Test case for #24912.
  5673  func (s *DockerSuite) TestBuildStepsWithProgress(c *check.C) {
  5674  	name := "testbuildstepswithprogress"
  5675  	totalRun := 5
  5676  	result := buildImageNew(name, withDockerfile("FROM busybox\n"+strings.Repeat("RUN echo foo\n", totalRun)))
  5677  	result.Assert(c, icmd.Success)
  5678  	c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step 1/%d : FROM busybox", 1+totalRun))
  5679  	for i := 2; i <= 1+totalRun; i++ {
  5680  		c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step %d/%d : RUN echo foo", i, 1+totalRun))
  5681  	}
  5682  }
  5683  
  5684  func (s *DockerSuite) TestBuildWithFailure(c *check.C) {
  5685  	name := "testbuildwithfailure"
  5686  
  5687  	// First test case can only detect `nobody` in runtime so all steps will show up
  5688  	dockerfile := "FROM busybox\nRUN nobody"
  5689  	result := buildImageNew(name, withDockerfile(dockerfile))
  5690  	c.Assert(result.Error, checker.NotNil)
  5691  	c.Assert(result.Stdout(), checker.Contains, "Step 1/2 : FROM busybox")
  5692  	c.Assert(result.Stdout(), checker.Contains, "Step 2/2 : RUN nobody")
  5693  
  5694  	// Second test case `FFOM` should have been detected before build runs so no steps
  5695  	dockerfile = "FFOM nobody\nRUN nobody"
  5696  	result = buildImageNew(name, withDockerfile(dockerfile))
  5697  	c.Assert(result.Error, checker.NotNil)
  5698  	c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 1/2 : FROM busybox")
  5699  	c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 2/2 : RUN nobody")
  5700  }
  5701  
  5702  func (s *DockerSuite) TestBuildCacheFrom(c *check.C) {
  5703  	testRequires(c, DaemonIsLinux) // All tests that do save are skipped in windows
  5704  	dockerfile := `
  5705  		FROM busybox
  5706  		ENV FOO=bar
  5707  		ADD baz /
  5708  		RUN touch bax`
  5709  	ctx, err := fakeContext(dockerfile, map[string]string{
  5710  		"Dockerfile": dockerfile,
  5711  		"baz":        "baz",
  5712  	})
  5713  	c.Assert(err, checker.IsNil)
  5714  	defer ctx.Close()
  5715  
  5716  	id1, err := buildImageFromContext("build1", ctx, true)
  5717  	c.Assert(err, checker.IsNil)
  5718  
  5719  	// rebuild with cache-from
  5720  	id2, out, err := buildImageFromContextWithOut("build2", ctx, true, "--cache-from=build1")
  5721  	c.Assert(err, checker.IsNil)
  5722  	c.Assert(id1, checker.Equals, id2)
  5723  	c.Assert(strings.Count(out, "Using cache"), checker.Equals, 3)
  5724  	dockerCmd(c, "rmi", "build2")
  5725  
  5726  	// no cache match with unknown source
  5727  	id2, out, err = buildImageFromContextWithOut("build2", ctx, true, "--cache-from=nosuchtag")
  5728  	c.Assert(err, checker.IsNil)
  5729  	c.Assert(id1, checker.Not(checker.Equals), id2)
  5730  	c.Assert(strings.Count(out, "Using cache"), checker.Equals, 0)
  5731  	dockerCmd(c, "rmi", "build2")
  5732  
  5733  	// clear parent images
  5734  	tempDir, err := ioutil.TempDir("", "test-build-cache-from-")
  5735  	if err != nil {
  5736  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  5737  	}
  5738  	defer os.RemoveAll(tempDir)
  5739  	tempFile := filepath.Join(tempDir, "img.tar")
  5740  	dockerCmd(c, "save", "-o", tempFile, "build1")
  5741  	dockerCmd(c, "rmi", "build1")
  5742  	dockerCmd(c, "load", "-i", tempFile)
  5743  	parentID, _ := dockerCmd(c, "inspect", "-f", "{{.Parent}}", "build1")
  5744  	c.Assert(strings.TrimSpace(parentID), checker.Equals, "")
  5745  
  5746  	// cache still applies without parents
  5747  	id2, out, err = buildImageFromContextWithOut("build2", ctx, true, "--cache-from=build1")
  5748  	c.Assert(err, checker.IsNil)
  5749  	c.Assert(id1, checker.Equals, id2)
  5750  	c.Assert(strings.Count(out, "Using cache"), checker.Equals, 3)
  5751  	history1, _ := dockerCmd(c, "history", "-q", "build2")
  5752  
  5753  	// Retry, no new intermediate images
  5754  	id3, out, err := buildImageFromContextWithOut("build3", ctx, true, "--cache-from=build1")
  5755  	c.Assert(err, checker.IsNil)
  5756  	c.Assert(id1, checker.Equals, id3)
  5757  	c.Assert(strings.Count(out, "Using cache"), checker.Equals, 3)
  5758  	history2, _ := dockerCmd(c, "history", "-q", "build3")
  5759  
  5760  	c.Assert(history1, checker.Equals, history2)
  5761  	dockerCmd(c, "rmi", "build2")
  5762  	dockerCmd(c, "rmi", "build3")
  5763  	dockerCmd(c, "rmi", "build1")
  5764  	dockerCmd(c, "load", "-i", tempFile)
  5765  
  5766  	// Modify file, everything up to last command and layers are reused
  5767  	dockerfile = `
  5768  		FROM busybox
  5769  		ENV FOO=bar
  5770  		ADD baz /
  5771  		RUN touch newfile`
  5772  	err = ioutil.WriteFile(filepath.Join(ctx.Dir, "Dockerfile"), []byte(dockerfile), 0644)
  5773  	c.Assert(err, checker.IsNil)
  5774  
  5775  	id2, out, err = buildImageFromContextWithOut("build2", ctx, true, "--cache-from=build1")
  5776  	c.Assert(err, checker.IsNil)
  5777  	c.Assert(id1, checker.Not(checker.Equals), id2)
  5778  	c.Assert(strings.Count(out, "Using cache"), checker.Equals, 2)
  5779  
  5780  	layers1Str, _ := dockerCmd(c, "inspect", "-f", "{{json .RootFS.Layers}}", "build1")
  5781  	layers2Str, _ := dockerCmd(c, "inspect", "-f", "{{json .RootFS.Layers}}", "build2")
  5782  
  5783  	var layers1 []string
  5784  	var layers2 []string
  5785  	c.Assert(json.Unmarshal([]byte(layers1Str), &layers1), checker.IsNil)
  5786  	c.Assert(json.Unmarshal([]byte(layers2Str), &layers2), checker.IsNil)
  5787  
  5788  	c.Assert(len(layers1), checker.Equals, len(layers2))
  5789  	for i := 0; i < len(layers1)-1; i++ {
  5790  		c.Assert(layers1[i], checker.Equals, layers2[i])
  5791  	}
  5792  	c.Assert(layers1[len(layers1)-1], checker.Not(checker.Equals), layers2[len(layers1)-1])
  5793  }
  5794  
  5795  func (s *DockerSuite) TestBuildNetNone(c *check.C) {
  5796  	testRequires(c, DaemonIsLinux)
  5797  	name := "testbuildnetnone"
  5798  	buildImageNew(name, withBuildFlags("--network=none"), withDockerfile(`
  5799    FROM busybox
  5800    RUN ping -c 1 8.8.8.8
  5801    `)).Assert(c, icmd.Expected{
  5802  		ExitCode: 1,
  5803  		Out:      "unreachable",
  5804  	})
  5805  }
  5806  
  5807  func (s *DockerSuite) TestBuildNetContainer(c *check.C) {
  5808  	testRequires(c, DaemonIsLinux)
  5809  
  5810  	id, _ := dockerCmd(c, "run", "--hostname", "foobar", "-d", "busybox", "nc", "-ll", "-p", "1234", "-e", "hostname")
  5811  
  5812  	name := "testbuildnetcontainer"
  5813  	buildImageSuccessfully(c, name, withBuildFlags("--network=container:"+strings.TrimSpace(id)),
  5814  		withDockerfile(`
  5815    FROM busybox
  5816    RUN nc localhost 1234 > /otherhost
  5817    `))
  5818  
  5819  	host, _ := dockerCmd(c, "run", "testbuildnetcontainer", "cat", "/otherhost")
  5820  	c.Assert(strings.TrimSpace(host), check.Equals, "foobar")
  5821  }
  5822  
  5823  func (s *DockerSuite) TestBuildSquashParent(c *check.C) {
  5824  	testRequires(c, ExperimentalDaemon)
  5825  	dockerFile := `
  5826  		FROM busybox
  5827  		RUN echo hello > /hello
  5828  		RUN echo world >> /hello
  5829  		RUN echo hello > /remove_me
  5830  		ENV HELLO world
  5831  		RUN rm /remove_me
  5832  		`
  5833  	// build and get the ID that we can use later for history comparison
  5834  	name := "test"
  5835  	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
  5836  	origID, err := getIDByName(name)
  5837  	c.Assert(err, checker.IsNil)
  5838  
  5839  	// build with squash
  5840  	buildImageSuccessfully(c, name, withBuildFlags("--squash"), withDockerfile(dockerFile))
  5841  	id, err := getIDByName(name)
  5842  	c.Assert(err, checker.IsNil)
  5843  
  5844  	out, _ := dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", "cat /hello")
  5845  	c.Assert(strings.TrimSpace(out), checker.Equals, "hello\nworld")
  5846  
  5847  	dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", "[ ! -f /remove_me ]")
  5848  	dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", `[ "$(echo $HELLO)" == "world" ]`)
  5849  
  5850  	// make sure the ID produced is the ID of the tag we specified
  5851  	inspectID, err := inspectImage("test", ".ID")
  5852  	c.Assert(err, checker.IsNil)
  5853  	c.Assert(inspectID, checker.Equals, id)
  5854  
  5855  	origHistory, _ := dockerCmd(c, "history", origID)
  5856  	testHistory, _ := dockerCmd(c, "history", "test")
  5857  
  5858  	splitOrigHistory := strings.Split(strings.TrimSpace(origHistory), "\n")
  5859  	splitTestHistory := strings.Split(strings.TrimSpace(testHistory), "\n")
  5860  	c.Assert(len(splitTestHistory), checker.Equals, len(splitOrigHistory)+1)
  5861  
  5862  	out, err = inspectImage(id, "len .RootFS.Layers")
  5863  	c.Assert(err, checker.IsNil)
  5864  	c.Assert(strings.TrimSpace(out), checker.Equals, "3")
  5865  }
  5866  
  5867  func (s *DockerSuite) TestBuildContChar(c *check.C) {
  5868  	name := "testbuildcontchar"
  5869  
  5870  	buildImageNew(name, withDockerfile(`FROM busybox\`)).Assert(c, icmd.Expected{
  5871  		Out: "Step 1/1 : FROM busybox",
  5872  	})
  5873  
  5874  	result := buildImageNew(name, withDockerfile(`FROM busybox
  5875  		 RUN echo hi \`))
  5876  	result.Assert(c, icmd.Success)
  5877  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5878  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi\n")
  5879  
  5880  	result = buildImageNew(name, withDockerfile(`FROM busybox
  5881  		 RUN echo hi \\`))
  5882  	result.Assert(c, icmd.Success)
  5883  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5884  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\n")
  5885  
  5886  	result = buildImageNew(name, withDockerfile(`FROM busybox
  5887  		 RUN echo hi \\\`))
  5888  	result.Assert(c, icmd.Success)
  5889  	c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox")
  5890  	c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\\\n")
  5891  }
  5892  
  5893  // TestBuildOpaqueDirectory tests that a build succeeds which
  5894  // creates opaque directories.
  5895  // See https://github.com/docker/docker/issues/25244
  5896  func (s *DockerSuite) TestBuildOpaqueDirectory(c *check.C) {
  5897  	testRequires(c, DaemonIsLinux)
  5898  	dockerFile := `
  5899  		FROM busybox
  5900  		RUN mkdir /dir1 && touch /dir1/f1
  5901  		RUN rm -rf /dir1 && mkdir /dir1 && touch /dir1/f2
  5902  		RUN touch /dir1/f3
  5903  		RUN [ -f /dir1/f2 ]
  5904  		`
  5905  	// Test that build succeeds, last command fails if opaque directory
  5906  	// was not handled correctly
  5907  	buildImageSuccessfully(c, "testopaquedirectory", withDockerfile(dockerFile))
  5908  }
  5909  
  5910  // Windows test for USER in dockerfile
  5911  func (s *DockerSuite) TestBuildWindowsUser(c *check.C) {
  5912  	testRequires(c, DaemonIsWindows)
  5913  	name := "testbuildwindowsuser"
  5914  	buildImageNew(name, withDockerfile(`FROM `+testEnv.MinimalBaseImage()+`
  5915  		RUN net user user /add
  5916  		USER user
  5917  		RUN set username
  5918  		`)).Assert(c, icmd.Expected{
  5919  		Out: "USERNAME=user",
  5920  	})
  5921  }
  5922  
  5923  // Verifies if COPY file . when WORKDIR is set to a non-existing directory,
  5924  // the directory is created and the file is copied into the directory,
  5925  // as opposed to the file being copied as a file with the name of the
  5926  // directory. Fix for 27545 (found on Windows, but regression good for Linux too).
  5927  // Note 27545 was reverted in 28505, but a new fix was added subsequently in 28514.
  5928  func (s *DockerSuite) TestBuildCopyFileDotWithWorkdir(c *check.C) {
  5929  	name := "testbuildcopyfiledotwithworkdir"
  5930  	buildImageSuccessfully(c, name, withBuildContext(c,
  5931  		withFile("Dockerfile", `FROM busybox
  5932  WORKDIR /foo
  5933  COPY file .
  5934  RUN ["cat", "/foo/file"]
  5935  `),
  5936  		withFile("file", "content"),
  5937  	))
  5938  }
  5939  
  5940  // Case-insensitive environment variables on Windows
  5941  func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) {
  5942  	testRequires(c, DaemonIsWindows)
  5943  	name := "testbuildwindowsenvcaseinsensitive"
  5944  	buildImageSuccessfully(c, name, withDockerfile(`
  5945  		FROM `+testEnv.MinimalBaseImage()+`
  5946  		ENV FOO=bar foo=baz
  5947    `))
  5948  	res := inspectFieldJSON(c, name, "Config.Env")
  5949  	if res != `["foo=baz"]` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped.
  5950  		c.Fatalf("Case insensitive environment variables on Windows failed. Got %s", res)
  5951  	}
  5952  }
  5953  
  5954  // Test case for 29667
  5955  func (s *DockerSuite) TestBuildWorkdirImageCmd(c *check.C) {
  5956  	image := "testworkdirimagecmd"
  5957  	buildImageSuccessfully(c, image, withDockerfile(`
  5958  FROM busybox
  5959  WORKDIR /foo/bar
  5960  `))
  5961  	out, _ := dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image)
  5962  
  5963  	// The Windows busybox image has a blank `cmd`
  5964  	lookingFor := `["sh"]`
  5965  	if testEnv.DaemonPlatform() == "windows" {
  5966  		lookingFor = "null"
  5967  	}
  5968  	c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor)
  5969  
  5970  	image = "testworkdirlabelimagecmd"
  5971  	buildImageSuccessfully(c, image, withDockerfile(`
  5972  FROM busybox
  5973  WORKDIR /foo/bar
  5974  LABEL a=b
  5975  `))
  5976  
  5977  	out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image)
  5978  	c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor)
  5979  }
  5980  
  5981  // Test case for 28902/28909
  5982  func (s *DockerSuite) TestBuildWorkdirCmd(c *check.C) {
  5983  	testRequires(c, DaemonIsLinux)
  5984  	name := "testbuildworkdircmd"
  5985  	dockerFile := `
  5986                  FROM busybox
  5987                  WORKDIR /
  5988                  `
  5989  	buildImageSuccessfully(c, name, withDockerfile(dockerFile))
  5990  	result := buildImageNew(name, withDockerfile(dockerFile))
  5991  	result.Assert(c, icmd.Success)
  5992  	c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 1)
  5993  }
  5994  
  5995  // FIXME(vdemeester) should be a unit test
  5996  func (s *DockerSuite) TestBuildLineErrorOnBuild(c *check.C) {
  5997  	name := "test_build_line_error_onbuild"
  5998  	buildImageNew(name, withDockerfile(`FROM busybox
  5999    ONBUILD
  6000    `)).Assert(c, icmd.Expected{
  6001  		ExitCode: 1,
  6002  		Err:      "Dockerfile parse error line 2: ONBUILD requires at least one argument",
  6003  	})
  6004  }
  6005  
  6006  // FIXME(vdemeester) should be a unit test
  6007  func (s *DockerSuite) TestBuildLineErrorUknownInstruction(c *check.C) {
  6008  	name := "test_build_line_error_unknown_instruction"
  6009  	buildImageNew(name, withDockerfile(`FROM busybox
  6010    RUN echo hello world
  6011    NOINSTRUCTION echo ba
  6012    RUN echo hello
  6013    ERROR
  6014    `)).Assert(c, icmd.Expected{
  6015  		ExitCode: 1,
  6016  		Err:      "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION",
  6017  	})
  6018  }
  6019  
  6020  // FIXME(vdemeester) should be a unit test
  6021  func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) {
  6022  	name := "test_build_line_error_with_empty_lines"
  6023  	buildImageNew(name, withDockerfile(`
  6024    FROM busybox
  6025  
  6026    RUN echo hello world
  6027  
  6028    NOINSTRUCTION echo ba
  6029  
  6030    CMD ["/bin/init"]
  6031    `)).Assert(c, icmd.Expected{
  6032  		ExitCode: 1,
  6033  		Err:      "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION",
  6034  	})
  6035  }
  6036  
  6037  // FIXME(vdemeester) should be a unit test
  6038  func (s *DockerSuite) TestBuildLineErrorWithComments(c *check.C) {
  6039  	name := "test_build_line_error_with_comments"
  6040  	buildImageNew(name, withDockerfile(`FROM busybox
  6041    # This will print hello world
  6042    # and then ba
  6043    RUN echo hello world
  6044    NOINSTRUCTION echo ba
  6045    `)).Assert(c, icmd.Expected{
  6046  		ExitCode: 1,
  6047  		Err:      "Dockerfile parse error line 5: Unknown instruction: NOINSTRUCTION",
  6048  	})
  6049  }