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