github.com/titanous/docker@v1.4.1/integration-cli/docker_cli_build_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"os"
     9  	"os/exec"
    10  	"path"
    11  	"path/filepath"
    12  	"reflect"
    13  	"regexp"
    14  	"strings"
    15  	"syscall"
    16  	"testing"
    17  	"time"
    18  
    19  	"github.com/docker/docker/pkg/archive"
    20  )
    21  
    22  func TestBuildShCmdJSONEntrypoint(t *testing.T) {
    23  	name := "testbuildshcmdjsonentrypoint"
    24  	defer deleteImages(name)
    25  
    26  	_, err := buildImage(
    27  		name,
    28  		`
    29      FROM busybox
    30      ENTRYPOINT ["/bin/echo"]
    31      CMD echo test
    32      `,
    33  		true)
    34  
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  
    39  	out, _, err := runCommandWithOutput(
    40  		exec.Command(
    41  			dockerBinary,
    42  			"run",
    43  			"--rm",
    44  			name))
    45  
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  
    50  	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
    51  		t.Fatal("CMD did not contain /bin/sh -c")
    52  	}
    53  
    54  	logDone("build - CMD should always contain /bin/sh -c when specified without JSON")
    55  }
    56  
    57  func TestBuildEnvironmentReplacementUser(t *testing.T) {
    58  	name := "testbuildenvironmentreplacement"
    59  	defer deleteImages(name)
    60  
    61  	_, err := buildImage(name, `
    62    FROM scratch
    63    ENV user foo
    64    USER ${user}
    65    `, true)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	res, err := inspectFieldJSON(name, "Config.User")
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	if res != `"foo"` {
    76  		t.Fatal("User foo from environment not in Config.User on image")
    77  	}
    78  
    79  	logDone("build - user environment replacement")
    80  }
    81  
    82  func TestBuildEnvironmentReplacementVolume(t *testing.T) {
    83  	name := "testbuildenvironmentreplacement"
    84  	defer deleteImages(name)
    85  
    86  	_, err := buildImage(name, `
    87    FROM scratch
    88    ENV volume /quux
    89    VOLUME ${volume}
    90    `, true)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	res, err := inspectFieldJSON(name, "Config.Volumes")
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	var volumes map[string]interface{}
   101  
   102  	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	if _, ok := volumes["/quux"]; !ok {
   107  		t.Fatal("Volume /quux from environment not in Config.Volumes on image")
   108  	}
   109  
   110  	logDone("build - volume environment replacement")
   111  }
   112  
   113  func TestBuildEnvironmentReplacementExpose(t *testing.T) {
   114  	name := "testbuildenvironmentreplacement"
   115  	defer deleteImages(name)
   116  
   117  	_, err := buildImage(name, `
   118    FROM scratch
   119    ENV port 80
   120    EXPOSE ${port}
   121    `, true)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
   127  	if err != nil {
   128  		t.Fatal(err)
   129  	}
   130  
   131  	var exposedPorts map[string]interface{}
   132  
   133  	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
   134  		t.Fatal(err)
   135  	}
   136  
   137  	if _, ok := exposedPorts["80/tcp"]; !ok {
   138  		t.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
   139  	}
   140  
   141  	logDone("build - expose environment replacement")
   142  }
   143  
   144  func TestBuildEnvironmentReplacementWorkdir(t *testing.T) {
   145  	name := "testbuildenvironmentreplacement"
   146  	defer deleteImages(name)
   147  
   148  	_, err := buildImage(name, `
   149    FROM busybox
   150    ENV MYWORKDIR /work
   151    RUN mkdir ${MYWORKDIR}
   152    WORKDIR ${MYWORKDIR}
   153    `, true)
   154  
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  
   159  	logDone("build - workdir environment replacement")
   160  }
   161  
   162  func TestBuildEnvironmentReplacementAddCopy(t *testing.T) {
   163  	name := "testbuildenvironmentreplacement"
   164  	defer deleteImages(name)
   165  
   166  	ctx, err := fakeContext(`
   167    FROM scratch
   168    ENV baz foo
   169    ENV quux bar
   170    ENV dot .
   171  
   172    ADD ${baz} ${dot}
   173    COPY ${quux} ${dot}
   174    `,
   175  		map[string]string{
   176  			"foo": "test1",
   177  			"bar": "test2",
   178  		})
   179  
   180  	if err != nil {
   181  		t.Fatal(err)
   182  	}
   183  	defer ctx.Close()
   184  
   185  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   186  		t.Fatal(err)
   187  	}
   188  
   189  	logDone("build - add/copy environment replacement")
   190  }
   191  
   192  func TestBuildEnvironmentReplacementEnv(t *testing.T) {
   193  	name := "testbuildenvironmentreplacement"
   194  
   195  	defer deleteImages(name)
   196  
   197  	_, err := buildImage(name,
   198  		`
   199    FROM scratch
   200    ENV foo foo
   201    ENV bar ${foo}
   202    `, true)
   203  
   204  	if err != nil {
   205  		t.Fatal(err)
   206  	}
   207  
   208  	res, err := inspectFieldJSON(name, "Config.Env")
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	envResult := []string{}
   214  
   215  	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
   216  		t.Fatal(err)
   217  	}
   218  
   219  	found := false
   220  
   221  	for _, env := range envResult {
   222  		parts := strings.SplitN(env, "=", 2)
   223  		if parts[0] == "bar" {
   224  			found = true
   225  			if parts[1] != "foo" {
   226  				t.Fatalf("Could not find replaced var for env `bar`: got %q instead of `foo`", parts[1])
   227  			}
   228  		}
   229  	}
   230  
   231  	if !found {
   232  		t.Fatal("Never found the `bar` env variable")
   233  	}
   234  
   235  	logDone("build - env environment replacement")
   236  }
   237  
   238  func TestBuildHandleEscapes(t *testing.T) {
   239  	name := "testbuildhandleescapes"
   240  
   241  	defer deleteImages(name)
   242  
   243  	_, err := buildImage(name,
   244  		`
   245    FROM scratch
   246    ENV FOO bar
   247    VOLUME ${FOO}
   248    `, true)
   249  
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  
   254  	var result map[string]map[string]struct{}
   255  
   256  	res, err := inspectFieldJSON(name, "Config.Volumes")
   257  	if err != nil {
   258  		t.Fatal(err)
   259  	}
   260  
   261  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   262  		t.Fatal(err)
   263  	}
   264  
   265  	if _, ok := result["bar"]; !ok {
   266  		t.Fatal("Could not find volume bar set from env foo in volumes table")
   267  	}
   268  
   269  	deleteImages(name)
   270  
   271  	_, err = buildImage(name,
   272  		`
   273    FROM scratch
   274    ENV FOO bar
   275    VOLUME \${FOO}
   276    `, true)
   277  
   278  	if err != nil {
   279  		t.Fatal(err)
   280  	}
   281  
   282  	res, err = inspectFieldJSON(name, "Config.Volumes")
   283  	if err != nil {
   284  		t.Fatal(err)
   285  	}
   286  
   287  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   288  		t.Fatal(err)
   289  	}
   290  
   291  	if _, ok := result["${FOO}"]; !ok {
   292  		t.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
   293  	}
   294  
   295  	deleteImages(name)
   296  
   297  	// this test in particular provides *7* backslashes and expects 6 to come back.
   298  	// Like above, the first escape is swallowed and the rest are treated as
   299  	// literals, this one is just less obvious because of all the character noise.
   300  
   301  	_, err = buildImage(name,
   302  		`
   303    FROM scratch
   304    ENV FOO bar
   305    VOLUME \\\\\\\${FOO}
   306    `, true)
   307  
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  
   312  	res, err = inspectFieldJSON(name, "Config.Volumes")
   313  	if err != nil {
   314  		t.Fatal(err)
   315  	}
   316  
   317  	if err = unmarshalJSON([]byte(res), &result); err != nil {
   318  		t.Fatal(err)
   319  	}
   320  
   321  	if _, ok := result[`\\\\\\${FOO}`]; !ok {
   322  		t.Fatal(`Could not find volume \\\\\\${FOO} set from env foo in volumes table`)
   323  	}
   324  
   325  	logDone("build - handle escapes")
   326  }
   327  
   328  func TestBuildOnBuildLowercase(t *testing.T) {
   329  	name := "testbuildonbuildlowercase"
   330  	name2 := "testbuildonbuildlowercase2"
   331  
   332  	defer deleteImages(name, name2)
   333  
   334  	_, err := buildImage(name,
   335  		`
   336    FROM busybox
   337    onbuild run echo quux
   338    `, true)
   339  
   340  	if err != nil {
   341  		t.Fatal(err)
   342  	}
   343  
   344  	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
   345    FROM %s
   346    `, name), true)
   347  
   348  	if err != nil {
   349  		t.Fatal(err)
   350  	}
   351  
   352  	if !strings.Contains(out, "quux") {
   353  		t.Fatalf("Did not receive the expected echo text, got %s", out)
   354  	}
   355  
   356  	if strings.Contains(out, "ONBUILD ONBUILD") {
   357  		t.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
   358  	}
   359  
   360  	logDone("build - handle case-insensitive onbuild statement")
   361  }
   362  
   363  func TestBuildEnvEscapes(t *testing.T) {
   364  	name := "testbuildenvescapes"
   365  	defer deleteImages(name)
   366  	defer deleteAllContainers()
   367  	_, err := buildImage(name,
   368  		`
   369      FROM busybox
   370      ENV TEST foo
   371      CMD echo \$
   372      `,
   373  		true)
   374  
   375  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
   376  
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	if strings.TrimSpace(out) != "$" {
   382  		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   383  	}
   384  
   385  	logDone("build - env should handle \\$ properly")
   386  }
   387  
   388  func TestBuildEnvOverwrite(t *testing.T) {
   389  	name := "testbuildenvoverwrite"
   390  	defer deleteImages(name)
   391  	defer deleteAllContainers()
   392  
   393  	_, err := buildImage(name,
   394  		`
   395      FROM busybox
   396      ENV TEST foo
   397      CMD echo ${TEST}
   398      `,
   399  		true)
   400  
   401  	if err != nil {
   402  		t.Fatal(err)
   403  	}
   404  
   405  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
   406  
   407  	if err != nil {
   408  		t.Fatal(err)
   409  	}
   410  
   411  	if strings.TrimSpace(out) != "bar" {
   412  		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
   413  	}
   414  
   415  	logDone("build - env should overwrite builder ENV during run")
   416  }
   417  
   418  func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
   419  	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
   420  	defer deleteImages("onbuild")
   421  	defer deleteImages(name)
   422  	defer deleteAllContainers()
   423  
   424  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   425  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   426  	if err != nil {
   427  		t.Fatal(out, err)
   428  	}
   429  
   430  	cleanedContainerID := stripTrailingCharacters(out)
   431  
   432  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
   433  
   434  	if _, err := runCommand(commitCmd); err != nil {
   435  		t.Fatal(err)
   436  	}
   437  
   438  	_, err = buildImage(name,
   439  		`FROM onbuild`,
   440  		true)
   441  	if err != nil {
   442  		if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
   443  			t.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
   444  		}
   445  	} else {
   446  		t.Fatal("Error must not be nil")
   447  	}
   448  	logDone("build - onbuild forbidden maintainer in source image")
   449  
   450  }
   451  
   452  func TestBuildOnBuildForbiddenFromInSourceImage(t *testing.T) {
   453  	name := "testbuildonbuildforbiddenfrominsourceimage"
   454  	defer deleteImages("onbuild")
   455  	defer deleteImages(name)
   456  	defer deleteAllContainers()
   457  
   458  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   459  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   460  	if err != nil {
   461  		t.Fatal(out, err)
   462  	}
   463  
   464  	cleanedContainerID := stripTrailingCharacters(out)
   465  
   466  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
   467  
   468  	if _, err := runCommand(commitCmd); err != nil {
   469  		t.Fatal(err)
   470  	}
   471  
   472  	_, err = buildImage(name,
   473  		`FROM onbuild`,
   474  		true)
   475  	if err != nil {
   476  		if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
   477  			t.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
   478  		}
   479  	} else {
   480  		t.Fatal("Error must not be nil")
   481  	}
   482  	logDone("build - onbuild forbidden from in source image")
   483  
   484  }
   485  
   486  func TestBuildOnBuildForbiddenChainedInSourceImage(t *testing.T) {
   487  	name := "testbuildonbuildforbiddenchainedinsourceimage"
   488  	defer deleteImages("onbuild")
   489  	defer deleteImages(name)
   490  	defer deleteAllContainers()
   491  
   492  	createCmd := exec.Command(dockerBinary, "create", "busybox", "true")
   493  	out, _, _, err := runCommandWithStdoutStderr(createCmd)
   494  	if err != nil {
   495  		t.Fatal(out, err)
   496  	}
   497  
   498  	cleanedContainerID := stripTrailingCharacters(out)
   499  
   500  	commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
   501  
   502  	if _, err := runCommand(commitCmd); err != nil {
   503  		t.Fatal(err)
   504  	}
   505  
   506  	_, err = buildImage(name,
   507  		`FROM onbuild`,
   508  		true)
   509  	if err != nil {
   510  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
   511  			t.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
   512  		}
   513  	} else {
   514  		t.Fatal("Error must not be nil")
   515  	}
   516  	logDone("build - onbuild forbidden chained in source image")
   517  
   518  }
   519  
   520  func TestBuildOnBuildCmdEntrypointJSON(t *testing.T) {
   521  	name1 := "onbuildcmd"
   522  	name2 := "onbuildgenerated"
   523  
   524  	defer deleteImages(name2)
   525  	defer deleteImages(name1)
   526  	defer deleteAllContainers()
   527  
   528  	_, err := buildImage(name1, `
   529  FROM busybox
   530  ONBUILD CMD ["hello world"]
   531  ONBUILD ENTRYPOINT ["echo"]
   532  ONBUILD RUN ["true"]`,
   533  		false)
   534  
   535  	if err != nil {
   536  		t.Fatal(err)
   537  	}
   538  
   539  	_, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false)
   540  
   541  	if err != nil {
   542  		t.Fatal(err)
   543  	}
   544  
   545  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   546  	if err != nil {
   547  		t.Fatal(err)
   548  	}
   549  
   550  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   551  		t.Fatal("did not get echo output from onbuild", out)
   552  	}
   553  
   554  	logDone("build - onbuild with json entrypoint/cmd")
   555  }
   556  
   557  func TestBuildOnBuildEntrypointJSON(t *testing.T) {
   558  	name1 := "onbuildcmd"
   559  	name2 := "onbuildgenerated"
   560  
   561  	defer deleteImages(name2)
   562  	defer deleteImages(name1)
   563  	defer deleteAllContainers()
   564  
   565  	_, err := buildImage(name1, `
   566  FROM busybox
   567  ONBUILD ENTRYPOINT ["echo"]`,
   568  		false)
   569  
   570  	if err != nil {
   571  		t.Fatal(err)
   572  	}
   573  
   574  	_, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
   575  
   576  	if err != nil {
   577  		t.Fatal(err)
   578  	}
   579  
   580  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
   581  	if err != nil {
   582  		t.Fatal(err)
   583  	}
   584  
   585  	if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
   586  		t.Fatal("got malformed output from onbuild", out)
   587  	}
   588  
   589  	logDone("build - onbuild with json entrypoint")
   590  }
   591  
   592  func TestBuildCacheADD(t *testing.T) {
   593  	name := "testbuildtwoimageswithadd"
   594  	defer deleteImages(name)
   595  	server, err := fakeStorage(map[string]string{
   596  		"robots.txt": "hello",
   597  		"index.html": "world",
   598  	})
   599  	if err != nil {
   600  		t.Fatal(err)
   601  	}
   602  	defer server.Close()
   603  	if _, err := buildImage(name,
   604  		fmt.Sprintf(`FROM scratch
   605  		ADD %s/robots.txt /`, server.URL),
   606  		true); err != nil {
   607  		t.Fatal(err)
   608  	}
   609  	if err != nil {
   610  		t.Fatal(err)
   611  	}
   612  	deleteImages(name)
   613  	_, out, err := buildImageWithOut(name,
   614  		fmt.Sprintf(`FROM scratch
   615  		ADD %s/index.html /`, server.URL),
   616  		true)
   617  	if err != nil {
   618  		t.Fatal(err)
   619  	}
   620  	if strings.Contains(out, "Using cache") {
   621  		t.Fatal("2nd build used cache on ADD, it shouldn't")
   622  	}
   623  
   624  	logDone("build - build two images with remote ADD")
   625  }
   626  
   627  func TestBuildSixtySteps(t *testing.T) {
   628  	name := "foobuildsixtysteps"
   629  	defer deleteImages(name)
   630  	ctx, err := fakeContext("FROM scratch\n"+strings.Repeat("ADD foo /\n", 60),
   631  		map[string]string{
   632  			"foo": "test1",
   633  		})
   634  	if err != nil {
   635  		t.Fatal(err)
   636  	}
   637  	defer ctx.Close()
   638  
   639  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   640  		t.Fatal(err)
   641  	}
   642  	logDone("build - build an image with sixty build steps")
   643  }
   644  
   645  func TestBuildAddSingleFileToRoot(t *testing.T) {
   646  	name := "testaddimg"
   647  	defer deleteImages(name)
   648  	ctx, err := fakeContext(`FROM busybox
   649  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   650  RUN echo 'dockerio:x:1001:' >> /etc/group
   651  RUN touch /exists
   652  RUN chown dockerio.dockerio /exists
   653  ADD test_file /
   654  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   655  RUN [ $(ls -l /test_file | awk '{print $1}') = '-rw-r--r--' ]
   656  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   657  		map[string]string{
   658  			"test_file": "test1",
   659  		})
   660  	if err != nil {
   661  		t.Fatal(err)
   662  	}
   663  	defer ctx.Close()
   664  
   665  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   666  		t.Fatal(err)
   667  	}
   668  	logDone("build - add single file to root")
   669  }
   670  
   671  // Issue #3960: "ADD src ." hangs
   672  func TestBuildAddSingleFileToWorkdir(t *testing.T) {
   673  	name := "testaddsinglefiletoworkdir"
   674  	defer deleteImages(name)
   675  	ctx, err := fakeContext(`FROM busybox
   676  ADD test_file .`,
   677  		map[string]string{
   678  			"test_file": "test1",
   679  		})
   680  	if err != nil {
   681  		t.Fatal(err)
   682  	}
   683  	defer ctx.Close()
   684  
   685  	done := make(chan struct{})
   686  	go func() {
   687  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
   688  			t.Fatal(err)
   689  		}
   690  		close(done)
   691  	}()
   692  	select {
   693  	case <-time.After(5 * time.Second):
   694  		t.Fatal("Build with adding to workdir timed out")
   695  	case <-done:
   696  	}
   697  	logDone("build - add single file to workdir")
   698  }
   699  
   700  func TestBuildAddSingleFileToExistDir(t *testing.T) {
   701  	name := "testaddsinglefiletoexistdir"
   702  	defer deleteImages(name)
   703  	ctx, err := fakeContext(`FROM busybox
   704  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   705  RUN echo 'dockerio:x:1001:' >> /etc/group
   706  RUN mkdir /exists
   707  RUN touch /exists/exists_file
   708  RUN chown -R dockerio.dockerio /exists
   709  ADD test_file /exists/
   710  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   711  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
   712  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   713  		map[string]string{
   714  			"test_file": "test1",
   715  		})
   716  	if err != nil {
   717  		t.Fatal(err)
   718  	}
   719  	defer ctx.Close()
   720  
   721  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   722  		t.Fatal(err)
   723  	}
   724  	logDone("build - add single file to existing dir")
   725  }
   726  
   727  func TestBuildCopyAddMultipleFiles(t *testing.T) {
   728  	name := "testcopymultiplefilestofile"
   729  	defer deleteImages(name)
   730  	ctx, err := fakeContext(`FROM busybox
   731  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   732  RUN echo 'dockerio:x:1001:' >> /etc/group
   733  RUN mkdir /exists
   734  RUN touch /exists/exists_file
   735  RUN chown -R dockerio.dockerio /exists
   736  COPY test_file1 test_file2 /exists/
   737  ADD test_file3 test_file4 https://docker.com/robots.txt /exists/
   738  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   739  RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ]
   740  RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ]
   741  
   742  RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ]
   743  RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ]
   744  RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ]
   745  
   746  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
   747  `,
   748  		map[string]string{
   749  			"test_file1": "test1",
   750  			"test_file2": "test2",
   751  			"test_file3": "test3",
   752  			"test_file4": "test4",
   753  		})
   754  	defer ctx.Close()
   755  	if err != nil {
   756  		t.Fatal(err)
   757  	}
   758  
   759  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   760  		t.Fatal(err)
   761  	}
   762  	logDone("build - mulitple file copy/add tests")
   763  }
   764  
   765  func TestBuildAddMultipleFilesToFile(t *testing.T) {
   766  	name := "testaddmultiplefilestofile"
   767  	defer deleteImages(name)
   768  	ctx, err := fakeContext(`FROM scratch
   769  	ADD file1.txt file2.txt test
   770          `,
   771  		map[string]string{
   772  			"file1.txt": "test1",
   773  			"file2.txt": "test1",
   774  		})
   775  	defer ctx.Close()
   776  	if err != nil {
   777  		t.Fatal(err)
   778  	}
   779  
   780  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   781  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   782  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
   783  	}
   784  
   785  	logDone("build - multiple add files to file")
   786  }
   787  
   788  func TestBuildAddMultipleFilesToFileWild(t *testing.T) {
   789  	name := "testaddmultiplefilestofilewild"
   790  	defer deleteImages(name)
   791  	ctx, err := fakeContext(`FROM scratch
   792  	ADD file*.txt test
   793          `,
   794  		map[string]string{
   795  			"file1.txt": "test1",
   796  			"file2.txt": "test1",
   797  		})
   798  	defer ctx.Close()
   799  	if err != nil {
   800  		t.Fatal(err)
   801  	}
   802  
   803  	expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
   804  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   805  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
   806  	}
   807  
   808  	logDone("build - multiple add files to file wild")
   809  }
   810  
   811  func TestBuildCopyMultipleFilesToFile(t *testing.T) {
   812  	name := "testcopymultiplefilestofile"
   813  	defer deleteImages(name)
   814  	ctx, err := fakeContext(`FROM scratch
   815  	COPY file1.txt file2.txt test
   816          `,
   817  		map[string]string{
   818  			"file1.txt": "test1",
   819  			"file2.txt": "test1",
   820  		})
   821  	defer ctx.Close()
   822  	if err != nil {
   823  		t.Fatal(err)
   824  	}
   825  
   826  	expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
   827  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
   828  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
   829  	}
   830  
   831  	logDone("build - multiple copy files to file")
   832  }
   833  
   834  func TestBuildCopyWildcard(t *testing.T) {
   835  	name := "testcopywildcard"
   836  	defer deleteImages(name)
   837  	server, err := fakeStorage(map[string]string{
   838  		"robots.txt": "hello",
   839  		"index.html": "world",
   840  	})
   841  	if err != nil {
   842  		t.Fatal(err)
   843  	}
   844  	defer server.Close()
   845  	ctx, err := fakeContext(fmt.Sprintf(`FROM busybox
   846  	COPY file*.txt /tmp/
   847  	RUN ls /tmp/file1.txt /tmp/file2.txt
   848  	RUN mkdir /tmp1
   849  	COPY dir* /tmp1/
   850  	RUN ls /tmp1/dirt /tmp1/nested_file /tmp1/nested_dir/nest_nest_file
   851  	RUN mkdir /tmp2
   852          ADD dir/*dir %s/robots.txt /tmp2/
   853  	RUN ls /tmp2/nest_nest_file /tmp2/robots.txt
   854  	`, server.URL),
   855  		map[string]string{
   856  			"file1.txt":                     "test1",
   857  			"file2.txt":                     "test2",
   858  			"dir/nested_file":               "nested file",
   859  			"dir/nested_dir/nest_nest_file": "2 times nested",
   860  			"dirt": "dirty",
   861  		})
   862  	defer ctx.Close()
   863  	if err != nil {
   864  		t.Fatal(err)
   865  	}
   866  
   867  	id1, err := buildImageFromContext(name, ctx, true)
   868  	if err != nil {
   869  		t.Fatal(err)
   870  	}
   871  
   872  	// Now make sure we use a cache the 2nd time
   873  	id2, err := buildImageFromContext(name, ctx, true)
   874  	if err != nil {
   875  		t.Fatal(err)
   876  	}
   877  
   878  	if id1 != id2 {
   879  		t.Fatal("didn't use the cache")
   880  	}
   881  
   882  	logDone("build - copy wild card")
   883  }
   884  
   885  func TestBuildCopyWildcardNoFind(t *testing.T) {
   886  	name := "testcopywildcardnofind"
   887  	defer deleteImages(name)
   888  	ctx, err := fakeContext(`FROM busybox
   889  	COPY file*.txt /tmp/
   890  	`, nil)
   891  	defer ctx.Close()
   892  	if err != nil {
   893  		t.Fatal(err)
   894  	}
   895  
   896  	_, err = buildImageFromContext(name, ctx, true)
   897  	if err == nil {
   898  		t.Fatal("should have failed to find a file")
   899  	}
   900  	if !strings.Contains(err.Error(), "No source files were specified") {
   901  		t.Fatalf("Wrong error %v, must be about no source files", err)
   902  	}
   903  
   904  	logDone("build - copy wild card no find")
   905  }
   906  
   907  func TestBuildCopyWildcardCache(t *testing.T) {
   908  	name := "testcopywildcardcache"
   909  	defer deleteImages(name)
   910  	ctx, err := fakeContext(`FROM busybox
   911  	COPY file1.txt /tmp/`,
   912  		map[string]string{
   913  			"file1.txt": "test1",
   914  		})
   915  	defer ctx.Close()
   916  	if err != nil {
   917  		t.Fatal(err)
   918  	}
   919  
   920  	id1, err := buildImageFromContext(name, ctx, true)
   921  	if err != nil {
   922  		t.Fatal(err)
   923  	}
   924  
   925  	// Now make sure we use a cache the 2nd time even with wild cards.
   926  	// Use the same context so the file is the same and the checksum will match
   927  	ctx.Add("Dockerfile", `FROM busybox
   928  	COPY file*.txt /tmp/`)
   929  
   930  	id2, err := buildImageFromContext(name, ctx, true)
   931  	if err != nil {
   932  		t.Fatal(err)
   933  	}
   934  
   935  	if id1 != id2 {
   936  		t.Fatal("didn't use the cache")
   937  	}
   938  
   939  	logDone("build - copy wild card cache")
   940  }
   941  
   942  func TestBuildAddSingleFileToNonExistingDir(t *testing.T) {
   943  	name := "testaddsinglefiletononexistingdir"
   944  	defer deleteImages(name)
   945  	ctx, err := fakeContext(`FROM busybox
   946  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   947  RUN echo 'dockerio:x:1001:' >> /etc/group
   948  RUN touch /exists
   949  RUN chown dockerio.dockerio /exists
   950  ADD test_file /test_dir/
   951  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
   952  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
   953  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   954  		map[string]string{
   955  			"test_file": "test1",
   956  		})
   957  	if err != nil {
   958  		t.Fatal(err)
   959  	}
   960  	defer ctx.Close()
   961  
   962  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   963  		t.Fatal(err)
   964  	}
   965  
   966  	logDone("build - add single file to non-existing dir")
   967  }
   968  
   969  func TestBuildAddDirContentToRoot(t *testing.T) {
   970  	name := "testadddircontenttoroot"
   971  	defer deleteImages(name)
   972  	ctx, err := fakeContext(`FROM busybox
   973  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   974  RUN echo 'dockerio:x:1001:' >> /etc/group
   975  RUN touch /exists
   976  RUN chown dockerio.dockerio exists
   977  ADD test_dir /
   978  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
   979  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
   980  		map[string]string{
   981  			"test_dir/test_file": "test1",
   982  		})
   983  	if err != nil {
   984  		t.Fatal(err)
   985  	}
   986  	defer ctx.Close()
   987  
   988  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
   989  		t.Fatal(err)
   990  	}
   991  	logDone("build - add directory contents to root")
   992  }
   993  
   994  func TestBuildAddDirContentToExistingDir(t *testing.T) {
   995  	name := "testadddircontenttoexistingdir"
   996  	defer deleteImages(name)
   997  	ctx, err := fakeContext(`FROM busybox
   998  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
   999  RUN echo 'dockerio:x:1001:' >> /etc/group
  1000  RUN mkdir /exists
  1001  RUN touch /exists/exists_file
  1002  RUN chown -R dockerio.dockerio /exists
  1003  ADD test_dir/ /exists/
  1004  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1005  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1006  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1007  		map[string]string{
  1008  			"test_dir/test_file": "test1",
  1009  		})
  1010  	if err != nil {
  1011  		t.Fatal(err)
  1012  	}
  1013  	defer ctx.Close()
  1014  
  1015  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1016  		t.Fatal(err)
  1017  	}
  1018  	logDone("build - add directory contents to existing dir")
  1019  }
  1020  
  1021  func TestBuildAddWholeDirToRoot(t *testing.T) {
  1022  	name := "testaddwholedirtoroot"
  1023  	defer deleteImages(name)
  1024  	ctx, err := fakeContext(`FROM busybox
  1025  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1026  RUN echo 'dockerio:x:1001:' >> /etc/group
  1027  RUN touch /exists
  1028  RUN chown dockerio.dockerio exists
  1029  ADD test_dir /test_dir
  1030  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1031  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1032  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1033  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '-rw-r--r--' ]
  1034  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1035  		map[string]string{
  1036  			"test_dir/test_file": "test1",
  1037  		})
  1038  	if err != nil {
  1039  		t.Fatal(err)
  1040  	}
  1041  	defer ctx.Close()
  1042  
  1043  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1044  		t.Fatal(err)
  1045  	}
  1046  	logDone("build - add whole directory to root")
  1047  }
  1048  
  1049  // Testing #5941
  1050  func TestBuildAddEtcToRoot(t *testing.T) {
  1051  	name := "testaddetctoroot"
  1052  	defer deleteImages(name)
  1053  	ctx, err := fakeContext(`FROM scratch
  1054  ADD . /`,
  1055  		map[string]string{
  1056  			"etc/test_file": "test1",
  1057  		})
  1058  	if err != nil {
  1059  		t.Fatal(err)
  1060  	}
  1061  	defer ctx.Close()
  1062  
  1063  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1064  		t.Fatal(err)
  1065  	}
  1066  	logDone("build - add etc directory to root")
  1067  }
  1068  
  1069  // Testing #9401
  1070  func TestBuildAddPreservesFilesSpecialBits(t *testing.T) {
  1071  	name := "testaddpreservesfilesspecialbits"
  1072  	defer deleteImages(name)
  1073  	ctx, err := fakeContext(`FROM busybox
  1074  ADD suidbin /usr/bin/suidbin
  1075  RUN chmod 4755 /usr/bin/suidbin
  1076  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]
  1077  ADD ./data/ /
  1078  RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`,
  1079  		map[string]string{
  1080  			"suidbin":             "suidbin",
  1081  			"/data/usr/test_file": "test1",
  1082  		})
  1083  	if err != nil {
  1084  		t.Fatal(err)
  1085  	}
  1086  	defer ctx.Close()
  1087  
  1088  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1089  		t.Fatal(err)
  1090  	}
  1091  	logDone("build - add preserves files special bits")
  1092  }
  1093  
  1094  func TestBuildCopySingleFileToRoot(t *testing.T) {
  1095  	name := "testcopysinglefiletoroot"
  1096  	defer deleteImages(name)
  1097  	ctx, err := fakeContext(`FROM busybox
  1098  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1099  RUN echo 'dockerio:x:1001:' >> /etc/group
  1100  RUN touch /exists
  1101  RUN chown dockerio.dockerio /exists
  1102  COPY test_file /
  1103  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1104  RUN [ $(ls -l /test_file | awk '{print $1}') = '-rw-r--r--' ]
  1105  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1106  		map[string]string{
  1107  			"test_file": "test1",
  1108  		})
  1109  	if err != nil {
  1110  		t.Fatal(err)
  1111  	}
  1112  	defer ctx.Close()
  1113  
  1114  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1115  		t.Fatal(err)
  1116  	}
  1117  	logDone("build - copy single file to root")
  1118  }
  1119  
  1120  // Issue #3960: "ADD src ." hangs - adapted for COPY
  1121  func TestBuildCopySingleFileToWorkdir(t *testing.T) {
  1122  	name := "testcopysinglefiletoworkdir"
  1123  	defer deleteImages(name)
  1124  	ctx, err := fakeContext(`FROM busybox
  1125  COPY test_file .`,
  1126  		map[string]string{
  1127  			"test_file": "test1",
  1128  		})
  1129  	if err != nil {
  1130  		t.Fatal(err)
  1131  	}
  1132  	defer ctx.Close()
  1133  
  1134  	done := make(chan struct{})
  1135  	go func() {
  1136  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1137  			t.Fatal(err)
  1138  		}
  1139  		close(done)
  1140  	}()
  1141  	select {
  1142  	case <-time.After(5 * time.Second):
  1143  		t.Fatal("Build with adding to workdir timed out")
  1144  	case <-done:
  1145  	}
  1146  	logDone("build - copy single file to workdir")
  1147  }
  1148  
  1149  func TestBuildCopySingleFileToExistDir(t *testing.T) {
  1150  	name := "testcopysinglefiletoexistdir"
  1151  	defer deleteImages(name)
  1152  	ctx, err := fakeContext(`FROM busybox
  1153  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1154  RUN echo 'dockerio:x:1001:' >> /etc/group
  1155  RUN mkdir /exists
  1156  RUN touch /exists/exists_file
  1157  RUN chown -R dockerio.dockerio /exists
  1158  COPY test_file /exists/
  1159  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1160  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1161  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1162  		map[string]string{
  1163  			"test_file": "test1",
  1164  		})
  1165  	if err != nil {
  1166  		t.Fatal(err)
  1167  	}
  1168  	defer ctx.Close()
  1169  
  1170  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1171  		t.Fatal(err)
  1172  	}
  1173  	logDone("build - copy single file to existing dir")
  1174  }
  1175  
  1176  func TestBuildCopySingleFileToNonExistDir(t *testing.T) {
  1177  	name := "testcopysinglefiletononexistdir"
  1178  	defer deleteImages(name)
  1179  	ctx, err := fakeContext(`FROM busybox
  1180  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1181  RUN echo 'dockerio:x:1001:' >> /etc/group
  1182  RUN touch /exists
  1183  RUN chown dockerio.dockerio /exists
  1184  COPY test_file /test_dir/
  1185  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1186  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1187  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1188  		map[string]string{
  1189  			"test_file": "test1",
  1190  		})
  1191  	if err != nil {
  1192  		t.Fatal(err)
  1193  	}
  1194  	defer ctx.Close()
  1195  
  1196  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1197  		t.Fatal(err)
  1198  	}
  1199  	logDone("build - copy single file to non-existing dir")
  1200  }
  1201  
  1202  func TestBuildCopyDirContentToRoot(t *testing.T) {
  1203  	name := "testcopydircontenttoroot"
  1204  	defer deleteImages(name)
  1205  	ctx, err := fakeContext(`FROM busybox
  1206  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1207  RUN echo 'dockerio:x:1001:' >> /etc/group
  1208  RUN touch /exists
  1209  RUN chown dockerio.dockerio exists
  1210  COPY test_dir /
  1211  RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ]
  1212  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1213  		map[string]string{
  1214  			"test_dir/test_file": "test1",
  1215  		})
  1216  	if err != nil {
  1217  		t.Fatal(err)
  1218  	}
  1219  	defer ctx.Close()
  1220  
  1221  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1222  		t.Fatal(err)
  1223  	}
  1224  	logDone("build - copy directory contents to root")
  1225  }
  1226  
  1227  func TestBuildCopyDirContentToExistDir(t *testing.T) {
  1228  	name := "testcopydircontenttoexistdir"
  1229  	defer deleteImages(name)
  1230  	ctx, err := fakeContext(`FROM busybox
  1231  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1232  RUN echo 'dockerio:x:1001:' >> /etc/group
  1233  RUN mkdir /exists
  1234  RUN touch /exists/exists_file
  1235  RUN chown -R dockerio.dockerio /exists
  1236  COPY test_dir/ /exists/
  1237  RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1238  RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]
  1239  RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`,
  1240  		map[string]string{
  1241  			"test_dir/test_file": "test1",
  1242  		})
  1243  	if err != nil {
  1244  		t.Fatal(err)
  1245  	}
  1246  	defer ctx.Close()
  1247  
  1248  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1249  		t.Fatal(err)
  1250  	}
  1251  	logDone("build - copy directory contents to existing dir")
  1252  }
  1253  
  1254  func TestBuildCopyWholeDirToRoot(t *testing.T) {
  1255  	name := "testcopywholedirtoroot"
  1256  	defer deleteImages(name)
  1257  	ctx, err := fakeContext(`FROM busybox
  1258  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1259  RUN echo 'dockerio:x:1001:' >> /etc/group
  1260  RUN touch /exists
  1261  RUN chown dockerio.dockerio exists
  1262  COPY test_dir /test_dir
  1263  RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ]
  1264  RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ]
  1265  RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ]
  1266  RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '-rw-r--r--' ]
  1267  RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`,
  1268  		map[string]string{
  1269  			"test_dir/test_file": "test1",
  1270  		})
  1271  	if err != nil {
  1272  		t.Fatal(err)
  1273  	}
  1274  	defer ctx.Close()
  1275  
  1276  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1277  		t.Fatal(err)
  1278  	}
  1279  	logDone("build - copy whole directory to root")
  1280  }
  1281  
  1282  func TestBuildCopyEtcToRoot(t *testing.T) {
  1283  	name := "testcopyetctoroot"
  1284  	defer deleteImages(name)
  1285  	ctx, err := fakeContext(`FROM scratch
  1286  COPY . /`,
  1287  		map[string]string{
  1288  			"etc/test_file": "test1",
  1289  		})
  1290  	if err != nil {
  1291  		t.Fatal(err)
  1292  	}
  1293  	defer ctx.Close()
  1294  
  1295  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1296  		t.Fatal(err)
  1297  	}
  1298  	logDone("build - copy etc directory to root")
  1299  }
  1300  
  1301  func TestBuildCopyDisallowRemote(t *testing.T) {
  1302  	name := "testcopydisallowremote"
  1303  	defer deleteImages(name)
  1304  	_, out, err := buildImageWithOut(name, `FROM scratch
  1305  COPY https://index.docker.io/robots.txt /`,
  1306  		true)
  1307  	if err == nil || !strings.Contains(out, "Source can't be a URL for COPY") {
  1308  		t.Fatalf("Error should be about disallowed remote source, got err: %s, out: %q", err, out)
  1309  	}
  1310  	logDone("build - copy - disallow copy from remote")
  1311  }
  1312  
  1313  func TestBuildAddBadLinks(t *testing.T) {
  1314  	const (
  1315  		dockerfile = `
  1316  			FROM scratch
  1317  			ADD links.tar /
  1318  			ADD foo.txt /symlink/
  1319  			`
  1320  		targetFile = "foo.txt"
  1321  	)
  1322  	var (
  1323  		name = "test-link-absolute"
  1324  	)
  1325  	defer deleteImages(name)
  1326  	ctx, err := fakeContext(dockerfile, nil)
  1327  	if err != nil {
  1328  		t.Fatal(err)
  1329  	}
  1330  	defer ctx.Close()
  1331  
  1332  	tempDir, err := ioutil.TempDir("", "test-link-absolute-temp-")
  1333  	if err != nil {
  1334  		t.Fatalf("failed to create temporary directory: %s", tempDir)
  1335  	}
  1336  	defer os.RemoveAll(tempDir)
  1337  
  1338  	symlinkTarget := fmt.Sprintf("/../../../../../../../../../../../..%s", tempDir)
  1339  	tarPath := filepath.Join(ctx.Dir, "links.tar")
  1340  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1341  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1342  
  1343  	tarOut, err := os.Create(tarPath)
  1344  	if err != nil {
  1345  		t.Fatal(err)
  1346  	}
  1347  
  1348  	tarWriter := tar.NewWriter(tarOut)
  1349  
  1350  	header := &tar.Header{
  1351  		Name:     "symlink",
  1352  		Typeflag: tar.TypeSymlink,
  1353  		Linkname: symlinkTarget,
  1354  		Mode:     0755,
  1355  		Uid:      0,
  1356  		Gid:      0,
  1357  	}
  1358  
  1359  	err = tarWriter.WriteHeader(header)
  1360  	if err != nil {
  1361  		t.Fatal(err)
  1362  	}
  1363  
  1364  	tarWriter.Close()
  1365  	tarOut.Close()
  1366  
  1367  	foo, err := os.Create(fooPath)
  1368  	if err != nil {
  1369  		t.Fatal(err)
  1370  	}
  1371  	defer foo.Close()
  1372  
  1373  	if _, err := foo.WriteString("test"); err != nil {
  1374  		t.Fatal(err)
  1375  	}
  1376  
  1377  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1378  		t.Fatal(err)
  1379  	}
  1380  
  1381  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1382  		t.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1383  	}
  1384  
  1385  	logDone("build - ADD must add files in container")
  1386  }
  1387  
  1388  func TestBuildAddBadLinksVolume(t *testing.T) {
  1389  	const (
  1390  		dockerfileTemplate = `
  1391  		FROM busybox
  1392  		RUN ln -s /../../../../../../../../%s /x
  1393  		VOLUME /x
  1394  		ADD foo.txt /x/`
  1395  		targetFile = "foo.txt"
  1396  	)
  1397  	var (
  1398  		name       = "test-link-absolute-volume"
  1399  		dockerfile = ""
  1400  	)
  1401  	defer deleteImages(name)
  1402  
  1403  	tempDir, err := ioutil.TempDir("", "test-link-absolute-volume-temp-")
  1404  	if err != nil {
  1405  		t.Fatalf("failed to create temporary directory: %s", tempDir)
  1406  	}
  1407  	defer os.RemoveAll(tempDir)
  1408  
  1409  	dockerfile = fmt.Sprintf(dockerfileTemplate, tempDir)
  1410  	nonExistingFile := filepath.Join(tempDir, targetFile)
  1411  
  1412  	ctx, err := fakeContext(dockerfile, nil)
  1413  	if err != nil {
  1414  		t.Fatal(err)
  1415  	}
  1416  	defer ctx.Close()
  1417  	fooPath := filepath.Join(ctx.Dir, targetFile)
  1418  
  1419  	foo, err := os.Create(fooPath)
  1420  	if err != nil {
  1421  		t.Fatal(err)
  1422  	}
  1423  	defer foo.Close()
  1424  
  1425  	if _, err := foo.WriteString("test"); err != nil {
  1426  		t.Fatal(err)
  1427  	}
  1428  
  1429  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1430  		t.Fatal(err)
  1431  	}
  1432  
  1433  	if _, err := os.Stat(nonExistingFile); err == nil || err != nil && !os.IsNotExist(err) {
  1434  		t.Fatalf("%s shouldn't have been written and it shouldn't exist", nonExistingFile)
  1435  	}
  1436  
  1437  	logDone("build - ADD should add files in volume")
  1438  }
  1439  
  1440  // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  1441  // when we can't access files in the context.
  1442  func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  1443  	{
  1444  		name := "testbuildinaccessiblefiles"
  1445  		defer deleteImages(name)
  1446  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"fileWithoutReadAccess": "foo"})
  1447  		if err != nil {
  1448  			t.Fatal(err)
  1449  		}
  1450  		defer ctx.Close()
  1451  		// This is used to ensure we detect inaccessible files early during build in the cli client
  1452  		pathToFileWithoutReadAccess := filepath.Join(ctx.Dir, "fileWithoutReadAccess")
  1453  
  1454  		if err = os.Chown(pathToFileWithoutReadAccess, 0, 0); err != nil {
  1455  			t.Fatalf("failed to chown file to root: %s", err)
  1456  		}
  1457  		if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil {
  1458  			t.Fatalf("failed to chmod file to 700: %s", err)
  1459  		}
  1460  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1461  		buildCmd.Dir = ctx.Dir
  1462  		out, _, err := runCommandWithOutput(buildCmd)
  1463  		if err == nil {
  1464  			t.Fatalf("build should have failed: %s %s", err, out)
  1465  		}
  1466  
  1467  		// check if we've detected the failure before we started building
  1468  		if !strings.Contains(out, "no permission to read from ") {
  1469  			t.Fatalf("output should've contained the string: no permission to read from but contained: %s", out)
  1470  		}
  1471  
  1472  		if !strings.Contains(out, "Error checking context is accessible") {
  1473  			t.Fatalf("output should've contained the string: Error checking context is accessible")
  1474  		}
  1475  	}
  1476  	{
  1477  		name := "testbuildinaccessibledirectory"
  1478  		defer deleteImages(name)
  1479  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", map[string]string{"directoryWeCantStat/bar": "foo"})
  1480  		if err != nil {
  1481  			t.Fatal(err)
  1482  		}
  1483  		defer ctx.Close()
  1484  		// This is used to ensure we detect inaccessible directories early during build in the cli client
  1485  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1486  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1487  
  1488  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1489  			t.Fatalf("failed to chown directory to root: %s", err)
  1490  		}
  1491  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1492  			t.Fatalf("failed to chmod directory to 755: %s", err)
  1493  		}
  1494  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1495  			t.Fatalf("failed to chmod file to 444: %s", err)
  1496  		}
  1497  
  1498  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1499  		buildCmd.Dir = ctx.Dir
  1500  		out, _, err := runCommandWithOutput(buildCmd)
  1501  		if err == nil {
  1502  			t.Fatalf("build should have failed: %s %s", err, out)
  1503  		}
  1504  
  1505  		// check if we've detected the failure before we started building
  1506  		if !strings.Contains(out, "can't stat") {
  1507  			t.Fatalf("output should've contained the string: can't access %s", out)
  1508  		}
  1509  
  1510  		if !strings.Contains(out, "Error checking context is accessible") {
  1511  			t.Fatalf("output should've contained the string: Error checking context is accessible")
  1512  		}
  1513  
  1514  	}
  1515  	{
  1516  		name := "testlinksok"
  1517  		defer deleteImages(name)
  1518  		ctx, err := fakeContext("FROM scratch\nADD . /foo/", nil)
  1519  		if err != nil {
  1520  			t.Fatal(err)
  1521  		}
  1522  		defer ctx.Close()
  1523  
  1524  		target := "../../../../../../../../../../../../../../../../../../../azA"
  1525  		if err := os.Symlink(filepath.Join(ctx.Dir, "g"), target); err != nil {
  1526  			t.Fatal(err)
  1527  		}
  1528  		defer os.Remove(target)
  1529  		// This is used to ensure we don't follow links when checking if everything in the context is accessible
  1530  		// This test doesn't require that we run commands as an unprivileged user
  1531  		if _, err := buildImageFromContext(name, ctx, true); err != nil {
  1532  			t.Fatal(err)
  1533  		}
  1534  	}
  1535  	{
  1536  		name := "testbuildignoredinaccessible"
  1537  		defer deleteImages(name)
  1538  		ctx, err := fakeContext("FROM scratch\nADD . /foo/",
  1539  			map[string]string{
  1540  				"directoryWeCantStat/bar": "foo",
  1541  				".dockerignore":           "directoryWeCantStat",
  1542  			})
  1543  		if err != nil {
  1544  			t.Fatal(err)
  1545  		}
  1546  		defer ctx.Close()
  1547  		// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
  1548  		pathToDirectoryWithoutReadAccess := filepath.Join(ctx.Dir, "directoryWeCantStat")
  1549  		pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  1550  		if err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0); err != nil {
  1551  			t.Fatalf("failed to chown directory to root: %s", err)
  1552  		}
  1553  		if err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444); err != nil {
  1554  			t.Fatalf("failed to chmod directory to 755: %s", err)
  1555  		}
  1556  		if err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700); err != nil {
  1557  			t.Fatalf("failed to chmod file to 444: %s", err)
  1558  		}
  1559  
  1560  		buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name))
  1561  		buildCmd.Dir = ctx.Dir
  1562  		if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  1563  			t.Fatalf("build should have worked: %s %s", err, out)
  1564  		}
  1565  
  1566  	}
  1567  	logDone("build - ADD from context with inaccessible files must fail")
  1568  	logDone("build - ADD from context with accessible links must work")
  1569  	logDone("build - ADD from context with ignored inaccessible files must work")
  1570  }
  1571  
  1572  func TestBuildForceRm(t *testing.T) {
  1573  	containerCountBefore, err := getContainerCount()
  1574  	if err != nil {
  1575  		t.Fatalf("failed to get the container count: %s", err)
  1576  	}
  1577  	name := "testbuildforcerm"
  1578  	defer deleteImages(name)
  1579  	ctx, err := fakeContext("FROM scratch\nRUN true\nRUN thiswillfail", nil)
  1580  	if err != nil {
  1581  		t.Fatal(err)
  1582  	}
  1583  	defer ctx.Close()
  1584  
  1585  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "--force-rm", ".")
  1586  	buildCmd.Dir = ctx.Dir
  1587  	if out, _, err := runCommandWithOutput(buildCmd); err == nil {
  1588  		t.Fatalf("failed to build the image: %s, %v", out, err)
  1589  	}
  1590  
  1591  	containerCountAfter, err := getContainerCount()
  1592  	if err != nil {
  1593  		t.Fatalf("failed to get the container count: %s", err)
  1594  	}
  1595  
  1596  	if containerCountBefore != containerCountAfter {
  1597  		t.Fatalf("--force-rm shouldn't have left containers behind")
  1598  	}
  1599  
  1600  	logDone("build - ensure --force-rm doesn't leave containers behind")
  1601  }
  1602  
  1603  func TestBuildRm(t *testing.T) {
  1604  	name := "testbuildrm"
  1605  	defer deleteImages(name)
  1606  	ctx, err := fakeContext("FROM scratch\nADD foo /\nADD foo /", map[string]string{"foo": "bar"})
  1607  	if err != nil {
  1608  		t.Fatal(err)
  1609  	}
  1610  	defer ctx.Close()
  1611  	{
  1612  		containerCountBefore, err := getContainerCount()
  1613  		if err != nil {
  1614  			t.Fatalf("failed to get the container count: %s", err)
  1615  		}
  1616  
  1617  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm", "-t", name, ".")
  1618  
  1619  		if err != nil {
  1620  			t.Fatal("failed to build the image", out)
  1621  		}
  1622  
  1623  		containerCountAfter, err := getContainerCount()
  1624  		if err != nil {
  1625  			t.Fatalf("failed to get the container count: %s", err)
  1626  		}
  1627  
  1628  		if containerCountBefore != containerCountAfter {
  1629  			t.Fatalf("-rm shouldn't have left containers behind")
  1630  		}
  1631  		deleteImages(name)
  1632  	}
  1633  
  1634  	{
  1635  		containerCountBefore, err := getContainerCount()
  1636  		if err != nil {
  1637  			t.Fatalf("failed to get the container count: %s", err)
  1638  		}
  1639  
  1640  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name, ".")
  1641  
  1642  		if err != nil {
  1643  			t.Fatal("failed to build the image", out)
  1644  		}
  1645  
  1646  		containerCountAfter, err := getContainerCount()
  1647  		if err != nil {
  1648  			t.Fatalf("failed to get the container count: %s", err)
  1649  		}
  1650  
  1651  		if containerCountBefore != containerCountAfter {
  1652  			t.Fatalf("--rm shouldn't have left containers behind")
  1653  		}
  1654  		deleteImages(name)
  1655  	}
  1656  
  1657  	{
  1658  		containerCountBefore, err := getContainerCount()
  1659  		if err != nil {
  1660  			t.Fatalf("failed to get the container count: %s", err)
  1661  		}
  1662  
  1663  		out, _, err := dockerCmdInDir(t, ctx.Dir, "build", "--rm=false", "-t", name, ".")
  1664  
  1665  		if err != nil {
  1666  			t.Fatal("failed to build the image", out)
  1667  		}
  1668  
  1669  		containerCountAfter, err := getContainerCount()
  1670  		if err != nil {
  1671  			t.Fatalf("failed to get the container count: %s", err)
  1672  		}
  1673  
  1674  		if containerCountBefore == containerCountAfter {
  1675  			t.Fatalf("--rm=false should have left containers behind")
  1676  		}
  1677  		deleteAllContainers()
  1678  		deleteImages(name)
  1679  
  1680  	}
  1681  
  1682  	logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
  1683  	logDone("build - ensure --rm=false overrides the default")
  1684  }
  1685  
  1686  func TestBuildWithVolumes(t *testing.T) {
  1687  	var (
  1688  		result   map[string]map[string]struct{}
  1689  		name     = "testbuildvolumes"
  1690  		emptyMap = make(map[string]struct{})
  1691  		expected = map[string]map[string]struct{}{
  1692  			"/test1":  emptyMap,
  1693  			"/test2":  emptyMap,
  1694  			"/test3":  emptyMap,
  1695  			"/test4":  emptyMap,
  1696  			"/test5":  emptyMap,
  1697  			"/test6":  emptyMap,
  1698  			"[/test7": emptyMap,
  1699  			"/test8]": emptyMap,
  1700  		}
  1701  	)
  1702  	defer deleteImages(name)
  1703  	_, err := buildImage(name,
  1704  		`FROM scratch
  1705  		VOLUME /test1
  1706  		VOLUME /test2
  1707      VOLUME /test3 /test4
  1708      VOLUME ["/test5", "/test6"]
  1709      VOLUME [/test7 /test8]
  1710      `,
  1711  		true)
  1712  	if err != nil {
  1713  		t.Fatal(err)
  1714  	}
  1715  	res, err := inspectFieldJSON(name, "Config.Volumes")
  1716  	if err != nil {
  1717  		t.Fatal(err)
  1718  	}
  1719  
  1720  	err = unmarshalJSON([]byte(res), &result)
  1721  	if err != nil {
  1722  		t.Fatal(err)
  1723  	}
  1724  
  1725  	equal := reflect.DeepEqual(&result, &expected)
  1726  
  1727  	if !equal {
  1728  		t.Fatalf("Volumes %s, expected %s", result, expected)
  1729  	}
  1730  
  1731  	logDone("build - with volumes")
  1732  }
  1733  
  1734  func TestBuildMaintainer(t *testing.T) {
  1735  	name := "testbuildmaintainer"
  1736  	expected := "dockerio"
  1737  	defer deleteImages(name)
  1738  	_, err := buildImage(name,
  1739  		`FROM scratch
  1740          MAINTAINER dockerio`,
  1741  		true)
  1742  	if err != nil {
  1743  		t.Fatal(err)
  1744  	}
  1745  	res, err := inspectField(name, "Author")
  1746  	if err != nil {
  1747  		t.Fatal(err)
  1748  	}
  1749  	if res != expected {
  1750  		t.Fatalf("Maintainer %s, expected %s", res, expected)
  1751  	}
  1752  	logDone("build - maintainer")
  1753  }
  1754  
  1755  func TestBuildUser(t *testing.T) {
  1756  	name := "testbuilduser"
  1757  	expected := "dockerio"
  1758  	defer deleteImages(name)
  1759  	_, err := buildImage(name,
  1760  		`FROM busybox
  1761  		RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  1762  		USER dockerio
  1763  		RUN [ $(whoami) = 'dockerio' ]`,
  1764  		true)
  1765  	if err != nil {
  1766  		t.Fatal(err)
  1767  	}
  1768  	res, err := inspectField(name, "Config.User")
  1769  	if err != nil {
  1770  		t.Fatal(err)
  1771  	}
  1772  	if res != expected {
  1773  		t.Fatalf("User %s, expected %s", res, expected)
  1774  	}
  1775  	logDone("build - user")
  1776  }
  1777  
  1778  func TestBuildRelativeWorkdir(t *testing.T) {
  1779  	name := "testbuildrelativeworkdir"
  1780  	expected := "/test2/test3"
  1781  	defer deleteImages(name)
  1782  	_, err := buildImage(name,
  1783  		`FROM busybox
  1784  		RUN [ "$PWD" = '/' ]
  1785  		WORKDIR test1
  1786  		RUN [ "$PWD" = '/test1' ]
  1787  		WORKDIR /test2
  1788  		RUN [ "$PWD" = '/test2' ]
  1789  		WORKDIR test3
  1790  		RUN [ "$PWD" = '/test2/test3' ]`,
  1791  		true)
  1792  	if err != nil {
  1793  		t.Fatal(err)
  1794  	}
  1795  	res, err := inspectField(name, "Config.WorkingDir")
  1796  	if err != nil {
  1797  		t.Fatal(err)
  1798  	}
  1799  	if res != expected {
  1800  		t.Fatalf("Workdir %s, expected %s", res, expected)
  1801  	}
  1802  	logDone("build - relative workdir")
  1803  }
  1804  
  1805  func TestBuildWorkdirWithEnvVariables(t *testing.T) {
  1806  	name := "testbuildworkdirwithenvvariables"
  1807  	expected := "/test1/test2/$MISSING_VAR"
  1808  	defer deleteImages(name)
  1809  	_, err := buildImage(name,
  1810  		`FROM busybox
  1811  		ENV DIRPATH /test1
  1812  		ENV SUBDIRNAME test2
  1813  		WORKDIR $DIRPATH
  1814  		WORKDIR $SUBDIRNAME/$MISSING_VAR`,
  1815  		true)
  1816  	if err != nil {
  1817  		t.Fatal(err)
  1818  	}
  1819  	res, err := inspectField(name, "Config.WorkingDir")
  1820  	if err != nil {
  1821  		t.Fatal(err)
  1822  	}
  1823  	if res != expected {
  1824  		t.Fatalf("Workdir %s, expected %s", res, expected)
  1825  	}
  1826  	logDone("build - workdir with env variables")
  1827  }
  1828  
  1829  func TestBuildEnv(t *testing.T) {
  1830  	name := "testbuildenv"
  1831  	expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
  1832  	defer deleteImages(name)
  1833  	_, err := buildImage(name,
  1834  		`FROM busybox
  1835  		ENV PATH /test:$PATH
  1836          ENV PORT 2375
  1837  		RUN [ $(env | grep PORT) = 'PORT=2375' ]`,
  1838  		true)
  1839  	if err != nil {
  1840  		t.Fatal(err)
  1841  	}
  1842  	res, err := inspectField(name, "Config.Env")
  1843  	if err != nil {
  1844  		t.Fatal(err)
  1845  	}
  1846  	if res != expected {
  1847  		t.Fatalf("Env %s, expected %s", res, expected)
  1848  	}
  1849  	logDone("build - env")
  1850  }
  1851  
  1852  func TestBuildContextCleanup(t *testing.T) {
  1853  	name := "testbuildcontextcleanup"
  1854  	defer deleteImages(name)
  1855  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  1856  	if err != nil {
  1857  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  1858  	}
  1859  	_, err = buildImage(name,
  1860  		`FROM scratch
  1861          ENTRYPOINT ["/bin/echo"]`,
  1862  		true)
  1863  	if err != nil {
  1864  		t.Fatal(err)
  1865  	}
  1866  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  1867  	if err != nil {
  1868  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  1869  	}
  1870  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  1871  		t.Fatalf("context should have been deleted, but wasn't")
  1872  	}
  1873  
  1874  	logDone("build - verify context cleanup works properly")
  1875  }
  1876  
  1877  func TestBuildContextCleanupFailedBuild(t *testing.T) {
  1878  	name := "testbuildcontextcleanup"
  1879  	defer deleteImages(name)
  1880  	defer deleteAllContainers()
  1881  	entries, err := ioutil.ReadDir("/var/lib/docker/tmp")
  1882  	if err != nil {
  1883  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  1884  	}
  1885  	_, err = buildImage(name,
  1886  		`FROM scratch
  1887  	RUN /non/existing/command`,
  1888  		true)
  1889  	if err == nil {
  1890  		t.Fatalf("expected build to fail, but it didn't")
  1891  	}
  1892  	entriesFinal, err := ioutil.ReadDir("/var/lib/docker/tmp")
  1893  	if err != nil {
  1894  		t.Fatalf("failed to list contents of tmp dir: %s", err)
  1895  	}
  1896  	if err = compareDirectoryEntries(entries, entriesFinal); err != nil {
  1897  		t.Fatalf("context should have been deleted, but wasn't")
  1898  	}
  1899  
  1900  	logDone("build - verify context cleanup works properly after a failed build")
  1901  }
  1902  
  1903  func TestBuildCmd(t *testing.T) {
  1904  	name := "testbuildcmd"
  1905  	expected := "[/bin/echo Hello World]"
  1906  	defer deleteImages(name)
  1907  	_, err := buildImage(name,
  1908  		`FROM scratch
  1909          CMD ["/bin/echo", "Hello World"]`,
  1910  		true)
  1911  	if err != nil {
  1912  		t.Fatal(err)
  1913  	}
  1914  	res, err := inspectField(name, "Config.Cmd")
  1915  	if err != nil {
  1916  		t.Fatal(err)
  1917  	}
  1918  	if res != expected {
  1919  		t.Fatalf("Cmd %s, expected %s", res, expected)
  1920  	}
  1921  	logDone("build - cmd")
  1922  }
  1923  
  1924  func TestBuildExpose(t *testing.T) {
  1925  	name := "testbuildexpose"
  1926  	expected := "map[2375/tcp:map[]]"
  1927  	defer deleteImages(name)
  1928  	_, err := buildImage(name,
  1929  		`FROM scratch
  1930          EXPOSE 2375`,
  1931  		true)
  1932  	if err != nil {
  1933  		t.Fatal(err)
  1934  	}
  1935  	res, err := inspectField(name, "Config.ExposedPorts")
  1936  	if err != nil {
  1937  		t.Fatal(err)
  1938  	}
  1939  	if res != expected {
  1940  		t.Fatalf("Exposed ports %s, expected %s", res, expected)
  1941  	}
  1942  	logDone("build - expose")
  1943  }
  1944  
  1945  func TestBuildEmptyEntrypointInheritance(t *testing.T) {
  1946  	name := "testbuildentrypointinheritance"
  1947  	name2 := "testbuildentrypointinheritance2"
  1948  	defer deleteImages(name, name2)
  1949  
  1950  	_, err := buildImage(name,
  1951  		`FROM busybox
  1952          ENTRYPOINT ["/bin/echo"]`,
  1953  		true)
  1954  	if err != nil {
  1955  		t.Fatal(err)
  1956  	}
  1957  	res, err := inspectField(name, "Config.Entrypoint")
  1958  	if err != nil {
  1959  		t.Fatal(err)
  1960  	}
  1961  
  1962  	expected := "[/bin/echo]"
  1963  	if res != expected {
  1964  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  1965  	}
  1966  
  1967  	_, err = buildImage(name2,
  1968  		fmt.Sprintf(`FROM %s
  1969          ENTRYPOINT []`, name),
  1970  		true)
  1971  	if err != nil {
  1972  		t.Fatal(err)
  1973  	}
  1974  	res, err = inspectField(name2, "Config.Entrypoint")
  1975  	if err != nil {
  1976  		t.Fatal(err)
  1977  	}
  1978  
  1979  	expected = "[]"
  1980  
  1981  	if res != expected {
  1982  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  1983  	}
  1984  
  1985  	logDone("build - empty entrypoint inheritance")
  1986  }
  1987  
  1988  func TestBuildEmptyEntrypoint(t *testing.T) {
  1989  	name := "testbuildentrypoint"
  1990  	defer deleteImages(name)
  1991  	expected := "[]"
  1992  
  1993  	_, err := buildImage(name,
  1994  		`FROM busybox
  1995          ENTRYPOINT []`,
  1996  		true)
  1997  	if err != nil {
  1998  		t.Fatal(err)
  1999  	}
  2000  	res, err := inspectField(name, "Config.Entrypoint")
  2001  	if err != nil {
  2002  		t.Fatal(err)
  2003  	}
  2004  	if res != expected {
  2005  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2006  	}
  2007  
  2008  	logDone("build - empty entrypoint")
  2009  }
  2010  
  2011  func TestBuildEntrypoint(t *testing.T) {
  2012  	name := "testbuildentrypoint"
  2013  	expected := "[/bin/echo]"
  2014  	defer deleteImages(name)
  2015  	_, err := buildImage(name,
  2016  		`FROM scratch
  2017          ENTRYPOINT ["/bin/echo"]`,
  2018  		true)
  2019  	if err != nil {
  2020  		t.Fatal(err)
  2021  	}
  2022  	res, err := inspectField(name, "Config.Entrypoint")
  2023  	if err != nil {
  2024  		t.Fatal(err)
  2025  	}
  2026  	if res != expected {
  2027  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2028  	}
  2029  
  2030  	logDone("build - entrypoint")
  2031  }
  2032  
  2033  // #6445 ensure ONBUILD triggers aren't committed to grandchildren
  2034  func TestBuildOnBuildLimitedInheritence(t *testing.T) {
  2035  	var (
  2036  		out2, out3 string
  2037  	)
  2038  	{
  2039  		name1 := "testonbuildtrigger1"
  2040  		dockerfile1 := `
  2041  		FROM busybox
  2042  		RUN echo "GRANDPARENT"
  2043  		ONBUILD RUN echo "ONBUILD PARENT"
  2044  		`
  2045  		ctx, err := fakeContext(dockerfile1, nil)
  2046  		if err != nil {
  2047  			t.Fatal(err)
  2048  		}
  2049  		defer ctx.Close()
  2050  
  2051  		out1, _, err := dockerCmdInDir(t, ctx.Dir, "build", "-t", name1, ".")
  2052  		if err != nil {
  2053  			t.Fatalf("build failed to complete: %s, %v", out1, err)
  2054  		}
  2055  		defer deleteImages(name1)
  2056  	}
  2057  	{
  2058  		name2 := "testonbuildtrigger2"
  2059  		dockerfile2 := `
  2060  		FROM testonbuildtrigger1
  2061  		`
  2062  		ctx, err := fakeContext(dockerfile2, nil)
  2063  		if err != nil {
  2064  			t.Fatal(err)
  2065  		}
  2066  		defer ctx.Close()
  2067  
  2068  		out2, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name2, ".")
  2069  		if err != nil {
  2070  			t.Fatalf("build failed to complete: %s, %v", out2, err)
  2071  		}
  2072  		defer deleteImages(name2)
  2073  	}
  2074  	{
  2075  		name3 := "testonbuildtrigger3"
  2076  		dockerfile3 := `
  2077  		FROM testonbuildtrigger2
  2078  		`
  2079  		ctx, err := fakeContext(dockerfile3, nil)
  2080  		if err != nil {
  2081  			t.Fatal(err)
  2082  		}
  2083  		defer ctx.Close()
  2084  
  2085  		out3, _, err = dockerCmdInDir(t, ctx.Dir, "build", "-t", name3, ".")
  2086  		if err != nil {
  2087  			t.Fatalf("build failed to complete: %s, %v", out3, err)
  2088  		}
  2089  
  2090  		defer deleteImages(name3)
  2091  	}
  2092  
  2093  	// ONBUILD should be run in second build.
  2094  	if !strings.Contains(out2, "ONBUILD PARENT") {
  2095  		t.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent")
  2096  	}
  2097  
  2098  	// ONBUILD should *not* be run in third build.
  2099  	if strings.Contains(out3, "ONBUILD PARENT") {
  2100  		t.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent")
  2101  	}
  2102  
  2103  	logDone("build - onbuild")
  2104  }
  2105  
  2106  func TestBuildWithCache(t *testing.T) {
  2107  	name := "testbuildwithcache"
  2108  	defer deleteImages(name)
  2109  	id1, err := buildImage(name,
  2110  		`FROM scratch
  2111  		MAINTAINER dockerio
  2112  		EXPOSE 5432
  2113          ENTRYPOINT ["/bin/echo"]`,
  2114  		true)
  2115  	if err != nil {
  2116  		t.Fatal(err)
  2117  	}
  2118  	id2, err := buildImage(name,
  2119  		`FROM scratch
  2120  		MAINTAINER dockerio
  2121  		EXPOSE 5432
  2122          ENTRYPOINT ["/bin/echo"]`,
  2123  		true)
  2124  	if err != nil {
  2125  		t.Fatal(err)
  2126  	}
  2127  	if id1 != id2 {
  2128  		t.Fatal("The cache should have been used but hasn't.")
  2129  	}
  2130  	logDone("build - with cache")
  2131  }
  2132  
  2133  func TestBuildWithoutCache(t *testing.T) {
  2134  	name := "testbuildwithoutcache"
  2135  	name2 := "testbuildwithoutcache2"
  2136  	defer deleteImages(name, name2)
  2137  	id1, err := buildImage(name,
  2138  		`FROM scratch
  2139  		MAINTAINER dockerio
  2140  		EXPOSE 5432
  2141          ENTRYPOINT ["/bin/echo"]`,
  2142  		true)
  2143  	if err != nil {
  2144  		t.Fatal(err)
  2145  	}
  2146  
  2147  	id2, err := buildImage(name2,
  2148  		`FROM scratch
  2149  		MAINTAINER dockerio
  2150  		EXPOSE 5432
  2151          ENTRYPOINT ["/bin/echo"]`,
  2152  		false)
  2153  	if err != nil {
  2154  		t.Fatal(err)
  2155  	}
  2156  	if id1 == id2 {
  2157  		t.Fatal("The cache should have been invalided but hasn't.")
  2158  	}
  2159  	logDone("build - without cache")
  2160  }
  2161  
  2162  func TestBuildADDLocalFileWithCache(t *testing.T) {
  2163  	name := "testbuildaddlocalfilewithcache"
  2164  	name2 := "testbuildaddlocalfilewithcache2"
  2165  	defer deleteImages(name, name2)
  2166  	dockerfile := `
  2167  		FROM busybox
  2168          MAINTAINER dockerio
  2169          ADD foo /usr/lib/bla/bar
  2170  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2171  	ctx, err := fakeContext(dockerfile, map[string]string{
  2172  		"foo": "hello",
  2173  	})
  2174  	defer ctx.Close()
  2175  	if err != nil {
  2176  		t.Fatal(err)
  2177  	}
  2178  	id1, err := buildImageFromContext(name, ctx, true)
  2179  	if err != nil {
  2180  		t.Fatal(err)
  2181  	}
  2182  	id2, err := buildImageFromContext(name2, ctx, true)
  2183  	if err != nil {
  2184  		t.Fatal(err)
  2185  	}
  2186  	if id1 != id2 {
  2187  		t.Fatal("The cache should have been used but hasn't.")
  2188  	}
  2189  	logDone("build - add local file with cache")
  2190  }
  2191  
  2192  func TestBuildADDMultipleLocalFileWithCache(t *testing.T) {
  2193  	name := "testbuildaddmultiplelocalfilewithcache"
  2194  	name2 := "testbuildaddmultiplelocalfilewithcache2"
  2195  	defer deleteImages(name, name2)
  2196  	dockerfile := `
  2197  		FROM busybox
  2198          MAINTAINER dockerio
  2199          ADD foo Dockerfile /usr/lib/bla/
  2200  		RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ]`
  2201  	ctx, err := fakeContext(dockerfile, map[string]string{
  2202  		"foo": "hello",
  2203  	})
  2204  	defer ctx.Close()
  2205  	if err != nil {
  2206  		t.Fatal(err)
  2207  	}
  2208  	id1, err := buildImageFromContext(name, ctx, true)
  2209  	if err != nil {
  2210  		t.Fatal(err)
  2211  	}
  2212  	id2, err := buildImageFromContext(name2, ctx, true)
  2213  	if err != nil {
  2214  		t.Fatal(err)
  2215  	}
  2216  	if id1 != id2 {
  2217  		t.Fatal("The cache should have been used but hasn't.")
  2218  	}
  2219  	logDone("build - add multiple local files with cache")
  2220  }
  2221  
  2222  func TestBuildADDLocalFileWithoutCache(t *testing.T) {
  2223  	name := "testbuildaddlocalfilewithoutcache"
  2224  	name2 := "testbuildaddlocalfilewithoutcache2"
  2225  	defer deleteImages(name, name2)
  2226  	dockerfile := `
  2227  		FROM busybox
  2228          MAINTAINER dockerio
  2229          ADD foo /usr/lib/bla/bar
  2230  		RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
  2231  	ctx, err := fakeContext(dockerfile, map[string]string{
  2232  		"foo": "hello",
  2233  	})
  2234  	defer ctx.Close()
  2235  	if err != nil {
  2236  		t.Fatal(err)
  2237  	}
  2238  	id1, err := buildImageFromContext(name, ctx, true)
  2239  	if err != nil {
  2240  		t.Fatal(err)
  2241  	}
  2242  	id2, err := buildImageFromContext(name2, ctx, false)
  2243  	if err != nil {
  2244  		t.Fatal(err)
  2245  	}
  2246  	if id1 == id2 {
  2247  		t.Fatal("The cache should have been invalided but hasn't.")
  2248  	}
  2249  	logDone("build - add local file without cache")
  2250  }
  2251  
  2252  func TestBuildCopyDirButNotFile(t *testing.T) {
  2253  	name := "testbuildcopydirbutnotfile"
  2254  	name2 := "testbuildcopydirbutnotfile2"
  2255  	defer deleteImages(name, name2)
  2256  	dockerfile := `
  2257          FROM scratch
  2258          COPY dir /tmp/`
  2259  	ctx, err := fakeContext(dockerfile, map[string]string{
  2260  		"dir/foo": "hello",
  2261  	})
  2262  	defer ctx.Close()
  2263  	if err != nil {
  2264  		t.Fatal(err)
  2265  	}
  2266  	id1, err := buildImageFromContext(name, ctx, true)
  2267  	if err != nil {
  2268  		t.Fatal(err)
  2269  	}
  2270  	// Check that adding file with similar name doesn't mess with cache
  2271  	if err := ctx.Add("dir_file", "hello2"); err != nil {
  2272  		t.Fatal(err)
  2273  	}
  2274  	id2, err := buildImageFromContext(name2, ctx, true)
  2275  	if err != nil {
  2276  		t.Fatal(err)
  2277  	}
  2278  	if id1 != id2 {
  2279  		t.Fatal("The cache should have been used but wasn't")
  2280  	}
  2281  	logDone("build - add current directory but not file")
  2282  }
  2283  
  2284  func TestBuildADDCurrentDirWithCache(t *testing.T) {
  2285  	name := "testbuildaddcurrentdirwithcache"
  2286  	name2 := name + "2"
  2287  	name3 := name + "3"
  2288  	name4 := name + "4"
  2289  	name5 := name + "5"
  2290  	defer deleteImages(name, name2, name3, name4, name5)
  2291  	dockerfile := `
  2292          FROM scratch
  2293          MAINTAINER dockerio
  2294          ADD . /usr/lib/bla`
  2295  	ctx, err := fakeContext(dockerfile, map[string]string{
  2296  		"foo": "hello",
  2297  	})
  2298  	defer ctx.Close()
  2299  	if err != nil {
  2300  		t.Fatal(err)
  2301  	}
  2302  	id1, err := buildImageFromContext(name, ctx, true)
  2303  	if err != nil {
  2304  		t.Fatal(err)
  2305  	}
  2306  	// Check that adding file invalidate cache of "ADD ."
  2307  	if err := ctx.Add("bar", "hello2"); err != nil {
  2308  		t.Fatal(err)
  2309  	}
  2310  	id2, err := buildImageFromContext(name2, ctx, true)
  2311  	if err != nil {
  2312  		t.Fatal(err)
  2313  	}
  2314  	if id1 == id2 {
  2315  		t.Fatal("The cache should have been invalided but hasn't.")
  2316  	}
  2317  	// Check that changing file invalidate cache of "ADD ."
  2318  	if err := ctx.Add("foo", "hello1"); err != nil {
  2319  		t.Fatal(err)
  2320  	}
  2321  	id3, err := buildImageFromContext(name3, ctx, true)
  2322  	if err != nil {
  2323  		t.Fatal(err)
  2324  	}
  2325  	if id2 == id3 {
  2326  		t.Fatal("The cache should have been invalided but hasn't.")
  2327  	}
  2328  	// Check that changing file to same content invalidate cache of "ADD ."
  2329  	time.Sleep(1 * time.Second) // wait second because of mtime precision
  2330  	if err := ctx.Add("foo", "hello1"); err != nil {
  2331  		t.Fatal(err)
  2332  	}
  2333  	id4, err := buildImageFromContext(name4, ctx, true)
  2334  	if err != nil {
  2335  		t.Fatal(err)
  2336  	}
  2337  	if id3 == id4 {
  2338  		t.Fatal("The cache should have been invalided but hasn't.")
  2339  	}
  2340  	id5, err := buildImageFromContext(name5, ctx, true)
  2341  	if err != nil {
  2342  		t.Fatal(err)
  2343  	}
  2344  	if id4 != id5 {
  2345  		t.Fatal("The cache should have been used but hasn't.")
  2346  	}
  2347  	logDone("build - add current directory with cache")
  2348  }
  2349  
  2350  func TestBuildADDCurrentDirWithoutCache(t *testing.T) {
  2351  	name := "testbuildaddcurrentdirwithoutcache"
  2352  	name2 := "testbuildaddcurrentdirwithoutcache2"
  2353  	defer deleteImages(name, name2)
  2354  	dockerfile := `
  2355          FROM scratch
  2356          MAINTAINER dockerio
  2357          ADD . /usr/lib/bla`
  2358  	ctx, err := fakeContext(dockerfile, map[string]string{
  2359  		"foo": "hello",
  2360  	})
  2361  	defer ctx.Close()
  2362  	if err != nil {
  2363  		t.Fatal(err)
  2364  	}
  2365  	id1, err := buildImageFromContext(name, ctx, true)
  2366  	if err != nil {
  2367  		t.Fatal(err)
  2368  	}
  2369  	id2, err := buildImageFromContext(name2, ctx, false)
  2370  	if err != nil {
  2371  		t.Fatal(err)
  2372  	}
  2373  	if id1 == id2 {
  2374  		t.Fatal("The cache should have been invalided but hasn't.")
  2375  	}
  2376  	logDone("build - add current directory without cache")
  2377  }
  2378  
  2379  func TestBuildADDRemoteFileWithCache(t *testing.T) {
  2380  	name := "testbuildaddremotefilewithcache"
  2381  	defer deleteImages(name)
  2382  	server, err := fakeStorage(map[string]string{
  2383  		"baz": "hello",
  2384  	})
  2385  	if err != nil {
  2386  		t.Fatal(err)
  2387  	}
  2388  	defer server.Close()
  2389  	id1, err := buildImage(name,
  2390  		fmt.Sprintf(`FROM scratch
  2391          MAINTAINER dockerio
  2392          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2393  		true)
  2394  	if err != nil {
  2395  		t.Fatal(err)
  2396  	}
  2397  	id2, err := buildImage(name,
  2398  		fmt.Sprintf(`FROM scratch
  2399          MAINTAINER dockerio
  2400          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2401  		true)
  2402  	if err != nil {
  2403  		t.Fatal(err)
  2404  	}
  2405  	if id1 != id2 {
  2406  		t.Fatal("The cache should have been used but hasn't.")
  2407  	}
  2408  	logDone("build - add remote file with cache")
  2409  }
  2410  
  2411  func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
  2412  	name := "testbuildaddremotefilewithoutcache"
  2413  	name2 := "testbuildaddremotefilewithoutcache2"
  2414  	defer deleteImages(name, name2)
  2415  	server, err := fakeStorage(map[string]string{
  2416  		"baz": "hello",
  2417  	})
  2418  	if err != nil {
  2419  		t.Fatal(err)
  2420  	}
  2421  	defer server.Close()
  2422  	id1, err := buildImage(name,
  2423  		fmt.Sprintf(`FROM scratch
  2424          MAINTAINER dockerio
  2425          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2426  		true)
  2427  	if err != nil {
  2428  		t.Fatal(err)
  2429  	}
  2430  	id2, err := buildImage(name2,
  2431  		fmt.Sprintf(`FROM scratch
  2432          MAINTAINER dockerio
  2433          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2434  		false)
  2435  	if err != nil {
  2436  		t.Fatal(err)
  2437  	}
  2438  	if id1 == id2 {
  2439  		t.Fatal("The cache should have been invalided but hasn't.")
  2440  	}
  2441  	logDone("build - add remote file without cache")
  2442  }
  2443  
  2444  func TestBuildADDRemoteFileMTime(t *testing.T) {
  2445  	name := "testbuildaddremotefilemtime"
  2446  	name2 := name + "2"
  2447  	name3 := name + "3"
  2448  	name4 := name + "4"
  2449  
  2450  	defer deleteImages(name, name2, name3, name4)
  2451  
  2452  	server, err := fakeStorage(map[string]string{"baz": "hello"})
  2453  	if err != nil {
  2454  		t.Fatal(err)
  2455  	}
  2456  	defer server.Close()
  2457  
  2458  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2459          MAINTAINER dockerio
  2460          ADD %s/baz /usr/lib/baz/quux`, server.URL), nil)
  2461  	if err != nil {
  2462  		t.Fatal(err)
  2463  	}
  2464  	defer ctx.Close()
  2465  
  2466  	id1, err := buildImageFromContext(name, ctx, true)
  2467  	if err != nil {
  2468  		t.Fatal(err)
  2469  	}
  2470  
  2471  	id2, err := buildImageFromContext(name2, ctx, true)
  2472  	if err != nil {
  2473  		t.Fatal(err)
  2474  	}
  2475  	if id1 != id2 {
  2476  		t.Fatal("The cache should have been used but wasn't - #1")
  2477  	}
  2478  
  2479  	// Now set baz's times to anything else and redo the build
  2480  	// This time the cache should not be used
  2481  	bazPath := path.Join(server.FakeContext.Dir, "baz")
  2482  	err = syscall.UtimesNano(bazPath, make([]syscall.Timespec, 2))
  2483  	if err != nil {
  2484  		t.Fatalf("Error setting mtime on %q: %v", bazPath, err)
  2485  	}
  2486  
  2487  	id3, err := buildImageFromContext(name3, ctx, true)
  2488  	if err != nil {
  2489  		t.Fatal(err)
  2490  	}
  2491  	if id1 == id3 {
  2492  		t.Fatal("The cache should not have been used but was")
  2493  	}
  2494  
  2495  	// And for good measure do it again and make sure cache is used this time
  2496  	id4, err := buildImageFromContext(name4, ctx, true)
  2497  	if err != nil {
  2498  		t.Fatal(err)
  2499  	}
  2500  	if id3 != id4 {
  2501  		t.Fatal("The cache should have been used but wasn't - #2")
  2502  	}
  2503  	logDone("build - add remote file testing mtime")
  2504  }
  2505  
  2506  func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
  2507  	name := "testbuildaddlocalandremotefilewithcache"
  2508  	defer deleteImages(name)
  2509  	server, err := fakeStorage(map[string]string{
  2510  		"baz": "hello",
  2511  	})
  2512  	if err != nil {
  2513  		t.Fatal(err)
  2514  	}
  2515  	defer server.Close()
  2516  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2517          MAINTAINER dockerio
  2518          ADD foo /usr/lib/bla/bar
  2519          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2520  		map[string]string{
  2521  			"foo": "hello world",
  2522  		})
  2523  	if err != nil {
  2524  		t.Fatal(err)
  2525  	}
  2526  	defer ctx.Close()
  2527  	id1, err := buildImageFromContext(name, ctx, true)
  2528  	if err != nil {
  2529  		t.Fatal(err)
  2530  	}
  2531  	id2, err := buildImageFromContext(name, ctx, true)
  2532  	if err != nil {
  2533  		t.Fatal(err)
  2534  	}
  2535  	if id1 != id2 {
  2536  		t.Fatal("The cache should have been used but hasn't.")
  2537  	}
  2538  	logDone("build - add local and remote file with cache")
  2539  }
  2540  
  2541  func testContextTar(t *testing.T, compression archive.Compression) {
  2542  	ctx, err := fakeContext(
  2543  		`FROM busybox
  2544  ADD foo /foo
  2545  CMD ["cat", "/foo"]`,
  2546  		map[string]string{
  2547  			"foo": "bar",
  2548  		},
  2549  	)
  2550  	defer ctx.Close()
  2551  	if err != nil {
  2552  		t.Fatal(err)
  2553  	}
  2554  	context, err := archive.Tar(ctx.Dir, compression)
  2555  	if err != nil {
  2556  		t.Fatalf("failed to build context tar: %v", err)
  2557  	}
  2558  	name := "contexttar"
  2559  	buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
  2560  	defer deleteImages(name)
  2561  	buildCmd.Stdin = context
  2562  
  2563  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  2564  		t.Fatalf("build failed to complete: %v %v", out, err)
  2565  	}
  2566  	logDone(fmt.Sprintf("build - build an image with a context tar, compression: %v", compression))
  2567  }
  2568  
  2569  func TestBuildContextTarGzip(t *testing.T) {
  2570  	testContextTar(t, archive.Gzip)
  2571  }
  2572  
  2573  func TestBuildContextTarNoCompression(t *testing.T) {
  2574  	testContextTar(t, archive.Uncompressed)
  2575  }
  2576  
  2577  func TestBuildNoContext(t *testing.T) {
  2578  	buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-")
  2579  	buildCmd.Stdin = strings.NewReader("FROM busybox\nCMD echo ok\n")
  2580  
  2581  	if out, _, err := runCommandWithOutput(buildCmd); err != nil {
  2582  		t.Fatalf("build failed to complete: %v %v", out, err)
  2583  	}
  2584  
  2585  	if out, _, err := dockerCmd(t, "run", "--rm", "nocontext"); out != "ok\n" || err != nil {
  2586  		t.Fatalf("run produced invalid output: %q, expected %q", out, "ok")
  2587  	}
  2588  
  2589  	deleteImages("nocontext")
  2590  	logDone("build - build an image with no context")
  2591  }
  2592  
  2593  // TODO: TestCaching
  2594  func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
  2595  	name := "testbuildaddlocalandremotefilewithoutcache"
  2596  	name2 := "testbuildaddlocalandremotefilewithoutcache2"
  2597  	defer deleteImages(name, name2)
  2598  	server, err := fakeStorage(map[string]string{
  2599  		"baz": "hello",
  2600  	})
  2601  	if err != nil {
  2602  		t.Fatal(err)
  2603  	}
  2604  	defer server.Close()
  2605  	ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
  2606          MAINTAINER dockerio
  2607          ADD foo /usr/lib/bla/bar
  2608          ADD %s/baz /usr/lib/baz/quux`, server.URL),
  2609  		map[string]string{
  2610  			"foo": "hello world",
  2611  		})
  2612  	if err != nil {
  2613  		t.Fatal(err)
  2614  	}
  2615  	defer ctx.Close()
  2616  	id1, err := buildImageFromContext(name, ctx, true)
  2617  	if err != nil {
  2618  		t.Fatal(err)
  2619  	}
  2620  	id2, err := buildImageFromContext(name2, ctx, false)
  2621  	if err != nil {
  2622  		t.Fatal(err)
  2623  	}
  2624  	if id1 == id2 {
  2625  		t.Fatal("The cache should have been invalided but hasn't.")
  2626  	}
  2627  	logDone("build - add local and remote file without cache")
  2628  }
  2629  
  2630  func TestBuildWithVolumeOwnership(t *testing.T) {
  2631  	name := "testbuildimg"
  2632  	defer deleteImages(name)
  2633  
  2634  	_, err := buildImage(name,
  2635  		`FROM busybox:latest
  2636          RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test
  2637          VOLUME /test`,
  2638  		true)
  2639  
  2640  	if err != nil {
  2641  		t.Fatal(err)
  2642  	}
  2643  
  2644  	cmd := exec.Command(dockerBinary, "run", "--rm", "testbuildimg", "ls", "-la", "/test")
  2645  	out, _, err := runCommandWithOutput(cmd)
  2646  	if err != nil {
  2647  		t.Fatal(out, err)
  2648  	}
  2649  
  2650  	if expected := "drw-------"; !strings.Contains(out, expected) {
  2651  		t.Fatalf("expected %s received %s", expected, out)
  2652  	}
  2653  
  2654  	if expected := "daemon   daemon"; !strings.Contains(out, expected) {
  2655  		t.Fatalf("expected %s received %s", expected, out)
  2656  	}
  2657  
  2658  	logDone("build - volume ownership")
  2659  }
  2660  
  2661  // testing #1405 - config.Cmd does not get cleaned up if
  2662  // utilizing cache
  2663  func TestBuildEntrypointRunCleanup(t *testing.T) {
  2664  	name := "testbuildcmdcleanup"
  2665  	defer deleteImages(name)
  2666  	if _, err := buildImage(name,
  2667  		`FROM busybox
  2668          RUN echo "hello"`,
  2669  		true); err != nil {
  2670  		t.Fatal(err)
  2671  	}
  2672  
  2673  	ctx, err := fakeContext(`FROM busybox
  2674          RUN echo "hello"
  2675          ADD foo /foo
  2676          ENTRYPOINT ["/bin/echo"]`,
  2677  		map[string]string{
  2678  			"foo": "hello",
  2679  		})
  2680  	defer ctx.Close()
  2681  	if err != nil {
  2682  		t.Fatal(err)
  2683  	}
  2684  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2685  		t.Fatal(err)
  2686  	}
  2687  	res, err := inspectField(name, "Config.Cmd")
  2688  	if err != nil {
  2689  		t.Fatal(err)
  2690  	}
  2691  	// Cmd must be cleaned up
  2692  	if expected := "<no value>"; res != expected {
  2693  		t.Fatalf("Cmd %s, expected %s", res, expected)
  2694  	}
  2695  	logDone("build - cleanup cmd after RUN")
  2696  }
  2697  
  2698  func TestBuildForbiddenContextPath(t *testing.T) {
  2699  	name := "testbuildforbidpath"
  2700  	defer deleteImages(name)
  2701  	ctx, err := fakeContext(`FROM scratch
  2702          ADD ../../ test/
  2703          `,
  2704  		map[string]string{
  2705  			"test.txt":  "test1",
  2706  			"other.txt": "other",
  2707  		})
  2708  	defer ctx.Close()
  2709  	if err != nil {
  2710  		t.Fatal(err)
  2711  	}
  2712  
  2713  	expected := "Forbidden path outside the build context: ../../ "
  2714  	if _, err := buildImageFromContext(name, ctx, true); err == nil || !strings.Contains(err.Error(), expected) {
  2715  		t.Fatalf("Wrong error: (should contain \"%s\") got:\n%v", expected, err)
  2716  	}
  2717  
  2718  	logDone("build - forbidden context path")
  2719  }
  2720  
  2721  func TestBuildADDFileNotFound(t *testing.T) {
  2722  	name := "testbuildaddnotfound"
  2723  	defer deleteImages(name)
  2724  	ctx, err := fakeContext(`FROM scratch
  2725          ADD foo /usr/local/bar`,
  2726  		map[string]string{"bar": "hello"})
  2727  	defer ctx.Close()
  2728  	if err != nil {
  2729  		t.Fatal(err)
  2730  	}
  2731  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2732  		if !strings.Contains(err.Error(), "foo: no such file or directory") {
  2733  			t.Fatalf("Wrong error %v, must be about missing foo file or directory", err)
  2734  		}
  2735  	} else {
  2736  		t.Fatal("Error must not be nil")
  2737  	}
  2738  	logDone("build - add file not found")
  2739  }
  2740  
  2741  func TestBuildInheritance(t *testing.T) {
  2742  	name := "testbuildinheritance"
  2743  	defer deleteImages(name)
  2744  
  2745  	_, err := buildImage(name,
  2746  		`FROM scratch
  2747  		EXPOSE 2375`,
  2748  		true)
  2749  	if err != nil {
  2750  		t.Fatal(err)
  2751  	}
  2752  	ports1, err := inspectField(name, "Config.ExposedPorts")
  2753  	if err != nil {
  2754  		t.Fatal(err)
  2755  	}
  2756  
  2757  	_, err = buildImage(name,
  2758  		fmt.Sprintf(`FROM %s
  2759  		ENTRYPOINT ["/bin/echo"]`, name),
  2760  		true)
  2761  	if err != nil {
  2762  		t.Fatal(err)
  2763  	}
  2764  
  2765  	res, err := inspectField(name, "Config.Entrypoint")
  2766  	if err != nil {
  2767  		t.Fatal(err)
  2768  	}
  2769  	if expected := "[/bin/echo]"; res != expected {
  2770  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  2771  	}
  2772  	ports2, err := inspectField(name, "Config.ExposedPorts")
  2773  	if err != nil {
  2774  		t.Fatal(err)
  2775  	}
  2776  	if ports1 != ports2 {
  2777  		t.Fatalf("Ports must be same: %s != %s", ports1, ports2)
  2778  	}
  2779  	logDone("build - inheritance")
  2780  }
  2781  
  2782  func TestBuildFails(t *testing.T) {
  2783  	name := "testbuildfails"
  2784  	defer deleteImages(name)
  2785  	defer deleteAllContainers()
  2786  	_, err := buildImage(name,
  2787  		`FROM busybox
  2788  		RUN sh -c "exit 23"`,
  2789  		true)
  2790  	if err != nil {
  2791  		if !strings.Contains(err.Error(), "returned a non-zero code: 23") {
  2792  			t.Fatalf("Wrong error %v, must be about non-zero code 23", err)
  2793  		}
  2794  	} else {
  2795  		t.Fatal("Error must not be nil")
  2796  	}
  2797  	logDone("build - fails")
  2798  }
  2799  
  2800  func TestBuildFailsDockerfileEmpty(t *testing.T) {
  2801  	name := "testbuildfails"
  2802  	defer deleteImages(name)
  2803  	_, err := buildImage(name, ``, true)
  2804  	if err != nil {
  2805  		if !strings.Contains(err.Error(), "Dockerfile cannot be empty") {
  2806  			t.Fatalf("Wrong error %v, must be about empty Dockerfile", err)
  2807  		}
  2808  	} else {
  2809  		t.Fatal("Error must not be nil")
  2810  	}
  2811  	logDone("build - fails with empty dockerfile")
  2812  }
  2813  
  2814  func TestBuildOnBuild(t *testing.T) {
  2815  	name := "testbuildonbuild"
  2816  	defer deleteImages(name)
  2817  	_, err := buildImage(name,
  2818  		`FROM busybox
  2819  		ONBUILD RUN touch foobar`,
  2820  		true)
  2821  	if err != nil {
  2822  		t.Fatal(err)
  2823  	}
  2824  	_, err = buildImage(name,
  2825  		fmt.Sprintf(`FROM %s
  2826  		RUN [ -f foobar ]`, name),
  2827  		true)
  2828  	if err != nil {
  2829  		t.Fatal(err)
  2830  	}
  2831  	logDone("build - onbuild")
  2832  }
  2833  
  2834  func TestBuildOnBuildForbiddenChained(t *testing.T) {
  2835  	name := "testbuildonbuildforbiddenchained"
  2836  	defer deleteImages(name)
  2837  	_, err := buildImage(name,
  2838  		`FROM busybox
  2839  		ONBUILD ONBUILD RUN touch foobar`,
  2840  		true)
  2841  	if err != nil {
  2842  		if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
  2843  			t.Fatalf("Wrong error %v, must be about chaining ONBUILD", err)
  2844  		}
  2845  	} else {
  2846  		t.Fatal("Error must not be nil")
  2847  	}
  2848  	logDone("build - onbuild forbidden chained")
  2849  }
  2850  
  2851  func TestBuildOnBuildForbiddenFrom(t *testing.T) {
  2852  	name := "testbuildonbuildforbiddenfrom"
  2853  	defer deleteImages(name)
  2854  	_, err := buildImage(name,
  2855  		`FROM busybox
  2856  		ONBUILD FROM scratch`,
  2857  		true)
  2858  	if err != nil {
  2859  		if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") {
  2860  			t.Fatalf("Wrong error %v, must be about FROM forbidden", err)
  2861  		}
  2862  	} else {
  2863  		t.Fatal("Error must not be nil")
  2864  	}
  2865  	logDone("build - onbuild forbidden from")
  2866  }
  2867  
  2868  func TestBuildOnBuildForbiddenMaintainer(t *testing.T) {
  2869  	name := "testbuildonbuildforbiddenmaintainer"
  2870  	defer deleteImages(name)
  2871  	_, err := buildImage(name,
  2872  		`FROM busybox
  2873  		ONBUILD MAINTAINER docker.io`,
  2874  		true)
  2875  	if err != nil {
  2876  		if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") {
  2877  			t.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err)
  2878  		}
  2879  	} else {
  2880  		t.Fatal("Error must not be nil")
  2881  	}
  2882  	logDone("build - onbuild forbidden maintainer")
  2883  }
  2884  
  2885  // gh #2446
  2886  func TestBuildAddToSymlinkDest(t *testing.T) {
  2887  	name := "testbuildaddtosymlinkdest"
  2888  	defer deleteImages(name)
  2889  	ctx, err := fakeContext(`FROM busybox
  2890          RUN mkdir /foo
  2891          RUN ln -s /foo /bar
  2892          ADD foo /bar/
  2893          RUN [ -f /bar/foo ]
  2894          RUN [ -f /foo/foo ]`,
  2895  		map[string]string{
  2896  			"foo": "hello",
  2897  		})
  2898  	if err != nil {
  2899  		t.Fatal(err)
  2900  	}
  2901  	defer ctx.Close()
  2902  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2903  		t.Fatal(err)
  2904  	}
  2905  	logDone("build - add to symlink destination")
  2906  }
  2907  
  2908  func TestBuildEscapeWhitespace(t *testing.T) {
  2909  	name := "testbuildescaping"
  2910  	defer deleteImages(name)
  2911  
  2912  	_, err := buildImage(name, `
  2913    FROM busybox
  2914    MAINTAINER "Docker \
  2915  IO <io@\
  2916  docker.com>"
  2917    `, true)
  2918  
  2919  	res, err := inspectField(name, "Author")
  2920  
  2921  	if err != nil {
  2922  		t.Fatal(err)
  2923  	}
  2924  
  2925  	if res != "Docker IO <io@docker.com>" {
  2926  		t.Fatal("Parsed string did not match the escaped string")
  2927  	}
  2928  
  2929  	logDone("build - validate escaping whitespace")
  2930  }
  2931  
  2932  func TestBuildDockerignore(t *testing.T) {
  2933  	name := "testbuilddockerignore"
  2934  	defer deleteImages(name)
  2935  	dockerfile := `
  2936          FROM busybox
  2937          ADD . /bla
  2938  		RUN [[ -f /bla/src/x.go ]]
  2939  		RUN [[ -f /bla/Makefile ]]
  2940  		RUN [[ ! -e /bla/src/_vendor ]]
  2941  		RUN [[ ! -e /bla/.gitignore ]]
  2942  		RUN [[ ! -e /bla/README.md ]]
  2943  		RUN [[ ! -e /bla/.git ]]`
  2944  	ctx, err := fakeContext(dockerfile, map[string]string{
  2945  		"Makefile":         "all:",
  2946  		".git/HEAD":        "ref: foo",
  2947  		"src/x.go":         "package main",
  2948  		"src/_vendor/v.go": "package main",
  2949  		".gitignore":       "",
  2950  		"README.md":        "readme",
  2951  		".dockerignore":    ".git\npkg\n.gitignore\nsrc/_vendor\n*.md",
  2952  	})
  2953  	defer ctx.Close()
  2954  	if err != nil {
  2955  		t.Fatal(err)
  2956  	}
  2957  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2958  		t.Fatal(err)
  2959  	}
  2960  	logDone("build - test .dockerignore")
  2961  }
  2962  
  2963  func TestBuildDockerignoreCleanPaths(t *testing.T) {
  2964  	name := "testbuilddockerignorecleanpaths"
  2965  	defer deleteImages(name)
  2966  	dockerfile := `
  2967          FROM busybox
  2968          ADD . /tmp/
  2969          RUN (! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)`
  2970  	ctx, err := fakeContext(dockerfile, map[string]string{
  2971  		"foo":           "foo",
  2972  		"foo2":          "foo2",
  2973  		"dir1/foo":      "foo in dir1",
  2974  		".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2",
  2975  	})
  2976  	if err != nil {
  2977  		t.Fatal(err)
  2978  	}
  2979  	defer ctx.Close()
  2980  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  2981  		t.Fatal(err)
  2982  	}
  2983  	logDone("build - test .dockerignore with clean paths")
  2984  }
  2985  
  2986  func TestBuildDockerignoringDockerfile(t *testing.T) {
  2987  	name := "testbuilddockerignoredockerfile"
  2988  	defer deleteImages(name)
  2989  	dockerfile := `
  2990          FROM scratch`
  2991  	ctx, err := fakeContext(dockerfile, map[string]string{
  2992  		"Dockerfile":    "FROM scratch",
  2993  		".dockerignore": "Dockerfile\n",
  2994  	})
  2995  	if err != nil {
  2996  		t.Fatal(err)
  2997  	}
  2998  	defer ctx.Close()
  2999  	if _, err = buildImageFromContext(name, ctx, true); err == nil {
  3000  		t.Fatalf("Didn't get expected error from ignoring Dockerfile")
  3001  	}
  3002  
  3003  	// now try it with ./Dockerfile
  3004  	ctx.Add(".dockerignore", "./Dockerfile\n")
  3005  	if _, err = buildImageFromContext(name, ctx, true); err == nil {
  3006  		t.Fatalf("Didn't get expected error from ignoring ./Dockerfile")
  3007  	}
  3008  
  3009  	logDone("build - test .dockerignore of Dockerfile")
  3010  }
  3011  
  3012  func TestBuildDockerignoringWholeDir(t *testing.T) {
  3013  	name := "testbuilddockerignorewholedir"
  3014  	defer deleteImages(name)
  3015  	dockerfile := `
  3016          FROM busybox
  3017  		COPY . /
  3018  		RUN [[ ! -e /.gitignore ]]
  3019  		RUN [[ -f /Makefile ]]`
  3020  	ctx, err := fakeContext(dockerfile, map[string]string{
  3021  		"Dockerfile":    "FROM scratch",
  3022  		"Makefile":      "all:",
  3023  		".dockerignore": ".*\n",
  3024  	})
  3025  	defer ctx.Close()
  3026  	if err != nil {
  3027  		t.Fatal(err)
  3028  	}
  3029  	if _, err = buildImageFromContext(name, ctx, true); err != nil {
  3030  		t.Fatal(err)
  3031  	}
  3032  	logDone("build - test .dockerignore whole dir with .*")
  3033  }
  3034  
  3035  func TestBuildLineBreak(t *testing.T) {
  3036  	name := "testbuildlinebreak"
  3037  	defer deleteImages(name)
  3038  	_, err := buildImage(name,
  3039  		`FROM  busybox
  3040  RUN    sh -c 'echo root:testpass \
  3041  	> /tmp/passwd'
  3042  RUN    mkdir -p /var/run/sshd
  3043  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3044  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3045  		true)
  3046  	if err != nil {
  3047  		t.Fatal(err)
  3048  	}
  3049  	logDone("build - line break with \\")
  3050  }
  3051  
  3052  func TestBuildEOLInLine(t *testing.T) {
  3053  	name := "testbuildeolinline"
  3054  	defer deleteImages(name)
  3055  	_, err := buildImage(name,
  3056  		`FROM   busybox
  3057  RUN    sh -c 'echo root:testpass > /tmp/passwd'
  3058  RUN    echo "foo \n bar"; echo "baz"
  3059  RUN    mkdir -p /var/run/sshd
  3060  RUN    [ "$(cat /tmp/passwd)" = "root:testpass" ]
  3061  RUN    [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]`,
  3062  		true)
  3063  	if err != nil {
  3064  		t.Fatal(err)
  3065  	}
  3066  	logDone("build - end of line in dockerfile instruction")
  3067  }
  3068  
  3069  func TestBuildCommentsShebangs(t *testing.T) {
  3070  	name := "testbuildcomments"
  3071  	defer deleteImages(name)
  3072  	_, err := buildImage(name,
  3073  		`FROM busybox
  3074  # This is an ordinary comment.
  3075  RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh
  3076  RUN [ ! -x /hello.sh ]
  3077  # comment with line break \
  3078  RUN chmod +x /hello.sh
  3079  RUN [ -x /hello.sh ]
  3080  RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ]
  3081  RUN [ "$(/hello.sh)" = "hello world" ]`,
  3082  		true)
  3083  	if err != nil {
  3084  		t.Fatal(err)
  3085  	}
  3086  	logDone("build - comments and shebangs")
  3087  }
  3088  
  3089  func TestBuildUsersAndGroups(t *testing.T) {
  3090  	name := "testbuildusers"
  3091  	defer deleteImages(name)
  3092  	_, err := buildImage(name,
  3093  		`FROM busybox
  3094  
  3095  # Make sure our defaults work
  3096  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ]
  3097  
  3098  # 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)
  3099  USER root
  3100  RUN [ "$(id -G):$(id -Gn)" = '0 10:root wheel' ]
  3101  
  3102  # Setup dockerio user and group
  3103  RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
  3104  RUN echo 'dockerio:x:1001:' >> /etc/group
  3105  
  3106  # Make sure we can switch to our user and all the information is exactly as we expect it to be
  3107  USER dockerio
  3108  RUN id -G
  3109  RUN id -Gn
  3110  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3111  
  3112  # Switch back to root and double check that worked exactly as we might expect it to
  3113  USER root
  3114  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ]
  3115  
  3116  # Add a "supplementary" group for our dockerio user
  3117  RUN echo 'supplementary:x:1002:dockerio' >> /etc/group
  3118  
  3119  # ... and then go verify that we get it like we expect
  3120  USER dockerio
  3121  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3122  USER 1001
  3123  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001 1002:dockerio supplementary' ]
  3124  
  3125  # super test the new "user:group" syntax
  3126  USER dockerio:dockerio
  3127  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3128  USER 1001:dockerio
  3129  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3130  USER dockerio:1001
  3131  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3132  USER 1001:1001
  3133  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/dockerio:dockerio/1001:dockerio' ]
  3134  USER dockerio:supplementary
  3135  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3136  USER dockerio:1002
  3137  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3138  USER 1001:supplementary
  3139  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3140  USER 1001:1002
  3141  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/dockerio:supplementary/1002:supplementary' ]
  3142  
  3143  # make sure unknown uid/gid still works properly
  3144  USER 1042:1043
  3145  RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`,
  3146  		true)
  3147  	if err != nil {
  3148  		t.Fatal(err)
  3149  	}
  3150  	logDone("build - users and groups")
  3151  }
  3152  
  3153  func TestBuildEnvUsage(t *testing.T) {
  3154  	name := "testbuildenvusage"
  3155  	defer deleteImages(name)
  3156  	dockerfile := `FROM busybox
  3157  ENV    HOME /root
  3158  ENV    PATH $HOME/bin:$PATH
  3159  ENV    PATH /tmp:$PATH
  3160  RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
  3161  ENV    FOO /foo/baz
  3162  ENV    BAR /bar
  3163  ENV    BAZ $BAR
  3164  ENV    FOOPATH $PATH:$FOO
  3165  RUN    [ "$BAR" = "$BAZ" ]
  3166  RUN    [ "$FOOPATH" = "$PATH:/foo/baz" ]
  3167  ENV	   FROM hello/docker/world
  3168  ENV    TO /docker/world/hello
  3169  ADD    $FROM $TO
  3170  RUN    [ "$(cat $TO)" = "hello" ]
  3171  `
  3172  	ctx, err := fakeContext(dockerfile, map[string]string{
  3173  		"hello/docker/world": "hello",
  3174  	})
  3175  	if err != nil {
  3176  		t.Fatal(err)
  3177  	}
  3178  	defer ctx.Close()
  3179  
  3180  	_, err = buildImageFromContext(name, ctx, true)
  3181  	if err != nil {
  3182  		t.Fatal(err)
  3183  	}
  3184  	logDone("build - environment variables usage")
  3185  }
  3186  
  3187  func TestBuildEnvUsage2(t *testing.T) {
  3188  	name := "testbuildenvusage2"
  3189  	defer deleteImages(name)
  3190  	dockerfile := `FROM busybox
  3191  ENV    abc=def
  3192  RUN    [ "$abc" = "def" ]
  3193  ENV    def="hello world"
  3194  RUN    [ "$def" = "hello world" ]
  3195  ENV    def=hello\ world
  3196  RUN    [ "$def" = "hello world" ]
  3197  ENV    v1=abc v2="hi there"
  3198  RUN    [ "$v1" = "abc" ]
  3199  RUN    [ "$v2" = "hi there" ]
  3200  ENV    v3='boogie nights' v4="with'quotes too"
  3201  RUN    [ "$v3" = "boogie nights" ]
  3202  RUN    [ "$v4" = "with'quotes too" ]
  3203  ENV    abc=zzz FROM=hello/docker/world
  3204  ENV    abc=zzz TO=/docker/world/hello
  3205  ADD    $FROM $TO
  3206  RUN    [ "$(cat $TO)" = "hello" ]
  3207  ENV    abc "zzz"
  3208  RUN    [ $abc = \"zzz\" ]
  3209  ENV    abc 'yyy'
  3210  RUN    [ $abc = \'yyy\' ]
  3211  ENV    abc=
  3212  RUN    [ "$abc" = "" ]
  3213  `
  3214  	ctx, err := fakeContext(dockerfile, map[string]string{
  3215  		"hello/docker/world": "hello",
  3216  	})
  3217  	if err != nil {
  3218  		t.Fatal(err)
  3219  	}
  3220  	_, err = buildImageFromContext(name, ctx, true)
  3221  	if err != nil {
  3222  		t.Fatal(err)
  3223  	}
  3224  	logDone("build - environment variables usage2")
  3225  }
  3226  
  3227  func TestBuildAddScript(t *testing.T) {
  3228  	name := "testbuildaddscript"
  3229  	defer deleteImages(name)
  3230  	dockerfile := `
  3231  FROM busybox
  3232  ADD test /test
  3233  RUN ["chmod","+x","/test"]
  3234  RUN ["/test"]
  3235  RUN [ "$(cat /testfile)" = 'test!' ]`
  3236  	ctx, err := fakeContext(dockerfile, map[string]string{
  3237  		"test": "#!/bin/sh\necho 'test!' > /testfile",
  3238  	})
  3239  	if err != nil {
  3240  		t.Fatal(err)
  3241  	}
  3242  	defer ctx.Close()
  3243  
  3244  	_, err = buildImageFromContext(name, ctx, true)
  3245  	if err != nil {
  3246  		t.Fatal(err)
  3247  	}
  3248  	logDone("build - add and run script")
  3249  }
  3250  
  3251  func TestBuildAddTar(t *testing.T) {
  3252  	name := "testbuildaddtar"
  3253  	defer deleteImages(name)
  3254  
  3255  	ctx := func() *FakeContext {
  3256  		dockerfile := `
  3257  FROM busybox
  3258  ADD test.tar /
  3259  RUN cat /test/foo | grep Hi
  3260  ADD test.tar /test.tar
  3261  RUN cat /test.tar/test/foo | grep Hi
  3262  ADD test.tar /unlikely-to-exist
  3263  RUN cat /unlikely-to-exist/test/foo | grep Hi
  3264  ADD test.tar /unlikely-to-exist-trailing-slash/
  3265  RUN cat /unlikely-to-exist-trailing-slash/test/foo | grep Hi
  3266  RUN mkdir /existing-directory
  3267  ADD test.tar /existing-directory
  3268  RUN cat /existing-directory/test/foo | grep Hi
  3269  ADD test.tar /existing-directory-trailing-slash/
  3270  RUN cat /existing-directory-trailing-slash/test/foo | grep Hi`
  3271  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3272  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3273  		if err != nil {
  3274  			t.Fatalf("failed to create test.tar archive: %v", err)
  3275  		}
  3276  		defer testTar.Close()
  3277  
  3278  		tw := tar.NewWriter(testTar)
  3279  
  3280  		if err := tw.WriteHeader(&tar.Header{
  3281  			Name: "test/foo",
  3282  			Size: 2,
  3283  		}); err != nil {
  3284  			t.Fatalf("failed to write tar file header: %v", err)
  3285  		}
  3286  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3287  			t.Fatalf("failed to write tar file content: %v", err)
  3288  		}
  3289  		if err := tw.Close(); err != nil {
  3290  			t.Fatalf("failed to close tar archive: %v", err)
  3291  		}
  3292  
  3293  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3294  			t.Fatalf("failed to open destination dockerfile: %v", err)
  3295  		}
  3296  		return &FakeContext{Dir: tmpDir}
  3297  	}()
  3298  	defer ctx.Close()
  3299  
  3300  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3301  		t.Fatalf("build failed to complete for TestBuildAddTar: %v", err)
  3302  	}
  3303  
  3304  	logDone("build - ADD tar")
  3305  }
  3306  
  3307  func TestBuildAddTarXz(t *testing.T) {
  3308  	name := "testbuildaddtarxz"
  3309  	defer deleteImages(name)
  3310  
  3311  	ctx := func() *FakeContext {
  3312  		dockerfile := `
  3313  			FROM busybox
  3314  			ADD test.tar.xz /
  3315  			RUN cat /test/foo | grep Hi`
  3316  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3317  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3318  		if err != nil {
  3319  			t.Fatalf("failed to create test.tar archive: %v", err)
  3320  		}
  3321  		defer testTar.Close()
  3322  
  3323  		tw := tar.NewWriter(testTar)
  3324  
  3325  		if err := tw.WriteHeader(&tar.Header{
  3326  			Name: "test/foo",
  3327  			Size: 2,
  3328  		}); err != nil {
  3329  			t.Fatalf("failed to write tar file header: %v", err)
  3330  		}
  3331  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3332  			t.Fatalf("failed to write tar file content: %v", err)
  3333  		}
  3334  		if err := tw.Close(); err != nil {
  3335  			t.Fatalf("failed to close tar archive: %v", err)
  3336  		}
  3337  		xzCompressCmd := exec.Command("xz", "test.tar")
  3338  		xzCompressCmd.Dir = tmpDir
  3339  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3340  		if err != nil {
  3341  			t.Fatal(err, out)
  3342  		}
  3343  
  3344  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3345  			t.Fatalf("failed to open destination dockerfile: %v", err)
  3346  		}
  3347  		return &FakeContext{Dir: tmpDir}
  3348  	}()
  3349  
  3350  	defer ctx.Close()
  3351  
  3352  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3353  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  3354  	}
  3355  
  3356  	logDone("build - ADD tar.xz")
  3357  }
  3358  
  3359  func TestBuildAddTarXzGz(t *testing.T) {
  3360  	name := "testbuildaddtarxzgz"
  3361  	defer deleteImages(name)
  3362  
  3363  	ctx := func() *FakeContext {
  3364  		dockerfile := `
  3365  			FROM busybox
  3366  			ADD test.tar.xz.gz /
  3367  			RUN ls /test.tar.xz.gz`
  3368  		tmpDir, err := ioutil.TempDir("", "fake-context")
  3369  		testTar, err := os.Create(filepath.Join(tmpDir, "test.tar"))
  3370  		if err != nil {
  3371  			t.Fatalf("failed to create test.tar archive: %v", err)
  3372  		}
  3373  		defer testTar.Close()
  3374  
  3375  		tw := tar.NewWriter(testTar)
  3376  
  3377  		if err := tw.WriteHeader(&tar.Header{
  3378  			Name: "test/foo",
  3379  			Size: 2,
  3380  		}); err != nil {
  3381  			t.Fatalf("failed to write tar file header: %v", err)
  3382  		}
  3383  		if _, err := tw.Write([]byte("Hi")); err != nil {
  3384  			t.Fatalf("failed to write tar file content: %v", err)
  3385  		}
  3386  		if err := tw.Close(); err != nil {
  3387  			t.Fatalf("failed to close tar archive: %v", err)
  3388  		}
  3389  
  3390  		xzCompressCmd := exec.Command("xz", "test.tar")
  3391  		xzCompressCmd.Dir = tmpDir
  3392  		out, _, err := runCommandWithOutput(xzCompressCmd)
  3393  		if err != nil {
  3394  			t.Fatal(err, out)
  3395  		}
  3396  
  3397  		gzipCompressCmd := exec.Command("gzip", "test.tar.xz")
  3398  		gzipCompressCmd.Dir = tmpDir
  3399  		out, _, err = runCommandWithOutput(gzipCompressCmd)
  3400  		if err != nil {
  3401  			t.Fatal(err, out)
  3402  		}
  3403  
  3404  		if err := ioutil.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644); err != nil {
  3405  			t.Fatalf("failed to open destination dockerfile: %v", err)
  3406  		}
  3407  		return &FakeContext{Dir: tmpDir}
  3408  	}()
  3409  
  3410  	defer ctx.Close()
  3411  
  3412  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3413  		t.Fatalf("build failed to complete for TestBuildAddTarXz: %v", err)
  3414  	}
  3415  
  3416  	logDone("build - ADD tar.xz.gz")
  3417  }
  3418  
  3419  func TestBuildFromGIT(t *testing.T) {
  3420  	name := "testbuildfromgit"
  3421  	defer deleteImages(name)
  3422  	git, err := fakeGIT("repo", map[string]string{
  3423  		"Dockerfile": `FROM busybox
  3424  					ADD first /first
  3425  					RUN [ -f /first ]
  3426  					MAINTAINER docker`,
  3427  		"first": "test git data",
  3428  	})
  3429  	if err != nil {
  3430  		t.Fatal(err)
  3431  	}
  3432  	defer git.Close()
  3433  
  3434  	_, err = buildImageFromPath(name, git.RepoURL, true)
  3435  	if err != nil {
  3436  		t.Fatal(err)
  3437  	}
  3438  	res, err := inspectField(name, "Author")
  3439  	if err != nil {
  3440  		t.Fatal(err)
  3441  	}
  3442  	if res != "docker" {
  3443  		t.Fatalf("Maintainer should be docker, got %s", res)
  3444  	}
  3445  	logDone("build - build from GIT")
  3446  }
  3447  
  3448  func TestBuildCleanupCmdOnEntrypoint(t *testing.T) {
  3449  	name := "testbuildcmdcleanuponentrypoint"
  3450  	defer deleteImages(name)
  3451  	if _, err := buildImage(name,
  3452  		`FROM scratch
  3453          CMD ["test"]
  3454  		ENTRYPOINT ["echo"]`,
  3455  		true); err != nil {
  3456  		t.Fatal(err)
  3457  	}
  3458  	if _, err := buildImage(name,
  3459  		fmt.Sprintf(`FROM %s
  3460  		ENTRYPOINT ["cat"]`, name),
  3461  		true); err != nil {
  3462  		t.Fatal(err)
  3463  	}
  3464  	res, err := inspectField(name, "Config.Cmd")
  3465  	if err != nil {
  3466  		t.Fatal(err)
  3467  	}
  3468  	if expected := "<no value>"; res != expected {
  3469  		t.Fatalf("Cmd %s, expected %s", res, expected)
  3470  	}
  3471  	res, err = inspectField(name, "Config.Entrypoint")
  3472  	if err != nil {
  3473  		t.Fatal(err)
  3474  	}
  3475  	if expected := "[cat]"; res != expected {
  3476  		t.Fatalf("Entrypoint %s, expected %s", res, expected)
  3477  	}
  3478  	logDone("build - cleanup cmd on ENTRYPOINT")
  3479  }
  3480  
  3481  func TestBuildClearCmd(t *testing.T) {
  3482  	name := "testbuildclearcmd"
  3483  	defer deleteImages(name)
  3484  	_, err := buildImage(name,
  3485  		`From scratch
  3486     ENTRYPOINT ["/bin/bash"]
  3487     CMD []`,
  3488  		true)
  3489  	if err != nil {
  3490  		t.Fatal(err)
  3491  	}
  3492  	res, err := inspectFieldJSON(name, "Config.Cmd")
  3493  	if err != nil {
  3494  		t.Fatal(err)
  3495  	}
  3496  	if res != "[]" {
  3497  		t.Fatalf("Cmd %s, expected %s", res, "[]")
  3498  	}
  3499  	logDone("build - clearcmd")
  3500  }
  3501  
  3502  func TestBuildEmptyCmd(t *testing.T) {
  3503  	name := "testbuildemptycmd"
  3504  	defer deleteImages(name)
  3505  	if _, err := buildImage(name, "FROM scratch\nMAINTAINER quux\n", true); err != nil {
  3506  		t.Fatal(err)
  3507  	}
  3508  	res, err := inspectFieldJSON(name, "Config.Cmd")
  3509  	if err != nil {
  3510  		t.Fatal(err)
  3511  	}
  3512  	if res != "null" {
  3513  		t.Fatalf("Cmd %s, expected %s", res, "null")
  3514  	}
  3515  	logDone("build - empty cmd")
  3516  }
  3517  
  3518  func TestBuildOnBuildOutput(t *testing.T) {
  3519  	name := "testbuildonbuildparent"
  3520  	defer deleteImages(name)
  3521  	if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil {
  3522  		t.Fatal(err)
  3523  	}
  3524  
  3525  	childname := "testbuildonbuildchild"
  3526  	defer deleteImages(childname)
  3527  
  3528  	_, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true)
  3529  	if err != nil {
  3530  		t.Fatal(err)
  3531  	}
  3532  
  3533  	if !strings.Contains(out, "Trigger 0, RUN echo foo") {
  3534  		t.Fatal("failed to find the ONBUILD output", out)
  3535  	}
  3536  
  3537  	logDone("build - onbuild output")
  3538  }
  3539  
  3540  func TestBuildInvalidTag(t *testing.T) {
  3541  	name := "abcd:" + makeRandomString(200)
  3542  	defer deleteImages(name)
  3543  	_, out, err := buildImageWithOut(name, "FROM scratch\nMAINTAINER quux\n", true)
  3544  	// if the error doesnt check for illegal tag name, or the image is built
  3545  	// then this should fail
  3546  	if !strings.Contains(out, "Illegal tag name") || strings.Contains(out, "Sending build context to Docker daemon") {
  3547  		t.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out)
  3548  	}
  3549  	logDone("build - invalid tag")
  3550  }
  3551  
  3552  func TestBuildCmdShDashC(t *testing.T) {
  3553  	name := "testbuildcmdshc"
  3554  	defer deleteImages(name)
  3555  	if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil {
  3556  		t.Fatal(err)
  3557  	}
  3558  
  3559  	res, err := inspectFieldJSON(name, "Config.Cmd")
  3560  	if err != nil {
  3561  		t.Fatal(err, res)
  3562  	}
  3563  
  3564  	expected := `["/bin/sh","-c","echo cmd"]`
  3565  
  3566  	if res != expected {
  3567  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3568  	}
  3569  
  3570  	logDone("build - cmd should have sh -c for non-json")
  3571  }
  3572  
  3573  func TestBuildCmdJSONNoShDashC(t *testing.T) {
  3574  	name := "testbuildcmdjson"
  3575  	defer deleteImages(name)
  3576  	if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil {
  3577  		t.Fatal(err)
  3578  	}
  3579  
  3580  	res, err := inspectFieldJSON(name, "Config.Cmd")
  3581  	if err != nil {
  3582  		t.Fatal(err, res)
  3583  	}
  3584  
  3585  	expected := `["echo","cmd"]`
  3586  
  3587  	if res != expected {
  3588  		t.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res)
  3589  	}
  3590  
  3591  	logDone("build - cmd should not have /bin/sh -c for json")
  3592  }
  3593  
  3594  func TestBuildIgnoreInvalidInstruction(t *testing.T) {
  3595  	name := "testbuildignoreinvalidinstruction"
  3596  	defer deleteImages(name)
  3597  
  3598  	out, _, err := buildImageWithOut(name, "FROM busybox\nfoo bar", true)
  3599  	if err != nil {
  3600  		t.Fatal(err, out)
  3601  	}
  3602  
  3603  	logDone("build - ignore invalid Dockerfile instruction")
  3604  }
  3605  
  3606  func TestBuildEntrypointInheritance(t *testing.T) {
  3607  	defer deleteImages("parent", "child")
  3608  	defer deleteAllContainers()
  3609  
  3610  	if _, err := buildImage("parent", `
  3611      FROM busybox
  3612      ENTRYPOINT exit 130
  3613      `, true); err != nil {
  3614  		t.Fatal(err)
  3615  	}
  3616  
  3617  	status, _ := runCommand(exec.Command(dockerBinary, "run", "parent"))
  3618  
  3619  	if status != 130 {
  3620  		t.Fatalf("expected exit code 130 but received %d", status)
  3621  	}
  3622  
  3623  	if _, err := buildImage("child", `
  3624      FROM parent
  3625      ENTRYPOINT exit 5
  3626      `, true); err != nil {
  3627  		t.Fatal(err)
  3628  	}
  3629  
  3630  	status, _ = runCommand(exec.Command(dockerBinary, "run", "child"))
  3631  
  3632  	if status != 5 {
  3633  		t.Fatalf("expected exit code 5 but received %d", status)
  3634  	}
  3635  
  3636  	logDone("build - clear entrypoint")
  3637  }
  3638  
  3639  func TestBuildEntrypointInheritanceInspect(t *testing.T) {
  3640  	var (
  3641  		name     = "testbuildepinherit"
  3642  		name2    = "testbuildepinherit2"
  3643  		expected = `["/bin/sh","-c","echo quux"]`
  3644  	)
  3645  
  3646  	defer deleteImages(name, name2)
  3647  	defer deleteAllContainers()
  3648  
  3649  	if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil {
  3650  		t.Fatal(err)
  3651  	}
  3652  
  3653  	if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil {
  3654  		t.Fatal(err)
  3655  	}
  3656  
  3657  	res, err := inspectFieldJSON(name2, "Config.Entrypoint")
  3658  	if err != nil {
  3659  		t.Fatal(err, res)
  3660  	}
  3661  
  3662  	if res != expected {
  3663  		t.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res)
  3664  	}
  3665  
  3666  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2))
  3667  	if err != nil {
  3668  		t.Fatal(err, out)
  3669  	}
  3670  
  3671  	expected = "quux"
  3672  
  3673  	if strings.TrimSpace(out) != expected {
  3674  		t.Fatalf("Expected output is %s, got %s", expected, out)
  3675  	}
  3676  
  3677  	logDone("build - entrypoint override inheritance properly")
  3678  }
  3679  
  3680  func TestBuildRunShEntrypoint(t *testing.T) {
  3681  	name := "testbuildentrypoint"
  3682  	defer deleteImages(name)
  3683  	_, err := buildImage(name,
  3684  		`FROM busybox
  3685                                  ENTRYPOINT /bin/echo`,
  3686  		true)
  3687  	if err != nil {
  3688  		t.Fatal(err)
  3689  	}
  3690  
  3691  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  3692  
  3693  	if err != nil {
  3694  		t.Fatal(err, out)
  3695  	}
  3696  
  3697  	logDone("build - entrypoint with /bin/echo running successfully")
  3698  }
  3699  
  3700  func TestBuildExoticShellInterpolation(t *testing.T) {
  3701  	name := "testbuildexoticshellinterpolation"
  3702  	defer deleteImages(name)
  3703  
  3704  	_, err := buildImage(name, `
  3705  		FROM busybox
  3706  		
  3707  		ENV SOME_VAR a.b.c
  3708  
  3709  		RUN [ "$SOME_VAR"       = 'a.b.c' ]
  3710  		RUN [ "${SOME_VAR}"     = 'a.b.c' ]
  3711  		RUN [ "${SOME_VAR%.*}"  = 'a.b'   ]
  3712  		RUN [ "${SOME_VAR%%.*}" = 'a'     ]
  3713  		RUN [ "${SOME_VAR#*.}"  = 'b.c'   ]
  3714  		RUN [ "${SOME_VAR##*.}" = 'c'     ]
  3715  		RUN [ "${SOME_VAR/c/d}" = 'a.b.d' ]
  3716  		RUN [ "${#SOME_VAR}"    = '5'     ]
  3717  
  3718  		RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = 'a.b.c' ]
  3719  		RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ]
  3720  		RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ]
  3721  		RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ]
  3722  	`, false)
  3723  	if err != nil {
  3724  		t.Fatal(err)
  3725  	}
  3726  
  3727  	logDone("build - exotic shell interpolation")
  3728  }
  3729  
  3730  func TestBuildVerifySingleQuoteFails(t *testing.T) {
  3731  	// This testcase is supposed to generate an error because the
  3732  	// JSON array we're passing in on the CMD uses single quotes instead
  3733  	// of double quotes (per the JSON spec). This means we interpret it
  3734  	// as a "string" insead of "JSON array" and pass it on to "sh -c" and
  3735  	// it should barf on it.
  3736  	name := "testbuildsinglequotefails"
  3737  	defer deleteImages(name)
  3738  	defer deleteAllContainers()
  3739  
  3740  	_, err := buildImage(name,
  3741  		`FROM busybox
  3742  		CMD [ '/bin/sh', '-c', 'echo hi' ]`,
  3743  		true)
  3744  	_, _, err = runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  3745  
  3746  	if err == nil {
  3747  		t.Fatal("The image was not supposed to be able to run")
  3748  	}
  3749  
  3750  	logDone("build - verify single quotes fail")
  3751  }
  3752  
  3753  func TestBuildVerboseOut(t *testing.T) {
  3754  	name := "testbuildverboseout"
  3755  	defer deleteImages(name)
  3756  
  3757  	_, out, err := buildImageWithOut(name,
  3758  		`FROM busybox
  3759  RUN echo 123`,
  3760  		false)
  3761  
  3762  	if err != nil {
  3763  		t.Fatal(err)
  3764  	}
  3765  	if !strings.Contains(out, "\n123\n") {
  3766  		t.Fatalf("Output should contain %q: %q", "123", out)
  3767  	}
  3768  
  3769  	logDone("build - verbose output from commands")
  3770  }
  3771  
  3772  func TestBuildWithTabs(t *testing.T) {
  3773  	name := "testbuildwithtabs"
  3774  	defer deleteImages(name)
  3775  	_, err := buildImage(name,
  3776  		"FROM busybox\nRUN echo\tone\t\ttwo", true)
  3777  	if err != nil {
  3778  		t.Fatal(err)
  3779  	}
  3780  	res, err := inspectFieldJSON(name, "ContainerConfig.Cmd")
  3781  	if err != nil {
  3782  		t.Fatal(err)
  3783  	}
  3784  	expected := "[\"/bin/sh\",\"-c\",\"echo\\u0009one\\u0009\\u0009two\"]"
  3785  	if res != expected {
  3786  		t.Fatalf("Missing tabs.\nGot:%s\nExp:%s", res, expected)
  3787  	}
  3788  	logDone("build - with tabs")
  3789  }
  3790  
  3791  func TestBuildStderr(t *testing.T) {
  3792  	// This test just makes sure that no non-error output goes
  3793  	// to stderr
  3794  	name := "testbuildstderr"
  3795  	defer deleteImages(name)
  3796  	_, _, stderr, err := buildImageWithStdoutStderr(name,
  3797  		"FROM busybox\nRUN echo one", true)
  3798  	if err != nil {
  3799  		t.Fatal(err)
  3800  	}
  3801  	if stderr != "" {
  3802  		t.Fatal("Stderr should have been empty, instead its: %q", stderr)
  3803  	}
  3804  	logDone("build - testing stderr")
  3805  }
  3806  
  3807  func TestBuildChownSingleFile(t *testing.T) {
  3808  	name := "testbuildchownsinglefile"
  3809  	defer deleteImages(name)
  3810  
  3811  	ctx, err := fakeContext(`
  3812  FROM busybox
  3813  COPY test /
  3814  RUN ls -l /test
  3815  RUN [ $(ls -l /test | awk '{print $3":"$4}') = 'root:root' ]
  3816  `, map[string]string{
  3817  		"test": "test",
  3818  	})
  3819  	if err != nil {
  3820  		t.Fatal(err)
  3821  	}
  3822  	defer ctx.Close()
  3823  
  3824  	if err := os.Chown(filepath.Join(ctx.Dir, "test"), 4242, 4242); err != nil {
  3825  		t.Fatal(err)
  3826  	}
  3827  
  3828  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3829  		t.Fatal(err)
  3830  	}
  3831  
  3832  	logDone("build - change permission on single file")
  3833  }
  3834  
  3835  func TestBuildSymlinkBreakout(t *testing.T) {
  3836  	name := "testbuildsymlinkbreakout"
  3837  	tmpdir, err := ioutil.TempDir("", name)
  3838  	if err != nil {
  3839  		t.Fatal(err)
  3840  	}
  3841  	defer os.RemoveAll(tmpdir)
  3842  	ctx := filepath.Join(tmpdir, "context")
  3843  	if err := os.MkdirAll(ctx, 0755); err != nil {
  3844  		t.Fatal(err)
  3845  	}
  3846  	if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte(`
  3847  	from busybox
  3848  	add symlink.tar /
  3849  	add inject /symlink/
  3850  	`), 0644); err != nil {
  3851  		t.Fatal(err)
  3852  	}
  3853  	inject := filepath.Join(ctx, "inject")
  3854  	if err := ioutil.WriteFile(inject, nil, 0644); err != nil {
  3855  		t.Fatal(err)
  3856  	}
  3857  	f, err := os.Create(filepath.Join(ctx, "symlink.tar"))
  3858  	if err != nil {
  3859  		t.Fatal(err)
  3860  	}
  3861  	w := tar.NewWriter(f)
  3862  	w.WriteHeader(&tar.Header{
  3863  		Name:     "symlink2",
  3864  		Typeflag: tar.TypeSymlink,
  3865  		Linkname: "/../../../../../../../../../../../../../../",
  3866  		Uid:      os.Getuid(),
  3867  		Gid:      os.Getgid(),
  3868  	})
  3869  	w.WriteHeader(&tar.Header{
  3870  		Name:     "symlink",
  3871  		Typeflag: tar.TypeSymlink,
  3872  		Linkname: filepath.Join("symlink2", tmpdir),
  3873  		Uid:      os.Getuid(),
  3874  		Gid:      os.Getgid(),
  3875  	})
  3876  	w.Close()
  3877  	f.Close()
  3878  	if _, err := buildImageFromContext(name, &FakeContext{Dir: ctx}, false); err != nil {
  3879  		t.Fatal(err)
  3880  	}
  3881  	if _, err := os.Lstat(filepath.Join(tmpdir, "inject")); err == nil {
  3882  		t.Fatal("symlink breakout - inject")
  3883  	} else if !os.IsNotExist(err) {
  3884  		t.Fatalf("unexpected error: %v", err)
  3885  	}
  3886  	logDone("build - symlink breakout")
  3887  }
  3888  
  3889  func TestBuildXZHost(t *testing.T) {
  3890  	name := "testbuildxzhost"
  3891  	defer deleteImages(name)
  3892  
  3893  	ctx, err := fakeContext(`
  3894  FROM busybox
  3895  ADD xz /usr/local/sbin/
  3896  RUN chmod 755 /usr/local/sbin/xz
  3897  ADD test.xz /
  3898  RUN [ ! -e /injected ]`,
  3899  		map[string]string{
  3900  			"test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" +
  3901  				"\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" +
  3902  				"\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21",
  3903  			"xz": "#!/bin/sh\ntouch /injected",
  3904  		})
  3905  
  3906  	if err != nil {
  3907  		t.Fatal(err)
  3908  	}
  3909  	defer ctx.Close()
  3910  
  3911  	if _, err := buildImageFromContext(name, ctx, true); err != nil {
  3912  		t.Fatal(err)
  3913  	}
  3914  
  3915  	logDone("build - xz host is being used")
  3916  }
  3917  
  3918  func TestBuildVolumesRetainContents(t *testing.T) {
  3919  	var (
  3920  		name     = "testbuildvolumescontent"
  3921  		expected = "some text"
  3922  	)
  3923  	defer deleteImages(name)
  3924  	ctx, err := fakeContext(`
  3925  FROM busybox
  3926  COPY content /foo/file
  3927  VOLUME /foo
  3928  CMD cat /foo/file`,
  3929  		map[string]string{
  3930  			"content": expected,
  3931  		})
  3932  	if err != nil {
  3933  		t.Fatal(err)
  3934  	}
  3935  	defer ctx.Close()
  3936  
  3937  	if _, err := buildImageFromContext(name, ctx, false); err != nil {
  3938  		t.Fatal(err)
  3939  	}
  3940  
  3941  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "--rm", name))
  3942  	if err != nil {
  3943  		t.Fatal(err)
  3944  	}
  3945  	if out != expected {
  3946  		t.Fatalf("expected file contents for /foo/file to be %q but received %q", expected, out)
  3947  	}
  3948  
  3949  	logDone("build - volumes retain contents in build")
  3950  }