github.com/campoy/docker@v1.8.0-rc1/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bufio"
     6  	"bytes"
     7  	"encoding/json"
     8  	"fmt"
     9  	"io/ioutil"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"reflect"
    14  	"regexp"
    15  	"runtime"
    16  	"strconv"
    17  	"strings"
    18  	"text/template"
    19  	"time"
    20  
    21  	"github.com/docker/docker/builder/command"
    22  	"github.com/docker/docker/pkg/archive"
    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 ["/bin/echo"]
    71      CMD echo test
    72      `,
    73  		true)
    74  
    75  	if err != nil {
    76  		c.Fatal(err)
    77  	}
    78  
    79  	out, _ := dockerCmd(c, "run", "--rm", name)
    80  
    81  	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
    82  		c.Fatalf("CMD did not contain /bin/sh -c : %s", out)
    83  	}
    84  
    85  }
    86  
    87  func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) {
    88  	name := "testbuildenvironmentreplacement"
    89  
    90  	_, err := buildImage(name, `
    91    FROM scratch
    92    ENV user foo
    93    USER ${user}
    94    `, true)
    95  	if err != nil {
    96  		c.Fatal(err)
    97  	}
    98  
    99  	res, err := inspectFieldJSON(name, "Config.User")
   100  	if err != nil {
   101  		c.Fatal(err)
   102  	}
   103  
   104  	if res != `"foo"` {
   105  		c.Fatal("User foo from environment not in Config.User on image")
   106  	}
   107  
   108  }
   109  
   110  func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) {
   111  	name := "testbuildenvironmentreplacement"
   112  
   113  	_, err := buildImage(name, `
   114    FROM scratch
   115    ENV volume /quux
   116    VOLUME ${volume}
   117    `, true)
   118  	if err != nil {
   119  		c.Fatal(err)
   120  	}
   121  
   122  	res, err := inspectFieldJSON(name, "Config.Volumes")
   123  	if err != nil {
   124  		c.Fatal(err)
   125  	}
   126  
   127  	var volumes map[string]interface{}
   128  
   129  	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
   130  		c.Fatal(err)
   131  	}
   132  
   133  	if _, ok := volumes["/quux"]; !ok {
   134  		c.Fatal("Volume /quux from environment not in Config.Volumes on image")
   135  	}
   136  
   137  }
   138  
   139  func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) {
   140  	name := "testbuildenvironmentreplacement"
   141  
   142  	_, err := buildImage(name, `
   143    FROM scratch
   144    ENV port 80
   145    EXPOSE ${port}
   146    `, true)
   147  	if err != nil {
   148  		c.Fatal(err)
   149  	}
   150  
   151  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
   152  	if err != nil {
   153  		c.Fatal(err)
   154  	}
   155  
   156  	var exposedPorts map[string]interface{}
   157  
   158  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
   159  		c.Fatal(err)
   160  	}
   161  
   162  	if _, ok := exposedPorts["80/tcp"]; !ok {
   163  		c.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
   164  	}
   165  
   166  }
   167  
   168  func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) {
   169  	name := "testbuildenvironmentreplacement"
   170  
   171  	_, err := buildImage(name, `
   172    FROM busybox
   173    ENV MYWORKDIR /work
   174    RUN mkdir ${MYWORKDIR}
   175    WORKDIR ${MYWORKDIR}
   176    `, true)
   177  
   178  	if err != nil {
   179  		c.Fatal(err)
   180  	}
   181  
   182  }
   183  
   184  func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) {
   185  	name := "testbuildenvironmentreplacement"
   186  
   187  	ctx, err := fakeContext(`
   188    FROM scratch
   189    ENV baz foo
   190    ENV quux bar
   191    ENV dot .
   192    ENV fee fff
   193    ENV gee ggg
   194  
   195    ADD ${baz} ${dot}
   196    COPY ${quux} ${dot}
   197    ADD ${zzz:-${fee}} ${dot}
   198    COPY ${zzz:-${gee}} ${dot}
   199    `,
   200  		map[string]string{
   201  			"foo": "test1",
   202  			"bar": "test2",
   203  			"fff": "test3",
   204  			"ggg": "test4",
   205  		})
   206  
   207  	if err != nil {
   208  		c.Fatal(err)
   209  	}
   210  	defer ctx.Close()
   211  
   212  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   213  		c.Fatal(err)
   214  	}
   215  
   216  }
   217  
   218  func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) {
   219  	name := "testbuildenvironmentreplacement"
   220  
   221  	_, err := buildImage(name,
   222  		`
   223    FROM busybox
   224    ENV foo zzz
   225    ENV bar ${foo}
   226    ENV abc1='$foo'
   227    ENV env1=$foo env2=${foo} env3="$foo" env4="${foo}"
   228    RUN [ "$abc1" = '$foo' ] && (echo "$abc1" | grep -q foo)
   229    ENV abc2="\$foo"
   230    RUN [ "$abc2" = '$foo' ] && (echo "$abc2" | grep -q foo)
   231    ENV abc3 '$foo'
   232    RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo)
   233    ENV abc4 "\$foo"
   234    RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo)
   235    `, true)
   236  
   237  	if err != nil {
   238  		c.Fatal(err)
   239  	}
   240  
   241  	res, err := inspectFieldJSON(name, "Config.Env")
   242  	if err != nil {
   243  		c.Fatal(err)
   244  	}
   245  
   246  	envResult := []string{}
   247  
   248  	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
   249  		c.Fatal(err)
   250  	}
   251  
   252  	found := false
   253  	envCount := 0
   254  
   255  	for _, env := range envResult {
   256  		parts := strings.SplitN(env, "=", 2)
   257  		if parts[0] == "bar" {
   258  			found = true
   259  			if parts[1] != "zzz" {
   260  				c.Fatalf("Could not find replaced var for env `bar`: got %q instead of `zzz`", parts[1])
   261  			}
   262  		} else if strings.HasPrefix(parts[0], "env") {
   263  			envCount++
   264  			if parts[1] != "zzz" {
   265  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   266  			}
   267  		} else if strings.HasPrefix(parts[0], "env") {
   268  			envCount++
   269  			if parts[1] != "foo" {
   270  				c.Fatalf("%s should be 'foo' but instead its %q", parts[0], parts[1])
   271  			}
   272  		}
   273  	}
   274  
   275  	if !found {
   276  		c.Fatal("Never found the `bar` env variable")
   277  	}
   278  
   279  	if envCount != 4 {
   280  		c.Fatalf("Didn't find all env vars - only saw %d\n%s", envCount, envResult)
   281  	}
   282  
   283  }
   284  
   285  func (s *DockerSuite) TestBuildHandleEscapes(c *check.C) {
   286  	name := "testbuildhandleescapes"
   287  
   288  	_, err := buildImage(name,
   289  		`
   290    FROM scratch
   291    ENV FOO bar
   292    VOLUME ${FOO}
   293    `, true)
   294  
   295  	if err != nil {
   296  		c.Fatal(err)
   297  	}
   298  
   299  	var result map[string]map[string]struct{}
   300  
   301  	res, err := inspectFieldJSON(name, "Config.Volumes")
   302  	if err != nil {
   303  		c.Fatal(err)
   304  	}
   305  
   306  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   307  		c.Fatal(err)
   308  	}
   309  
   310  	if _, ok := result["bar"]; !ok {
   311  		c.Fatal("Could not find volume bar set from env foo in volumes table")
   312  	}
   313  
   314  	deleteImages(name)
   315  
   316  	_, err = buildImage(name,
   317  		`
   318    FROM scratch
   319    ENV FOO bar
   320    VOLUME \${FOO}
   321    `, true)
   322  
   323  	if err != nil {
   324  		c.Fatal(err)
   325  	}
   326  
   327  	res, err = inspectFieldJSON(name, "Config.Volumes")
   328  	if err != nil {
   329  		c.Fatal(err)
   330  	}
   331  
   332  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   333  		c.Fatal(err)
   334  	}
   335  
   336  	if _, ok := result["${FOO}"]; !ok {
   337  		c.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
   338  	}
   339  
   340  	deleteImages(name)
   341  
   342  	// this test in particular provides *7* backslashes and expects 6 to come back.
   343  	// Like above, the first escape is swallowed and the rest are treated as
   344  	// literals, this one is just less obvious because of all the character noise.
   345  
   346  	_, err = buildImage(name,
   347  		`
   348    FROM scratch
   349    ENV FOO bar
   350    VOLUME \\\\\\\${FOO}
   351    `, true)
   352  
   353  	if err != nil {
   354  		c.Fatal(err)
   355  	}
   356  
   357  	res, err = inspectFieldJSON(name, "Config.Volumes")
   358  	if err != nil {
   359  		c.Fatal(err)
   360  	}
   361  
   362  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   363  		c.Fatal(err)
   364  	}
   365  
   366  	if _, ok := result[`\\\${FOO}`]; !ok {
   367  		c.Fatal(`Could not find volume \\\${FOO} set from env foo in volumes table`, result)
   368  	}
   369  
   370  }
   371  
   372  func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) {
   373  	name := "testbuildonbuildlowercase"
   374  	name2 := "testbuildonbuildlowercase2"
   375  
   376  	_, err := buildImage(name,
   377  		`
   378    FROM busybox
   379    onbuild run echo quux
   380    `, true)
   381  
   382  	if err != nil {
   383  		c.Fatal(err)
   384  	}
   385  
   386  	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
   387    FROM %s
   388    `, name), true)
   389  
   390  	if err != nil {
   391  		c.Fatal(err)
   392  	}
   393  
   394  	if !strings.Contains(out, "quux") {
   395  		c.Fatalf("Did not receive the expected echo text, got %s", out)
   396  	}
   397  
   398  	if strings.Contains(out, "ONBUILD ONBUILD") {
   399  		c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
   400  	}
   401  
   402  }
   403  
   404  func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) {
   405  	name := "testbuildenvescapes"
   406  	_, err := buildImage(name,
   407  		`
   408      FROM busybox
   409      ENV TEST foo
   410      CMD echo \$
   411      `,
   412  		true)
   413  
   414  	if err != nil {
   415  		c.Fatal(err)
   416  	}
   417  
   418  	out, _ := dockerCmd(c, "run", "-t", name)
   419  
   420  	if strings.TrimSpace(out) != "$" {
   421  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   422  	}
   423  
   424  }
   425  
   426  func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) {
   427  	name := "testbuildenvoverwrite"
   428  
   429  	_, err := buildImage(name,
   430  		`
   431      FROM busybox
   432      ENV TEST foo
   433      CMD echo ${TEST}
   434      `,
   435  		true)
   436  
   437  	if err != nil {
   438  		c.Fatal(err)
   439  	}
   440  
   441  	out, _ := dockerCmd(c, "run", "-e", "TEST=bar", "-t", name)
   442  
   443  	if strings.TrimSpace(out) != "bar" {
   444  		c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   445  	}
   446  
   447  }
   448  
   449  func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainerInSourceImage(c *check.C) {
   450  	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
   451  
   452  	out, _ := dockerCmd(c, "create", "busybox", "true")
   453  
   454  	cleanedContainerID := strings.TrimSpace(out)
   455  
   456  	dockerCmd(c, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
   457  
   458  	_, err := buildImage(name,
   459  		`FROM onbuild`,
   460  		true)
   461  	if err != nil {
   462  		if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
   463  			c.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
   464  		}
   465  	} else {
   466  		c.Fatal("Error must not be nil")
   467  	}
   468  
   469  }
   470  
   471  func (s *DockerSuite) TestBuildOnBuildForbiddenFromInSourceImage(c *check.C) {
   472  	name := "testbuildonbuildforbiddenfrominsourceimage"
   473  
   474  	out, _ := dockerCmd(c, "create", "busybox", "true")
   475  
   476  	cleanedContainerID := strings.TrimSpace(out)
   477  
   478  	dockerCmd(c, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
   479  
   480  	_, err := buildImage(name,
   481  		`FROM onbuild`,
   482  		true)
   483  	if err != nil {
   484  		if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
   485  			c.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
   486  		}
   487  	} else {
   488  		c.Fatal("Error must not be nil")
   489  	}
   490  
   491  }
   492  
   493  func (s *DockerSuite) TestBuildOnBuildForbiddenChainedInSourceImage(c *check.C) {
   494  	name := "testbuildonbuildforbiddenchainedinsourceimage"
   495  
   496  	out, _ := dockerCmd(c, "create", "busybox", "true")
   497  
   498  	cleanedContainerID := strings.TrimSpace(out)
   499  
   500  	dockerCmd(c, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
   501  
   502  	_, err := buildImage(name,
   503  		`FROM onbuild`,
   504  		true)
   505  	if err != nil {
   506  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
   507  			c.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
   508  		}
   509  	} else {
   510  		c.Fatal("Error must not be nil")
   511  	}
   512  
   513  }
   514  
   515  func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) {
   516  	name1 := "onbuildcmd"
   517  	name2 := "onbuildgenerated"
   518  
   519  	_, err := buildImage(name1, `
   520  FROM busybox
   521  ONBUILD CMD ["hello world"]
   522  ONBUILD ENTRYPOINT ["echo"]
   523  ONBUILD RUN ["true"]`,
   524  		false)
   525  
   526  	if err != nil {
   527  		c.Fatal(err)
   528  	}
   529  
   530  	_, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false)
   531  
   532  	if err != nil {
   533  		c.Fatal(err)
   534  	}
   535  
   536  	out, _ := dockerCmd(c, "run", "-t", name2)
   537  
   538  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   539  		c.Fatal("did not get echo output from onbuild", out)
   540  	}
   541  
   542  }
   543  
   544  func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) {
   545  	name1 := "onbuildcmd"
   546  	name2 := "onbuildgenerated"
   547  
   548  	_, err := buildImage(name1, `
   549  FROM busybox
   550  ONBUILD ENTRYPOINT ["echo"]`,
   551  		false)
   552  
   553  	if err != nil {
   554  		c.Fatal(err)
   555  	}
   556  
   557  	_, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
   558  
   559  	if err != nil {
   560  		c.Fatal(err)
   561  	}
   562  
   563  	out, _ := dockerCmd(c, "run", "-t", name2)
   564  
   565  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   566  		c.Fatal("got malformed output from onbuild", out)
   567  	}
   568  
   569  }
   570  
   571  func (s *DockerSuite) TestBuildCacheAdd(c *check.C) {
   572  	name := "testbuildtwoimageswithadd"
   573  	server, err := fakeStorage(map[string]string{
   574  		"robots.txt": "hello",
   575  		"index.html": "world",
   576  	})
   577  	if err != nil {
   578  		c.Fatal(err)
   579  	}
   580  	defer server.Close()
   581  
   582  	if _, err := buildImage(name,
   583  		fmt.Sprintf(`FROM scratch
   584  		ADD %s/robots.txt /`, server.URL()),
   585  		true); err != nil {
   586  		c.Fatal(err)
   587  	}
   588  	if err != nil {
   589  		c.Fatal(err)
   590  	}
   591  	deleteImages(name)
   592  	_, out, err := buildImageWithOut(name,
   593  		fmt.Sprintf(`FROM scratch
   594  		ADD %s/index.html /`, server.URL()),
   595  		true)
   596  	if err != nil {
   597  		c.Fatal(err)
   598  	}
   599  	if strings.Contains(out, "Using cache") {
   600  		c.Fatal("2nd build used cache on ADD, it shouldn't")
   601  	}
   602  
   603  }
   604  
   605  func (s *DockerSuite) TestBuildLastModified(c *check.C) {
   606  	name := "testbuildlastmodified"
   607  
   608  	server, err := fakeStorage(map[string]string{
   609  		"file": "hello",
   610  	})
   611  	if err != nil {
   612  		c.Fatal(err)
   613  	}
   614  	defer server.Close()
   615  
   616  	var out, out2 string
   617  
   618  	dFmt := `FROM busybox
   619  ADD %s/file /
   620  RUN ls -le /file`
   621  
   622  	dockerfile := fmt.Sprintf(dFmt, server.URL())
   623  
   624  	if _, out, err = buildImageWithOut(name, dockerfile, false); err != nil {
   625  		c.Fatal(err)
   626  	}
   627  
   628  	originMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out)
   629  	// Make sure our regexp is correct
   630  	if strings.Index(originMTime, "/file") < 0 {
   631  		c.Fatalf("Missing ls info on 'file':\n%s", out)
   632  	}
   633  
   634  	// Build it again and make sure the mtime of the file didn't change.
   635  	// Wait a few seconds to make sure the time changed enough to notice
   636  	time.Sleep(2 * time.Second)
   637  
   638  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   639  		c.Fatal(err)
   640  	}
   641  
   642  	newMTime := regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   643  	if newMTime != originMTime {
   644  		c.Fatalf("MTime changed:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   645  	}
   646  
   647  	// Now 'touch' the file and make sure the timestamp DID change this time
   648  	// Create a new fakeStorage instead of just using Add() to help windows
   649  	server, err = fakeStorage(map[string]string{
   650  		"file": "hello",
   651  	})
   652  	if err != nil {
   653  		c.Fatal(err)
   654  	}
   655  	defer server.Close()
   656  
   657  	dockerfile = fmt.Sprintf(dFmt, server.URL())
   658  
   659  	if _, out2, err = buildImageWithOut(name, dockerfile, false); err != nil {
   660  		c.Fatal(err)
   661  	}
   662  
   663  	newMTime = regexp.MustCompile(`root.*/file.*\n`).FindString(out2)
   664  	if newMTime == originMTime {
   665  		c.Fatalf("MTime didn't change:\nOrigin:%s\nNew:%s", originMTime, newMTime)
   666  	}
   667  
   668  }
   669  
   670  func (s *DockerSuite) TestBuildSixtySteps(c *check.C) {
   671  	name := "foobuildsixtysteps"
   672  	ctx, err := fakeContext("FROM scratch\n"+strings.Repeat("ADD foo /\n", 60),
   673  		map[string]string{
   674  			"foo": "test1",
   675  		})
   676  	if err != nil {
   677  		c.Fatal(err)
   678  	}
   679  	defer ctx.Close()
   680  
   681  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   682  		c.Fatal(err)
   683  	}
   684  }
   685  
   686  func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) {
   687  	name := "testaddimg"
   688  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   689  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   690  RUN echo 'dockerio:x:1001:' >> /etc/group
   691  RUN touch /exists
   692  RUN chown dockerio.dockerio /exists
   693  ADD test_file /
   694  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   695  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
   696  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
   697  		map[string]string{
   698  			"test_file": "test1",
   699  		})
   700  	if err != nil {
   701  		c.Fatal(err)
   702  	}
   703  	defer ctx.Close()
   704  
   705  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   706  		c.Fatal(err)
   707  	}
   708  }
   709  
   710  // Issue #3960: "ADD src ." hangs
   711  func (s *DockerSuite) TestBuildAddSingleFileToWorkdir(c *check.C) {
   712  	name := "testaddsinglefiletoworkdir"
   713  	ctx, err := fakeContext(`FROM busybox
   714  ADD test_file .`,
   715  		map[string]string{
   716  			"test_file": "test1",
   717  		})
   718  	if err != nil {
   719  		c.Fatal(err)
   720  	}
   721  	defer ctx.Close()
   722  
   723  	errChan := make(chan error)
   724  	go func() {
   725  		_, err := buildImageFromContext(name, ctx, true)
   726  		errChan <- err
   727  		close(errChan)
   728  	}()
   729  	select {
   730  	case <-time.After(5 * time.Second):
   731  		c.Fatal("Build with adding to workdir timed out")
   732  	case err := <-errChan:
   733  		c.Assert(err, check.IsNil)
   734  	}
   735  }
   736  
   737  func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) {
   738  	name := "testaddsinglefiletoexistdir"
   739  	ctx, err := fakeContext(`FROM busybox
   740  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   741  RUN echo 'dockerio:x:1001:' >> /etc/group
   742  RUN mkdir /exists
   743  RUN touch /exists/exists_file
   744  RUN chown -R dockerio.dockerio /exists
   745  ADD test_file /exists/
   746  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   747  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   748  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   749  		map[string]string{
   750  			"test_file": "test1",
   751  		})
   752  	if err != nil {
   753  		c.Fatal(err)
   754  	}
   755  	defer ctx.Close()
   756  
   757  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   758  		c.Fatal(err)
   759  	}
   760  }
   761  
   762  func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) {
   763  	server, err := fakeStorage(map[string]string{
   764  		"robots.txt": "hello",
   765  	})
   766  	if err != nil {
   767  		c.Fatal(err)
   768  	}
   769  	defer server.Close()
   770  
   771  	name := "testcopymultiplefilestofile"
   772  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   773  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   774  RUN echo 'dockerio:x:1001:' >> /etc/group
   775  RUN mkdir /exists
   776  RUN touch /exists/exists_file
   777  RUN chown -R dockerio.dockerio /exists
   778  COPY test_file1 test_file2 /exists/
   779  ADD test_file3 test_file4 %s/robots.txt /exists/
   780  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   781  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   782  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   783  
   784  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   785  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   786  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   787  
   788  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   789  `, server.URL()),
   790  		map[string]string{
   791  			"test_file1": "test1",
   792  			"test_file2": "test2",
   793  			"test_file3": "test3",
   794  			"test_file4": "test4",
   795  		})
   796  	defer ctx.Close()
   797  	if err != nil {
   798  		c.Fatal(err)
   799  	}
   800  
   801  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   802  		c.Fatal(err)
   803  	}
   804  }
   805  
   806  func (s *DockerSuite) TestBuildAddMultipleFilesToFile(c *check.C) {
   807  	name := "testaddmultiplefilestofile"
   808  	ctx, err := fakeContext(`FROM scratch
   809  	ADD file1.txt file2.txt test
   810  	`,
   811  		map[string]string{
   812  			"file1.txt": "test1",
   813  			"file2.txt": "test1",
   814  		})
   815  	defer ctx.Close()
   816  	if err != nil {
   817  		c.Fatal(err)
   818  	}
   819  
   820  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   821  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   822  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   823  	}
   824  
   825  }
   826  
   827  func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFile(c *check.C) {
   828  	name := "testjsonaddmultiplefilestofile"
   829  	ctx, err := fakeContext(`FROM scratch
   830  	ADD ["file1.txt", "file2.txt", "test"]
   831  	`,
   832  		map[string]string{
   833  			"file1.txt": "test1",
   834  			"file2.txt": "test1",
   835  		})
   836  	defer ctx.Close()
   837  	if err != nil {
   838  		c.Fatal(err)
   839  	}
   840  
   841  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   842  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   843  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   844  	}
   845  
   846  }
   847  
   848  func (s *DockerSuite) TestBuildAddMultipleFilesToFileWild(c *check.C) {
   849  	name := "testaddmultiplefilestofilewild"
   850  	ctx, err := fakeContext(`FROM scratch
   851  	ADD file*.txt test
   852  	`,
   853  		map[string]string{
   854  			"file1.txt": "test1",
   855  			"file2.txt": "test1",
   856  		})
   857  	defer ctx.Close()
   858  	if err != nil {
   859  		c.Fatal(err)
   860  	}
   861  
   862  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   863  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   864  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   865  	}
   866  
   867  }
   868  
   869  func (s *DockerSuite) TestBuildJSONAddMultipleFilesToFileWild(c *check.C) {
   870  	name := "testjsonaddmultiplefilestofilewild"
   871  	ctx, err := fakeContext(`FROM scratch
   872  	ADD ["file*.txt", "test"]
   873  	`,
   874  		map[string]string{
   875  			"file1.txt": "test1",
   876  			"file2.txt": "test1",
   877  		})
   878  	defer ctx.Close()
   879  	if err != nil {
   880  		c.Fatal(err)
   881  	}
   882  
   883  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   884  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   885  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   886  	}
   887  
   888  }
   889  
   890  func (s *DockerSuite) TestBuildCopyMultipleFilesToFile(c *check.C) {
   891  	name := "testcopymultiplefilestofile"
   892  	ctx, err := fakeContext(`FROM scratch
   893  	COPY file1.txt file2.txt test
   894  	`,
   895  		map[string]string{
   896  			"file1.txt": "test1",
   897  			"file2.txt": "test1",
   898  		})
   899  	defer ctx.Close()
   900  	if err != nil {
   901  		c.Fatal(err)
   902  	}
   903  
   904  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
   905  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   906  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   907  	}
   908  
   909  }
   910  
   911  func (s *DockerSuite) TestBuildJSONCopyMultipleFilesToFile(c *check.C) {
   912  	name := "testjsoncopymultiplefilestofile"
   913  	ctx, err := fakeContext(`FROM scratch
   914  	COPY ["file1.txt", "file2.txt", "test"]
   915  	`,
   916  		map[string]string{
   917  			"file1.txt": "test1",
   918  			"file2.txt": "test1",
   919  		})
   920  	defer ctx.Close()
   921  	if err != nil {
   922  		c.Fatal(err)
   923  	}
   924  
   925  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
   926  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   927  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
   928  	}
   929  
   930  }
   931  
   932  func (s *DockerSuite) TestBuildAddFileWithWhitespace(c *check.C) {
   933  	name := "testaddfilewithwhitespace"
   934  	ctx, err := fakeContext(`FROM busybox
   935  RUN mkdir "/test dir"
   936  RUN mkdir "/test_dir"
   937  ADD [ "test file1", "/test_file1" ]
   938  ADD [ "test_file2", "/test file2" ]
   939  ADD [ "test file3", "/test file3" ]
   940  ADD [ "test dir/test_file4", "/test_dir/test_file4" ]
   941  ADD [ "test_dir/test_file5", "/test dir/test_file5" ]
   942  ADD [ "test dir/test_file6", "/test dir/test_file6" ]
   943  RUN [ $(cat "/test_file1") = 'test1' ]
   944  RUN [ $(cat "/test file2") = 'test2' ]
   945  RUN [ $(cat "/test file3") = 'test3' ]
   946  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
   947  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
   948  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
   949  		map[string]string{
   950  			"test file1":          "test1",
   951  			"test_file2":          "test2",
   952  			"test file3":          "test3",
   953  			"test dir/test_file4": "test4",
   954  			"test_dir/test_file5": "test5",
   955  			"test dir/test_file6": "test6",
   956  		})
   957  	defer ctx.Close()
   958  	if err != nil {
   959  		c.Fatal(err)
   960  	}
   961  
   962  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   963  		c.Fatal(err)
   964  	}
   965  }
   966  
   967  func (s *DockerSuite) TestBuildCopyFileWithWhitespace(c *check.C) {
   968  	name := "testcopyfilewithwhitespace"
   969  	ctx, err := fakeContext(`FROM busybox
   970  RUN mkdir "/test dir"
   971  RUN mkdir "/test_dir"
   972  COPY [ "test file1", "/test_file1" ]
   973  COPY [ "test_file2", "/test file2" ]
   974  COPY [ "test file3", "/test file3" ]
   975  COPY [ "test dir/test_file4", "/test_dir/test_file4" ]
   976  COPY [ "test_dir/test_file5", "/test dir/test_file5" ]
   977  COPY [ "test dir/test_file6", "/test dir/test_file6" ]
   978  RUN [ $(cat "/test_file1") = 'test1' ]
   979  RUN [ $(cat "/test file2") = 'test2' ]
   980  RUN [ $(cat "/test file3") = 'test3' ]
   981  RUN [ $(cat "/test_dir/test_file4") = 'test4' ]
   982  RUN [ $(cat "/test dir/test_file5") = 'test5' ]
   983  RUN [ $(cat "/test dir/test_file6") = 'test6' ]`,
   984  		map[string]string{
   985  			"test file1":          "test1",
   986  			"test_file2":          "test2",
   987  			"test file3":          "test3",
   988  			"test dir/test_file4": "test4",
   989  			"test_dir/test_file5": "test5",
   990  			"test dir/test_file6": "test6",
   991  		})
   992  	defer ctx.Close()
   993  	if err != nil {
   994  		c.Fatal(err)
   995  	}
   996  
   997  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   998  		c.Fatal(err)
   999  	}
  1000  }
  1001  
  1002  func (s *DockerSuite) TestBuildAddMultipleFilesToFileWithWhitespace(c *check.C) {
  1003  	name := "testaddmultiplefilestofilewithwhitespace"
  1004  	ctx, err := fakeContext(`FROM busybox
  1005  	ADD [ "test file1", "test file2", "test" ]
  1006      `,
  1007  		map[string]string{
  1008  			"test file1": "test1",
  1009  			"test file2": "test2",
  1010  		})
  1011  	defer ctx.Close()
  1012  	if err != nil {
  1013  		c.Fatal(err)
  1014  	}
  1015  
  1016  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
  1017  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1018  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1019  	}
  1020  
  1021  }
  1022  
  1023  func (s *DockerSuite) TestBuildCopyMultipleFilesToFileWithWhitespace(c *check.C) {
  1024  	name := "testcopymultiplefilestofilewithwhitespace"
  1025  	ctx, err := fakeContext(`FROM busybox
  1026  	COPY [ "test file1", "test file2", "test" ]
  1027          `,
  1028  		map[string]string{
  1029  			"test file1": "test1",
  1030  			"test file2": "test2",
  1031  		})
  1032  	defer ctx.Close()
  1033  	if err != nil {
  1034  		c.Fatal(err)
  1035  	}
  1036  
  1037  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
  1038  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  1039  		c.Fatalf("Wrong error: (should contain %q) got:\n%v", expected, err)
  1040  	}
  1041  
  1042  }
  1043  
  1044  func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) {
  1045  	name := "testcopywildcard"
  1046  	server, err := fakeStorage(map[string]string{
  1047  		"robots.txt": "hello",
  1048  		"index.html": "world",
  1049  	})
  1050  	if err != nil {
  1051  		c.Fatal(err)
  1052  	}
  1053  	defer server.Close()
  1054  
  1055  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1056  	COPY file*.txt /tmp/
  1057  	RUN ls /tmp/file1.txt /tmp/file2.txt
  1058  	RUN mkdir /tmp1
  1059  	COPY dir* /tmp1/
  1060  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
  1061  	RUN mkdir /tmp2
  1062          ADD dir/*dir %s/robots.txt /tmp2/
  1063  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
  1064  	`, server.URL()),
  1065  		map[string]string{
  1066  			"file1.txt":                     "test1",
  1067  			"file2.txt":                     "test2",
  1068  			"dir/nested_file":               "nested file",
  1069  			"dir/nested_dir/nest_nest_file": "2 times nested",
  1070  			"dirt": "dirty",
  1071  		})
  1072  	if err != nil {
  1073  		c.Fatal(err)
  1074  	}
  1075  	defer ctx.Close()
  1076  
  1077  	id1, err := buildImageFromContext(name, ctx, true)
  1078  	if err != nil {
  1079  		c.Fatal(err)
  1080  	}
  1081  
  1082  	// Now make sure we use a cache the 2nd time
  1083  	id2, err := buildImageFromContext(name, ctx, true)
  1084  	if err != nil {
  1085  		c.Fatal(err)
  1086  	}
  1087  
  1088  	if id1 != id2 {
  1089  		c.Fatal("didn't use the cache")
  1090  	}
  1091  
  1092  }
  1093  
  1094  func (s *DockerSuite) TestBuildCopyWildcardNoFind(c *check.C) {
  1095  	name := "testcopywildcardnofind"
  1096  	ctx, err := fakeContext(`FROM busybox
  1097  	COPY file*.txt /tmp/
  1098  	`, nil)
  1099  	defer ctx.Close()
  1100  	if err != nil {
  1101  		c.Fatal(err)
  1102  	}
  1103  
  1104  	_, err = buildImageFromContext(name, ctx, true)
  1105  	if err == nil {
  1106  		c.Fatal("should have failed to find a file")
  1107  	}
  1108  	if !strings.Contains(err.Error(), "No source files were specified") {
  1109  		c.Fatalf("Wrong error %v, must be about no source files", err)
  1110  	}
  1111  
  1112  }
  1113  
  1114  func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) {
  1115  	name := "testcopywildcardinname"
  1116  	ctx, err := fakeContext(`FROM busybox
  1117  	COPY *.txt /tmp/
  1118  	RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ]
  1119  	`, map[string]string{"*.txt": "hi there"})
  1120  
  1121  	if err != nil {
  1122  		// Normally we would do c.Fatal(err) here but given that
  1123  		// the odds of this failing are so rare, it must be because
  1124  		// the OS we're running the client on doesn't support * in
  1125  		// filenames (like windows).  So, instead of failing the test
  1126  		// just let it pass. Then we don't need to explicitly
  1127  		// say which OSs this works on or not.
  1128  		return
  1129  	}
  1130  	defer ctx.Close()
  1131  
  1132  	_, err = buildImageFromContext(name, ctx, true)
  1133  	if err != nil {
  1134  		c.Fatalf("should have built: %q", err)
  1135  	}
  1136  }
  1137  
  1138  func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) {
  1139  	name := "testcopywildcardcache"
  1140  	ctx, err := fakeContext(`FROM busybox
  1141  	COPY file1.txt /tmp/`,
  1142  		map[string]string{
  1143  			"file1.txt": "test1",
  1144  		})
  1145  	defer ctx.Close()
  1146  	if err != nil {
  1147  		c.Fatal(err)
  1148  	}
  1149  
  1150  	id1, err := buildImageFromContext(name, ctx, true)
  1151  	if err != nil {
  1152  		c.Fatal(err)
  1153  	}
  1154  
  1155  	// Now make sure we use a cache the 2nd time even with wild cards.
  1156  	// Use the same context so the file is the same and the checksum will match
  1157  	ctx.Add("Dockerfile", `FROM busybox
  1158  	COPY file*.txt /tmp/`)
  1159  
  1160  	id2, err := buildImageFromContext(name, ctx, true)
  1161  	if err != nil {
  1162  		c.Fatal(err)
  1163  	}
  1164  
  1165  	if id1 != id2 {
  1166  		c.Fatal("didn't use the cache")
  1167  	}
  1168  
  1169  }
  1170  
  1171  func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) {
  1172  	name := "testaddsinglefiletononexistingdir"
  1173  	ctx, err := fakeContext(`FROM busybox
  1174  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1175  RUN echo 'dockerio:x:1001:' >> /etc/group
  1176  RUN touch /exists
  1177  RUN chown dockerio.dockerio /exists
  1178  ADD test_file /test_dir/
  1179  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1180  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1181  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1182  		map[string]string{
  1183  			"test_file": "test1",
  1184  		})
  1185  	if err != nil {
  1186  		c.Fatal(err)
  1187  	}
  1188  	defer ctx.Close()
  1189  
  1190  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1191  		c.Fatal(err)
  1192  	}
  1193  
  1194  }
  1195  
  1196  func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) {
  1197  	name := "testadddircontenttoroot"
  1198  	ctx, err := fakeContext(`FROM busybox
  1199  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1200  RUN echo 'dockerio:x:1001:' >> /etc/group
  1201  RUN touch /exists
  1202  RUN chown dockerio.dockerio exists
  1203  ADD test_dir /
  1204  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1205  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1206  		map[string]string{
  1207  			"test_dir/test_file": "test1",
  1208  		})
  1209  	if err != nil {
  1210  		c.Fatal(err)
  1211  	}
  1212  	defer ctx.Close()
  1213  
  1214  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1215  		c.Fatal(err)
  1216  	}
  1217  }
  1218  
  1219  func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) {
  1220  	name := "testadddircontenttoexistingdir"
  1221  	ctx, err := fakeContext(`FROM busybox
  1222  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1223  RUN echo 'dockerio:x:1001:' >> /etc/group
  1224  RUN mkdir /exists
  1225  RUN touch /exists/exists_file
  1226  RUN chown -R dockerio.dockerio /exists
  1227  ADD test_dir/ /exists/
  1228  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1229  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1230  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1231  		map[string]string{
  1232  			"test_dir/test_file": "test1",
  1233  		})
  1234  	if err != nil {
  1235  		c.Fatal(err)
  1236  	}
  1237  	defer ctx.Close()
  1238  
  1239  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1240  		c.Fatal(err)
  1241  	}
  1242  }
  1243  
  1244  func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) {
  1245  	name := "testaddwholedirtoroot"
  1246  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1247  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1248  RUN echo 'dockerio:x:1001:' >> /etc/group
  1249  RUN touch /exists
  1250  RUN chown dockerio.dockerio exists
  1251  ADD test_dir /test_dir
  1252  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1253  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1254  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1255  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1256  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1257  		map[string]string{
  1258  			"test_dir/test_file": "test1",
  1259  		})
  1260  	if err != nil {
  1261  		c.Fatal(err)
  1262  	}
  1263  	defer ctx.Close()
  1264  
  1265  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1266  		c.Fatal(err)
  1267  	}
  1268  }
  1269  
  1270  // Testing #5941
  1271  func (s *DockerSuite) TestBuildAddEtcToRoot(c *check.C) {
  1272  	name := "testaddetctoroot"
  1273  	ctx, err := fakeContext(`FROM scratch
  1274  ADD . /`,
  1275  		map[string]string{
  1276  			"etc/test_file": "test1",
  1277  		})
  1278  	if err != nil {
  1279  		c.Fatal(err)
  1280  	}
  1281  	defer ctx.Close()
  1282  
  1283  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1284  		c.Fatal(err)
  1285  	}
  1286  }
  1287  
  1288  // Testing #9401
  1289  func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) {
  1290  	name := "testaddpreservesfilesspecialbits"
  1291  	ctx, err := fakeContext(`FROM busybox
  1292  ADD suidbin /usr/bin/suidbin
  1293  RUN chmod 4755 /usr/bin/suidbin
  1294  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
  1295  ADD ./data/ /
  1296  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
  1297  		map[string]string{
  1298  			"suidbin":             "suidbin",
  1299  			"/data/usr/test_file": "test1",
  1300  		})
  1301  	if err != nil {
  1302  		c.Fatal(err)
  1303  	}
  1304  	defer ctx.Close()
  1305  
  1306  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1307  		c.Fatal(err)
  1308  	}
  1309  }
  1310  
  1311  func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) {
  1312  	name := "testcopysinglefiletoroot"
  1313  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1314  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1315  RUN echo 'dockerio:x:1001:' >> /etc/group
  1316  RUN touch /exists
  1317  RUN chown dockerio.dockerio /exists
  1318  COPY test_file /
  1319  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1320  RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ]
  1321  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1322  		map[string]string{
  1323  			"test_file": "test1",
  1324  		})
  1325  	if err != nil {
  1326  		c.Fatal(err)
  1327  	}
  1328  	defer ctx.Close()
  1329  
  1330  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1331  		c.Fatal(err)
  1332  	}
  1333  }
  1334  
  1335  // Issue #3960: "ADD src ." hangs - adapted for COPY
  1336  func (s *DockerSuite) TestBuildCopySingleFileToWorkdir(c *check.C) {
  1337  	name := "testcopysinglefiletoworkdir"
  1338  	ctx, err := fakeContext(`FROM busybox
  1339  COPY test_file .`,
  1340  		map[string]string{
  1341  			"test_file": "test1",
  1342  		})
  1343  	if err != nil {
  1344  		c.Fatal(err)
  1345  	}
  1346  	defer ctx.Close()
  1347  
  1348  	errChan := make(chan error)
  1349  	go func() {
  1350  		_, err := buildImageFromContext(name, ctx, true)
  1351  		errChan <- err
  1352  		close(errChan)
  1353  	}()
  1354  	select {
  1355  	case <-time.After(5 * time.Second):
  1356  		c.Fatal("Build with adding to workdir timed out")
  1357  	case err := <-errChan:
  1358  		c.Assert(err, check.IsNil)
  1359  	}
  1360  }
  1361  
  1362  func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) {
  1363  	name := "testcopysinglefiletoexistdir"
  1364  	ctx, err := fakeContext(`FROM busybox
  1365  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1366  RUN echo 'dockerio:x:1001:' >> /etc/group
  1367  RUN mkdir /exists
  1368  RUN touch /exists/exists_file
  1369  RUN chown -R dockerio.dockerio /exists
  1370  COPY test_file /exists/
  1371  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1372  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1373  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1374  		map[string]string{
  1375  			"test_file": "test1",
  1376  		})
  1377  	if err != nil {
  1378  		c.Fatal(err)
  1379  	}
  1380  	defer ctx.Close()
  1381  
  1382  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1383  		c.Fatal(err)
  1384  	}
  1385  }
  1386  
  1387  func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) {
  1388  	name := "testcopysinglefiletononexistdir"
  1389  	ctx, err := fakeContext(`FROM busybox
  1390  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1391  RUN echo 'dockerio:x:1001:' >> /etc/group
  1392  RUN touch /exists
  1393  RUN chown dockerio.dockerio /exists
  1394  COPY test_file /test_dir/
  1395  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1396  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1397  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1398  		map[string]string{
  1399  			"test_file": "test1",
  1400  		})
  1401  	if err != nil {
  1402  		c.Fatal(err)
  1403  	}
  1404  	defer ctx.Close()
  1405  
  1406  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1407  		c.Fatal(err)
  1408  	}
  1409  }
  1410  
  1411  func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) {
  1412  	name := "testcopydircontenttoroot"
  1413  	ctx, err := fakeContext(`FROM busybox
  1414  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1415  RUN echo 'dockerio:x:1001:' >> /etc/group
  1416  RUN touch /exists
  1417  RUN chown dockerio.dockerio exists
  1418  COPY test_dir /
  1419  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1420  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1421  		map[string]string{
  1422  			"test_dir/test_file": "test1",
  1423  		})
  1424  	if err != nil {
  1425  		c.Fatal(err)
  1426  	}
  1427  	defer ctx.Close()
  1428  
  1429  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1430  		c.Fatal(err)
  1431  	}
  1432  }
  1433  
  1434  func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) {
  1435  	name := "testcopydircontenttoexistdir"
  1436  	ctx, err := fakeContext(`FROM busybox
  1437  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1438  RUN echo 'dockerio:x:1001:' >> /etc/group
  1439  RUN mkdir /exists
  1440  RUN touch /exists/exists_file
  1441  RUN chown -R dockerio.dockerio /exists
  1442  COPY test_dir/ /exists/
  1443  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1444  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1445  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1446  		map[string]string{
  1447  			"test_dir/test_file": "test1",
  1448  		})
  1449  	if err != nil {
  1450  		c.Fatal(err)
  1451  	}
  1452  	defer ctx.Close()
  1453  
  1454  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1455  		c.Fatal(err)
  1456  	}
  1457  }
  1458  
  1459  func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) {
  1460  	name := "testcopywholedirtoroot"
  1461  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
  1462  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1463  RUN echo 'dockerio:x:1001:' >> /etc/group
  1464  RUN touch /exists
  1465  RUN chown dockerio.dockerio exists
  1466  COPY test_dir /test_dir
  1467  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1468  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1469  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1470  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ]
  1471  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod),
  1472  		map[string]string{
  1473  			"test_dir/test_file": "test1",
  1474  		})
  1475  	if err != nil {
  1476  		c.Fatal(err)
  1477  	}
  1478  	defer ctx.Close()
  1479  
  1480  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1481  		c.Fatal(err)
  1482  	}
  1483  }
  1484  
  1485  func (s *DockerSuite) TestBuildCopyEtcToRoot(c *check.C) {
  1486  	name := "testcopyetctoroot"
  1487  	ctx, err := fakeContext(`FROM scratch
  1488  COPY . /`,
  1489  		map[string]string{
  1490  			"etc/test_file": "test1",
  1491  		})
  1492  	if err != nil {
  1493  		c.Fatal(err)
  1494  	}
  1495  	defer ctx.Close()
  1496  
  1497  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1498  		c.Fatal(err)
  1499  	}
  1500  }
  1501  
  1502  func (s *DockerSuite) TestBuildCopyDisallowRemote(c *check.C) {
  1503  	name := "testcopydisallowremote"
  1504  	_, out, err := buildImageWithOut(name, `FROM scratch
  1505  COPY https://index.docker.io/robots.txt /`,
  1506  		true)
  1507  	if err == nil || !strings.Contains(out, "Source can't be a URL for COPY") {
  1508  		c.Fatalf("Error should be about disallowed remote source, got err: %s, out: %q", err, out)
  1509  	}
  1510  }
  1511  
  1512  func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) {
  1513  	const (
  1514  		dockerfile = `
  1515  			FROM scratch
  1516  			ADD links.tar /
  1517  			ADD foo.txt /symlink/
  1518  			`
  1519  		targetFile = "foo.txt"
  1520  	)
  1521  	var (
  1522  		name = "test-link-absolute"
  1523  	)
  1524  	ctx, err := fakeContext(dockerfile, nil)
  1525  	if err != nil {
  1526  		c.Fatal(err)
  1527  	}
  1528  	defer ctx.Close()
  1529  
  1530  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
  1531  	if err != nil {
  1532  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1533  	}
  1534  	defer os.RemoveAll(tempDir)
  1535  
  1536  	var symlinkTarget string
  1537  	if runtime.GOOS == "windows" {
  1538  		var driveLetter string
  1539  		if abs, err := filepath.Abs(tempDir); err != nil {
  1540  			c.Fatal(err)
  1541  		} else {
  1542  			driveLetter = abs[:1]
  1543  		}
  1544  		tempDirWithoutDrive := tempDir[2:]
  1545  		symlinkTarget = fmt.Sprintf(`%s:\..\..\..\..\..\..\..\..\..\..\..\..%s`, driveLetter, tempDirWithoutDrive)
  1546  	} else {
  1547  		symlinkTarget = fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
  1548  	}
  1549  
  1550  	tarPath := filepath.Join(ctx.Dir, "links.tar")
  1551  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1552  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1553  
  1554  	tarOut, err := os.Create(tarPath)
  1555  	if err != nil {
  1556  		c.Fatal(err)
  1557  	}
  1558  
  1559  	tarWriter := tar.NewWriter(tarOut)
  1560  
  1561  	header := &tar.Header{
  1562  		Name:     "symlink",
  1563  		Typeflag: tar.TypeSymlink,
  1564  		Linkname: symlinkTarget,
  1565  		Mode:     0755,
  1566  		Uid:      0,
  1567  		Gid:      0,
  1568  	}
  1569  
  1570  	err = tarWriter.WriteHeader(header)
  1571  	if err != nil {
  1572  		c.Fatal(err)
  1573  	}
  1574  
  1575  	tarWriter.Close()
  1576  	tarOut.Close()
  1577  
  1578  	foo, err := os.Create(fooPath)
  1579  	if err != nil {
  1580  		c.Fatal(err)
  1581  	}
  1582  	defer foo.Close()
  1583  
  1584  	if _, err := foo.WriteString("test"); err != nil {
  1585  		c.Fatal(err)
  1586  	}
  1587  
  1588  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1589  		c.Fatal(err)
  1590  	}
  1591  
  1592  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1593  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1594  	}
  1595  
  1596  }
  1597  
  1598  func (s *DockerSuite) TestBuildAddBadLinksVolume(c *check.C) {
  1599  	const (
  1600  		dockerfileTemplate = `
  1601  		FROM busybox
  1602  		RUN ln -s /../../../../../../../../%s /x
  1603  		VOLUME /x
  1604  		ADD foo.txt /x/`
  1605  		targetFile = "foo.txt"
  1606  	)
  1607  	var (
  1608  		name       = "test-link-absolute-volume"
  1609  		dockerfile = ""
  1610  	)
  1611  
  1612  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1613  	if err != nil {
  1614  		c.Fatalf("failed to create temporary directory: %s", tempDir)
  1615  	}
  1616  	defer os.RemoveAll(tempDir)
  1617  
  1618  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1619  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1620  
  1621  	ctx, err := fakeContext(dockerfile, nil)
  1622  	if err != nil {
  1623  		c.Fatal(err)
  1624  	}
  1625  	defer ctx.Close()
  1626  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1627  
  1628  	foo, err := os.Create(fooPath)
  1629  	if err != nil {
  1630  		c.Fatal(err)
  1631  	}
  1632  	defer foo.Close()
  1633  
  1634  	if _, err := foo.WriteString("test"); err != nil {
  1635  		c.Fatal(err)
  1636  	}
  1637  
  1638  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1639  		c.Fatal(err)
  1640  	}
  1641  
  1642  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1643  		c.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1644  	}
  1645  
  1646  }
  1647  
  1648  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1649  // when we can't access files in the context.
  1650  func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) {
  1651  	testRequires(c, UnixCli) // test uses chown/chmod: not available on windows
  1652  
  1653  	{
  1654  		name := "testbuildinaccessiblefiles"
  1655  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1656  		if err != nil {
  1657  			c.Fatal(err)
  1658  		}
  1659  		defer ctx.Close()
  1660  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1661  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1662  
  1663  		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1664  			c.Fatalf("failed to chown file to root: %s", err)
  1665  		}
  1666  		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1667  			c.Fatalf("failed to chmod file to 700: %s", err)
  1668  		}
  1669  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1670  		buildCmd.Dir = ctx.Dir
  1671  		out, _, err := runCommandWithOutput(buildCmd)
  1672  		if err == nil {
  1673  			c.Fatalf("build should have failed: %s %s", err, out)
  1674  		}
  1675  
  1676  		// check if we've detected the failure before we started building
  1677  		if !strings.Contains(out, "no permission to read from ") {
  1678  			c.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  1679  		}
  1680  
  1681  		if !strings.Contains(out, "Error checking context") {
  1682  			c.Fatalf("output should've contained the string: Error checking context")
  1683  		}
  1684  	}
  1685  	{
  1686  		name := "testbuildinaccessibledirectory"
  1687  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1688  		if err != nil {
  1689  			c.Fatal(err)
  1690  		}
  1691  		defer ctx.Close()
  1692  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1693  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1694  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1695  
  1696  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1697  			c.Fatalf("failed to chown directory to root: %s", err)
  1698  		}
  1699  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1700  			c.Fatalf("failed to chmod directory to 444: %s", err)
  1701  		}
  1702  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1703  			c.Fatalf("failed to chmod file to 700: %s", err)
  1704  		}
  1705  
  1706  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1707  		buildCmd.Dir = ctx.Dir
  1708  		out, _, err := runCommandWithOutput(buildCmd)
  1709  		if err == nil {
  1710  			c.Fatalf("build should have failed: %s %s", err, out)
  1711  		}
  1712  
  1713  		// check if we've detected the failure before we started building
  1714  		if !strings.Contains(out, "can't stat") {
  1715  			c.Fatalf("output should've contained the string: can't access %s", out)
  1716  		}
  1717  
  1718  		if !strings.Contains(out, "Error checking context") {
  1719  			c.Fatalf("output should've contained the string: Error checking context\ngot:%s", out)
  1720  		}
  1721  
  1722  	}
  1723  	{
  1724  		name := "testlinksok"
  1725  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
  1726  		if err != nil {
  1727  			c.Fatal(err)
  1728  		}
  1729  		defer ctx.Close()
  1730  
  1731  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1732  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1733  			c.Fatal(err)
  1734  		}
  1735  		defer os.Remove(target)
  1736  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1737  		// This test doesn't require that we run commands as an unprivileged user
  1738  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1739  			c.Fatal(err)
  1740  		}
  1741  	}
  1742  	{
  1743  		name := "testbuildignoredinaccessible"
  1744  		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
  1745  			map[string]string{
  1746  				"directoryWeCantStat/bar": "foo",
  1747  				".dockerignore":           "directoryWeCantStat",
  1748  			})
  1749  		if err != nil {
  1750  			c.Fatal(err)
  1751  		}
  1752  		defer ctx.Close()
  1753  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1754  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1755  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1756  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1757  			c.Fatalf("failed to chown directory to root: %s", err)
  1758  		}
  1759  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1760  			c.Fatalf("failed to chmod directory to 755: %s", err)
  1761  		}
  1762  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1763  			c.Fatalf("failed to chmod file to 444: %s", err)
  1764  		}
  1765  
  1766  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1767  		buildCmd.Dir = ctx.Dir
  1768  		if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  1769  			c.Fatalf("build should have worked: %s %s", err, out)
  1770  		}
  1771  
  1772  	}
  1773  }
  1774  
  1775  func (s *DockerSuite) TestBuildForceRm(c *check.C) {
  1776  	containerCountBefore, err := getContainerCount()
  1777  	if err != nil {
  1778  		c.Fatalf("failed to get the container count: %s", err)
  1779  	}
  1780  	name := "testbuildforcerm"
  1781  	ctx, err := fakeContext("FROM scratch\nRUN true\nRUN thiswillfail", nil)
  1782  	if err != nil {
  1783  		c.Fatal(err)
  1784  	}
  1785  	defer ctx.Close()
  1786  
  1787  	dockerCmdInDir(c, ctx.Dir, "build", "-t", name, "--force-rm", ".")
  1788  
  1789  	containerCountAfter, err := getContainerCount()
  1790  	if err != nil {
  1791  		c.Fatalf("failed to get the container count: %s", err)
  1792  	}
  1793  
  1794  	if containerCountBefore != containerCountAfter {
  1795  		c.Fatalf("--force-rm shouldn't have left containers behind")
  1796  	}
  1797  
  1798  }
  1799  
  1800  // Test that an infinite sleep during a build is killed if the client disconnects.
  1801  // This test is fairly hairy because there are lots of ways to race.
  1802  // Strategy:
  1803  // * Monitor the output of docker events starting from before
  1804  // * Run a 1-year-long sleep from a docker build.
  1805  // * When docker events sees container start, close the "docker build" command
  1806  // * Wait for docker events to emit a dying event.
  1807  func (s *DockerSuite) TestBuildCancelationKillsSleep(c *check.C) {
  1808  	name := "testbuildcancelation"
  1809  
  1810  	// (Note: one year, will never finish)
  1811  	ctx, err := fakeContext("FROM busybox\nRUN sleep 31536000", nil)
  1812  	if err != nil {
  1813  		c.Fatal(err)
  1814  	}
  1815  	defer ctx.Close()
  1816  
  1817  	finish := make(chan struct{})
  1818  	defer close(finish)
  1819  
  1820  	eventStart := make(chan struct{})
  1821  	eventDie := make(chan struct{})
  1822  	containerID := make(chan string)
  1823  
  1824  	startEpoch := daemonTime(c).Unix()
  1825  	// Watch for events since epoch.
  1826  	eventsCmd := exec.Command(
  1827  		dockerBinary, "events",
  1828  		"--since", strconv.FormatInt(startEpoch, 10))
  1829  	stdout, err := eventsCmd.StdoutPipe()
  1830  	if err != nil {
  1831  		c.Fatal(err)
  1832  	}
  1833  	if err := eventsCmd.Start(); err != nil {
  1834  		c.Fatal(err)
  1835  	}
  1836  	defer eventsCmd.Process.Kill()
  1837  
  1838  	// Goroutine responsible for watching start/die events from `docker events`
  1839  	go func() {
  1840  		cid := <-containerID
  1841  
  1842  		matchStart := regexp.MustCompile(cid + `(.*) start$`)
  1843  		matchDie := regexp.MustCompile(cid + `(.*) die$`)
  1844  
  1845  		//
  1846  		// Read lines of `docker events` looking for container start and stop.
  1847  		//
  1848  		scanner := bufio.NewScanner(stdout)
  1849  		for scanner.Scan() {
  1850  			switch {
  1851  			case matchStart.MatchString(scanner.Text()):
  1852  				close(eventStart)
  1853  			case matchDie.MatchString(scanner.Text()):
  1854  				close(eventDie)
  1855  			}
  1856  		}
  1857  	}()
  1858  
  1859  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, ".")
  1860  	buildCmd.Dir = ctx.Dir
  1861  
  1862  	stdoutBuild, err := buildCmd.StdoutPipe()
  1863  	if err := buildCmd.Start(); err != nil {
  1864  		c.Fatalf("failed to run build: %s", err)
  1865  	}
  1866  
  1867  	matchCID := regexp.MustCompile("Running in ")
  1868  	scanner := bufio.NewScanner(stdoutBuild)
  1869  	for scanner.Scan() {
  1870  		line := scanner.Text()
  1871  		if ok := matchCID.MatchString(line); ok {
  1872  			containerID <- line[len(line)-12:]
  1873  			break
  1874  		}
  1875  	}
  1876  
  1877  	select {
  1878  	case <-time.After(5 * time.Second):
  1879  		c.Fatal("failed to observe build container start in timely fashion")
  1880  	case <-eventStart:
  1881  		// Proceeds from here when we see the container fly past in the
  1882  		// output of "docker events".
  1883  		// Now we know the container is running.
  1884  	}
  1885  
  1886  	// Send a kill to the `docker build` command.
  1887  	// Causes the underlying build to be cancelled due to socket close.
  1888  	if err := buildCmd.Process.Kill(); err != nil {
  1889  		c.Fatalf("error killing build command: %s", err)
  1890  	}
  1891  
  1892  	// Get the exit status of `docker build`, check it exited because killed.
  1893  	if err := buildCmd.Wait(); err != nil && !isKilled(err) {
  1894  		c.Fatalf("wait failed during build run: %T %s", err, err)
  1895  	}
  1896  
  1897  	select {
  1898  	case <-time.After(5 * time.Second):
  1899  		// If we don't get here in a timely fashion, it wasn't killed.
  1900  		c.Fatal("container cancel did not succeed")
  1901  	case <-eventDie:
  1902  		// We saw the container shut down in the `docker events` stream,
  1903  		// as expected.
  1904  	}
  1905  
  1906  }
  1907  
  1908  func (s *DockerSuite) TestBuildRm(c *check.C) {
  1909  	name := "testbuildrm"
  1910  	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD 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  	var (
  1989  		result   map[string]map[string]struct{}
  1990  		name     = "testbuildvolumes"
  1991  		emptyMap = make(map[string]struct{})
  1992  		expected = map[string]map[string]struct{}{
  1993  			"/test1":  emptyMap,
  1994  			"/test2":  emptyMap,
  1995  			"/test3":  emptyMap,
  1996  			"/test4":  emptyMap,
  1997  			"/test5":  emptyMap,
  1998  			"/test6":  emptyMap,
  1999  			"[/test7": emptyMap,
  2000  			"/test8]": emptyMap,
  2001  		}
  2002  	)
  2003  	_, err := buildImage(name,
  2004  		`FROM scratch
  2005  		VOLUME /test1
  2006  		VOLUME /test2
  2007      VOLUME /test3 /test4
  2008      VOLUME ["/test5", "/test6"]
  2009      VOLUME [/test7 /test8]
  2010      `,
  2011  		true)
  2012  	if err != nil {
  2013  		c.Fatal(err)
  2014  	}
  2015  	res, err := inspectFieldJSON(name, "Config.Volumes")
  2016  	if err != nil {
  2017  		c.Fatal(err)
  2018  	}
  2019  
  2020  	err = unmarshalJSON([]byte(res), &result)
  2021  	if err != nil {
  2022  		c.Fatal(err)
  2023  	}
  2024  
  2025  	equal := reflect.DeepEqual(&result, &expected)
  2026  
  2027  	if !equal {
  2028  		c.Fatalf("Volumes %s, expected %s", result, expected)
  2029  	}
  2030  
  2031  }
  2032  
  2033  func (s *DockerSuite) TestBuildMaintainer(c *check.C) {
  2034  	name := "testbuildmaintainer"
  2035  	expected := "dockerio"
  2036  	_, err := buildImage(name,
  2037  		`FROM scratch
  2038          MAINTAINER dockerio`,
  2039  		true)
  2040  	if err != nil {
  2041  		c.Fatal(err)
  2042  	}
  2043  	res, err := inspectField(name, "Author")
  2044  	if err != nil {
  2045  		c.Fatal(err)
  2046  	}
  2047  	if res != expected {
  2048  		c.Fatalf("Maintainer %s, expected %s", res, expected)
  2049  	}
  2050  }
  2051  
  2052  func (s *DockerSuite) TestBuildUser(c *check.C) {
  2053  	name := "testbuilduser"
  2054  	expected := "dockerio"
  2055  	_, err := buildImage(name,
  2056  		`FROM busybox
  2057  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  2058  		USER dockerio
  2059  		RUN [ $(whoami) = 'dockerio' ]`,
  2060  		true)
  2061  	if err != nil {
  2062  		c.Fatal(err)
  2063  	}
  2064  	res, err := inspectField(name, "Config.User")
  2065  	if err != nil {
  2066  		c.Fatal(err)
  2067  	}
  2068  	if res != expected {
  2069  		c.Fatalf("User %s, expected %s", res, expected)
  2070  	}
  2071  }
  2072  
  2073  func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) {
  2074  	name := "testbuildrelativeworkdir"
  2075  	expected := "/test2/test3"
  2076  	_, err := buildImage(name,
  2077  		`FROM busybox
  2078  		RUN [ "$PWD" = '/' ]
  2079  		WORKDIR test1
  2080  		RUN [ "$PWD" = '/test1' ]
  2081  		WORKDIR /test2
  2082  		RUN [ "$PWD" = '/test2' ]
  2083  		WORKDIR test3
  2084  		RUN [ "$PWD" = '/test2/test3' ]`,
  2085  		true)
  2086  	if err != nil {
  2087  		c.Fatal(err)
  2088  	}
  2089  	res, err := inspectField(name, "Config.WorkingDir")
  2090  	if err != nil {
  2091  		c.Fatal(err)
  2092  	}
  2093  	if res != expected {
  2094  		c.Fatalf("Workdir %s, expected %s", res, expected)
  2095  	}
  2096  }
  2097  
  2098  func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) {
  2099  	name := "testbuildworkdirwithenvvariables"
  2100  	expected := "/test1/test2"
  2101  	_, err := buildImage(name,
  2102  		`FROM busybox
  2103  		ENV DIRPATH /test1
  2104  		ENV SUBDIRNAME test2
  2105  		WORKDIR $DIRPATH
  2106  		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
  2107  		true)
  2108  	if err != nil {
  2109  		c.Fatal(err)
  2110  	}
  2111  	res, err := inspectField(name, "Config.WorkingDir")
  2112  	if err != nil {
  2113  		c.Fatal(err)
  2114  	}
  2115  	if res != expected {
  2116  		c.Fatalf("Workdir %s, expected %s", res, expected)
  2117  	}
  2118  }
  2119  
  2120  func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) {
  2121  	name := "testbuildrelativecopy"
  2122  	dockerfile := `
  2123  		FROM busybox
  2124  			WORKDIR /test1
  2125  			WORKDIR test2
  2126  			RUN [ "$PWD" = '/test1/test2' ]
  2127  			COPY foo ./
  2128  			RUN [ "$(cat /test1/test2/foo)" = 'hello' ]
  2129  			ADD foo ./bar/baz
  2130  			RUN [ "$(cat /test1/test2/bar/baz)" = 'hello' ]
  2131  			COPY foo ./bar/baz2
  2132  			RUN [ "$(cat /test1/test2/bar/baz2)" = 'hello' ]
  2133  			WORKDIR ..
  2134  			COPY foo ./
  2135  			RUN [ "$(cat /test1/foo)" = 'hello' ]
  2136  			COPY foo /test3/
  2137  			RUN [ "$(cat /test3/foo)" = 'hello' ]
  2138  			WORKDIR /test4
  2139  			COPY . .
  2140  			RUN [ "$(cat /test4/foo)" = 'hello' ]
  2141  			WORKDIR /test5/test6
  2142  			COPY foo ../
  2143  			RUN [ "$(cat /test5/foo)" = 'hello' ]
  2144  			`
  2145  	ctx, err := fakeContext(dockerfile, map[string]string{
  2146  		"foo": "hello",
  2147  	})
  2148  	defer ctx.Close()
  2149  	if err != nil {
  2150  		c.Fatal(err)
  2151  	}
  2152  	_, err = buildImageFromContext(name, ctx, false)
  2153  	if err != nil {
  2154  		c.Fatal(err)
  2155  	}
  2156  }
  2157  
  2158  func (s *DockerSuite) TestBuildEnv(c *check.C) {
  2159  	name := "testbuildenv"
  2160  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  2161  	_, err := buildImage(name,
  2162  		`FROM busybox
  2163  		ENV PATH /test:$PATH
  2164          ENV PORT 2375
  2165  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  2166  		true)
  2167  	if err != nil {
  2168  		c.Fatal(err)
  2169  	}
  2170  	res, err := inspectField(name, "Config.Env")
  2171  	if err != nil {
  2172  		c.Fatal(err)
  2173  	}
  2174  	if res != expected {
  2175  		c.Fatalf("Env %s, expected %s", res, expected)
  2176  	}
  2177  }
  2178  
  2179  func (s *DockerSuite) TestBuildContextCleanup(c *check.C) {
  2180  	testRequires(c, SameHostDaemon)
  2181  
  2182  	name := "testbuildcontextcleanup"
  2183  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2184  	if err != nil {
  2185  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2186  	}
  2187  	_, err = buildImage(name,
  2188  		`FROM scratch
  2189          ENTRYPOINT ["/bin/echo"]`,
  2190  		true)
  2191  	if err != nil {
  2192  		c.Fatal(err)
  2193  	}
  2194  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2195  	if err != nil {
  2196  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2197  	}
  2198  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2199  		c.Fatalf("context should have been deleted, but wasn't")
  2200  	}
  2201  
  2202  }
  2203  
  2204  func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) {
  2205  	testRequires(c, SameHostDaemon)
  2206  
  2207  	name := "testbuildcontextcleanup"
  2208  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2209  	if err != nil {
  2210  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2211  	}
  2212  	_, err = buildImage(name,
  2213  		`FROM scratch
  2214  	RUN /non/existing/command`,
  2215  		true)
  2216  	if err == nil {
  2217  		c.Fatalf("expected build to fail, but it didn't")
  2218  	}
  2219  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  2220  	if err != nil {
  2221  		c.Fatalf("failed to list contents of tmp dir: %s", err)
  2222  	}
  2223  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  2224  		c.Fatalf("context should have been deleted, but wasn't")
  2225  	}
  2226  
  2227  }
  2228  
  2229  func (s *DockerSuite) TestBuildCmd(c *check.C) {
  2230  	name := "testbuildcmd"
  2231  	expected := "{[/bin/echo Hello World]}"
  2232  	_, err := buildImage(name,
  2233  		`FROM scratch
  2234          CMD ["/bin/echo", "Hello World"]`,
  2235  		true)
  2236  	if err != nil {
  2237  		c.Fatal(err)
  2238  	}
  2239  	res, err := inspectField(name, "Config.Cmd")
  2240  	if err != nil {
  2241  		c.Fatal(err)
  2242  	}
  2243  	if res != expected {
  2244  		c.Fatalf("Cmd %s, expected %s", res, expected)
  2245  	}
  2246  }
  2247  
  2248  func (s *DockerSuite) TestBuildExpose(c *check.C) {
  2249  	name := "testbuildexpose"
  2250  	expected := "map[2375/tcp:{}]"
  2251  	_, err := buildImage(name,
  2252  		`FROM scratch
  2253          EXPOSE 2375`,
  2254  		true)
  2255  	if err != nil {
  2256  		c.Fatal(err)
  2257  	}
  2258  	res, err := inspectField(name, "Config.ExposedPorts")
  2259  	if err != nil {
  2260  		c.Fatal(err)
  2261  	}
  2262  	if res != expected {
  2263  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  2264  	}
  2265  }
  2266  
  2267  func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) {
  2268  	// start building docker file with a large number of ports
  2269  	portList := make([]string, 50)
  2270  	line := make([]string, 100)
  2271  	expectedPorts := make([]int, len(portList)*len(line))
  2272  	for i := 0; i < len(portList); i++ {
  2273  		for j := 0; j < len(line); j++ {
  2274  			p := i*len(line) + j + 1
  2275  			line[j] = strconv.Itoa(p)
  2276  			expectedPorts[p-1] = p
  2277  		}
  2278  		if i == len(portList)-1 {
  2279  			portList[i] = strings.Join(line, " ")
  2280  		} else {
  2281  			portList[i] = strings.Join(line, " ") + ` \`
  2282  		}
  2283  	}
  2284  
  2285  	dockerfile := `FROM scratch
  2286  	EXPOSE {{range .}} {{.}}
  2287  	{{end}}`
  2288  	tmpl := template.Must(template.New("dockerfile").Parse(dockerfile))
  2289  	buf := bytes.NewBuffer(nil)
  2290  	tmpl.Execute(buf, portList)
  2291  
  2292  	name := "testbuildexpose"
  2293  	_, err := buildImage(name, buf.String(), true)
  2294  	if err != nil {
  2295  		c.Fatal(err)
  2296  	}
  2297  
  2298  	// check if all the ports are saved inside Config.ExposedPorts
  2299  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
  2300  	if err != nil {
  2301  		c.Fatal(err)
  2302  	}
  2303  	var exposedPorts map[string]interface{}
  2304  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
  2305  		c.Fatal(err)
  2306  	}
  2307  
  2308  	for _, p := range expectedPorts {
  2309  		ep := fmt.Sprintf("%d/tcp", p)
  2310  		if _, ok := exposedPorts[ep]; !ok {
  2311  			c.Errorf("Port(%s) is not exposed", ep)
  2312  		} else {
  2313  			delete(exposedPorts, ep)
  2314  		}
  2315  	}
  2316  	if len(exposedPorts) != 0 {
  2317  		c.Errorf("Unexpected extra exposed ports %v", exposedPorts)
  2318  	}
  2319  }
  2320  
  2321  func (s *DockerSuite) TestBuildExposeOrder(c *check.C) {
  2322  	buildID := func(name, exposed string) string {
  2323  		_, err := buildImage(name, fmt.Sprintf(`FROM scratch
  2324  		EXPOSE %s`, exposed), true)
  2325  		if err != nil {
  2326  			c.Fatal(err)
  2327  		}
  2328  		id, err := inspectField(name, "Id")
  2329  		if err != nil {
  2330  			c.Fatal(err)
  2331  		}
  2332  		return id
  2333  	}
  2334  
  2335  	id1 := buildID("testbuildexpose1", "80 2375")
  2336  	id2 := buildID("testbuildexpose2", "2375 80")
  2337  	if id1 != id2 {
  2338  		c.Errorf("EXPOSE should invalidate the cache only when ports actually changed")
  2339  	}
  2340  }
  2341  
  2342  func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) {
  2343  	name := "testbuildexposeuppercaseproto"
  2344  	expected := "map[5678/udp:{}]"
  2345  	_, err := buildImage(name,
  2346  		`FROM scratch
  2347          EXPOSE 5678/UDP`,
  2348  		true)
  2349  	if err != nil {
  2350  		c.Fatal(err)
  2351  	}
  2352  	res, err := inspectField(name, "Config.ExposedPorts")
  2353  	if err != nil {
  2354  		c.Fatal(err)
  2355  	}
  2356  	if res != expected {
  2357  		c.Fatalf("Exposed ports %s, expected %s", res, expected)
  2358  	}
  2359  }
  2360  
  2361  func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) {
  2362  	name := "testbuildentrypointinheritance"
  2363  	name2 := "testbuildentrypointinheritance2"
  2364  
  2365  	_, err := buildImage(name,
  2366  		`FROM busybox
  2367          ENTRYPOINT ["/bin/echo"]`,
  2368  		true)
  2369  	if err != nil {
  2370  		c.Fatal(err)
  2371  	}
  2372  	res, err := inspectField(name, "Config.Entrypoint")
  2373  	if err != nil {
  2374  		c.Fatal(err)
  2375  	}
  2376  
  2377  	expected := "{[/bin/echo]}"
  2378  	if res != expected {
  2379  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2380  	}
  2381  
  2382  	_, err = buildImage(name2,
  2383  		fmt.Sprintf(`FROM %s
  2384          ENTRYPOINT []`, name),
  2385  		true)
  2386  	if err != nil {
  2387  		c.Fatal(err)
  2388  	}
  2389  	res, err = inspectField(name2, "Config.Entrypoint")
  2390  	if err != nil {
  2391  		c.Fatal(err)
  2392  	}
  2393  
  2394  	expected = "{[]}"
  2395  
  2396  	if res != expected {
  2397  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2398  	}
  2399  
  2400  }
  2401  
  2402  func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) {
  2403  	name := "testbuildentrypoint"
  2404  	expected := "{[]}"
  2405  
  2406  	_, err := buildImage(name,
  2407  		`FROM busybox
  2408          ENTRYPOINT []`,
  2409  		true)
  2410  	if err != nil {
  2411  		c.Fatal(err)
  2412  	}
  2413  	res, err := inspectField(name, "Config.Entrypoint")
  2414  	if err != nil {
  2415  		c.Fatal(err)
  2416  	}
  2417  	if res != expected {
  2418  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2419  	}
  2420  
  2421  }
  2422  
  2423  func (s *DockerSuite) TestBuildEntrypoint(c *check.C) {
  2424  	name := "testbuildentrypoint"
  2425  	expected := "{[/bin/echo]}"
  2426  	_, err := buildImage(name,
  2427  		`FROM scratch
  2428          ENTRYPOINT ["/bin/echo"]`,
  2429  		true)
  2430  	if err != nil {
  2431  		c.Fatal(err)
  2432  	}
  2433  	res, err := inspectField(name, "Config.Entrypoint")
  2434  	if err != nil {
  2435  		c.Fatal(err)
  2436  	}
  2437  	if res != expected {
  2438  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  2439  	}
  2440  
  2441  }
  2442  
  2443  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  2444  func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) {
  2445  	var (
  2446  		out2, out3 string
  2447  	)
  2448  	{
  2449  		name1 := "testonbuildtrigger1"
  2450  		dockerfile1 := `
  2451  		FROM busybox
  2452  		RUN echo "GRANDPARENT"
  2453  		ONBUILD RUN echo "ONBUILD PARENT"
  2454  		`
  2455  		ctx, err := fakeContext(dockerfile1, nil)
  2456  		if err != nil {
  2457  			c.Fatal(err)
  2458  		}
  2459  		defer ctx.Close()
  2460  
  2461  		out1, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name1, ".")
  2462  		if err != nil {
  2463  			c.Fatalf("build failed to complete: %s, %v", out1, err)
  2464  		}
  2465  	}
  2466  	{
  2467  		name2 := "testonbuildtrigger2"
  2468  		dockerfile2 := `
  2469  		FROM testonbuildtrigger1
  2470  		`
  2471  		ctx, err := fakeContext(dockerfile2, nil)
  2472  		if err != nil {
  2473  			c.Fatal(err)
  2474  		}
  2475  		defer ctx.Close()
  2476  
  2477  		out2, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name2, ".")
  2478  		if err != nil {
  2479  			c.Fatalf("build failed to complete: %s, %v", out2, err)
  2480  		}
  2481  	}
  2482  	{
  2483  		name3 := "testonbuildtrigger3"
  2484  		dockerfile3 := `
  2485  		FROM testonbuildtrigger2
  2486  		`
  2487  		ctx, err := fakeContext(dockerfile3, nil)
  2488  		if err != nil {
  2489  			c.Fatal(err)
  2490  		}
  2491  		defer ctx.Close()
  2492  
  2493  		out3, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name3, ".")
  2494  		if err != nil {
  2495  			c.Fatalf("build failed to complete: %s, %v", out3, err)
  2496  		}
  2497  
  2498  	}
  2499  
  2500  	// ONBUILD should be run in second build.
  2501  	if !strings.Contains(out2, "ONBUILD PARENT") {
  2502  		c.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
  2503  	}
  2504  
  2505  	// ONBUILD should *not* be run in third build.
  2506  	if strings.Contains(out3, "ONBUILD PARENT") {
  2507  		c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  2508  	}
  2509  
  2510  }
  2511  
  2512  func (s *DockerSuite) TestBuildWithCache(c *check.C) {
  2513  	name := "testbuildwithcache"
  2514  	id1, err := buildImage(name,
  2515  		`FROM scratch
  2516  		MAINTAINER dockerio
  2517  		EXPOSE 5432
  2518          ENTRYPOINT ["/bin/echo"]`,
  2519  		true)
  2520  	if err != nil {
  2521  		c.Fatal(err)
  2522  	}
  2523  	id2, err := buildImage(name,
  2524  		`FROM scratch
  2525  		MAINTAINER dockerio
  2526  		EXPOSE 5432
  2527          ENTRYPOINT ["/bin/echo"]`,
  2528  		true)
  2529  	if err != nil {
  2530  		c.Fatal(err)
  2531  	}
  2532  	if id1 != id2 {
  2533  		c.Fatal("The cache should have been used but hasn't.")
  2534  	}
  2535  }
  2536  
  2537  func (s *DockerSuite) TestBuildWithoutCache(c *check.C) {
  2538  	name := "testbuildwithoutcache"
  2539  	name2 := "testbuildwithoutcache2"
  2540  	id1, err := buildImage(name,
  2541  		`FROM scratch
  2542  		MAINTAINER dockerio
  2543  		EXPOSE 5432
  2544          ENTRYPOINT ["/bin/echo"]`,
  2545  		true)
  2546  	if err != nil {
  2547  		c.Fatal(err)
  2548  	}
  2549  
  2550  	id2, err := buildImage(name2,
  2551  		`FROM scratch
  2552  		MAINTAINER dockerio
  2553  		EXPOSE 5432
  2554          ENTRYPOINT ["/bin/echo"]`,
  2555  		false)
  2556  	if err != nil {
  2557  		c.Fatal(err)
  2558  	}
  2559  	if id1 == id2 {
  2560  		c.Fatal("The cache should have been invalided but hasn't.")
  2561  	}
  2562  }
  2563  
  2564  func (s *DockerSuite) TestBuildConditionalCache(c *check.C) {
  2565  	name := "testbuildconditionalcache"
  2566  
  2567  	dockerfile := `
  2568  		FROM busybox
  2569          ADD foo /tmp/`
  2570  	ctx, err := fakeContext(dockerfile, map[string]string{
  2571  		"foo": "hello",
  2572  	})
  2573  	if err != nil {
  2574  		c.Fatal(err)
  2575  	}
  2576  	defer ctx.Close()
  2577  
  2578  	id1, err := buildImageFromContext(name, ctx, true)
  2579  	if err != nil {
  2580  		c.Fatalf("Error building #1: %s", err)
  2581  	}
  2582  
  2583  	if err := ctx.Add("foo", "bye"); err != nil {
  2584  		c.Fatalf("Error modifying foo: %s", err)
  2585  	}
  2586  
  2587  	id2, err := buildImageFromContext(name, ctx, false)
  2588  	if err != nil {
  2589  		c.Fatalf("Error building #2: %s", err)
  2590  	}
  2591  	if id2 == id1 {
  2592  		c.Fatal("Should not have used the cache")
  2593  	}
  2594  
  2595  	id3, err := buildImageFromContext(name, ctx, true)
  2596  	if err != nil {
  2597  		c.Fatalf("Error building #3: %s", err)
  2598  	}
  2599  	if id3 != id2 {
  2600  		c.Fatal("Should have used the cache")
  2601  	}
  2602  }
  2603  
  2604  func (s *DockerSuite) TestBuildAddLocalFileWithCache(c *check.C) {
  2605  	name := "testbuildaddlocalfilewithcache"
  2606  	name2 := "testbuildaddlocalfilewithcache2"
  2607  	dockerfile := `
  2608  		FROM busybox
  2609          MAINTAINER dockerio
  2610          ADD foo /usr/lib/bla/bar
  2611  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2612  	ctx, err := fakeContext(dockerfile, map[string]string{
  2613  		"foo": "hello",
  2614  	})
  2615  	defer ctx.Close()
  2616  	if err != nil {
  2617  		c.Fatal(err)
  2618  	}
  2619  	id1, err := buildImageFromContext(name, ctx, true)
  2620  	if err != nil {
  2621  		c.Fatal(err)
  2622  	}
  2623  	id2, err := buildImageFromContext(name2, ctx, true)
  2624  	if err != nil {
  2625  		c.Fatal(err)
  2626  	}
  2627  	if id1 != id2 {
  2628  		c.Fatal("The cache should have been used but hasn't.")
  2629  	}
  2630  }
  2631  
  2632  func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) {
  2633  	name := "testbuildaddmultiplelocalfilewithcache"
  2634  	name2 := "testbuildaddmultiplelocalfilewithcache2"
  2635  	dockerfile := `
  2636  		FROM busybox
  2637          MAINTAINER dockerio
  2638          ADD foo Dockerfile /usr/lib/bla/
  2639  		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
  2640  	ctx, err := fakeContext(dockerfile, map[string]string{
  2641  		"foo": "hello",
  2642  	})
  2643  	defer ctx.Close()
  2644  	if err != nil {
  2645  		c.Fatal(err)
  2646  	}
  2647  	id1, err := buildImageFromContext(name, ctx, true)
  2648  	if err != nil {
  2649  		c.Fatal(err)
  2650  	}
  2651  	id2, err := buildImageFromContext(name2, ctx, true)
  2652  	if err != nil {
  2653  		c.Fatal(err)
  2654  	}
  2655  	if id1 != id2 {
  2656  		c.Fatal("The cache should have been used but hasn't.")
  2657  	}
  2658  }
  2659  
  2660  func (s *DockerSuite) TestBuildAddLocalFileWithoutCache(c *check.C) {
  2661  	name := "testbuildaddlocalfilewithoutcache"
  2662  	name2 := "testbuildaddlocalfilewithoutcache2"
  2663  	dockerfile := `
  2664  		FROM busybox
  2665          MAINTAINER dockerio
  2666          ADD foo /usr/lib/bla/bar
  2667  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2668  	ctx, err := fakeContext(dockerfile, map[string]string{
  2669  		"foo": "hello",
  2670  	})
  2671  	defer ctx.Close()
  2672  	if err != nil {
  2673  		c.Fatal(err)
  2674  	}
  2675  	id1, err := buildImageFromContext(name, ctx, true)
  2676  	if err != nil {
  2677  		c.Fatal(err)
  2678  	}
  2679  	id2, err := buildImageFromContext(name2, ctx, false)
  2680  	if err != nil {
  2681  		c.Fatal(err)
  2682  	}
  2683  	if id1 == id2 {
  2684  		c.Fatal("The cache should have been invalided but hasn't.")
  2685  	}
  2686  }
  2687  
  2688  func (s *DockerSuite) TestBuildCopyDirButNotFile(c *check.C) {
  2689  	name := "testbuildcopydirbutnotfile"
  2690  	name2 := "testbuildcopydirbutnotfile2"
  2691  	dockerfile := `
  2692          FROM scratch
  2693          COPY dir /tmp/`
  2694  	ctx, err := fakeContext(dockerfile, map[string]string{
  2695  		"dir/foo": "hello",
  2696  	})
  2697  	defer ctx.Close()
  2698  	if err != nil {
  2699  		c.Fatal(err)
  2700  	}
  2701  	id1, err := buildImageFromContext(name, ctx, true)
  2702  	if err != nil {
  2703  		c.Fatal(err)
  2704  	}
  2705  	// Check that adding file with similar name doesn't mess with cache
  2706  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  2707  		c.Fatal(err)
  2708  	}
  2709  	id2, err := buildImageFromContext(name2, ctx, true)
  2710  	if err != nil {
  2711  		c.Fatal(err)
  2712  	}
  2713  	if id1 != id2 {
  2714  		c.Fatal("The cache should have been used but wasn't")
  2715  	}
  2716  }
  2717  
  2718  func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) {
  2719  	name := "testbuildaddcurrentdirwithcache"
  2720  	name2 := name + "2"
  2721  	name3 := name + "3"
  2722  	name4 := name + "4"
  2723  	dockerfile := `
  2724          FROM scratch
  2725          MAINTAINER dockerio
  2726          ADD . /usr/lib/bla`
  2727  	ctx, err := fakeContext(dockerfile, map[string]string{
  2728  		"foo": "hello",
  2729  	})
  2730  	defer ctx.Close()
  2731  	if err != nil {
  2732  		c.Fatal(err)
  2733  	}
  2734  	id1, err := buildImageFromContext(name, ctx, true)
  2735  	if err != nil {
  2736  		c.Fatal(err)
  2737  	}
  2738  	// Check that adding file invalidate cache of "ADD ."
  2739  	if err := ctx.Add("bar", "hello2"); err != nil {
  2740  		c.Fatal(err)
  2741  	}
  2742  	id2, err := buildImageFromContext(name2, ctx, true)
  2743  	if err != nil {
  2744  		c.Fatal(err)
  2745  	}
  2746  	if id1 == id2 {
  2747  		c.Fatal("The cache should have been invalided but hasn't.")
  2748  	}
  2749  	// Check that changing file invalidate cache of "ADD ."
  2750  	if err := ctx.Add("foo", "hello1"); err != nil {
  2751  		c.Fatal(err)
  2752  	}
  2753  	id3, err := buildImageFromContext(name3, ctx, true)
  2754  	if err != nil {
  2755  		c.Fatal(err)
  2756  	}
  2757  	if id2 == id3 {
  2758  		c.Fatal("The cache should have been invalided but hasn't.")
  2759  	}
  2760  	// Check that changing file to same content with different mtime does not
  2761  	// invalidate cache of "ADD ."
  2762  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  2763  	if err := ctx.Add("foo", "hello1"); err != nil {
  2764  		c.Fatal(err)
  2765  	}
  2766  	id4, err := buildImageFromContext(name4, ctx, true)
  2767  	if err != nil {
  2768  		c.Fatal(err)
  2769  	}
  2770  	if id3 != id4 {
  2771  		c.Fatal("The cache should have been used but hasn't.")
  2772  	}
  2773  }
  2774  
  2775  func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) {
  2776  	name := "testbuildaddcurrentdirwithoutcache"
  2777  	name2 := "testbuildaddcurrentdirwithoutcache2"
  2778  	dockerfile := `
  2779          FROM scratch
  2780          MAINTAINER dockerio
  2781          ADD . /usr/lib/bla`
  2782  	ctx, err := fakeContext(dockerfile, map[string]string{
  2783  		"foo": "hello",
  2784  	})
  2785  	defer ctx.Close()
  2786  	if err != nil {
  2787  		c.Fatal(err)
  2788  	}
  2789  	id1, err := buildImageFromContext(name, ctx, true)
  2790  	if err != nil {
  2791  		c.Fatal(err)
  2792  	}
  2793  	id2, err := buildImageFromContext(name2, ctx, false)
  2794  	if err != nil {
  2795  		c.Fatal(err)
  2796  	}
  2797  	if id1 == id2 {
  2798  		c.Fatal("The cache should have been invalided but hasn't.")
  2799  	}
  2800  }
  2801  
  2802  func (s *DockerSuite) TestBuildAddRemoteFileWithCache(c *check.C) {
  2803  	name := "testbuildaddremotefilewithcache"
  2804  	server, err := fakeStorage(map[string]string{
  2805  		"baz": "hello",
  2806  	})
  2807  	if err != nil {
  2808  		c.Fatal(err)
  2809  	}
  2810  	defer server.Close()
  2811  
  2812  	id1, err := buildImage(name,
  2813  		fmt.Sprintf(`FROM scratch
  2814          MAINTAINER dockerio
  2815          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2816  		true)
  2817  	if err != nil {
  2818  		c.Fatal(err)
  2819  	}
  2820  	id2, err := buildImage(name,
  2821  		fmt.Sprintf(`FROM scratch
  2822          MAINTAINER dockerio
  2823          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2824  		true)
  2825  	if err != nil {
  2826  		c.Fatal(err)
  2827  	}
  2828  	if id1 != id2 {
  2829  		c.Fatal("The cache should have been used but hasn't.")
  2830  	}
  2831  }
  2832  
  2833  func (s *DockerSuite) TestBuildAddRemoteFileWithoutCache(c *check.C) {
  2834  	name := "testbuildaddremotefilewithoutcache"
  2835  	name2 := "testbuildaddremotefilewithoutcache2"
  2836  	server, err := fakeStorage(map[string]string{
  2837  		"baz": "hello",
  2838  	})
  2839  	if err != nil {
  2840  		c.Fatal(err)
  2841  	}
  2842  	defer server.Close()
  2843  
  2844  	id1, err := buildImage(name,
  2845  		fmt.Sprintf(`FROM scratch
  2846          MAINTAINER dockerio
  2847          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2848  		true)
  2849  	if err != nil {
  2850  		c.Fatal(err)
  2851  	}
  2852  	id2, err := buildImage(name2,
  2853  		fmt.Sprintf(`FROM scratch
  2854          MAINTAINER dockerio
  2855          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2856  		false)
  2857  	if err != nil {
  2858  		c.Fatal(err)
  2859  	}
  2860  	if id1 == id2 {
  2861  		c.Fatal("The cache should have been invalided but hasn't.")
  2862  	}
  2863  }
  2864  
  2865  func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) {
  2866  	name := "testbuildaddremotefilemtime"
  2867  	name2 := name + "2"
  2868  	name3 := name + "3"
  2869  
  2870  	files := map[string]string{"baz": "hello"}
  2871  	server, err := fakeStorage(files)
  2872  	if err != nil {
  2873  		c.Fatal(err)
  2874  	}
  2875  	defer server.Close()
  2876  
  2877  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2878          MAINTAINER dockerio
  2879          ADD %s/baz /usr/lib/baz/quux`, server.URL()), nil)
  2880  	if err != nil {
  2881  		c.Fatal(err)
  2882  	}
  2883  	defer ctx.Close()
  2884  
  2885  	id1, err := buildImageFromContext(name, ctx, true)
  2886  	if err != nil {
  2887  		c.Fatal(err)
  2888  	}
  2889  
  2890  	id2, err := buildImageFromContext(name2, ctx, true)
  2891  	if err != nil {
  2892  		c.Fatal(err)
  2893  	}
  2894  	if id1 != id2 {
  2895  		c.Fatal("The cache should have been used but wasn't - #1")
  2896  	}
  2897  
  2898  	// Now create a different server with same contents (causes different mtime)
  2899  	// The cache should still be used
  2900  
  2901  	// allow some time for clock to pass as mtime precision is only 1s
  2902  	time.Sleep(2 * time.Second)
  2903  
  2904  	server2, err := fakeStorage(files)
  2905  	if err != nil {
  2906  		c.Fatal(err)
  2907  	}
  2908  	defer server2.Close()
  2909  
  2910  	ctx2, err := fakeContext(fmt.Sprintf(`FROM scratch
  2911          MAINTAINER dockerio
  2912          ADD %s/baz /usr/lib/baz/quux`, server2.URL()), nil)
  2913  	if err != nil {
  2914  		c.Fatal(err)
  2915  	}
  2916  	defer ctx2.Close()
  2917  	id3, err := buildImageFromContext(name3, ctx2, true)
  2918  	if err != nil {
  2919  		c.Fatal(err)
  2920  	}
  2921  	if id1 != id3 {
  2922  		c.Fatal("The cache should have been used but wasn't")
  2923  	}
  2924  }
  2925  
  2926  func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithCache(c *check.C) {
  2927  	name := "testbuildaddlocalandremotefilewithcache"
  2928  	server, err := fakeStorage(map[string]string{
  2929  		"baz": "hello",
  2930  	})
  2931  	if err != nil {
  2932  		c.Fatal(err)
  2933  	}
  2934  	defer server.Close()
  2935  
  2936  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2937          MAINTAINER dockerio
  2938          ADD foo /usr/lib/bla/bar
  2939          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  2940  		map[string]string{
  2941  			"foo": "hello world",
  2942  		})
  2943  	if err != nil {
  2944  		c.Fatal(err)
  2945  	}
  2946  	defer ctx.Close()
  2947  	id1, err := buildImageFromContext(name, ctx, true)
  2948  	if err != nil {
  2949  		c.Fatal(err)
  2950  	}
  2951  	id2, err := buildImageFromContext(name, ctx, true)
  2952  	if err != nil {
  2953  		c.Fatal(err)
  2954  	}
  2955  	if id1 != id2 {
  2956  		c.Fatal("The cache should have been used but hasn't.")
  2957  	}
  2958  }
  2959  
  2960  func testContextTar(c *check.C, compression archive.Compression) {
  2961  	ctx, err := fakeContext(
  2962  		`FROM busybox
  2963  ADD foo /foo
  2964  CMD ["cat", "/foo"]`,
  2965  		map[string]string{
  2966  			"foo": "bar",
  2967  		},
  2968  	)
  2969  	defer ctx.Close()
  2970  	if err != nil {
  2971  		c.Fatal(err)
  2972  	}
  2973  	context, err := archive.Tar(ctx.Dir, compression)
  2974  	if err != nil {
  2975  		c.Fatalf("failed to build context tar: %v", err)
  2976  	}
  2977  	name := "contexttar"
  2978  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  2979  	buildCmd.Stdin = context
  2980  
  2981  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  2982  		c.Fatalf("build failed to complete: %v %v", out, err)
  2983  	}
  2984  }
  2985  
  2986  func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) {
  2987  	testContextTar(c, archive.Gzip)
  2988  }
  2989  
  2990  func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) {
  2991  	testContextTar(c, archive.Uncompressed)
  2992  }
  2993  
  2994  func (s *DockerSuite) TestBuildNoContext(c *check.C) {
  2995  	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
  2996  	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
  2997  
  2998  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  2999  		c.Fatalf("build failed to complete: %v %v", out, err)
  3000  	}
  3001  
  3002  	if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" {
  3003  		c.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  3004  	}
  3005  }
  3006  
  3007  // TODO: TestCaching
  3008  func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithoutCache(c *check.C) {
  3009  	name := "testbuildaddlocalandremotefilewithoutcache"
  3010  	name2 := "testbuildaddlocalandremotefilewithoutcache2"
  3011  	server, err := fakeStorage(map[string]string{
  3012  		"baz": "hello",
  3013  	})
  3014  	if err != nil {
  3015  		c.Fatal(err)
  3016  	}
  3017  	defer server.Close()
  3018  
  3019  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  3020          MAINTAINER dockerio
  3021          ADD foo /usr/lib/bla/bar
  3022          ADD %s/baz /usr/lib/baz/quux`, server.URL()),
  3023  		map[string]string{
  3024  			"foo": "hello world",
  3025  		})
  3026  	if err != nil {
  3027  		c.Fatal(err)
  3028  	}
  3029  	defer ctx.Close()
  3030  	id1, err := buildImageFromContext(name, ctx, true)
  3031  	if err != nil {
  3032  		c.Fatal(err)
  3033  	}
  3034  	id2, err := buildImageFromContext(name2, ctx, false)
  3035  	if err != nil {
  3036  		c.Fatal(err)
  3037  	}
  3038  	if id1 == id2 {
  3039  		c.Fatal("The cache should have been invalided but hasn't.")
  3040  	}
  3041  }
  3042  
  3043  func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) {
  3044  	name := "testbuildimg"
  3045  
  3046  	_, err := buildImage(name,
  3047  		`FROM busybox:latest
  3048          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  3049          VOLUME /test`,
  3050  		true)
  3051  
  3052  	if err != nil {
  3053  		c.Fatal(err)
  3054  	}
  3055  
  3056  	out, _ := dockerCmd(c, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  3057  
  3058  	if expected := "drw-------"; !strings.Contains(out, expected) {
  3059  		c.Fatalf("expected %s received %s", expected, out)
  3060  	}
  3061  
  3062  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  3063  		c.Fatalf("expected %s received %s", expected, out)
  3064  	}
  3065  
  3066  }
  3067  
  3068  // testing #1405 - config.Cmd does not get cleaned up if
  3069  // utilizing cache
  3070  func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) {
  3071  	name := "testbuildcmdcleanup"
  3072  	if _, err := buildImage(name,
  3073  		`FROM busybox
  3074          RUN echo "hello"`,
  3075  		true); err != nil {
  3076  		c.Fatal(err)
  3077  	}
  3078  
  3079  	ctx, err := fakeContext(`FROM busybox
  3080          RUN echo "hello"
  3081          ADD foo /foo
  3082          ENTRYPOINT ["/bin/echo"]`,
  3083  		map[string]string{
  3084  			"foo": "hello",
  3085  		})
  3086  	defer ctx.Close()
  3087  	if err != nil {
  3088  		c.Fatal(err)
  3089  	}
  3090  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3091  		c.Fatal(err)
  3092  	}
  3093  	res, err := inspectField(name, "Config.Cmd")
  3094  	if err != nil {
  3095  		c.Fatal(err)
  3096  	}
  3097  	// Cmd must be cleaned up
  3098  	if res != "<nil>" {
  3099  		c.Fatalf("Cmd %s, expected nil", res)
  3100  	}
  3101  }
  3102  
  3103  func (s *DockerSuite) TestBuildForbiddenContextPath(c *check.C) {
  3104  	name := "testbuildforbidpath"
  3105  	ctx, err := fakeContext(`FROM scratch
  3106          ADD ../../ test/
  3107          `,
  3108  		map[string]string{
  3109  			"test.txt":  "test1",
  3110  			"other.txt": "other",
  3111  		})
  3112  	defer ctx.Close()
  3113  	if err != nil {
  3114  		c.Fatal(err)
  3115  	}
  3116  
  3117  	expected := "Forbidden path outside the build context: ../../ "
  3118  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  3119  		c.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
  3120  	}
  3121  
  3122  }
  3123  
  3124  func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) {
  3125  	name := "testbuildaddnotfound"
  3126  	ctx, err := fakeContext(`FROM scratch
  3127          ADD foo /usr/local/bar`,
  3128  		map[string]string{"bar": "hello"})
  3129  	defer ctx.Close()
  3130  	if err != nil {
  3131  		c.Fatal(err)
  3132  	}
  3133  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3134  		if !strings.Contains(err.Error(), "foo: no such file or directory") {
  3135  			c.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  3136  		}
  3137  	} else {
  3138  		c.Fatal("Error must not be nil")
  3139  	}
  3140  }
  3141  
  3142  func (s *DockerSuite) TestBuildInheritance(c *check.C) {
  3143  	name := "testbuildinheritance"
  3144  
  3145  	_, err := buildImage(name,
  3146  		`FROM scratch
  3147  		EXPOSE 2375`,
  3148  		true)
  3149  	if err != nil {
  3150  		c.Fatal(err)
  3151  	}
  3152  	ports1, err := inspectField(name, "Config.ExposedPorts")
  3153  	if err != nil {
  3154  		c.Fatal(err)
  3155  	}
  3156  
  3157  	_, err = buildImage(name,
  3158  		fmt.Sprintf(`FROM %s
  3159  		ENTRYPOINT ["/bin/echo"]`, name),
  3160  		true)
  3161  	if err != nil {
  3162  		c.Fatal(err)
  3163  	}
  3164  
  3165  	res, err := inspectField(name, "Config.Entrypoint")
  3166  	if err != nil {
  3167  		c.Fatal(err)
  3168  	}
  3169  	if expected := "{[/bin/echo]}"; res != expected {
  3170  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  3171  	}
  3172  	ports2, err := inspectField(name, "Config.ExposedPorts")
  3173  	if err != nil {
  3174  		c.Fatal(err)
  3175  	}
  3176  	if ports1 != ports2 {
  3177  		c.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  3178  	}
  3179  }
  3180  
  3181  func (s *DockerSuite) TestBuildFails(c *check.C) {
  3182  	name := "testbuildfails"
  3183  	_, err := buildImage(name,
  3184  		`FROM busybox
  3185  		RUN sh -c "exit 23"`,
  3186  		true)
  3187  	if err != nil {
  3188  		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  3189  			c.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  3190  		}
  3191  	} else {
  3192  		c.Fatal("Error must not be nil")
  3193  	}
  3194  }
  3195  
  3196  func (s *DockerSuite) TestBuildFailsDockerfileEmpty(c *check.C) {
  3197  	name := "testbuildfails"
  3198  	_, err := buildImage(name, ``, true)
  3199  	if err != nil {
  3200  		if !strings.Contains(err.Error(), "The Dockerfile (Dockerfile) cannot be empty") {
  3201  			c.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
  3202  		}
  3203  	} else {
  3204  		c.Fatal("Error must not be nil")
  3205  	}
  3206  }
  3207  
  3208  func (s *DockerSuite) TestBuildOnBuild(c *check.C) {
  3209  	name := "testbuildonbuild"
  3210  	_, err := buildImage(name,
  3211  		`FROM busybox
  3212  		ONBUILD RUN touch foobar`,
  3213  		true)
  3214  	if err != nil {
  3215  		c.Fatal(err)
  3216  	}
  3217  	_, err = buildImage(name,
  3218  		fmt.Sprintf(`FROM %s
  3219  		RUN [ -f foobar ]`, name),
  3220  		true)
  3221  	if err != nil {
  3222  		c.Fatal(err)
  3223  	}
  3224  }
  3225  
  3226  func (s *DockerSuite) TestBuildOnBuildForbiddenChained(c *check.C) {
  3227  	name := "testbuildonbuildforbiddenchained"
  3228  	_, err := buildImage(name,
  3229  		`FROM busybox
  3230  		ONBUILD ONBUILD RUN touch foobar`,
  3231  		true)
  3232  	if err != nil {
  3233  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
  3234  			c.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
  3235  		}
  3236  	} else {
  3237  		c.Fatal("Error must not be nil")
  3238  	}
  3239  }
  3240  
  3241  func (s *DockerSuite) TestBuildOnBuildForbiddenFrom(c *check.C) {
  3242  	name := "testbuildonbuildforbiddenfrom"
  3243  	_, err := buildImage(name,
  3244  		`FROM busybox
  3245  		ONBUILD FROM scratch`,
  3246  		true)
  3247  	if err != nil {
  3248  		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
  3249  			c.Fatalf("Wrong error %v, must be about FROM forbidden", err)
  3250  		}
  3251  	} else {
  3252  		c.Fatal("Error must not be nil")
  3253  	}
  3254  }
  3255  
  3256  func (s *DockerSuite) TestBuildOnBuildForbiddenMaintainer(c *check.C) {
  3257  	name := "testbuildonbuildforbiddenmaintainer"
  3258  	_, err := buildImage(name,
  3259  		`FROM busybox
  3260  		ONBUILD MAINTAINER docker.io`,
  3261  		true)
  3262  	if err != nil {
  3263  		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
  3264  			c.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
  3265  		}
  3266  	} else {
  3267  		c.Fatal("Error must not be nil")
  3268  	}
  3269  }
  3270  
  3271  // gh #2446
  3272  func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) {
  3273  	name := "testbuildaddtosymlinkdest"
  3274  	ctx, err := fakeContext(`FROM busybox
  3275          RUN mkdir /foo
  3276          RUN ln -s /foo /bar
  3277          ADD foo /bar/
  3278          RUN [ -f /bar/foo ]
  3279          RUN [ -f /foo/foo ]`,
  3280  		map[string]string{
  3281  			"foo": "hello",
  3282  		})
  3283  	if err != nil {
  3284  		c.Fatal(err)
  3285  	}
  3286  	defer ctx.Close()
  3287  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3288  		c.Fatal(err)
  3289  	}
  3290  }
  3291  
  3292  func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) {
  3293  	name := "testbuildescaping"
  3294  
  3295  	_, err := buildImage(name, `
  3296    FROM busybox
  3297    MAINTAINER "Docker \
  3298  IO <io@\
  3299  docker.com>"
  3300    `, true)
  3301  	if err != nil {
  3302  		c.Fatal(err)
  3303  	}
  3304  
  3305  	res, err := inspectField(name, "Author")
  3306  
  3307  	if err != nil {
  3308  		c.Fatal(err)
  3309  	}
  3310  
  3311  	if res != "\"Docker IO <io@docker.com>\"" {
  3312  		c.Fatalf("Parsed string did not match the escaped string. Got: %q", res)
  3313  	}
  3314  
  3315  }
  3316  
  3317  func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) {
  3318  	// Verify that strings that look like ints are still passed as strings
  3319  	name := "testbuildstringing"
  3320  
  3321  	_, err := buildImage(name, `
  3322    FROM busybox
  3323    MAINTAINER 123
  3324    `, true)
  3325  
  3326  	if err != nil {
  3327  		c.Fatal(err)
  3328  	}
  3329  
  3330  	out, _ := dockerCmd(c, "inspect", name)
  3331  
  3332  	if !strings.Contains(out, "\"123\"") {
  3333  		c.Fatalf("Output does not contain the int as a string:\n%s", out)
  3334  	}
  3335  
  3336  }
  3337  
  3338  func (s *DockerSuite) TestBuildDockerignore(c *check.C) {
  3339  	name := "testbuilddockerignore"
  3340  	dockerfile := `
  3341          FROM busybox
  3342          ADD . /bla
  3343  		RUN [[ -f /bla/src/x.go ]]
  3344  		RUN [[ -f /bla/Makefile ]]
  3345  		RUN [[ ! -e /bla/src/_vendor ]]
  3346  		RUN [[ ! -e /bla/.gitignore ]]
  3347  		RUN [[ ! -e /bla/README.md ]]
  3348  		RUN [[ ! -e /bla/dir/foo ]]
  3349  		RUN [[ ! -e /bla/foo ]]
  3350  		RUN [[ ! -e /bla/.git ]]`
  3351  	ctx, err := fakeContext(dockerfile, map[string]string{
  3352  		"Makefile":         "all:",
  3353  		".git/HEAD":        "ref: foo",
  3354  		"src/x.go":         "package main",
  3355  		"src/_vendor/v.go": "package main",
  3356  		"dir/foo":          "",
  3357  		".gitignore":       "",
  3358  		"README.md":        "readme",
  3359  		".dockerignore": `
  3360  .git
  3361  pkg
  3362  .gitignore
  3363  src/_vendor
  3364  *.md
  3365  dir`,
  3366  	})
  3367  	if err != nil {
  3368  		c.Fatal(err)
  3369  	}
  3370  	defer ctx.Close()
  3371  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3372  		c.Fatal(err)
  3373  	}
  3374  }
  3375  
  3376  func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) {
  3377  	name := "testbuilddockerignorecleanpaths"
  3378  	dockerfile := `
  3379          FROM busybox
  3380          ADD . /tmp/
  3381          RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
  3382  	ctx, err := fakeContext(dockerfile, map[string]string{
  3383  		"foo":           "foo",
  3384  		"foo2":          "foo2",
  3385  		"dir1/foo":      "foo in dir1",
  3386  		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
  3387  	})
  3388  	if err != nil {
  3389  		c.Fatal(err)
  3390  	}
  3391  	defer ctx.Close()
  3392  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3393  		c.Fatal(err)
  3394  	}
  3395  }
  3396  
  3397  func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) {
  3398  	name := "testbuilddockerignoreexceptions"
  3399  	dockerfile := `
  3400          FROM busybox
  3401          ADD . /bla
  3402  		RUN [[ -f /bla/src/x.go ]]
  3403  		RUN [[ -f /bla/Makefile ]]
  3404  		RUN [[ ! -e /bla/src/_vendor ]]
  3405  		RUN [[ ! -e /bla/.gitignore ]]
  3406  		RUN [[ ! -e /bla/README.md ]]
  3407  		RUN [[  -e /bla/dir/dir/foo ]]
  3408  		RUN [[ ! -e /bla/dir/foo1 ]]
  3409  		RUN [[ -f /bla/dir/e ]]
  3410  		RUN [[ -f /bla/dir/e-dir/foo ]]
  3411  		RUN [[ ! -e /bla/foo ]]
  3412  		RUN [[ ! -e /bla/.git ]]`
  3413  	ctx, err := fakeContext(dockerfile, map[string]string{
  3414  		"Makefile":         "all:",
  3415  		".git/HEAD":        "ref: foo",
  3416  		"src/x.go":         "package main",
  3417  		"src/_vendor/v.go": "package main",
  3418  		"dir/foo":          "",
  3419  		"dir/foo1":         "",
  3420  		"dir/dir/f1":       "",
  3421  		"dir/dir/foo":      "",
  3422  		"dir/e":            "",
  3423  		"dir/e-dir/foo":    "",
  3424  		".gitignore":       "",
  3425  		"README.md":        "readme",
  3426  		".dockerignore": `
  3427  .git
  3428  pkg
  3429  .gitignore
  3430  src/_vendor
  3431  *.md
  3432  dir
  3433  !dir/e*
  3434  !dir/dir/foo`,
  3435  	})
  3436  	if err != nil {
  3437  		c.Fatal(err)
  3438  	}
  3439  	defer ctx.Close()
  3440  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3441  		c.Fatal(err)
  3442  	}
  3443  }
  3444  
  3445  func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) {
  3446  	name := "testbuilddockerignoredockerfile"
  3447  	dockerfile := `
  3448          FROM busybox
  3449  		ADD . /tmp/
  3450  		RUN ! ls /tmp/Dockerfile
  3451  		RUN ls /tmp/.dockerignore`
  3452  	ctx, err := fakeContext(dockerfile, map[string]string{
  3453  		"Dockerfile":    dockerfile,
  3454  		".dockerignore": "Dockerfile\n",
  3455  	})
  3456  	if err != nil {
  3457  		c.Fatal(err)
  3458  	}
  3459  	defer ctx.Close()
  3460  
  3461  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3462  		c.Fatalf("Didn't ignore Dockerfile correctly:%s", err)
  3463  	}
  3464  
  3465  	// now try it with ./Dockerfile
  3466  	ctx.Add(".dockerignore", "./Dockerfile\n")
  3467  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3468  		c.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err)
  3469  	}
  3470  
  3471  }
  3472  
  3473  func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) {
  3474  	name := "testbuilddockerignoredockerfile"
  3475  	dockerfile := `
  3476          FROM busybox
  3477  		ADD . /tmp/
  3478  		RUN ls /tmp/Dockerfile
  3479  		RUN ! ls /tmp/MyDockerfile
  3480  		RUN ls /tmp/.dockerignore`
  3481  	ctx, err := fakeContext(dockerfile, map[string]string{
  3482  		"Dockerfile":    "Should not use me",
  3483  		"MyDockerfile":  dockerfile,
  3484  		".dockerignore": "MyDockerfile\n",
  3485  	})
  3486  	if err != nil {
  3487  		c.Fatal(err)
  3488  	}
  3489  	defer ctx.Close()
  3490  
  3491  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3492  		c.Fatalf("Didn't ignore MyDockerfile correctly:%s", err)
  3493  	}
  3494  
  3495  	// now try it with ./MyDockerfile
  3496  	ctx.Add(".dockerignore", "./MyDockerfile\n")
  3497  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3498  		c.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err)
  3499  	}
  3500  
  3501  }
  3502  
  3503  func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) {
  3504  	name := "testbuilddockerignoredockerignore"
  3505  	dockerfile := `
  3506          FROM busybox
  3507  		ADD . /tmp/
  3508  		RUN ! ls /tmp/.dockerignore
  3509  		RUN ls /tmp/Dockerfile`
  3510  	ctx, err := fakeContext(dockerfile, map[string]string{
  3511  		"Dockerfile":    dockerfile,
  3512  		".dockerignore": ".dockerignore\n",
  3513  	})
  3514  	defer ctx.Close()
  3515  	if err != nil {
  3516  		c.Fatal(err)
  3517  	}
  3518  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3519  		c.Fatalf("Didn't ignore .dockerignore correctly:%s", err)
  3520  	}
  3521  }
  3522  
  3523  func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) {
  3524  	var id1 string
  3525  	var id2 string
  3526  
  3527  	name := "testbuilddockerignoretouchdockerfile"
  3528  	dockerfile := `
  3529          FROM busybox
  3530  		ADD . /tmp/`
  3531  	ctx, err := fakeContext(dockerfile, map[string]string{
  3532  		"Dockerfile":    dockerfile,
  3533  		".dockerignore": "Dockerfile\n",
  3534  	})
  3535  	defer ctx.Close()
  3536  	if err != nil {
  3537  		c.Fatal(err)
  3538  	}
  3539  
  3540  	if id1, err = buildImageFromContext(name, ctx, true); err != nil {
  3541  		c.Fatalf("Didn't build it correctly:%s", err)
  3542  	}
  3543  
  3544  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3545  		c.Fatalf("Didn't build it correctly:%s", err)
  3546  	}
  3547  	if id1 != id2 {
  3548  		c.Fatalf("Didn't use the cache - 1")
  3549  	}
  3550  
  3551  	// Now make sure touching Dockerfile doesn't invalidate the cache
  3552  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3553  		c.Fatalf("Didn't add Dockerfile: %s", err)
  3554  	}
  3555  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3556  		c.Fatalf("Didn't build it correctly:%s", err)
  3557  	}
  3558  	if id1 != id2 {
  3559  		c.Fatalf("Didn't use the cache - 2")
  3560  	}
  3561  
  3562  	// One more time but just 'touch' it instead of changing the content
  3563  	if err = ctx.Add("Dockerfile", dockerfile+"\n# hi"); err != nil {
  3564  		c.Fatalf("Didn't add Dockerfile: %s", err)
  3565  	}
  3566  	if id2, err = buildImageFromContext(name, ctx, true); err != nil {
  3567  		c.Fatalf("Didn't build it correctly:%s", err)
  3568  	}
  3569  	if id1 != id2 {
  3570  		c.Fatalf("Didn't use the cache - 3")
  3571  	}
  3572  
  3573  }
  3574  
  3575  func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) {
  3576  	name := "testbuilddockerignorewholedir"
  3577  	dockerfile := `
  3578          FROM busybox
  3579  		COPY . /
  3580  		RUN [[ ! -e /.gitignore ]]
  3581  		RUN [[ -f /Makefile ]]`
  3582  	ctx, err := fakeContext(dockerfile, map[string]string{
  3583  		"Dockerfile":    "FROM scratch",
  3584  		"Makefile":      "all:",
  3585  		".gitignore":    "",
  3586  		".dockerignore": ".*\n",
  3587  	})
  3588  	c.Assert(err, check.IsNil)
  3589  	defer ctx.Close()
  3590  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3591  		c.Fatal(err)
  3592  	}
  3593  
  3594  	c.Assert(ctx.Add(".dockerfile", "*"), check.IsNil)
  3595  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3596  		c.Fatal(err)
  3597  	}
  3598  
  3599  	c.Assert(ctx.Add(".dockerfile", "."), check.IsNil)
  3600  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3601  		c.Fatal(err)
  3602  	}
  3603  
  3604  	c.Assert(ctx.Add(".dockerfile", "?"), check.IsNil)
  3605  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3606  		c.Fatal(err)
  3607  	}
  3608  }
  3609  
  3610  func (s *DockerSuite) TestBuildDockerignoringBadExclusion(c *check.C) {
  3611  	name := "testbuilddockerignorewholedir"
  3612  	dockerfile := `
  3613          FROM busybox
  3614  		COPY . /
  3615  		RUN [[ ! -e /.gitignore ]]
  3616  		RUN [[ -f /Makefile ]]`
  3617  	ctx, err := fakeContext(dockerfile, map[string]string{
  3618  		"Dockerfile":    "FROM scratch",
  3619  		"Makefile":      "all:",
  3620  		".gitignore":    "",
  3621  		".dockerignore": "!\n",
  3622  	})
  3623  	c.Assert(err, check.IsNil)
  3624  	defer ctx.Close()
  3625  	if _, err = buildImageFromContext(name, ctx, true); err == nil {
  3626  		c.Fatalf("Build was supposed to fail but didn't")
  3627  	}
  3628  
  3629  	if err.Error() != "failed to build the image: Error checking context: 'Illegal exclusion pattern: !'.\n" {
  3630  		c.Fatalf("Incorrect output, got:%q", err.Error())
  3631  	}
  3632  }
  3633  
  3634  func (s *DockerSuite) TestBuildLineBreak(c *check.C) {
  3635  	name := "testbuildlinebreak"
  3636  	_, err := buildImage(name,
  3637  		`FROM  busybox
  3638  RUN    sh -c 'echo root:testpass \
  3639  	> /tmp/passwd'
  3640  RUN    mkdir -p /var/run/sshd
  3641  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3642  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3643  		true)
  3644  	if err != nil {
  3645  		c.Fatal(err)
  3646  	}
  3647  }
  3648  
  3649  func (s *DockerSuite) TestBuildEOLInLine(c *check.C) {
  3650  	name := "testbuildeolinline"
  3651  	_, err := buildImage(name,
  3652  		`FROM   busybox
  3653  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  3654  RUN    echo "foo \n bar"; echo "baz"
  3655  RUN    mkdir -p /var/run/sshd
  3656  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3657  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3658  		true)
  3659  	if err != nil {
  3660  		c.Fatal(err)
  3661  	}
  3662  }
  3663  
  3664  func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) {
  3665  	name := "testbuildcomments"
  3666  	_, err := buildImage(name,
  3667  		`FROM busybox
  3668  # This is an ordinary comment.
  3669  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  3670  RUN [ ! -x /hello.sh ]
  3671  # comment with line break \
  3672  RUN chmod +x /hello.sh
  3673  RUN [ -x /hello.sh ]
  3674  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  3675  RUN [ "$(/hello.sh)" = "hello world" ]`,
  3676  		true)
  3677  	if err != nil {
  3678  		c.Fatal(err)
  3679  	}
  3680  }
  3681  
  3682  func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) {
  3683  	name := "testbuildusers"
  3684  	_, err := buildImage(name,
  3685  		`FROM busybox
  3686  
  3687  # Make sure our defaults work
  3688  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  3689  
  3690  # 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)
  3691  USER root
  3692  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  3693  
  3694  # Setup dockerio user and group
  3695  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  3696  RUN echo 'dockerio:x:1001:' >> /etc/group
  3697  
  3698  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  3699  USER dockerio
  3700  RUN id -G
  3701  RUN id -Gn
  3702  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3703  
  3704  # Switch back to root and double check that worked exactly as we might expect it to
  3705  USER root
  3706  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
  3707  
  3708  # Add a "supplementary" group for our dockerio user
  3709  RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
  3710  
  3711  # ... and then go verify that we get it like we expect
  3712  USER dockerio
  3713  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3714  USER 1001
  3715  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3716  
  3717  # super test the new "user:group" syntax
  3718  USER dockerio:dockerio
  3719  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3720  USER 1001:dockerio
  3721  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3722  USER dockerio:1001
  3723  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3724  USER 1001:1001
  3725  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3726  USER dockerio:supplementary
  3727  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3728  USER dockerio:1002
  3729  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3730  USER 1001:supplementary
  3731  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3732  USER 1001:1002
  3733  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3734  
  3735  # make sure unknown uid/gid still works properly
  3736  USER 1042:1043
  3737  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
  3738  		true)
  3739  	if err != nil {
  3740  		c.Fatal(err)
  3741  	}
  3742  }
  3743  
  3744  func (s *DockerSuite) TestBuildEnvUsage(c *check.C) {
  3745  	name := "testbuildenvusage"
  3746  	dockerfile := `FROM busybox
  3747  ENV    HOME /root
  3748  ENV    PATH $HOME/bin:$PATH
  3749  ENV    PATH /tmp:$PATH
  3750  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  3751  ENV    FOO /foo/baz
  3752  ENV    BAR /bar
  3753  ENV    BAZ $BAR
  3754  ENV    FOOPATH $PATH:$FOO
  3755  RUN    [ "$BAR" = "$BAZ" ]
  3756  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  3757  ENV	   FROM hello/docker/world
  3758  ENV    TO /docker/world/hello
  3759  ADD    $FROM $TO
  3760  RUN    [ "$(cat $TO)" = "hello" ]
  3761  ENV    abc=def
  3762  ENV    ghi=$abc
  3763  RUN    [ "$ghi" = "def" ]
  3764  `
  3765  	ctx, err := fakeContext(dockerfile, map[string]string{
  3766  		"hello/docker/world": "hello",
  3767  	})
  3768  	if err != nil {
  3769  		c.Fatal(err)
  3770  	}
  3771  	defer ctx.Close()
  3772  
  3773  	_, err = buildImageFromContext(name, ctx, true)
  3774  	if err != nil {
  3775  		c.Fatal(err)
  3776  	}
  3777  }
  3778  
  3779  func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) {
  3780  	name := "testbuildenvusage2"
  3781  	dockerfile := `FROM busybox
  3782  ENV    abc=def
  3783  RUN    [ "$abc" = "def" ]
  3784  ENV    def="hello world"
  3785  RUN    [ "$def" = "hello world" ]
  3786  ENV    def=hello\ world
  3787  RUN    [ "$def" = "hello world" ]
  3788  ENV    v1=abc v2="hi there"
  3789  RUN    [ "$v1" = "abc" ]
  3790  RUN    [ "$v2" = "hi there" ]
  3791  ENV    v3='boogie nights' v4="with'quotes too"
  3792  RUN    [ "$v3" = "boogie nights" ]
  3793  RUN    [ "$v4" = "with'quotes too" ]
  3794  ENV    abc=zzz FROM=hello/docker/world
  3795  ENV    abc=zzz TO=/docker/world/hello
  3796  ADD    $FROM $TO
  3797  RUN    [ "$(cat $TO)" = "hello" ]
  3798  ENV    abc "zzz"
  3799  RUN    [ $abc = "zzz" ]
  3800  ENV    abc 'yyy'
  3801  RUN    [ $abc = 'yyy' ]
  3802  ENV    abc=
  3803  RUN    [ "$abc" = "" ]
  3804  
  3805  # use grep to make sure if the builder substitutes \$foo by mistake
  3806  # we don't get a false positive
  3807  ENV    abc=\$foo
  3808  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  3809  ENV    abc \$foo
  3810  RUN    [ "$abc" = "\$foo" ] && (echo "$abc" | grep foo)
  3811  
  3812  ENV    abc=\'foo\'
  3813  RUN    [ "$abc" = "'foo'" ]
  3814  ENV    abc=\"foo\"
  3815  RUN    [ "$abc" = "\"foo\"" ]
  3816  ENV    abc "foo"
  3817  RUN    [ "$abc" = "foo" ]
  3818  ENV    abc 'foo'
  3819  RUN    [ "$abc" = 'foo' ]
  3820  ENV    abc \'foo\'
  3821  RUN    [ "$abc" = "'foo'" ]
  3822  ENV    abc \"foo\"
  3823  RUN    [ "$abc" = '"foo"' ]
  3824  
  3825  ENV    abc=ABC
  3826  RUN    [ "$abc" = "ABC" ]
  3827  ENV    def=${abc:-DEF}
  3828  RUN    [ "$def" = "ABC" ]
  3829  ENV    def=${ccc:-DEF}
  3830  RUN    [ "$def" = "DEF" ]
  3831  ENV    def=${ccc:-${def}xx}
  3832  RUN    [ "$def" = "DEFxx" ]
  3833  ENV    def=${def:+ALT}
  3834  RUN    [ "$def" = "ALT" ]
  3835  ENV    def=${def:+${abc}:}
  3836  RUN    [ "$def" = "ABC:" ]
  3837  ENV    def=${ccc:-\$abc:}
  3838  RUN    [ "$def" = '$abc:' ]
  3839  ENV    def=${ccc:-\${abc}:}
  3840  RUN    [ "$def" = '${abc:}' ]
  3841  ENV    mypath=${mypath:+$mypath:}/home
  3842  RUN    [ "$mypath" = '/home' ]
  3843  ENV    mypath=${mypath:+$mypath:}/away
  3844  RUN    [ "$mypath" = '/home:/away' ]
  3845  
  3846  ENV    e1=bar
  3847  ENV    e2=$e1
  3848  ENV    e3=$e11
  3849  ENV    e4=\$e1
  3850  ENV    e5=\$e11
  3851  RUN    [ "$e0,$e1,$e2,$e3,$e4,$e5" = ',bar,bar,,$e1,$e11' ]
  3852  
  3853  ENV    ee1 bar
  3854  ENV    ee2 $ee1
  3855  ENV    ee3 $ee11
  3856  ENV    ee4 \$ee1
  3857  ENV    ee5 \$ee11
  3858  RUN    [ "$ee1,$ee2,$ee3,$ee4,$ee5" = 'bar,bar,,$ee1,$ee11' ]
  3859  
  3860  ENV    eee1="foo"
  3861  ENV    eee2='foo'
  3862  ENV    eee3 "foo"
  3863  ENV    eee4 'foo'
  3864  RUN    [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ]
  3865  
  3866  `
  3867  	ctx, err := fakeContext(dockerfile, map[string]string{
  3868  		"hello/docker/world": "hello",
  3869  	})
  3870  	if err != nil {
  3871  		c.Fatal(err)
  3872  	}
  3873  	defer ctx.Close()
  3874  
  3875  	_, err = buildImageFromContext(name, ctx, true)
  3876  	if err != nil {
  3877  		c.Fatal(err)
  3878  	}
  3879  }
  3880  
  3881  func (s *DockerSuite) TestBuildAddScript(c *check.C) {
  3882  	name := "testbuildaddscript"
  3883  	dockerfile := `
  3884  FROM busybox
  3885  ADD test /test
  3886  RUN ["chmod","+x","/test"]
  3887  RUN ["/test"]
  3888  RUN [ "$(cat /testfile)" = 'test!' ]`
  3889  	ctx, err := fakeContext(dockerfile, map[string]string{
  3890  		"test": "#!/bin/sh\necho 'test!' > /testfile",
  3891  	})
  3892  	if err != nil {
  3893  		c.Fatal(err)
  3894  	}
  3895  	defer ctx.Close()
  3896  
  3897  	_, err = buildImageFromContext(name, ctx, true)
  3898  	if err != nil {
  3899  		c.Fatal(err)
  3900  	}
  3901  }
  3902  
  3903  func (s *DockerSuite) TestBuildAddTar(c *check.C) {
  3904  	name := "testbuildaddtar"
  3905  
  3906  	ctx := func() *FakeContext {
  3907  		dockerfile := `
  3908  FROM busybox
  3909  ADD test.tar /
  3910  RUN cat /test/foo | grep Hi
  3911  ADD test.tar /test.tar
  3912  RUN cat /test.tar/test/foo | grep Hi
  3913  ADD test.tar /unlikely-to-exist
  3914  RUN cat /unlikely-to-exist/test/foo | grep Hi
  3915  ADD test.tar /unlikely-to-exist-trailing-slash/
  3916  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  3917  RUN mkdir /existing-directory
  3918  ADD test.tar /existing-directory
  3919  RUN cat /existing-directory/test/foo | grep Hi
  3920  ADD test.tar /existing-directory-trailing-slash/
  3921  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  3922  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3923  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3924  		if err != nil {
  3925  			c.Fatalf("failed to create test.tar archive: %v", err)
  3926  		}
  3927  		defer testTar.Close()
  3928  
  3929  		tw := tar.NewWriter(testTar)
  3930  
  3931  		if err := tw.WriteHeader(&tar.Header{
  3932  			Name: "test/foo",
  3933  			Size: 2,
  3934  		}); err != nil {
  3935  			c.Fatalf("failed to write tar file header: %v", err)
  3936  		}
  3937  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3938  			c.Fatalf("failed to write tar file content: %v", err)
  3939  		}
  3940  		if err := tw.Close(); err != nil {
  3941  			c.Fatalf("failed to close tar archive: %v", err)
  3942  		}
  3943  
  3944  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3945  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3946  		}
  3947  		return fakeContextFromDir(tmpDir)
  3948  	}()
  3949  	defer ctx.Close()
  3950  
  3951  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3952  		c.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  3953  	}
  3954  
  3955  }
  3956  
  3957  func (s *DockerSuite) TestBuildAddTarXz(c *check.C) {
  3958  	name := "testbuildaddtarxz"
  3959  
  3960  	ctx := func() *FakeContext {
  3961  		dockerfile := `
  3962  			FROM busybox
  3963  			ADD test.tar.xz /
  3964  			RUN cat /test/foo | grep Hi`
  3965  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3966  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3967  		if err != nil {
  3968  			c.Fatalf("failed to create test.tar archive: %v", err)
  3969  		}
  3970  		defer testTar.Close()
  3971  
  3972  		tw := tar.NewWriter(testTar)
  3973  
  3974  		if err := tw.WriteHeader(&tar.Header{
  3975  			Name: "test/foo",
  3976  			Size: 2,
  3977  		}); err != nil {
  3978  			c.Fatalf("failed to write tar file header: %v", err)
  3979  		}
  3980  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3981  			c.Fatalf("failed to write tar file content: %v", err)
  3982  		}
  3983  		if err := tw.Close(); err != nil {
  3984  			c.Fatalf("failed to close tar archive: %v", err)
  3985  		}
  3986  
  3987  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  3988  		xzCompressCmd.Dir = tmpDir
  3989  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3990  		if err != nil {
  3991  			c.Fatal(err, out)
  3992  		}
  3993  
  3994  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3995  			c.Fatalf("failed to open destination dockerfile: %v", err)
  3996  		}
  3997  		return fakeContextFromDir(tmpDir)
  3998  	}()
  3999  
  4000  	defer ctx.Close()
  4001  
  4002  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4003  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4004  	}
  4005  
  4006  }
  4007  
  4008  func (s *DockerSuite) TestBuildAddTarXzGz(c *check.C) {
  4009  	name := "testbuildaddtarxzgz"
  4010  
  4011  	ctx := func() *FakeContext {
  4012  		dockerfile := `
  4013  			FROM busybox
  4014  			ADD test.tar.xz.gz /
  4015  			RUN ls /test.tar.xz.gz`
  4016  		tmpDir, err := ioutil.TempDir("", "fake-context")
  4017  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  4018  		if err != nil {
  4019  			c.Fatalf("failed to create test.tar archive: %v", err)
  4020  		}
  4021  		defer testTar.Close()
  4022  
  4023  		tw := tar.NewWriter(testTar)
  4024  
  4025  		if err := tw.WriteHeader(&tar.Header{
  4026  			Name: "test/foo",
  4027  			Size: 2,
  4028  		}); err != nil {
  4029  			c.Fatalf("failed to write tar file header: %v", err)
  4030  		}
  4031  		if _, err := tw.Write([]byte("Hi")); err != nil {
  4032  			c.Fatalf("failed to write tar file content: %v", err)
  4033  		}
  4034  		if err := tw.Close(); err != nil {
  4035  			c.Fatalf("failed to close tar archive: %v", err)
  4036  		}
  4037  
  4038  		xzCompressCmd := exec.Command("xz", "-k", "test.tar")
  4039  		xzCompressCmd.Dir = tmpDir
  4040  		out, _, err := runCommandWithOutput(xzCompressCmd)
  4041  		if err != nil {
  4042  			c.Fatal(err, out)
  4043  		}
  4044  
  4045  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  4046  		gzipCompressCmd.Dir = tmpDir
  4047  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  4048  		if err != nil {
  4049  			c.Fatal(err, out)
  4050  		}
  4051  
  4052  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  4053  			c.Fatalf("failed to open destination dockerfile: %v", err)
  4054  		}
  4055  		return fakeContextFromDir(tmpDir)
  4056  	}()
  4057  
  4058  	defer ctx.Close()
  4059  
  4060  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4061  		c.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  4062  	}
  4063  
  4064  }
  4065  
  4066  func (s *DockerSuite) TestBuildFromGIT(c *check.C) {
  4067  	name := "testbuildfromgit"
  4068  	git, err := newFakeGit("repo", map[string]string{
  4069  		"Dockerfile": `FROM busybox
  4070  					ADD first /first
  4071  					RUN [ -f /first ]
  4072  					MAINTAINER docker`,
  4073  		"first": "test git data",
  4074  	}, true)
  4075  	if err != nil {
  4076  		c.Fatal(err)
  4077  	}
  4078  	defer git.Close()
  4079  
  4080  	_, err = buildImageFromPath(name, git.RepoURL, true)
  4081  	if err != nil {
  4082  		c.Fatal(err)
  4083  	}
  4084  	res, err := inspectField(name, "Author")
  4085  	if err != nil {
  4086  		c.Fatal(err)
  4087  	}
  4088  	if res != "docker" {
  4089  		c.Fatalf("Maintainer should be docker, got %s", res)
  4090  	}
  4091  }
  4092  
  4093  func (s *DockerSuite) TestBuildFromGITWithContext(c *check.C) {
  4094  	name := "testbuildfromgit"
  4095  	git, err := newFakeGit("repo", map[string]string{
  4096  		"docker/Dockerfile": `FROM busybox
  4097  					ADD first /first
  4098  					RUN [ -f /first ]
  4099  					MAINTAINER docker`,
  4100  		"docker/first": "test git data",
  4101  	}, true)
  4102  	if err != nil {
  4103  		c.Fatal(err)
  4104  	}
  4105  	defer git.Close()
  4106  
  4107  	u := fmt.Sprintf("%s#master:docker", git.RepoURL)
  4108  	_, err = buildImageFromPath(name, u, true)
  4109  	if err != nil {
  4110  		c.Fatal(err)
  4111  	}
  4112  	res, err := inspectField(name, "Author")
  4113  	if err != nil {
  4114  		c.Fatal(err)
  4115  	}
  4116  	if res != "docker" {
  4117  		c.Fatalf("Maintainer should be docker, got %s", res)
  4118  	}
  4119  }
  4120  
  4121  func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) {
  4122  	name := "testbuildfromremotetarball"
  4123  
  4124  	buffer := new(bytes.Buffer)
  4125  	tw := tar.NewWriter(buffer)
  4126  	defer tw.Close()
  4127  
  4128  	dockerfile := []byte(`FROM busybox
  4129  					MAINTAINER docker`)
  4130  	if err := tw.WriteHeader(&tar.Header{
  4131  		Name: "Dockerfile",
  4132  		Size: int64(len(dockerfile)),
  4133  	}); err != nil {
  4134  		c.Fatalf("failed to write tar file header: %v", err)
  4135  	}
  4136  	if _, err := tw.Write(dockerfile); err != nil {
  4137  		c.Fatalf("failed to write tar file content: %v", err)
  4138  	}
  4139  	if err := tw.Close(); err != nil {
  4140  		c.Fatalf("failed to close tar archive: %v", err)
  4141  	}
  4142  
  4143  	server, err := fakeBinaryStorage(map[string]*bytes.Buffer{
  4144  		"testT.tar": buffer,
  4145  	})
  4146  	c.Assert(err, check.IsNil)
  4147  
  4148  	defer server.Close()
  4149  
  4150  	_, err = buildImageFromPath(name, server.URL()+"/testT.tar", true)
  4151  	c.Assert(err, check.IsNil)
  4152  
  4153  	res, err := inspectField(name, "Author")
  4154  	c.Assert(err, check.IsNil)
  4155  
  4156  	if res != "docker" {
  4157  		c.Fatalf("Maintainer should be docker, got %s", res)
  4158  	}
  4159  }
  4160  
  4161  func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) {
  4162  	name := "testbuildcmdcleanuponentrypoint"
  4163  	if _, err := buildImage(name,
  4164  		`FROM scratch
  4165          CMD ["test"]
  4166  		ENTRYPOINT ["echo"]`,
  4167  		true); err != nil {
  4168  		c.Fatal(err)
  4169  	}
  4170  	if _, err := buildImage(name,
  4171  		fmt.Sprintf(`FROM %s
  4172  		ENTRYPOINT ["cat"]`, name),
  4173  		true); err != nil {
  4174  		c.Fatal(err)
  4175  	}
  4176  	res, err := inspectField(name, "Config.Cmd")
  4177  	if err != nil {
  4178  		c.Fatal(err)
  4179  	}
  4180  	if res != "<nil>" {
  4181  		c.Fatalf("Cmd %s, expected nil", res)
  4182  	}
  4183  
  4184  	res, err = inspectField(name, "Config.Entrypoint")
  4185  	if err != nil {
  4186  		c.Fatal(err)
  4187  	}
  4188  	if expected := "{[cat]}"; res != expected {
  4189  		c.Fatalf("Entrypoint %s, expected %s", res, expected)
  4190  	}
  4191  }
  4192  
  4193  func (s *DockerSuite) TestBuildClearCmd(c *check.C) {
  4194  	name := "testbuildclearcmd"
  4195  	_, err := buildImage(name,
  4196  		`From scratch
  4197     ENTRYPOINT ["/bin/bash"]
  4198     CMD []`,
  4199  		true)
  4200  	if err != nil {
  4201  		c.Fatal(err)
  4202  	}
  4203  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4204  	if err != nil {
  4205  		c.Fatal(err)
  4206  	}
  4207  	if res != "[]" {
  4208  		c.Fatalf("Cmd %s, expected %s", res, "[]")
  4209  	}
  4210  }
  4211  
  4212  func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) {
  4213  	name := "testbuildemptycmd"
  4214  	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
  4215  		c.Fatal(err)
  4216  	}
  4217  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4218  	if err != nil {
  4219  		c.Fatal(err)
  4220  	}
  4221  	if res != "null" {
  4222  		c.Fatalf("Cmd %s, expected %s", res, "null")
  4223  	}
  4224  }
  4225  
  4226  func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) {
  4227  	name := "testbuildonbuildparent"
  4228  	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
  4229  		c.Fatal(err)
  4230  	}
  4231  
  4232  	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
  4233  	if err != nil {
  4234  		c.Fatal(err)
  4235  	}
  4236  
  4237  	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
  4238  		c.Fatal("failed to find the ONBUILD output", out)
  4239  	}
  4240  
  4241  }
  4242  
  4243  func (s *DockerSuite) TestBuildInvalidTag(c *check.C) {
  4244  	name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200)
  4245  	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
  4246  	// if the error doesnt check for illegal tag name, or the image is built
  4247  	// then this should fail
  4248  	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
  4249  		c.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
  4250  	}
  4251  }
  4252  
  4253  func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) {
  4254  	name := "testbuildcmdshc"
  4255  	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
  4256  		c.Fatal(err)
  4257  	}
  4258  
  4259  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4260  	if err != nil {
  4261  		c.Fatal(err, res)
  4262  	}
  4263  
  4264  	expected := `["/bin/sh","-c","echo cmd"]`
  4265  
  4266  	if res != expected {
  4267  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4268  	}
  4269  
  4270  }
  4271  
  4272  func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) {
  4273  	// Test to make sure that when we strcat arrays we take into account
  4274  	// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
  4275  	// look the same
  4276  	name := "testbuildcmdspaces"
  4277  	var id1 string
  4278  	var id2 string
  4279  	var err error
  4280  
  4281  	if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil {
  4282  		c.Fatal(err)
  4283  	}
  4284  
  4285  	if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil {
  4286  		c.Fatal(err)
  4287  	}
  4288  
  4289  	if id1 == id2 {
  4290  		c.Fatal("Should not have resulted in the same CMD")
  4291  	}
  4292  
  4293  	// Now do the same with ENTRYPOINT
  4294  	if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil {
  4295  		c.Fatal(err)
  4296  	}
  4297  
  4298  	if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil {
  4299  		c.Fatal(err)
  4300  	}
  4301  
  4302  	if id1 == id2 {
  4303  		c.Fatal("Should not have resulted in the same ENTRYPOINT")
  4304  	}
  4305  
  4306  }
  4307  
  4308  func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) {
  4309  	name := "testbuildcmdjson"
  4310  	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
  4311  		c.Fatal(err)
  4312  	}
  4313  
  4314  	res, err := inspectFieldJSON(name, "Config.Cmd")
  4315  	if err != nil {
  4316  		c.Fatal(err, res)
  4317  	}
  4318  
  4319  	expected := `["echo","cmd"]`
  4320  
  4321  	if res != expected {
  4322  		c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  4323  	}
  4324  
  4325  }
  4326  
  4327  func (s *DockerSuite) TestBuildErrorInvalidInstruction(c *check.C) {
  4328  	name := "testbuildignoreinvalidinstruction"
  4329  
  4330  	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
  4331  	if err == nil {
  4332  		c.Fatalf("Should have failed: %s", out)
  4333  	}
  4334  
  4335  }
  4336  
  4337  func (s *DockerSuite) TestBuildEntrypointInheritance(c *check.C) {
  4338  
  4339  	if _, err := buildImage("parent", `
  4340      FROM busybox
  4341      ENTRYPOINT exit 130
  4342      `, true); err != nil {
  4343  		c.Fatal(err)
  4344  	}
  4345  
  4346  	if _, status, _ := dockerCmdWithError(c, "run", "parent"); status != 130 {
  4347  		c.Fatalf("expected exit code 130 but received %d", status)
  4348  	}
  4349  
  4350  	if _, err := buildImage("child", `
  4351      FROM parent
  4352      ENTRYPOINT exit 5
  4353      `, true); err != nil {
  4354  		c.Fatal(err)
  4355  	}
  4356  
  4357  	if _, status, _ := dockerCmdWithError(c, "run", "child"); status != 5 {
  4358  		c.Fatalf("expected exit code 5 but received %d", status)
  4359  	}
  4360  
  4361  }
  4362  
  4363  func (s *DockerSuite) TestBuildEntrypointInheritanceInspect(c *check.C) {
  4364  	var (
  4365  		name     = "testbuildepinherit"
  4366  		name2    = "testbuildepinherit2"
  4367  		expected = `["/bin/sh","-c","echo quux"]`
  4368  	)
  4369  
  4370  	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
  4371  		c.Fatal(err)
  4372  	}
  4373  
  4374  	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
  4375  		c.Fatal(err)
  4376  	}
  4377  
  4378  	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
  4379  	if err != nil {
  4380  		c.Fatal(err, res)
  4381  	}
  4382  
  4383  	if res != expected {
  4384  		c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  4385  	}
  4386  
  4387  	out, _ := dockerCmd(c, "run", "-t", name2)
  4388  
  4389  	expected = "quux"
  4390  
  4391  	if strings.TrimSpace(out) != expected {
  4392  		c.Fatalf("Expected output is %s, got %s", expected, out)
  4393  	}
  4394  
  4395  }
  4396  
  4397  func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) {
  4398  	name := "testbuildentrypoint"
  4399  	_, err := buildImage(name,
  4400  		`FROM busybox
  4401                                  ENTRYPOINT /bin/echo`,
  4402  		true)
  4403  	if err != nil {
  4404  		c.Fatal(err)
  4405  	}
  4406  
  4407  	dockerCmd(c, "run", "--rm", name)
  4408  }
  4409  
  4410  func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) {
  4411  	name := "testbuildexoticshellinterpolation"
  4412  
  4413  	_, err := buildImage(name, `
  4414  		FROM busybox
  4415  
  4416  		ENV SOME_VAR a.b.c
  4417  
  4418  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  4419  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  4420  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  4421  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  4422  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  4423  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  4424  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  4425  		RUN [ "${#SOME_VAR}"    = '5'     ]
  4426  
  4427  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  4428  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  4429  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  4430  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  4431  	`, false)
  4432  	if err != nil {
  4433  		c.Fatal(err)
  4434  	}
  4435  
  4436  }
  4437  
  4438  func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) {
  4439  	// This testcase is supposed to generate an error because the
  4440  	// JSON array we're passing in on the CMD uses single quotes instead
  4441  	// of double quotes (per the JSON spec). This means we interpret it
  4442  	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
  4443  	// it should barf on it.
  4444  	name := "testbuildsinglequotefails"
  4445  
  4446  	if _, err := buildImage(name,
  4447  		`FROM busybox
  4448  		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
  4449  		true); err != nil {
  4450  		c.Fatal(err)
  4451  	}
  4452  
  4453  	if _, _, err := dockerCmdWithError(c, "run", "--rm", name); err == nil {
  4454  		c.Fatal("The image was not supposed to be able to run")
  4455  	}
  4456  
  4457  }
  4458  
  4459  func (s *DockerSuite) TestBuildVerboseOut(c *check.C) {
  4460  	name := "testbuildverboseout"
  4461  
  4462  	_, out, err := buildImageWithOut(name,
  4463  		`FROM busybox
  4464  RUN echo 123`,
  4465  		false)
  4466  
  4467  	if err != nil {
  4468  		c.Fatal(err)
  4469  	}
  4470  	if !strings.Contains(out, "\n123\n") {
  4471  		c.Fatalf("Output should contain %q: %q", "123", out)
  4472  	}
  4473  
  4474  }
  4475  
  4476  func (s *DockerSuite) TestBuildWithTabs(c *check.C) {
  4477  	name := "testbuildwithtabs"
  4478  	_, err := buildImage(name,
  4479  		"FROM busybox\nRUN echo\tone\t\ttwo", true)
  4480  	if err != nil {
  4481  		c.Fatal(err)
  4482  	}
  4483  	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
  4484  	if err != nil {
  4485  		c.Fatal(err)
  4486  	}
  4487  	expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]`
  4488  	expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates
  4489  	if res != expected1 && res != expected2 {
  4490  		c.Fatalf("Missing tabs.\nGot: %s\nExp: %s or %s", res, expected1, expected2)
  4491  	}
  4492  }
  4493  
  4494  func (s *DockerSuite) TestBuildLabels(c *check.C) {
  4495  	name := "testbuildlabel"
  4496  	expected := `{"License":"GPL","Vendor":"Acme"}`
  4497  	_, err := buildImage(name,
  4498  		`FROM busybox
  4499  		LABEL Vendor=Acme
  4500                  LABEL License GPL`,
  4501  		true)
  4502  	if err != nil {
  4503  		c.Fatal(err)
  4504  	}
  4505  	res, err := inspectFieldJSON(name, "Config.Labels")
  4506  	if err != nil {
  4507  		c.Fatal(err)
  4508  	}
  4509  	if res != expected {
  4510  		c.Fatalf("Labels %s, expected %s", res, expected)
  4511  	}
  4512  }
  4513  
  4514  func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
  4515  	name := "testbuildlabelcache"
  4516  
  4517  	id1, err := buildImage(name,
  4518  		`FROM busybox
  4519  		LABEL Vendor=Acme`, false)
  4520  	if err != nil {
  4521  		c.Fatalf("Build 1 should have worked: %v", err)
  4522  	}
  4523  
  4524  	id2, err := buildImage(name,
  4525  		`FROM busybox
  4526  		LABEL Vendor=Acme`, true)
  4527  	if err != nil || id1 != id2 {
  4528  		c.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4529  	}
  4530  
  4531  	id2, err = buildImage(name,
  4532  		`FROM busybox
  4533  		LABEL Vendor=Acme1`, true)
  4534  	if err != nil || id1 == id2 {
  4535  		c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err)
  4536  	}
  4537  
  4538  	id2, err = buildImage(name,
  4539  		`FROM busybox
  4540  		LABEL Vendor Acme`, true) // Note: " " and "=" should be same
  4541  	if err != nil || id1 != id2 {
  4542  		c.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err)
  4543  	}
  4544  
  4545  	// Now make sure the cache isn't used by mistake
  4546  	id1, err = buildImage(name,
  4547  		`FROM busybox
  4548         LABEL f1=b1 f2=b2`, false)
  4549  	if err != nil {
  4550  		c.Fatalf("Build 5 should have worked: %q", err)
  4551  	}
  4552  
  4553  	id2, err = buildImage(name,
  4554  		`FROM busybox
  4555         LABEL f1="b1 f2=b2"`, true)
  4556  	if err != nil || id1 == id2 {
  4557  		c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err)
  4558  	}
  4559  
  4560  }
  4561  
  4562  func (s *DockerSuite) TestBuildStderr(c *check.C) {
  4563  	// This test just makes sure that no non-error output goes
  4564  	// to stderr
  4565  	name := "testbuildstderr"
  4566  	_, _, stderr, err := buildImageWithStdoutStderr(name,
  4567  		"FROM busybox\nRUN echo one", true)
  4568  	if err != nil {
  4569  		c.Fatal(err)
  4570  	}
  4571  
  4572  	if runtime.GOOS == "windows" {
  4573  		// stderr might contain a security warning on windows
  4574  		lines := strings.Split(stderr, "\n")
  4575  		for _, v := range lines {
  4576  			if v != "" && !strings.Contains(v, "SECURITY WARNING:") {
  4577  				c.Fatalf("Stderr contains unexpected output line: %q", v)
  4578  			}
  4579  		}
  4580  	} else {
  4581  		if stderr != "" {
  4582  			c.Fatalf("Stderr should have been empty, instead its: %q", stderr)
  4583  		}
  4584  	}
  4585  }
  4586  
  4587  func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) {
  4588  	testRequires(c, UnixCli) // test uses chown: not available on windows
  4589  
  4590  	name := "testbuildchownsinglefile"
  4591  
  4592  	ctx, err := fakeContext(`
  4593  FROM busybox
  4594  COPY test /
  4595  RUN ls -l /test
  4596  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  4597  `, map[string]string{
  4598  		"test": "test",
  4599  	})
  4600  	if err != nil {
  4601  		c.Fatal(err)
  4602  	}
  4603  	defer ctx.Close()
  4604  
  4605  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  4606  		c.Fatal(err)
  4607  	}
  4608  
  4609  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4610  		c.Fatal(err)
  4611  	}
  4612  
  4613  }
  4614  
  4615  func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) {
  4616  	name := "testbuildsymlinkbreakout"
  4617  	tmpdir, err := ioutil.TempDir("", name)
  4618  	if err != nil {
  4619  		c.Fatal(err)
  4620  	}
  4621  	defer os.RemoveAll(tmpdir)
  4622  	ctx := filepath.Join(tmpdir, "context")
  4623  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4624  		c.Fatal(err)
  4625  	}
  4626  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  4627  	from busybox
  4628  	add symlink.tar /
  4629  	add inject /symlink/
  4630  	`), 0644); err != nil {
  4631  		c.Fatal(err)
  4632  	}
  4633  	inject := filepath.Join(ctx, "inject")
  4634  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  4635  		c.Fatal(err)
  4636  	}
  4637  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  4638  	if err != nil {
  4639  		c.Fatal(err)
  4640  	}
  4641  	w := tar.NewWriter(f)
  4642  	w.WriteHeader(&tar.Header{
  4643  		Name:     "symlink2",
  4644  		Typeflag: tar.TypeSymlink,
  4645  		Linkname: "/../../../../../../../../../../../../../../",
  4646  		Uid:      os.Getuid(),
  4647  		Gid:      os.Getgid(),
  4648  	})
  4649  	w.WriteHeader(&tar.Header{
  4650  		Name:     "symlink",
  4651  		Typeflag: tar.TypeSymlink,
  4652  		Linkname: filepath.Join("symlink2", tmpdir),
  4653  		Uid:      os.Getuid(),
  4654  		Gid:      os.Getgid(),
  4655  	})
  4656  	w.Close()
  4657  	f.Close()
  4658  	if _, err := buildImageFromContext(name, fakeContextFromDir(ctx), false); err != nil {
  4659  		c.Fatal(err)
  4660  	}
  4661  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  4662  		c.Fatal("symlink breakout - inject")
  4663  	} else if !os.IsNotExist(err) {
  4664  		c.Fatalf("unexpected error: %v", err)
  4665  	}
  4666  }
  4667  
  4668  func (s *DockerSuite) TestBuildXZHost(c *check.C) {
  4669  	name := "testbuildxzhost"
  4670  
  4671  	ctx, err := fakeContext(`
  4672  FROM busybox
  4673  ADD xz /usr/local/sbin/
  4674  RUN chmod 755 /usr/local/sbin/xz
  4675  ADD test.xz /
  4676  RUN [ ! -e /injected ]`,
  4677  		map[string]string{
  4678  			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
  4679  				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
  4680  				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
  4681  			"xz": "#!/bin/sh\ntouch /injected",
  4682  		})
  4683  
  4684  	if err != nil {
  4685  		c.Fatal(err)
  4686  	}
  4687  	defer ctx.Close()
  4688  
  4689  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  4690  		c.Fatal(err)
  4691  	}
  4692  
  4693  }
  4694  
  4695  func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) {
  4696  	var (
  4697  		name     = "testbuildvolumescontent"
  4698  		expected = "some text"
  4699  	)
  4700  	ctx, err := fakeContext(`
  4701  FROM busybox
  4702  COPY content /foo/file
  4703  VOLUME /foo
  4704  CMD cat /foo/file`,
  4705  		map[string]string{
  4706  			"content": expected,
  4707  		})
  4708  	if err != nil {
  4709  		c.Fatal(err)
  4710  	}
  4711  	defer ctx.Close()
  4712  
  4713  	if _, err := buildImageFromContext(name, ctx, false); err != nil {
  4714  		c.Fatal(err)
  4715  	}
  4716  
  4717  	out, _ := dockerCmd(c, "run", "--rm", name)
  4718  	if out != expected {
  4719  		c.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  4720  	}
  4721  
  4722  }
  4723  
  4724  func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) {
  4725  
  4726  	ctx, err := fakeContext(`FROM busybox
  4727  	RUN echo from Dockerfile`,
  4728  		map[string]string{
  4729  			"Dockerfile":       "FROM busybox\nRUN echo from Dockerfile",
  4730  			"files/Dockerfile": "FROM busybox\nRUN echo from files/Dockerfile",
  4731  			"files/dFile":      "FROM busybox\nRUN echo from files/dFile",
  4732  			"dFile":            "FROM busybox\nRUN echo from dFile",
  4733  			"files/dFile2":     "FROM busybox\nRUN echo from files/dFile2",
  4734  		})
  4735  	defer ctx.Close()
  4736  	if err != nil {
  4737  		c.Fatal(err)
  4738  	}
  4739  
  4740  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4741  	if err != nil {
  4742  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4743  	}
  4744  	if !strings.Contains(out, "from Dockerfile") {
  4745  		c.Fatalf("test1 should have used Dockerfile, output:%s", out)
  4746  	}
  4747  
  4748  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-f", filepath.Join("files", "Dockerfile"), "-t", "test2", ".")
  4749  	if err != nil {
  4750  		c.Fatal(err)
  4751  	}
  4752  	if !strings.Contains(out, "from files/Dockerfile") {
  4753  		c.Fatalf("test2 should have used files/Dockerfile, output:%s", out)
  4754  	}
  4755  
  4756  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", filepath.Join("files", "dFile")), "-t", "test3", ".")
  4757  	if err != nil {
  4758  		c.Fatal(err)
  4759  	}
  4760  	if !strings.Contains(out, "from files/dFile") {
  4761  		c.Fatalf("test3 should have used files/dFile, output:%s", out)
  4762  	}
  4763  
  4764  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--file=dFile", "-t", "test4", ".")
  4765  	if err != nil {
  4766  		c.Fatal(err)
  4767  	}
  4768  	if !strings.Contains(out, "from dFile") {
  4769  		c.Fatalf("test4 should have used dFile, output:%s", out)
  4770  	}
  4771  
  4772  	dirWithNoDockerfile, _ := ioutil.TempDir(os.TempDir(), "test5")
  4773  	nonDockerfileFile := filepath.Join(dirWithNoDockerfile, "notDockerfile")
  4774  	if _, err = os.Create(nonDockerfileFile); err != nil {
  4775  		c.Fatal(err)
  4776  	}
  4777  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", fmt.Sprintf("--file=%s", nonDockerfileFile), "-t", "test5", ".")
  4778  
  4779  	if err == nil {
  4780  		c.Fatalf("test5 was supposed to fail to find passwd")
  4781  	}
  4782  
  4783  	if expected := fmt.Sprintf("The Dockerfile (%s) must be within the build context (.)", nonDockerfileFile); !strings.Contains(out, expected) {
  4784  		c.Fatalf("wrong error messsage:%v\nexpected to contain=%v", out, expected)
  4785  	}
  4786  
  4787  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test6", "..")
  4788  	if err != nil {
  4789  		c.Fatalf("test6 failed: %s", err)
  4790  	}
  4791  	if !strings.Contains(out, "from Dockerfile") {
  4792  		c.Fatalf("test6 should have used root Dockerfile, output:%s", out)
  4793  	}
  4794  
  4795  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join(ctx.Dir, "files", "Dockerfile"), "-t", "test7", "..")
  4796  	if err != nil {
  4797  		c.Fatalf("test7 failed: %s", err)
  4798  	}
  4799  	if !strings.Contains(out, "from files/Dockerfile") {
  4800  		c.Fatalf("test7 should have used files Dockerfile, output:%s", out)
  4801  	}
  4802  
  4803  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", filepath.Join("..", "Dockerfile"), "-t", "test8", ".")
  4804  	if err == nil || !strings.Contains(out, "must be within the build context") {
  4805  		c.Fatalf("test8 should have failed with Dockerfile out of context: %s", err)
  4806  	}
  4807  
  4808  	tmpDir := os.TempDir()
  4809  	out, _, err = dockerCmdInDir(c, tmpDir, "build", "-t", "test9", ctx.Dir)
  4810  	if err != nil {
  4811  		c.Fatalf("test9 - failed: %s", err)
  4812  	}
  4813  	if !strings.Contains(out, "from Dockerfile") {
  4814  		c.Fatalf("test9 should have used root Dockerfile, output:%s", out)
  4815  	}
  4816  
  4817  	out, _, err = dockerCmdInDir(c, filepath.Join(ctx.Dir, "files"), "build", "-f", "dFile2", "-t", "test10", ".")
  4818  	if err != nil {
  4819  		c.Fatalf("test10 should have worked: %s", err)
  4820  	}
  4821  	if !strings.Contains(out, "from files/dFile2") {
  4822  		c.Fatalf("test10 should have used files/dFile2, output:%s", out)
  4823  	}
  4824  
  4825  }
  4826  
  4827  func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) {
  4828  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  4829  
  4830  	ctx, err := fakeContext(`FROM busybox
  4831  	RUN echo from dockerfile`,
  4832  		map[string]string{
  4833  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  4834  		})
  4835  	defer ctx.Close()
  4836  	if err != nil {
  4837  		c.Fatal(err)
  4838  	}
  4839  
  4840  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4841  	if err != nil {
  4842  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4843  	}
  4844  
  4845  	if !strings.Contains(out, "from dockerfile") {
  4846  		c.Fatalf("Missing proper output: %s", out)
  4847  	}
  4848  
  4849  }
  4850  
  4851  func (s *DockerSuite) TestBuildWithTwoDockerfiles(c *check.C) {
  4852  	testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows
  4853  
  4854  	ctx, err := fakeContext(`FROM busybox
  4855  RUN echo from Dockerfile`,
  4856  		map[string]string{
  4857  			"dockerfile": "FROM busybox\nRUN echo from dockerfile",
  4858  		})
  4859  	defer ctx.Close()
  4860  	if err != nil {
  4861  		c.Fatal(err)
  4862  	}
  4863  
  4864  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".")
  4865  	if err != nil {
  4866  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4867  	}
  4868  
  4869  	if !strings.Contains(out, "from Dockerfile") {
  4870  		c.Fatalf("Missing proper output: %s", out)
  4871  	}
  4872  
  4873  }
  4874  
  4875  func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) {
  4876  
  4877  	server, err := fakeStorage(map[string]string{"baz": `FROM busybox
  4878  RUN echo from baz
  4879  COPY * /tmp/
  4880  RUN find /tmp/`})
  4881  	if err != nil {
  4882  		c.Fatal(err)
  4883  	}
  4884  	defer server.Close()
  4885  
  4886  	ctx, err := fakeContext(`FROM busybox
  4887  RUN echo from Dockerfile`,
  4888  		map[string]string{})
  4889  	defer ctx.Close()
  4890  	if err != nil {
  4891  		c.Fatal(err)
  4892  	}
  4893  
  4894  	// Make sure that -f is ignored and that we don't use the Dockerfile
  4895  	// that's in the current dir
  4896  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz")
  4897  	if err != nil {
  4898  		c.Fatalf("Failed to build: %s\n%s", out, err)
  4899  	}
  4900  
  4901  	if !strings.Contains(out, "from baz") ||
  4902  		strings.Contains(out, "/tmp/baz") ||
  4903  		!strings.Contains(out, "/tmp/Dockerfile") {
  4904  		c.Fatalf("Missing proper output: %s", out)
  4905  	}
  4906  
  4907  }
  4908  
  4909  func (s *DockerSuite) TestBuildFromStdinWithF(c *check.C) {
  4910  
  4911  	ctx, err := fakeContext(`FROM busybox
  4912  RUN echo from Dockerfile`,
  4913  		map[string]string{})
  4914  	defer ctx.Close()
  4915  	if err != nil {
  4916  		c.Fatal(err)
  4917  	}
  4918  
  4919  	// Make sure that -f is ignored and that we don't use the Dockerfile
  4920  	// that's in the current dir
  4921  	dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-")
  4922  	dockerCommand.Dir = ctx.Dir
  4923  	dockerCommand.Stdin = strings.NewReader(`FROM busybox
  4924  RUN echo from baz
  4925  COPY * /tmp/
  4926  RUN find /tmp/`)
  4927  	out, status, err := runCommandWithOutput(dockerCommand)
  4928  	if err != nil || status != 0 {
  4929  		c.Fatalf("Error building: %s", err)
  4930  	}
  4931  
  4932  	if !strings.Contains(out, "from baz") ||
  4933  		strings.Contains(out, "/tmp/baz") ||
  4934  		!strings.Contains(out, "/tmp/Dockerfile") {
  4935  		c.Fatalf("Missing proper output: %s", out)
  4936  	}
  4937  
  4938  }
  4939  
  4940  func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) {
  4941  	name := "testbuildfromofficial"
  4942  	fromNames := []string{
  4943  		"busybox",
  4944  		"docker.io/busybox",
  4945  		"index.docker.io/busybox",
  4946  		"library/busybox",
  4947  		"docker.io/library/busybox",
  4948  		"index.docker.io/library/busybox",
  4949  	}
  4950  	for idx, fromName := range fromNames {
  4951  		imgName := fmt.Sprintf("%s%d", name, idx)
  4952  		_, err := buildImage(imgName, "FROM "+fromName, true)
  4953  		if err != nil {
  4954  			c.Errorf("Build failed using FROM %s: %s", fromName, err)
  4955  		}
  4956  		deleteImages(imgName)
  4957  	}
  4958  }
  4959  
  4960  func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) {
  4961  	testRequires(c, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2)
  4962  
  4963  	name := "testbuilddockerfileoutsidecontext"
  4964  	tmpdir, err := ioutil.TempDir("", name)
  4965  	if err != nil {
  4966  		c.Fatal(err)
  4967  	}
  4968  	defer os.RemoveAll(tmpdir)
  4969  	ctx := filepath.Join(tmpdir, "context")
  4970  	if err := os.MkdirAll(ctx, 0755); err != nil {
  4971  		c.Fatal(err)
  4972  	}
  4973  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM scratch\nENV X Y"), 0644); err != nil {
  4974  		c.Fatal(err)
  4975  	}
  4976  	wd, err := os.Getwd()
  4977  	if err != nil {
  4978  		c.Fatal(err)
  4979  	}
  4980  	defer os.Chdir(wd)
  4981  	if err := os.Chdir(ctx); err != nil {
  4982  		c.Fatal(err)
  4983  	}
  4984  	if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM scratch\nENV x y"), 0644); err != nil {
  4985  		c.Fatal(err)
  4986  	}
  4987  	if err := os.Symlink(filepath.Join("..", "outsideDockerfile"), filepath.Join(ctx, "dockerfile1")); err != nil {
  4988  		c.Fatal(err)
  4989  	}
  4990  	if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
  4991  		c.Fatal(err)
  4992  	}
  4993  
  4994  	for _, dockerfilePath := range []string{
  4995  		filepath.Join("..", "outsideDockerfile"),
  4996  		filepath.Join(ctx, "dockerfile1"),
  4997  		filepath.Join(ctx, "dockerfile2"),
  4998  	} {
  4999  		out, _, err := dockerCmdWithError(c, "build", "-t", name, "--no-cache", "-f", dockerfilePath, ".")
  5000  		if err == nil {
  5001  			c.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
  5002  		}
  5003  		if !strings.Contains(out, "must be within the build context") && !strings.Contains(out, "Cannot locate Dockerfile") {
  5004  			c.Fatalf("Unexpected error with %s. Out: %s", dockerfilePath, out)
  5005  		}
  5006  		deleteImages(name)
  5007  	}
  5008  
  5009  	os.Chdir(tmpdir)
  5010  
  5011  	// Path to Dockerfile should be resolved relative to working directory, not relative to context.
  5012  	// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
  5013  	out, _, err := dockerCmdWithError(c, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx)
  5014  	if err == nil {
  5015  		c.Fatalf("Expected error. Out: %s", out)
  5016  	}
  5017  }
  5018  
  5019  func (s *DockerSuite) TestBuildSpaces(c *check.C) {
  5020  	// Test to make sure that leading/trailing spaces on a command
  5021  	// doesn't change the error msg we get
  5022  	var (
  5023  		err1 error
  5024  		err2 error
  5025  	)
  5026  
  5027  	name := "testspaces"
  5028  	ctx, err := fakeContext("FROM busybox\nCOPY\n",
  5029  		map[string]string{
  5030  			"Dockerfile": "FROM busybox\nCOPY\n",
  5031  		})
  5032  	if err != nil {
  5033  		c.Fatal(err)
  5034  	}
  5035  	defer ctx.Close()
  5036  
  5037  	if _, err1 = buildImageFromContext(name, ctx, false); err1 == nil {
  5038  		c.Fatal("Build 1 was supposed to fail, but didn't")
  5039  	}
  5040  
  5041  	ctx.Add("Dockerfile", "FROM busybox\nCOPY    ")
  5042  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5043  		c.Fatal("Build 2 was supposed to fail, but didn't")
  5044  	}
  5045  
  5046  	removeLogTimestamps := func(s string) string {
  5047  		return regexp.MustCompile(`time="(.*?)"`).ReplaceAllString(s, `time=[TIMESTAMP]`)
  5048  	}
  5049  
  5050  	// Skip over the times
  5051  	e1 := removeLogTimestamps(err1.Error())
  5052  	e2 := removeLogTimestamps(err2.Error())
  5053  
  5054  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5055  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5056  		c.Fatalf("Build 2's error wasn't the same as build 1's\n1:%s\n2:%s", err1, err2)
  5057  	}
  5058  
  5059  	ctx.Add("Dockerfile", "FROM busybox\n   COPY")
  5060  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5061  		c.Fatal("Build 3 was supposed to fail, but didn't")
  5062  	}
  5063  
  5064  	// Skip over the times
  5065  	e1 = removeLogTimestamps(err1.Error())
  5066  	e2 = removeLogTimestamps(err2.Error())
  5067  
  5068  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5069  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5070  		c.Fatalf("Build 3's error wasn't the same as build 1's\n1:%s\n3:%s", err1, err2)
  5071  	}
  5072  
  5073  	ctx.Add("Dockerfile", "FROM busybox\n   COPY    ")
  5074  	if _, err2 = buildImageFromContext(name, ctx, false); err2 == nil {
  5075  		c.Fatal("Build 4 was supposed to fail, but didn't")
  5076  	}
  5077  
  5078  	// Skip over the times
  5079  	e1 = removeLogTimestamps(err1.Error())
  5080  	e2 = removeLogTimestamps(err2.Error())
  5081  
  5082  	// Ignore whitespace since that's what were verifying doesn't change stuff
  5083  	if strings.Replace(e1, " ", "", -1) != strings.Replace(e2, " ", "", -1) {
  5084  		c.Fatalf("Build 4's error wasn't the same as build 1's\n1:%s\n4:%s", err1, err2)
  5085  	}
  5086  
  5087  }
  5088  
  5089  func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) {
  5090  	// Test to make sure that spaces in quotes aren't lost
  5091  	name := "testspacesquotes"
  5092  
  5093  	dockerfile := `FROM busybox
  5094  RUN echo "  \
  5095    foo  "`
  5096  
  5097  	_, out, err := buildImageWithOut(name, dockerfile, false)
  5098  	if err != nil {
  5099  		c.Fatal("Build failed:", err)
  5100  	}
  5101  
  5102  	expecting := "\n    foo  \n"
  5103  	if !strings.Contains(out, expecting) {
  5104  		c.Fatalf("Bad output: %q expecting to contain %q", out, expecting)
  5105  	}
  5106  
  5107  }
  5108  
  5109  // #4393
  5110  func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) {
  5111  	buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-")
  5112  	buildCmd.Stdin = strings.NewReader(`
  5113  	FROM busybox
  5114  	RUN touch /foo
  5115  	VOLUME /foo
  5116  	`)
  5117  
  5118  	out, _, err := runCommandWithOutput(buildCmd)
  5119  	if err == nil || !strings.Contains(out, "file exists") {
  5120  		c.Fatalf("expected build to fail when file exists in container at requested volume path")
  5121  	}
  5122  
  5123  }
  5124  
  5125  func (s *DockerSuite) TestBuildMissingArgs(c *check.C) {
  5126  	// Test to make sure that all Dockerfile commands (except the ones listed
  5127  	// in skipCmds) will generate an error if no args are provided.
  5128  	// Note: INSERT is deprecated so we exclude it because of that.
  5129  	skipCmds := map[string]struct{}{
  5130  		"CMD":        {},
  5131  		"RUN":        {},
  5132  		"ENTRYPOINT": {},
  5133  		"INSERT":     {},
  5134  	}
  5135  
  5136  	for cmd := range command.Commands {
  5137  		cmd = strings.ToUpper(cmd)
  5138  		if _, ok := skipCmds[cmd]; ok {
  5139  			continue
  5140  		}
  5141  
  5142  		var dockerfile string
  5143  		if cmd == "FROM" {
  5144  			dockerfile = cmd
  5145  		} else {
  5146  			// Add FROM to make sure we don't complain about it missing
  5147  			dockerfile = "FROM busybox\n" + cmd
  5148  		}
  5149  
  5150  		ctx, err := fakeContext(dockerfile, map[string]string{})
  5151  		if err != nil {
  5152  			c.Fatal(err)
  5153  		}
  5154  		defer ctx.Close()
  5155  		var out string
  5156  		if out, err = buildImageFromContext("args", ctx, true); err == nil {
  5157  			c.Fatalf("%s was supposed to fail. Out:%s", cmd, out)
  5158  		}
  5159  		if !strings.Contains(err.Error(), cmd+" requires") {
  5160  			c.Fatalf("%s returned the wrong type of error:%s", cmd, err)
  5161  		}
  5162  	}
  5163  
  5164  }
  5165  
  5166  func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) {
  5167  	_, out, err := buildImageWithOut("sc", "FROM scratch", true)
  5168  	if err == nil {
  5169  		c.Fatalf("Build was supposed to fail")
  5170  	}
  5171  	if !strings.Contains(out, "No image was generated") {
  5172  		c.Fatalf("Wrong error message: %v", out)
  5173  	}
  5174  }
  5175  
  5176  func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
  5177  	ctx, err := fakeContext("FROM busybox\n",
  5178  		map[string]string{
  5179  			"..gitme": "",
  5180  		})
  5181  	if err != nil {
  5182  		c.Fatal(err)
  5183  	}
  5184  	defer ctx.Close()
  5185  
  5186  	if _, err = buildImageFromContext("sc", ctx, false); err != nil {
  5187  		c.Fatalf("Build was supposed to work: %s", err)
  5188  	}
  5189  }
  5190  
  5191  func (s *DockerSuite) TestBuildNotVerbose(c *check.C) {
  5192  
  5193  	ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
  5194  	if err != nil {
  5195  		c.Fatal(err)
  5196  	}
  5197  	defer ctx.Close()
  5198  
  5199  	// First do it w/verbose - baseline
  5200  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-t", "verbose", ".")
  5201  	if err != nil {
  5202  		c.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
  5203  	}
  5204  	if !strings.Contains(out, "hi there") {
  5205  		c.Fatalf("missing output:%s\n", out)
  5206  	}
  5207  
  5208  	// Now do it w/o verbose
  5209  	out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-q", "-t", "verbose", ".")
  5210  	if err != nil {
  5211  		c.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
  5212  	}
  5213  	if strings.Contains(out, "hi there") {
  5214  		c.Fatalf("Bad output, should not contain 'hi there':%s", out)
  5215  	}
  5216  
  5217  }
  5218  
  5219  func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
  5220  	name := "testbuildrunonejson"
  5221  
  5222  	ctx, err := fakeContext(`FROM hello-world:frozen
  5223  RUN [ "/hello" ]`, map[string]string{})
  5224  	if err != nil {
  5225  		c.Fatal(err)
  5226  	}
  5227  	defer ctx.Close()
  5228  
  5229  	out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-t", name, ".")
  5230  	if err != nil {
  5231  		c.Fatalf("failed to build the image: %s, %v", out, err)
  5232  	}
  5233  
  5234  	if !strings.Contains(out, "Hello from Docker") {
  5235  		c.Fatalf("bad output: %s", out)
  5236  	}
  5237  
  5238  }
  5239  
  5240  func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) {
  5241  	name := "testbuildemptystringvolume"
  5242  
  5243  	_, err := buildImage(name, `
  5244    FROM busybox
  5245    ENV foo=""
  5246    VOLUME $foo
  5247    `, false)
  5248  	if err == nil {
  5249  		c.Fatal("Should have failed to build")
  5250  	}
  5251  
  5252  }
  5253  
  5254  func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) {
  5255  	testRequires(c, NativeExecDriver)
  5256  	testRequires(c, SameHostDaemon)
  5257  
  5258  	cgroupParent := "test"
  5259  	data, err := ioutil.ReadFile("/proc/self/cgroup")
  5260  	if err != nil {
  5261  		c.Fatalf("failed to read '/proc/self/cgroup - %v", err)
  5262  	}
  5263  	selfCgroupPaths := parseCgroupPaths(string(data))
  5264  	_, found := selfCgroupPaths["memory"]
  5265  	if !found {
  5266  		c.Fatalf("unable to find self cpu cgroup path. CgroupsPath: %v", selfCgroupPaths)
  5267  	}
  5268  	cmd := exec.Command(dockerBinary, "build", "--cgroup-parent", cgroupParent, "-")
  5269  	cmd.Stdin = strings.NewReader(`
  5270  FROM busybox
  5271  RUN cat /proc/self/cgroup
  5272  `)
  5273  
  5274  	out, _, err := runCommandWithOutput(cmd)
  5275  	if err != nil {
  5276  		c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err)
  5277  	}
  5278  }
  5279  
  5280  func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) {
  5281  	// Check to make sure our build output prints the Dockerfile cmd
  5282  	// property - there was a bug that caused it to be duplicated on the
  5283  	// Step X  line
  5284  	name := "testbuildnodupoutput"
  5285  
  5286  	_, out, err := buildImageWithOut(name, `
  5287    FROM busybox
  5288    RUN env`, false)
  5289  	if err != nil {
  5290  		c.Fatalf("Build should have worked: %q", err)
  5291  	}
  5292  
  5293  	exp := "\nStep 1 : RUN env\n"
  5294  	if !strings.Contains(out, exp) {
  5295  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
  5296  	}
  5297  }
  5298  
  5299  func (s *DockerSuite) TestBuildBadCmdFlag(c *check.C) {
  5300  	name := "testbuildbadcmdflag"
  5301  
  5302  	_, out, err := buildImageWithOut(name, `
  5303    FROM busybox
  5304    MAINTAINER --boo joe@example.com`, false)
  5305  	if err == nil {
  5306  		c.Fatal("Build should have failed")
  5307  	}
  5308  
  5309  	exp := "\nUnknown flag: boo\n"
  5310  	if !strings.Contains(out, exp) {
  5311  		c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp)
  5312  	}
  5313  }
  5314  
  5315  func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) {
  5316  	// Test to make sure the bad command is quoted with just "s and
  5317  	// not as a Go []string
  5318  	name := "testbuildbadrunerrmsg"
  5319  	_, out, err := buildImageWithOut(name, `
  5320    FROM busybox
  5321    RUN badEXE a1 \& a2	a3`, false) // tab between a2 and a3
  5322  	if err == nil {
  5323  		c.Fatal("Should have failed to build")
  5324  	}
  5325  
  5326  	exp := `The command '/bin/sh -c badEXE a1 \& a2	a3' returned a non-zero code: 127`
  5327  	if !strings.Contains(out, exp) {
  5328  		c.Fatalf("RUN doesn't have the correct output:\nGot:%s\nExpected:%s", out, exp)
  5329  	}
  5330  }
  5331  
  5332  func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) {
  5333  	repoName := s.setupTrustedImage(c, "trusted-build")
  5334  	dockerFile := fmt.Sprintf(`
  5335    FROM %s
  5336    RUN []
  5337      `, repoName)
  5338  
  5339  	name := "testtrustedbuild"
  5340  
  5341  	buildCmd := buildImageCmd(name, dockerFile, true)
  5342  	s.trustedCmd(buildCmd)
  5343  	out, _, err := runCommandWithOutput(buildCmd)
  5344  	if err != nil {
  5345  		c.Fatalf("Error running trusted build: %s\n%s", err, out)
  5346  	}
  5347  
  5348  	if !strings.Contains(out, fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7])) {
  5349  		c.Fatalf("Unexpected output on trusted build:\n%s", out)
  5350  	}
  5351  
  5352  	// Build command does not create untrusted tag
  5353  	//dockerCmd(c, "rmi", repoName)
  5354  }
  5355  
  5356  func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) {
  5357  	repoName := fmt.Sprintf("%v/dockercli/build-untrusted-tag:latest", privateRegistryURL)
  5358  	dockerFile := fmt.Sprintf(`
  5359    FROM %s
  5360    RUN []
  5361      `, repoName)
  5362  
  5363  	name := "testtrustedbuilduntrustedtag"
  5364  
  5365  	buildCmd := buildImageCmd(name, dockerFile, true)
  5366  	s.trustedCmd(buildCmd)
  5367  	out, _, err := runCommandWithOutput(buildCmd)
  5368  	if err == nil {
  5369  		c.Fatalf("Expected error on trusted build with untrusted tag: %s\n%s", err, out)
  5370  	}
  5371  
  5372  	if !strings.Contains(out, fmt.Sprintf("no trust data available")) {
  5373  		c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out)
  5374  	}
  5375  }