github.com/oyvindsk/docker@v1.5.0/integration-cli/docker_cli_build_test.go (about)

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