diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index 53ea52b4d5..7755cef416 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -27,49 +27,29 @@ import ( ) func (s *DockerSuite) TestBuildJSONEmptyRun(c *check.C) { - name := "testbuildjsonemptyrun" - - _, err := buildImage( - name, - ` + buildImageSuccessfully(c, "testbuildjsonemptyrun", withDockerfile(` FROM busybox RUN [] - `, - true) - - if err != nil { - c.Fatal("error when dealing with a RUN statement with empty JSON array") - } - + `)) } func (s *DockerSuite) TestBuildShCmdJSONEntrypoint(c *check.C) { name := "testbuildshcmdjsonentrypoint" + expected := "/bin/sh -c echo test" + if daemonPlatform == "windows" { + expected = "cmd /S /C echo test" + } - _, err := buildImage( - name, - ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENTRYPOINT ["echo"] CMD echo test - `, - true) - if err != nil { - c.Fatal(err) - } - + `)) out, _ := dockerCmd(c, "run", "--rm", name) - if daemonPlatform == "windows" { - if !strings.Contains(out, "cmd /S /C echo test") { - c.Fatalf("CMD did not contain cmd /S /C echo test : %q", out) - } - } else { - if strings.TrimSpace(out) != "/bin/sh -c echo test" { - c.Fatalf("CMD did not contain /bin/sh -c : %q", out) - } + if strings.TrimSpace(out) != expected { + c.Fatalf("CMD did not contain %q : %q", expected, out) } - } func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) { @@ -77,21 +57,16 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementUser(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildenvironmentreplacement" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM scratch ENV user foo USER ${user} - `, true) - if err != nil { - c.Fatal(err) - } - + `)) res := inspectFieldJSON(c, name, "Config.User") if res != `"foo"` { c.Fatal("User foo from environment not in Config.User on image") } - } func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) { @@ -105,23 +80,14 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementVolume(c *check.C) { volumePath = "/quux" } - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM `+minimalBaseImage()+` ENV volume `+volumePath+` VOLUME ${volume} - `, true) - if err != nil { - c.Fatal(err) - } - - res := inspectFieldJSON(c, name, "Config.Volumes") + `)) var volumes map[string]interface{} - - if err := json.Unmarshal([]byte(res), &volumes); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Volumes", &volumes) if _, ok := volumes[volumePath]; !ok { c.Fatal("Volume " + volumePath + " from environment not in Config.Volumes on image") } @@ -133,27 +99,17 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildenvironmentreplacement" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM scratch ENV port 80 EXPOSE ${port} ENV ports " 99 100 " EXPOSE ${ports} - `, true) - if err != nil { - c.Fatal(err) - } - - res := inspectFieldJSON(c, name, "Config.ExposedPorts") + `)) var exposedPorts map[string]interface{} - - if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.ExposedPorts", &exposedPorts) exp := []int{80, 99, 100} - for _, p := range exp { tmp := fmt.Sprintf("%d/tcp", p) if _, ok := exposedPorts[tmp]; !ok { @@ -166,23 +122,28 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementExpose(c *check.C) { func (s *DockerSuite) TestBuildEnvironmentReplacementWorkdir(c *check.C) { name := "testbuildenvironmentreplacement" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENV MYWORKDIR /work RUN mkdir ${MYWORKDIR} WORKDIR ${MYWORKDIR} - `, true) + `)) + res := inspectFieldJSON(c, name, "Config.WorkingDir") - if err != nil { - c.Fatal(err) + expected := `"/work"` + if daemonPlatform == "windows" { + expected = `"C:\\work"` + } + if res != expected { + c.Fatalf("Workdir /workdir from environment not in Config.WorkingDir on image: %s", res) } - } func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) { name := "testbuildenvironmentreplacement" - ctx, err := fakeContext(` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM `+minimalBaseImage()+` ENV baz foo ENV quux bar @@ -194,23 +155,12 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementAddCopy(c *check.C) { COPY ${quux} ${dot} ADD ${zzz:-${fee}} ${dot} COPY ${zzz:-${gee}} ${dot} - `, - map[string]string{ - "foo": "test1", - "bar": "test2", - "fff": "test3", - "ggg": "test4", - }) - - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - + `), + withFile("foo", "test1"), + withFile("bar", "test2"), + withFile("fff", "test3"), + withFile("ggg", "test4"), + )) } func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) { @@ -218,8 +168,7 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildenvironmentreplacement" - _, err := buildImage(name, - ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENV foo zzz ENV bar ${foo} @@ -232,20 +181,10 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) { RUN [ "$abc3" = '$foo' ] && (echo "$abc3" | grep -q foo) ENV abc4 "\$foo" RUN [ "$abc4" = '$foo' ] && (echo "$abc4" | grep -q foo) - `, true) - - if err != nil { - c.Fatal(err) - } - - res := inspectFieldJSON(c, name, "Config.Env") + `)) envResult := []string{} - - if err = json.Unmarshal([]byte(res), &envResult); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Env", &envResult) found := false envCount := 0 @@ -279,114 +218,70 @@ func (s *DockerSuite) TestBuildEnvironmentReplacementEnv(c *check.C) { } -func (s *DockerSuite) TestBuildHandleEscapes(c *check.C) { +func (s *DockerSuite) TestBuildHandleEscapesInVolume(c *check.C) { // The volume paths used in this test are invalid on Windows testRequires(c, DaemonIsLinux) name := "testbuildhandleescapes" - _, err := buildImage(name, - ` + testCases := []struct { + volumeValue string + expected string + }{ + { + volumeValue: "${FOO}", + expected: "bar", + }, + { + volumeValue: `\${FOO}`, + expected: "${FOO}", + }, + // this test in particular provides *7* backslashes and expects 6 to come back. + // Like above, the first escape is swallowed and the rest are treated as + // literals, this one is just less obvious because of all the character noise. + { + volumeValue: `\\\\\\\${FOO}`, + expected: `\\\${FOO}`, + }, + } + + for _, tc := range testCases { + buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(` FROM scratch ENV FOO bar - VOLUME ${FOO} - `, true) + VOLUME %s + `, tc.volumeValue))) - if err != nil { - c.Fatal(err) + var result map[string]map[string]struct{} + inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result) + if _, ok := result[tc.expected]; !ok { + c.Fatalf("Could not find volume %s set from env foo in volumes table, got %q", tc.expected, result) + } + + // Remove the image for the next iteration + dockerCmd(c, "rmi", name) } - - var result map[string]map[string]struct{} - - res := inspectFieldJSON(c, name, "Config.Volumes") - - if err = json.Unmarshal([]byte(res), &result); err != nil { - c.Fatal(err) - } - - if _, ok := result["bar"]; !ok { - c.Fatalf("Could not find volume bar set from env foo in volumes table, got %q", result) - } - - deleteImages(name) - - _, err = buildImage(name, - ` - FROM scratch - ENV FOO bar - VOLUME \${FOO} - `, true) - - if err != nil { - c.Fatal(err) - } - - res = inspectFieldJSON(c, name, "Config.Volumes") - - if err = json.Unmarshal([]byte(res), &result); err != nil { - c.Fatal(err) - } - - if _, ok := result["${FOO}"]; !ok { - c.Fatalf("Could not find volume ${FOO} set from env foo in volumes table, got %q", result) - } - - deleteImages(name) - - // this test in particular provides *7* backslashes and expects 6 to come back. - // Like above, the first escape is swallowed and the rest are treated as - // literals, this one is just less obvious because of all the character noise. - - _, err = buildImage(name, - ` - FROM scratch - ENV FOO bar - VOLUME \\\\\\\${FOO} - `, true) - - if err != nil { - c.Fatal(err) - } - - res = inspectFieldJSON(c, name, "Config.Volumes") - - if err = json.Unmarshal([]byte(res), &result); err != nil { - c.Fatal(err) - } - - if _, ok := result[`\\\${FOO}`]; !ok { - c.Fatalf(`Could not find volume \\\${FOO} set from env foo in volumes table, got %q`, result) - } - } func (s *DockerSuite) TestBuildOnBuildLowercase(c *check.C) { name := "testbuildonbuildlowercase" name2 := "testbuildonbuildlowercase2" - _, err := buildImage(name, - ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox onbuild run echo quux - `, true) + `)) - if err != nil { - c.Fatal(err) - } - - _, out, err := buildImageWithOut(name2, fmt.Sprintf(` + result := buildImageNew(name2, withDockerfile(fmt.Sprintf(` FROM %s - `, name), true) + `, name))) + result.Assert(c, icmd.Success) - if err != nil { - c.Fatal(err) + if !strings.Contains(result.Combined(), "quux") { + c.Fatalf("Did not receive the expected echo text, got %s", result.Combined()) } - if !strings.Contains(out, "quux") { - c.Fatalf("Did not receive the expected echo text, got %s", out) - } - - if strings.Contains(out, "ONBUILD ONBUILD") { - c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out) + if strings.Contains(result.Combined(), "ONBUILD ONBUILD") { + c.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", result.Combined()) } } @@ -395,20 +290,13 @@ func (s *DockerSuite) TestBuildEnvEscapes(c *check.C) { // ENV expansions work differently in Windows testRequires(c, DaemonIsLinux) name := "testbuildenvescapes" - _, err := buildImage(name, - ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENV TEST foo CMD echo \$ - `, - true) - - if err != nil { - c.Fatal(err) - } + `)) out, _ := dockerCmd(c, "run", "-t", name) - if strings.TrimSpace(out) != "$" { c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out)) } @@ -419,77 +307,51 @@ func (s *DockerSuite) TestBuildEnvOverwrite(c *check.C) { // ENV expansions work differently in Windows testRequires(c, DaemonIsLinux) name := "testbuildenvoverwrite" - - _, err := buildImage(name, - ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENV TEST foo CMD echo ${TEST} - `, - true) - - if err != nil { - c.Fatal(err) - } + `)) out, _ := dockerCmd(c, "run", "-e", "TEST=bar", "-t", name) - if strings.TrimSpace(out) != "bar" { c.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out)) } } +// FIXME(vdemeester) why we disabled cache here ? func (s *DockerSuite) TestBuildOnBuildCmdEntrypointJSON(c *check.C) { name1 := "onbuildcmd" name2 := "onbuildgenerated" - _, err := buildImage(name1, ` + buildImageSuccessfully(c, name1, withDockerfile(` FROM busybox ONBUILD CMD ["hello world"] ONBUILD ENTRYPOINT ["echo"] -ONBUILD RUN ["true"]`, - false) +ONBUILD RUN ["true"]`)) - if err != nil { - c.Fatal(err) - } - - _, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false) - - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s`, name1))) out, _ := dockerCmd(c, "run", name2) - if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) { c.Fatalf("did not get echo output from onbuild. Got: %q", out) } } +// FIXME(vdemeester) why we disabled cache here ? func (s *DockerSuite) TestBuildOnBuildEntrypointJSON(c *check.C) { name1 := "onbuildcmd" name2 := "onbuildgenerated" - _, err := buildImage(name1, ` + buildImageSuccessfully(c, name1, withDockerfile(` FROM busybox -ONBUILD ENTRYPOINT ["echo"]`, - false) +ONBUILD ENTRYPOINT ["echo"]`)) - if err != nil { - c.Fatal(err) - } - - _, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false) - - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1))) out, _ := dockerCmd(c, "run", name2) - if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) { c.Fatal("got malformed output from onbuild", out) } @@ -626,8 +488,8 @@ ADD folder/file /test/changetarget`, func (s *DockerSuite) TestBuildAddSingleFileToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddimg" - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + buildImageSuccessfully(c, "testaddimg", withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -635,18 +497,8 @@ RUN chown dockerio.dockerio /exists ADD test_file / RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod), - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)), + withFile("test_file", "test1"))) } // Issue #3960: "ADD src ." hangs @@ -678,8 +530,8 @@ ADD test_file .`, func (s *DockerSuite) TestBuildAddSingleFileToExistDir(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddsinglefiletoexistdir" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testaddsinglefiletoexistdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN mkdir /exists @@ -688,18 +540,8 @@ RUN chown -R dockerio.dockerio /exists ADD test_file /exists/ RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ] RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_file", "test1"))) } func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) { @@ -712,8 +554,8 @@ func (s *DockerSuite) TestBuildCopyAddMultipleFiles(c *check.C) { } defer server.Close() - name := "testcopymultiplefilestofile" - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + buildImageSuccessfully(c, "testcopymultiplefilestofile", withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN mkdir /exists @@ -724,141 +566,75 @@ ADD test_file3 test_file4 %s/robots.txt /exists/ RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ] RUN [ $(ls -l /exists/test_file1 | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /exists/test_file2 | awk '{print $3":"$4}') = 'root:root' ] - RUN [ $(ls -l /exists/test_file3 | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /exists/test_file4 | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /exists/robots.txt | awk '{print $3":"$4}') = 'root:root' ] - RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ] -`, server.URL()), - map[string]string{ - "test_file1": "test1", - "test_file2": "test2", - "test_file3": "test3", - "test_file4": "test4", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +`, server.URL())), + withFile("test_file1", "test1"), + withFile("test_file2", "test2"), + withFile("test_file3", "test3"), + withFile("test_file3", "test3"), + withFile("test_file4", "test4"))) } -// This test is mainly for user namespaces to verify that new directories +// These tests are mainly for user namespaces to verify that new directories // are created as the remapped root uid/gid pair -func (s *DockerSuite) TestBuildAddToNewDestination(c *check.C) { - testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddtonewdest" - ctx, err := fakeContext(`FROM busybox -ADD . /new_dir -RUN ls -l / -RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, - map[string]string{ - "test_dir/test_file": "test file", - }) - if err != nil { - c.Fatal(err) +func (s *DockerSuite) TestBuildUsernamespaceValidateRemappedRoot(c *check.C) { + testRequires(c, DaemonIsLinux) + testCases := []string{ + "ADD . /new_dir", + "COPY test_dir /new_dir", + "WORKDIR /new_dir", } - defer ctx.Close() + name := "testbuildusernamespacevalidateremappedroot" + for _, tc := range testCases { + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox +%s +RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, tc)), + withFile("test_dir/test_file", "test file"))) - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) + dockerCmd(c, "rmi", name) } } -// This test is mainly for user namespaces to verify that new directories -// are created as the remapped root uid/gid pair -func (s *DockerSuite) TestBuildCopyToNewParentDirectory(c *check.C) { - testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopytonewdir" - ctx, err := fakeContext(`FROM busybox -COPY test_dir /new_dir -RUN ls -l /new_dir -RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, - map[string]string{ - "test_dir/test_file": "test file", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } -} - -// This test is mainly for user namespaces to verify that new directories -// are created as the remapped root uid/gid pair -func (s *DockerSuite) TestBuildWorkdirIsContainerRoot(c *check.C) { - testRequires(c, DaemonIsLinux) // Linux specific test - name := "testworkdirownership" - if _, err := buildImage(name, `FROM busybox -WORKDIR /new_dir -RUN ls -l / -RUN [ $(ls -l / | grep new_dir | awk '{print $3":"$4}') = 'root:root' ]`, true); err != nil { - c.Fatal(err) - } -} - -func (s *DockerSuite) TestBuildAddFileWithWhitespace(c *check.C) { +func (s *DockerSuite) TestBuildAddAndCopyFileWithWhitespace(c *check.C) { testRequires(c, DaemonIsLinux) // Not currently passing on Windows name := "testaddfilewithwhitespace" - ctx, err := fakeContext(`FROM busybox + + for _, command := range []string{"ADD", "COPY"} { + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN mkdir "/test dir" RUN mkdir "/test_dir" -ADD [ "test file1", "/test_file1" ] -ADD [ "test_file2", "/test file2" ] -ADD [ "test file3", "/test file3" ] -ADD [ "test dir/test_file4", "/test_dir/test_file4" ] -ADD [ "test_dir/test_file5", "/test dir/test_file5" ] -ADD [ "test dir/test_file6", "/test dir/test_file6" ] +%s [ "test file1", "/test_file1" ] +%s [ "test_file2", "/test file2" ] +%s [ "test file3", "/test file3" ] +%s [ "test dir/test_file4", "/test_dir/test_file4" ] +%s [ "test_dir/test_file5", "/test dir/test_file5" ] +%s [ "test dir/test_file6", "/test dir/test_file6" ] RUN [ $(cat "/test_file1") = 'test1' ] RUN [ $(cat "/test file2") = 'test2' ] RUN [ $(cat "/test file3") = 'test3' ] RUN [ $(cat "/test_dir/test_file4") = 'test4' ] RUN [ $(cat "/test dir/test_file5") = 'test5' ] -RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, - map[string]string{ - "test file1": "test1", - "test_file2": "test2", - "test file3": "test3", - "test dir/test_file4": "test4", - "test_dir/test_file5": "test5", - "test dir/test_file6": "test6", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() +RUN [ $(cat "/test dir/test_file6") = 'test6' ]`, command, command, command, command, command, command)), + withFile("test file1", "test1"), + withFile("test_file2", "test2"), + withFile("test file3", "test3"), + withFile("test dir/test_file4", "test4"), + withFile("test_dir/test_file5", "test5"), + withFile("test dir/test_file6", "test6"), + )) - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) + dockerCmd(c, "rmi", name) } } -func (s *DockerSuite) TestBuildCopyFileWithWhitespace(c *check.C) { - dockerfile := `FROM busybox -RUN mkdir "/test dir" -RUN mkdir "/test_dir" -COPY [ "test file1", "/test_file1" ] -COPY [ "test_file2", "/test file2" ] -COPY [ "test file3", "/test file3" ] -COPY [ "test dir/test_file4", "/test_dir/test_file4" ] -COPY [ "test_dir/test_file5", "/test dir/test_file5" ] -COPY [ "test dir/test_file6", "/test dir/test_file6" ] -RUN [ $(cat "/test_file1") = 'test1' ] -RUN [ $(cat "/test file2") = 'test2' ] -RUN [ $(cat "/test file3") = 'test3' ] -RUN [ $(cat "/test_dir/test_file4") = 'test4' ] -RUN [ $(cat "/test dir/test_file5") = 'test5' ] -RUN [ $(cat "/test dir/test_file6") = 'test6' ]` - - if daemonPlatform == "windows" { - dockerfile = `FROM ` + WindowsBaseImage + ` +func (s *DockerSuite) TestBuildCopyFileWithWhitespaceOnWindows(c *check.C) { + testRequires(c, DaemonIsWindows) + dockerfile := `FROM ` + WindowsBaseImage + ` RUN mkdir "C:/test dir" RUN mkdir "C:/test_dir" COPY [ "test file1", "/test_file1" ] @@ -873,26 +649,17 @@ RUN find "test3" "C:/test file3" RUN find "test4" "C:/test_dir/test_file4" RUN find "test5" "C:/test dir/test_file5" RUN find "test6" "C:/test dir/test_file6"` - } name := "testcopyfilewithwhitespace" - ctx, err := fakeContext(dockerfile, - map[string]string{ - "test file1": "test1", - "test_file2": "test2", - "test file3": "test3", - "test dir/test_file4": "test4", - "test_dir/test_file5": "test5", - "test dir/test_file6": "test6", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("test file1", "test1"), + withFile("test_file2", "test2"), + withFile("test file3", "test3"), + withFile("test dir/test_file4", "test4"), + withFile("test_dir/test_file5", "test5"), + withFile("test dir/test_file6", "test6"), + )) } func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) { @@ -946,27 +713,23 @@ func (s *DockerSuite) TestBuildCopyWildcard(c *check.C) { } func (s *DockerSuite) TestBuildCopyWildcardInName(c *check.C) { - name := "testcopywildcardinname" - ctx, err := fakeContext(`FROM busybox + // Run this only on Linux + // Below is the original comment (that I don't agree with — vdemeester) + // Normally we would do c.Fatal(err) here but given that + // the odds of this failing are so rare, it must be because + // the OS we're running the client on doesn't support * in + // filenames (like windows). So, instead of failing the test + // just let it pass. Then we don't need to explicitly + // say which OSs this works on or not. + testRequires(c, DaemonIsLinux) + + buildImageSuccessfully(c, "testcopywildcardinname", withBuildContext(c, + withFile("Dockerfile", `FROM busybox COPY *.txt /tmp/ RUN [ "$(cat /tmp/\*.txt)" = 'hi there' ] - `, map[string]string{"*.txt": "hi there"}) - - if err != nil { - // Normally we would do c.Fatal(err) here but given that - // the odds of this failing are so rare, it must be because - // the OS we're running the client on doesn't support * in - // filenames (like windows). So, instead of failing the test - // just let it pass. Then we don't need to explicitly - // say which OSs this works on or not. - return - } - defer ctx.Close() - - _, err = buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatalf("should have built: %q", err) - } + `), + withFile("*.txt", "hi there"), + )) } func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) { @@ -1004,8 +767,8 @@ func (s *DockerSuite) TestBuildCopyWildcardCache(c *check.C) { func (s *DockerSuite) TestBuildAddSingleFileToNonExistingDir(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddsinglefiletononexistingdir" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testaddsinglefiletononexistingdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -1013,49 +776,28 @@ RUN chown dockerio.dockerio /exists ADD test_file /test_dir/ RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_file", "test1"))) } func (s *DockerSuite) TestBuildAddDirContentToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testadddircontenttoroot" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testadddircontenttoroot", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists RUN chown dockerio.dockerio exists ADD test_dir / RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_dir/test_file", "test1"))) } func (s *DockerSuite) TestBuildAddDirContentToExistingDir(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testadddircontenttoexistingdir" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testadddircontenttoexistingdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN mkdir /exists @@ -1064,24 +806,14 @@ RUN chown -R dockerio.dockerio /exists ADD test_dir/ /exists/ RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ] RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ] -RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`, - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`), + withFile("test_dir/test_file", "test1"))) } func (s *DockerSuite) TestBuildAddWholeDirToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddwholedirtoroot" - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + buildImageSuccessfully(c, "testaddwholedirtoroot", withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -1091,67 +823,40 @@ RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod), - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)), + withFile("test_dir/test_file", "test1"))) } -// Testing #5941 -func (s *DockerSuite) TestBuildAddEtcToRoot(c *check.C) { - name := "testaddetctoroot" - - ctx, err := fakeContext(`FROM `+minimalBaseImage()+` -ADD . /`, - map[string]string{ - "etc/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +// Testing #5941 : Having an etc directory in context conflicts with the /etc/mtab +func (s *DockerSuite) TestBuildAddOrCopyEtcToRootShouldNotConflict(c *check.C) { + buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c, + withFile("Dockerfile", `FROM `+minimalBaseImage()+` +ADD . /`), + withFile("etc/test_file", "test1"))) + buildImageSuccessfully(c, "testcopyetctoroot", withBuildContext(c, + withFile("Dockerfile", `FROM `+minimalBaseImage()+` +COPY . /`), + withFile("etc/test_file", "test1"))) } -// Testing #9401 +// Testing #9401 : Losing setuid flag after a ADD func (s *DockerSuite) TestBuildAddPreservesFilesSpecialBits(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testaddpreservesfilesspecialbits" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testaddetctoroot", withBuildContext(c, + withFile("Dockerfile", `FROM busybox ADD suidbin /usr/bin/suidbin RUN chmod 4755 /usr/bin/suidbin RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ] ADD ./data/ / -RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`, - map[string]string{ - "suidbin": "suidbin", - "/data/usr/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /usr/bin/suidbin | awk '{print $1}') = '-rwsr-xr-x' ]`), + withFile("suidbin", "suidbin"), + withFile("/data/usr/test_file", "test1"))) } func (s *DockerSuite) TestBuildCopySingleFileToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopysinglefiletoroot" - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + buildImageSuccessfully(c, "testcopysinglefiletoroot", withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -1159,18 +864,8 @@ RUN chown dockerio.dockerio /exists COPY test_file / RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_file | awk '{print $1}') = '%s' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod), - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)), + withFile("test_file", "test1"))) } // Issue #3960: "ADD src ." hangs - adapted for COPY @@ -1202,8 +897,8 @@ COPY test_file .`, func (s *DockerSuite) TestBuildCopySingleFileToExistDir(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopysinglefiletoexistdir" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testcopysinglefiletoexistdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN mkdir /exists @@ -1212,24 +907,14 @@ RUN chown -R dockerio.dockerio /exists COPY test_file /exists/ RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ] RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_file", "test1"))) } func (s *DockerSuite) TestBuildCopySingleFileToNonExistDir(c *check.C) { - testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopysinglefiletononexistdir" - ctx, err := fakeContext(`FROM busybox + testRequires(c, DaemonIsLinux) // Linux specific + buildImageSuccessfully(c, "testcopysinglefiletononexistdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -1237,48 +922,28 @@ RUN chown dockerio.dockerio /exists COPY test_file /test_dir/ RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_file", "test1"))) } func (s *DockerSuite) TestBuildCopyDirContentToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopydircontenttoroot" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testcopydircontenttoroot", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists RUN chown dockerio.dockerio exists COPY test_dir / RUN [ $(ls -l /test_file | awk '{print $3":"$4}') = 'root:root' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`), + withFile("test_dir/test_file", "test1"))) } func (s *DockerSuite) TestBuildCopyDirContentToExistDir(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopydircontenttoexistdir" - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, "testcopydircontenttoexistdir", withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN mkdir /exists @@ -1287,24 +952,14 @@ RUN chown -R dockerio.dockerio /exists COPY test_dir/ /exists/ RUN [ $(ls -l / | grep exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ] RUN [ $(ls -l /exists/exists_file | awk '{print $3":"$4}') = 'dockerio:dockerio' ] -RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`, - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists/test_file | awk '{print $3":"$4}') = 'root:root' ]`), + withFile("test_dir/test_file", "test1"))) } func (s *DockerSuite) TestBuildCopyWholeDirToRoot(c *check.C) { testRequires(c, DaemonIsLinux) // Linux specific test - name := "testcopywholedirtoroot" - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + buildImageSuccessfully(c, "testcopywholedirtoroot", withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd RUN echo 'dockerio:x:1001:' >> /etc/group RUN touch /exists @@ -1314,36 +969,8 @@ RUN [ $(ls -l / | grep test_dir | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l / | grep test_dir | awk '{print $1}') = 'drwxr-xr-x' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $3":"$4}') = 'root:root' ] RUN [ $(ls -l /test_dir/test_file | awk '{print $1}') = '%s' ] -RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod), - map[string]string{ - "test_dir/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } -} - -func (s *DockerSuite) TestBuildCopyEtcToRoot(c *check.C) { - name := "testcopyetctoroot" - - ctx, err := fakeContext(`FROM `+minimalBaseImage()+` -COPY . /`, - map[string]string{ - "etc/test_file": "test1", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +RUN [ $(ls -l /exists | awk '{print $3":"$4}') = 'dockerio:dockerio' ]`, expectedFileChmod)), + withFile("test_dir/test_file", "test1"))) } func (s *DockerSuite) TestBuildAddBadLinks(c *check.C) { @@ -1504,19 +1131,20 @@ func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) { if err = os.Chmod(pathToFileWithoutReadAccess, 0700); err != nil { c.Fatalf("failed to chmod file to 700: %s", err) } - buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)) - buildCmd.Dir = ctx.Dir - out, _, err := runCommandWithOutput(buildCmd) - if err == nil { - c.Fatalf("build should have failed: %s %s", err, out) + result := icmd.RunCmd(icmd.Cmd{ + Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)}, + Dir: ctx.Dir, + }) + if result.Error == nil { + c.Fatalf("build should have failed: %s %s", result.Error, result.Combined()) } // check if we've detected the failure before we started building - if !strings.Contains(out, "no permission to read from ") { - c.Fatalf("output should've contained the string: no permission to read from but contained: %s", out) + if !strings.Contains(result.Combined(), "no permission to read from ") { + c.Fatalf("output should've contained the string: no permission to read from but contained: %s", result.Combined()) } - if !strings.Contains(out, "Error checking context") { + if !strings.Contains(result.Combined(), "Error checking context") { c.Fatalf("output should've contained the string: Error checking context") } } @@ -1541,20 +1169,21 @@ func (s *DockerSuite) TestBuildWithInaccessibleFilesInContext(c *check.C) { c.Fatalf("failed to chmod file to 700: %s", err) } - buildCmd := exec.Command("su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)) - buildCmd.Dir = ctx.Dir - out, _, err := runCommandWithOutput(buildCmd) - if err == nil { - c.Fatalf("build should have failed: %s %s", err, out) + result := icmd.RunCmd(icmd.Cmd{ + Command: []string{"su", "unprivilegeduser", "-c", fmt.Sprintf("%s build -t %s .", dockerBinary, name)}, + Dir: ctx.Dir, + }) + if result.Error == nil { + c.Fatalf("build should have failed: %s %s", result.Error, result.Combined()) } // check if we've detected the failure before we started building - if !strings.Contains(out, "can't stat") { - c.Fatalf("output should've contained the string: can't access %s", out) + if !strings.Contains(result.Combined(), "can't stat") { + c.Fatalf("output should've contained the string: can't access %s", result.Combined()) } - if !strings.Contains(out, "Error checking context") { - c.Fatalf("output should've contained the string: Error checking context\ngot:%s", out) + if !strings.Contains(result.Combined(), "Error checking context") { + c.Fatalf("output should've contained the string: Error checking context\ngot:%s", result.Combined()) } } @@ -1617,15 +1246,12 @@ func (s *DockerSuite) TestBuildForceRm(c *check.C) { } name := "testbuildforcerm" - ctx, err := fakeContext(`FROM `+minimalBaseImage()+` + buildImageNew(name, withBuildFlags("--force-rm"), withBuildContext(c, + withFile("Dockerfile", `FROM `+minimalBaseImage()+` RUN true - RUN thiswillfail`, nil) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - dockerCmdInDir(c, ctx.Dir, "build", "-t", name, "--force-rm", ".") + RUN thiswillfail`))).Assert(c, icmd.Expected{ + ExitCode: 1, + }) containerCountAfter, err := getContainerCount() if err != nil { @@ -1641,83 +1267,51 @@ func (s *DockerSuite) TestBuildForceRm(c *check.C) { func (s *DockerSuite) TestBuildRm(c *check.C) { name := "testbuildrm" - ctx, err := fakeContext(`FROM `+minimalBaseImage()+` - ADD foo / - ADD foo /`, map[string]string{"foo": "bar"}) - if err != nil { - c.Fatal(err) + testCases := []struct { + buildflags []string + shouldLeftContainerBehind bool + }{ + // Default case (i.e. --rm=true) + { + buildflags: []string{}, + shouldLeftContainerBehind: false, + }, + { + buildflags: []string{"--rm"}, + shouldLeftContainerBehind: false, + }, + { + buildflags: []string{"--rm=false"}, + shouldLeftContainerBehind: true, + }, } - defer ctx.Close() - { + + for _, tc := range testCases { containerCountBefore, err := getContainerCount() if err != nil { c.Fatalf("failed to get the container count: %s", err) } - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm", "-t", name, ".") - - if err != nil { - c.Fatal("failed to build the image", out) - } + buildImageSuccessfully(c, name, withBuildFlags(tc.buildflags...), withDockerfile(`FROM busybox + RUN echo hello world`)) containerCountAfter, err := getContainerCount() if err != nil { c.Fatalf("failed to get the container count: %s", err) } - if containerCountBefore != containerCountAfter { - c.Fatalf("-rm shouldn't have left containers behind") + if tc.shouldLeftContainerBehind { + if containerCountBefore == containerCountAfter { + c.Fatalf("flags %v should have left containers behind", tc.buildflags) + } + } else { + if containerCountBefore != containerCountAfter { + c.Fatalf("flags %v shouldn't have left containers behind", tc.buildflags) + } } - deleteImages(name) + + dockerCmd(c, "rmi", name) } - - { - containerCountBefore, err := getContainerCount() - if err != nil { - c.Fatalf("failed to get the container count: %s", err) - } - - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name, ".") - - if err != nil { - c.Fatal("failed to build the image", out) - } - - containerCountAfter, err := getContainerCount() - if err != nil { - c.Fatalf("failed to get the container count: %s", err) - } - - if containerCountBefore != containerCountAfter { - c.Fatalf("--rm shouldn't have left containers behind") - } - deleteImages(name) - } - - { - containerCountBefore, err := getContainerCount() - if err != nil { - c.Fatalf("failed to get the container count: %s", err) - } - - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--rm=false", "-t", name, ".") - - if err != nil { - c.Fatal("failed to build the image", out) - } - - containerCountAfter, err := getContainerCount() - if err != nil { - c.Fatalf("failed to get the container count: %s", err) - } - - if containerCountBefore == containerCountAfter { - c.Fatalf("--rm=false should have left containers behind") - } - deleteImages(name) - - } - } func (s *DockerSuite) TestBuildWithVolumes(c *check.C) { @@ -1737,27 +1331,18 @@ func (s *DockerSuite) TestBuildWithVolumes(c *check.C) { "/test8]": emptyMap, } ) - _, err := buildImage(name, - `FROM scratch + + buildImageSuccessfully(c, name, withDockerfile(`FROM scratch VOLUME /test1 VOLUME /test2 VOLUME /test3 /test4 VOLUME ["/test5", "/test6"] VOLUME [/test7 /test8] - `, - true) - if err != nil { - c.Fatal(err) - } - res := inspectFieldJSON(c, name, "Config.Volumes") + `)) - err = json.Unmarshal([]byte(res), &result) - if err != nil { - c.Fatal(err) - } + inspectFieldAndUnmarshall(c, name, "Config.Volumes", &result) equal := reflect.DeepEqual(&result, &expected) - if !equal { c.Fatalf("Volumes %s, expected %s", result, expected) } @@ -1767,14 +1352,10 @@ func (s *DockerSuite) TestBuildWithVolumes(c *check.C) { func (s *DockerSuite) TestBuildMaintainer(c *check.C) { name := "testbuildmaintainer" + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + MAINTAINER dockerio`)) + expected := "dockerio" - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - MAINTAINER dockerio`, - true) - if err != nil { - c.Fatal(err) - } res := inspectField(c, name, "Author") if res != expected { c.Fatalf("Maintainer %s, expected %s", res, expected) @@ -1785,15 +1366,10 @@ func (s *DockerSuite) TestBuildUser(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuilduser" expected := "dockerio" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd USER dockerio - RUN [ $(whoami) = 'dockerio' ]`, - true) - if err != nil { - c.Fatal(err) - } + RUN [ $(whoami) = 'dockerio' ]`)) res := inspectField(c, name, "Config.User") if res != expected { c.Fatalf("User %s, expected %s", res, expected) @@ -1825,19 +1401,15 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) { expectedFinal = `/test2/test3` } - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox RUN sh -c "[ "$PWD" = "`+expected1+`" ]" WORKDIR test1 RUN sh -c "[ "$PWD" = "`+expected2+`" ]" WORKDIR /test2 RUN sh -c "[ "$PWD" = "`+expected3+`" ]" WORKDIR test3 - RUN sh -c "[ "$PWD" = "`+expected4+`" ]"`, - true) - if err != nil { - c.Fatal(err) - } + RUN sh -c "[ "$PWD" = "`+expected4+`" ]"`)) + res := inspectField(c, name, "Config.WorkingDir") if res != expectedFinal { c.Fatalf("Workdir %s, expected %s", res, expectedFinal) @@ -1848,30 +1420,23 @@ func (s *DockerSuite) TestBuildRelativeWorkdir(c *check.C) { // Windows semantics. Most path handling verifications are in unit tests func (s *DockerSuite) TestBuildWindowsWorkdirProcessing(c *check.C) { testRequires(c, DaemonIsWindows) - name := "testbuildwindowsworkdirprocessing" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, "testbuildwindowsworkdirprocessing", withDockerfile(`FROM busybox WORKDIR C:\\foo WORKDIR bar RUN sh -c "[ "$PWD" = "C:/foo/bar" ]" - `, - true) - if err != nil { - c.Fatal(err) - } + `)) } // #22181 Regression test. Most paths handling verifications are in unit test. // One functional test for end-to-end func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { testRequires(c, DaemonIsWindows) - name := "testbuildwindowsaddcopypathprocessing" // TODO Windows (@jhowardmsft). Needs a follow-up PR to 22181 to // support backslash such as .\\ being equivalent to ./ and c:\\ being // equivalent to c:/. This is not currently (nor ever has been) supported // by docker on the Windows platform. - dockerfile := ` - FROM busybox + buildImageSuccessfully(c, "testbuildwindowsaddcopypathprocessing", withBuildContext(c, + withFile("Dockerfile", `FROM busybox # No trailing slash on COPY/ADD # Results in dir being changed to a file WORKDIR /wc1 @@ -1889,21 +1454,12 @@ func (s *DockerSuite) TestBuildWindowsAddCopyPathProcessing(c *check.C) { ADD wd2 c:/wd2/ RUN sh -c "[ $(cat c:/wd1/wd1) = 'hellowd1' ]" RUN sh -c "[ $(cat c:/wd2/wd2) = 'worldwd2' ]" - ` - ctx, err := fakeContext(dockerfile, map[string]string{ - "wc1": "hellowc1", - "wc2": "worldwc2", - "wd1": "hellowd1", - "wd2": "worldwd2", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - _, err = buildImageFromContext(name, ctx, false) - if err != nil { - c.Fatal(err) - } + `), + withFile("wc1", "hellowc1"), + withFile("wc2", "worldwc2"), + withFile("wd1", "hellowd1"), + withFile("wd2", "worldwd2"), + )) } func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) { @@ -1916,16 +1472,11 @@ func (s *DockerSuite) TestBuildWorkdirWithEnvVariables(c *check.C) { expected = `/test1/test2` } - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox ENV DIRPATH /test1 ENV SUBDIRNAME test2 WORKDIR $DIRPATH - WORKDIR $SUBDIRNAME/$MISSING_VAR`, - true) - if err != nil { - c.Fatal(err) - } + WORKDIR $SUBDIRNAME/$MISSING_VAR`)) res := inspectField(c, name, "Config.WorkingDir") if res != expected { c.Fatalf("Workdir %s, expected %s", res, expected) @@ -1943,12 +1494,11 @@ func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) { expected = `/test1/test2` } - name := "testbuildrelativecopy" - dockerfile := ` - FROM busybox + buildImageSuccessfully(c, "testbuildrelativecopy", withBuildContext(c, + withFile("Dockerfile", `FROM busybox WORKDIR /test1 WORKDIR test2 - RUN sh -c "[ "$PWD" = '` + expected + `' ]" + RUN sh -c "[ "$PWD" = '`+expected+`' ]" COPY foo ./ RUN sh -c "[ $(cat /test1/test2/foo) = 'hello' ]" ADD foo ./bar/baz @@ -1966,53 +1516,37 @@ func (s *DockerSuite) TestBuildRelativeCopy(c *check.C) { WORKDIR /test5/test6 COPY foo ../ RUN sh -c "[ $(cat /test5/foo) = 'hello' ]" - ` - ctx, err := fakeContext(dockerfile, map[string]string{ - "foo": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - _, err = buildImageFromContext(name, ctx, false) - if err != nil { - c.Fatal(err) - } + `), + withFile("foo", "hello"), + )) } func (s *DockerSuite) TestBuildBlankName(c *check.C) { name := "testbuildblankname" - _, _, stderr, err := buildImageWithStdoutStderr(name, - `FROM busybox - ENV =`, - true) - if err == nil { - c.Fatal("Build was supposed to fail but didn't") - } - if !strings.Contains(stderr, "ENV names can not be blank") { - c.Fatalf("Missing error message, got: %s", stderr) + testCases := []struct { + expression string + expectedStderr string + }{ + { + expression: "ENV =", + expectedStderr: "ENV names can not be blank", + }, + { + expression: "LABEL =", + expectedStderr: "LABEL names can not be blank", + }, + { + expression: "ARG =foo", + expectedStderr: "ARG names can not be blank", + }, } - _, _, stderr, err = buildImageWithStdoutStderr(name, - `FROM busybox - LABEL =`, - true) - if err == nil { - c.Fatal("Build was supposed to fail but didn't") - } - if !strings.Contains(stderr, "LABEL names can not be blank") { - c.Fatalf("Missing error message, got: %s", stderr) - } - - _, _, stderr, err = buildImageWithStdoutStderr(name, - `FROM busybox - ARG =foo`, - true) - if err == nil { - c.Fatal("Build was supposed to fail but didn't") - } - if !strings.Contains(stderr, "ARG names can not be blank") { - c.Fatalf("Missing error message, got: %s", stderr) + for _, tc := range testCases { + buildImageNew(name, withDockerfile(fmt.Sprintf(`FROM busybox + %s`, tc.expression))).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: tc.expectedStderr, + }) } } @@ -2020,15 +1554,10 @@ func (s *DockerSuite) TestBuildEnv(c *check.C) { testRequires(c, DaemonIsLinux) // ENV expansion is different in Windows name := "testbuildenv" expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox ENV PATH /test:$PATH - ENV PORT 2375 - RUN [ $(env | grep PORT) = 'PORT=2375' ]`, - true) - if err != nil { - c.Fatal(err) - } + ENV PORT 2375 + RUN [ $(env | grep PORT) = 'PORT=2375' ]`)) res := inspectField(c, name, "Config.Env") if res != expected { c.Fatalf("Env %s, expected %s", res, expected) @@ -2040,14 +1569,11 @@ func (s *DockerSuite) TestBuildPATH(c *check.C) { defPath := "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - fn := func(dockerfile string, exp string) { - _, err := buildImage("testbldpath", dockerfile, true) - c.Assert(err, check.IsNil) - + fn := func(dockerfile string, expected string) { + buildImageSuccessfully(c, "testbldpath", withDockerfile(dockerfile)) res := inspectField(c, "testbldpath", "Config.Env") - - if res != exp { - c.Fatalf("Env %q, expected %q for dockerfile:%q", res, exp, dockerfile) + if res != expected { + c.Fatalf("Env %q, expected %q for dockerfile:%q", res, expected, dockerfile) } } @@ -2075,13 +1601,10 @@ func (s *DockerSuite) TestBuildContextCleanup(c *check.C) { if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } - _, err = buildImage(name, - `FROM `+minimalBaseImage()+` - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } + + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + ENTRYPOINT ["/bin/echo"]`)) + entriesFinal, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) @@ -2100,13 +1623,12 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) { if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) } - _, err = buildImage(name, - `FROM `+minimalBaseImage()+` - RUN /non/existing/command`, - true) - if err == nil { - c.Fatalf("expected build to fail, but it didn't") - } + + buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+` + RUN /non/existing/command`)).Assert(c, icmd.Expected{ + ExitCode: 1, + }) + entriesFinal, err := ioutil.ReadDir(filepath.Join(dockerBasePath, "tmp")) if err != nil { c.Fatalf("failed to list contents of tmp dir: %s", err) @@ -2119,15 +1641,11 @@ func (s *DockerSuite) TestBuildContextCleanupFailedBuild(c *check.C) { func (s *DockerSuite) TestBuildCmd(c *check.C) { name := "testbuildcmd" - expected := "[/bin/echo Hello World]" - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - CMD ["/bin/echo", "Hello World"]`, - true) - if err != nil { - c.Fatal(err) - } + + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + CMD ["/bin/echo", "Hello World"]`)) + res := inspectField(c, name, "Config.Cmd") if res != expected { c.Fatalf("Cmd %s, expected %s", res, expected) @@ -2138,13 +1656,10 @@ func (s *DockerSuite) TestBuildExpose(c *check.C) { testRequires(c, DaemonIsLinux) // Expose not implemented on Windows name := "testbuildexpose" expected := "map[2375/tcp:{}]" - _, err := buildImage(name, - `FROM scratch - EXPOSE 2375`, - true) - if err != nil { - c.Fatal(err) - } + + buildImageSuccessfully(c, name, withDockerfile(`FROM scratch + EXPOSE 2375`)) + res := inspectField(c, name, "Config.ExposedPorts") if res != expected { c.Fatalf("Exposed ports %s, expected %s", res, expected) @@ -2178,10 +1693,7 @@ func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) { tmpl.Execute(buf, portList) name := "testbuildexpose" - _, err := buildImage(name, buf.String(), true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(buf.String())) // check if all the ports are saved inside Config.ExposedPorts res := inspectFieldJSON(c, name, "Config.ExposedPorts") @@ -2206,11 +1718,8 @@ func (s *DockerSuite) TestBuildExposeMorePorts(c *check.C) { func (s *DockerSuite) TestBuildExposeOrder(c *check.C) { testRequires(c, DaemonIsLinux) // Expose not implemented on Windows buildID := func(name, exposed string) string { - _, err := buildImage(name, fmt.Sprintf(`FROM scratch - EXPOSE %s`, exposed), true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM scratch + EXPOSE %s`, exposed))) id := inspectField(c, name, "Id") return id } @@ -2226,13 +1735,8 @@ func (s *DockerSuite) TestBuildExposeUpperCaseProto(c *check.C) { testRequires(c, DaemonIsLinux) // Expose not implemented on Windows name := "testbuildexposeuppercaseproto" expected := "map[5678/udp:{}]" - _, err := buildImage(name, - `FROM scratch - EXPOSE 5678/UDP`, - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM scratch + EXPOSE 5678/UDP`)) res := inspectField(c, name, "Config.ExposedPorts") if res != expected { c.Fatalf("Exposed ports %s, expected %s", res, expected) @@ -2243,13 +1747,8 @@ func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) { name := "testbuildentrypointinheritance" name2 := "testbuildentrypointinheritance2" - _, err := buildImage(name, - `FROM busybox - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + ENTRYPOINT ["/bin/echo"]`)) res := inspectField(c, name, "Config.Entrypoint") expected := "[/bin/echo]" @@ -2257,34 +1756,23 @@ func (s *DockerSuite) TestBuildEmptyEntrypointInheritance(c *check.C) { c.Fatalf("Entrypoint %s, expected %s", res, expected) } - _, err = buildImage(name2, - fmt.Sprintf(`FROM %s - ENTRYPOINT []`, name), - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf(`FROM %s + ENTRYPOINT []`, name))) res = inspectField(c, name2, "Config.Entrypoint") expected = "[]" - if res != expected { c.Fatalf("Entrypoint %s, expected %s", res, expected) } - } func (s *DockerSuite) TestBuildEmptyEntrypoint(c *check.C) { name := "testbuildentrypoint" expected := "[]" - _, err := buildImage(name, - `FROM busybox - ENTRYPOINT []`, - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + ENTRYPOINT []`)) + res := inspectField(c, name, "Config.Entrypoint") if res != expected { c.Fatalf("Entrypoint %s, expected %s", res, expected) @@ -2296,13 +1784,9 @@ func (s *DockerSuite) TestBuildEntrypoint(c *check.C) { name := "testbuildentrypoint" expected := "[/bin/echo]" - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + ENTRYPOINT ["/bin/echo"]`)) + res := inspectField(c, name, "Config.Entrypoint") if res != expected { c.Fatalf("Entrypoint %s, expected %s", res, expected) @@ -2312,127 +1796,48 @@ func (s *DockerSuite) TestBuildEntrypoint(c *check.C) { // #6445 ensure ONBUILD triggers aren't committed to grandchildren func (s *DockerSuite) TestBuildOnBuildLimitedInheritence(c *check.C) { - var ( - out2, out3 string - ) - { - name1 := "testonbuildtrigger1" - dockerfile1 := ` + buildImageSuccessfully(c, "testonbuildtrigger1", withDockerfile(` FROM busybox RUN echo "GRANDPARENT" ONBUILD RUN echo "ONBUILD PARENT" - ` - ctx, err := fakeContext(dockerfile1, nil) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out1, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", name1, ".") - if err != nil { - c.Fatalf("build failed to complete: %s, %v", out1, err) - } - } - { - name2 := "testonbuildtrigger2" - dockerfile2 := ` - FROM testonbuildtrigger1 - ` - ctx, err := fakeContext(dockerfile2, nil) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out2, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name2, ".") - if err != nil { - c.Fatalf("build failed to complete: %s, %v", out2, err) - } - } - { - name3 := "testonbuildtrigger3" - dockerfile3 := ` - FROM testonbuildtrigger2 - ` - ctx, err := fakeContext(dockerfile3, nil) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out3, _, err = dockerCmdInDir(c, ctx.Dir, "build", "-t", name3, ".") - if err != nil { - c.Fatalf("build failed to complete: %s, %v", out3, err) - } - - } - + `)) // ONBUILD should be run in second build. - if !strings.Contains(out2, "ONBUILD PARENT") { - c.Fatalf("ONBUILD instruction did not run in child of ONBUILD parent") - } - + buildImageNew("testonbuildtrigger2", withDockerfile("FROM testonbuildtrigger1")).Assert(c, icmd.Expected{ + Out: "ONBUILD PARENT", + }) // ONBUILD should *not* be run in third build. - if strings.Contains(out3, "ONBUILD PARENT") { + result := buildImageNew("testonbuildtrigger3", withDockerfile("FROM testonbuildtrigger2")) + result.Assert(c, icmd.Success) + if strings.Contains(result.Combined(), "ONBUILD PARENT") { c.Fatalf("ONBUILD instruction ran in grandchild of ONBUILD parent") } - } -func (s *DockerSuite) TestBuildWithCache(c *check.C) { +func (s *DockerSuite) TestBuildSameDockerfileWithAndWithoutCache(c *check.C) { testRequires(c, DaemonIsLinux) // Expose not implemented on Windows name := "testbuildwithcache" - id1, err := buildImage(name, - `FROM scratch + dockerfile := `FROM scratch MAINTAINER dockerio EXPOSE 5432 - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImage(name, - `FROM scratch - MAINTAINER dockerio - EXPOSE 5432 - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } + ENTRYPOINT ["/bin/echo"]` + buildImageSuccessfully(c, name, withDockerfile(dockerfile)) + id1, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withDockerfile(dockerfile)) + id2, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile)) + id3, err := getIDByName(name) + c.Assert(err, checker.IsNil) if id1 != id2 { c.Fatal("The cache should have been used but hasn't.") } -} - -func (s *DockerSuite) TestBuildWithoutCache(c *check.C) { - testRequires(c, DaemonIsLinux) // Expose not implemented on Windows - name := "testbuildwithoutcache" - name2 := "testbuildwithoutcache2" - id1, err := buildImage(name, - `FROM scratch - MAINTAINER dockerio - EXPOSE 5432 - ENTRYPOINT ["/bin/echo"]`, - true) - if err != nil { - c.Fatal(err) - } - - id2, err := buildImage(name2, - `FROM scratch - MAINTAINER dockerio - EXPOSE 5432 - ENTRYPOINT ["/bin/echo"]`, - false) - if err != nil { - c.Fatal(err) - } - if id1 == id2 { + if id1 == id3 { c.Fatal("The cache should have been invalided but hasn't.") } } +// Make sure that ADD/COPY still populate the cache even if they don't use it func (s *DockerSuite) TestBuildConditionalCache(c *check.C) { name := "testbuildconditionalcache" @@ -2456,7 +1861,8 @@ func (s *DockerSuite) TestBuildConditionalCache(c *check.C) { c.Fatalf("Error modifying foo: %s", err) } - id2, err := buildImageFromContext(name, ctx, false) + // Updating a file should invalidate the cache + id2, err := buildImageFromContext(name, ctx, true) if err != nil { c.Fatalf("Error building #2: %s", err) } @@ -2473,39 +1879,9 @@ func (s *DockerSuite) TestBuildConditionalCache(c *check.C) { } } -func (s *DockerSuite) TestBuildAddLocalFileWithCache(c *check.C) { - // local files are not owned by the correct user - testRequires(c, NotUserNamespace) - name := "testbuildaddlocalfilewithcache" - name2 := "testbuildaddlocalfilewithcache2" - dockerfile := ` - FROM busybox - MAINTAINER dockerio - ADD foo /usr/lib/bla/bar - RUN sh -c "[ $(cat /usr/lib/bla/bar) = "hello" ]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "foo": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - id1, err := buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImageFromContext(name2, ctx, true) - if err != nil { - c.Fatal(err) - } - if id1 != id2 { - c.Fatal("The cache should have been used but hasn't.") - } -} - -func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) { +// FIXME(vdemeester) this really seems to test the same thing as before +func (s *DockerSuite) TestBuildAddMultipleLocalFileWithAndWithoutCache(c *check.C) { name := "testbuildaddmultiplelocalfilewithcache" - name2 := "testbuildaddmultiplelocalfilewithcache2" dockerfile := ` FROM busybox MAINTAINER dockerio @@ -2522,41 +1898,18 @@ func (s *DockerSuite) TestBuildAddMultipleLocalFileWithCache(c *check.C) { if err != nil { c.Fatal(err) } - id2, err := buildImageFromContext(name2, ctx, true) + id2, err := buildImageFromContext(name, ctx, true) + if err != nil { + c.Fatal(err) + } + id3, err := buildImageFromContext(name, ctx, false) if err != nil { c.Fatal(err) } if id1 != id2 { c.Fatal("The cache should have been used but hasn't.") } -} - -func (s *DockerSuite) TestBuildAddLocalFileWithoutCache(c *check.C) { - // local files are not owned by the correct user - testRequires(c, NotUserNamespace) - name := "testbuildaddlocalfilewithoutcache" - name2 := "testbuildaddlocalfilewithoutcache2" - dockerfile := ` - FROM busybox - MAINTAINER dockerio - ADD foo /usr/lib/bla/bar - RUN sh -c "[ $(cat /usr/lib/bla/bar) = "hello" ]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "foo": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - id1, err := buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImageFromContext(name2, ctx, false) - if err != nil { - c.Fatal(err) - } - if id1 == id2 { + if id1 == id3 { c.Fatal("The cache should have been invalided but hasn't.") } } @@ -2649,9 +2002,9 @@ func (s *DockerSuite) TestBuildAddCurrentDirWithCache(c *check.C) { } } +// FIXME(vdemeester) this really seems to test the same thing as before (TestBuildAddMultipleLocalFileWithAndWithoutCache) func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) { name := "testbuildaddcurrentdirwithoutcache" - name2 := "testbuildaddcurrentdirwithoutcache2" dockerfile := ` FROM ` + minimalBaseImage() + ` MAINTAINER dockerio @@ -2667,7 +2020,7 @@ func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) { if err != nil { c.Fatal(err) } - id2, err := buildImageFromContext(name2, ctx, false) + id2, err := buildImageFromContext(name, ctx, false) if err != nil { c.Fatal(err) } @@ -2676,7 +2029,7 @@ func (s *DockerSuite) TestBuildAddCurrentDirWithoutCache(c *check.C) { } } -func (s *DockerSuite) TestBuildAddRemoteFileWithCache(c *check.C) { +func (s *DockerSuite) TestBuildAddRemoteFileWithAndWithoutCache(c *check.C) { name := "testbuildaddremotefilewithcache" server, err := fakeStorage(map[string]string{ "baz": "hello", @@ -2686,55 +2039,23 @@ func (s *DockerSuite) TestBuildAddRemoteFileWithCache(c *check.C) { } defer server.Close() - id1, err := buildImage(name, - fmt.Sprintf(`FROM `+minimalBaseImage()+` + dockerfile := fmt.Sprintf(`FROM `+minimalBaseImage()+` MAINTAINER dockerio - ADD %s/baz /usr/lib/baz/quux`, server.URL()), - true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImage(name, - fmt.Sprintf(`FROM `+minimalBaseImage()+` - MAINTAINER dockerio - ADD %s/baz /usr/lib/baz/quux`, server.URL()), - true) - if err != nil { - c.Fatal(err) - } + ADD %s/baz /usr/lib/baz/quux`, server.URL()) + buildImageSuccessfully(c, name, withDockerfile(dockerfile)) + id1, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withDockerfile(dockerfile)) + id2, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withoutCache, withDockerfile(dockerfile)) + id3, err := getIDByName(name) + c.Assert(err, checker.IsNil) + if id1 != id2 { c.Fatal("The cache should have been used but hasn't.") } -} - -func (s *DockerSuite) TestBuildAddRemoteFileWithoutCache(c *check.C) { - name := "testbuildaddremotefilewithoutcache" - name2 := "testbuildaddremotefilewithoutcache2" - server, err := fakeStorage(map[string]string{ - "baz": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer server.Close() - - id1, err := buildImage(name, - fmt.Sprintf(`FROM `+minimalBaseImage()+` - MAINTAINER dockerio - ADD %s/baz /usr/lib/baz/quux`, server.URL()), - true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImage(name2, - fmt.Sprintf(`FROM `+minimalBaseImage()+` - MAINTAINER dockerio - ADD %s/baz /usr/lib/baz/quux`, server.URL()), - false) - if err != nil { - c.Fatal(err) - } - if id1 == id2 { + if id1 == id3 { c.Fatal("The cache should have been invalided but hasn't.") } } @@ -2800,7 +2121,8 @@ func (s *DockerSuite) TestBuildAddRemoteFileMTime(c *check.C) { } } -func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithCache(c *check.C) { +// FIXME(vdemeester) this really seems to test the same thing as before (combined) +func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithAndWithoutCache(c *check.C) { name := "testbuildaddlocalandremotefilewithcache" server, err := fakeStorage(map[string]string{ "baz": "hello", @@ -2829,9 +2151,16 @@ func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithCache(c *check.C) { if err != nil { c.Fatal(err) } + id3, err := buildImageFromContext(name, ctx, false) + if err != nil { + c.Fatal(err) + } if id1 != id2 { c.Fatal("The cache should have been used but hasn't.") } + if id1 == id3 { + c.Fatal("The cache should have been invalidated but hasn't.") + } } func testContextTar(c *check.C, compression archive.Compression) { @@ -2852,12 +2181,11 @@ CMD ["cat", "/foo"]`, c.Fatalf("failed to build context tar: %v", err) } name := "contexttar" - buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-") - buildCmd.Stdin = context - if out, _, err := runCommandWithOutput(buildCmd); err != nil { - c.Fatalf("build failed to complete: %v %v", out, err) - } + icmd.RunCmd(icmd.Cmd{ + Command: []string{dockerBinary, "build", "-t", name, "-"}, + Stdin: context, + }).Assert(c, icmd.Success) } func (s *DockerSuite) TestBuildContextTarGzip(c *check.C) { @@ -2869,76 +2197,31 @@ func (s *DockerSuite) TestBuildContextTarNoCompression(c *check.C) { } func (s *DockerSuite) TestBuildNoContext(c *check.C) { - buildCmd := exec.Command(dockerBinary, "build", "-t", "nocontext", "-") - buildCmd.Stdin = strings.NewReader( - `FROM busybox - CMD ["echo", "ok"]`) - - if out, _, err := runCommandWithOutput(buildCmd); err != nil { - c.Fatalf("build failed to complete: %v %v", out, err) - } + name := "nocontext" + icmd.RunCmd(icmd.Cmd{ + Command: []string{dockerBinary, "build", "-t", name, "-"}, + Stdin: strings.NewReader( + `FROM busybox + CMD ["echo", "ok"]`), + }).Assert(c, icmd.Success) if out, _ := dockerCmd(c, "run", "--rm", "nocontext"); out != "ok\n" { c.Fatalf("run produced invalid output: %q, expected %q", out, "ok") } } -// TODO: TestCaching -func (s *DockerSuite) TestBuildAddLocalAndRemoteFilesWithoutCache(c *check.C) { - name := "testbuildaddlocalandremotefilewithoutcache" - name2 := "testbuildaddlocalandremotefilewithoutcache2" - server, err := fakeStorage(map[string]string{ - "baz": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer server.Close() - - ctx, err := fakeContext(fmt.Sprintf(`FROM `+minimalBaseImage()+` - MAINTAINER dockerio - ADD foo /usr/lib/bla/bar - ADD %s/baz /usr/lib/baz/quux`, server.URL()), - map[string]string{ - "foo": "hello world", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - id1, err := buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } - id2, err := buildImageFromContext(name2, ctx, false) - if err != nil { - c.Fatal(err) - } - if id1 == id2 { - c.Fatal("The cache should have been invalidated but hasn't.") - } -} - func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildimg" - _, err := buildImage(name, - `FROM busybox:latest + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox:latest RUN mkdir /test && chown daemon:daemon /test && chmod 0600 /test - VOLUME /test`, - true) - - if err != nil { - c.Fatal(err) - } + VOLUME /test`)) out, _ := dockerCmd(c, "run", "--rm", "testbuildimg", "ls", "-la", "/test") - if expected := "drw-------"; !strings.Contains(out, expected) { c.Fatalf("expected %s received %s", expected, out) } - if expected := "daemon daemon"; !strings.Contains(out, expected) { c.Fatalf("expected %s received %s", expected, out) } @@ -2949,27 +2232,16 @@ func (s *DockerSuite) TestBuildWithVolumeOwnership(c *check.C) { // utilizing cache func (s *DockerSuite) TestBuildEntrypointRunCleanup(c *check.C) { name := "testbuildcmdcleanup" - if _, err := buildImage(name, - `FROM busybox - RUN echo "hello"`, - true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + RUN echo "hello"`)) - ctx, err := fakeContext(`FROM busybox + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", `FROM busybox RUN echo "hello" ADD foo /foo - ENTRYPOINT ["/bin/echo"]`, - map[string]string{ - "foo": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + ENTRYPOINT ["/bin/echo"]`), + withFile("foo", "hello"))) + res := inspectField(c, name, "Config.Cmd") // Cmd must be cleaned up if res != "[]" { @@ -2985,42 +2257,25 @@ func (s *DockerSuite) TestBuildAddFileNotFound(c *check.C) { expected = "foo: The system cannot find the file specified" } - ctx, err := fakeContext(`FROM `+minimalBaseImage()+` - ADD foo /usr/local/bar`, - map[string]string{"bar": "hello"}) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - if !strings.Contains(err.Error(), expected) { - c.Fatalf("Wrong error %v, must be about missing foo file or directory", err) - } - } else { - c.Fatal("Error must not be nil") - } + buildImageNew(name, withBuildContext(c, + withFile("Dockerfile", `FROM `+minimalBaseImage()+` + ADD foo /usr/local/bar`), + withFile("bar", "hello"))).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: expected, + }) } func (s *DockerSuite) TestBuildInheritance(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildinheritance" - _, err := buildImage(name, - `FROM scratch - EXPOSE 2375`, - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM scratch + EXPOSE 2375`)) ports1 := inspectField(c, name, "Config.ExposedPorts") - _, err = buildImage(name, - fmt.Sprintf(`FROM %s - ENTRYPOINT ["/bin/echo"]`, name), - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s + ENTRYPOINT ["/bin/echo"]`, name))) res := inspectField(c, name, "Config.Entrypoint") if expected := "[/bin/echo]"; res != expected { @@ -3034,35 +2289,19 @@ func (s *DockerSuite) TestBuildInheritance(c *check.C) { func (s *DockerSuite) TestBuildFails(c *check.C) { name := "testbuildfails" - _, err := buildImage(name, - `FROM busybox - RUN sh -c "exit 23"`, - true) - if err != nil { - if !strings.Contains(err.Error(), "returned a non-zero code: 23") { - c.Fatalf("Wrong error %v, must be about non-zero code 23", err) - } - } else { - c.Fatal("Error must not be nil") - } + buildImageNew(name, withDockerfile(`FROM busybox + RUN sh -c "exit 23"`)).Assert(c, icmd.Expected{ + ExitCode: 23, + Err: "returned a non-zero code: 23", + }) } func (s *DockerSuite) TestBuildOnBuild(c *check.C) { name := "testbuildonbuild" - _, err := buildImage(name, - `FROM busybox - ONBUILD RUN touch foobar`, - true) - if err != nil { - c.Fatal(err) - } - _, err = buildImage(name, - fmt.Sprintf(`FROM %s - RUN [ -f foobar ]`, name), - true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + ONBUILD RUN touch foobar`)) + buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s + RUN [ -f foobar ]`, name))) } // gh #2446 @@ -3072,40 +2311,30 @@ func (s *DockerSuite) TestBuildAddToSymlinkDest(c *check.C) { makeLink = `mklink /D C:\bar C:\foo` } name := "testbuildaddtosymlinkdest" - ctx, err := fakeContext(`FROM busybox - RUN sh -c "mkdir /foo" - RUN `+makeLink+` - ADD foo /bar/ - RUN sh -c "[ -f /bar/foo ]" - RUN sh -c "[ -f /foo/foo ]"`, - map[string]string{ - "foo": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` + FROM busybox + RUN sh -c "mkdir /foo" + RUN `+makeLink+` + ADD foo /bar/ + RUN sh -c "[ -f /bar/foo ]" + RUN sh -c "[ -f /foo/foo ]"`), + withFile("foo", "hello"), + )) } func (s *DockerSuite) TestBuildEscapeWhitespace(c *check.C) { name := "testbuildescapewhitespace" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` # ESCAPE=\ FROM busybox MAINTAINER "Docker \ IO " - `, true) - if err != nil { - c.Fatal(err) - } + `)) res := inspectField(c, name, "Author") - if res != "\"Docker IO \"" { c.Fatalf("Parsed string did not match the escaped string. Got: %q", res) } @@ -3116,17 +2345,11 @@ func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) { // Verify that strings that look like ints are still passed as strings name := "testbuildstringing" - _, err := buildImage(name, ` - FROM busybox - MAINTAINER 123 - `, true) - - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile(` + FROM busybox + MAINTAINER 123`)) out, _ := dockerCmd(c, "inspect", name) - if !strings.Contains(out, "\"123\"") { c.Fatalf("Output does not contain the int as a string:\n%s", out) } @@ -3135,9 +2358,10 @@ func (s *DockerSuite) TestBuildVerifyIntString(c *check.C) { func (s *DockerSuite) TestBuildDockerignore(c *check.C) { name := "testbuilddockerignore" - dockerfile := ` - FROM busybox - ADD . /bla + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` + FROM busybox + ADD . /bla RUN sh -c "[[ -f /bla/src/x.go ]]" RUN sh -c "[[ -f /bla/Makefile ]]" RUN sh -c "[[ ! -e /bla/src/_vendor ]]" @@ -3148,62 +2372,48 @@ func (s *DockerSuite) TestBuildDockerignore(c *check.C) { RUN sh -c "[[ ! -e /bla/.git ]]" RUN sh -c "[[ ! -e v.cc ]]" RUN sh -c "[[ ! -e src/v.cc ]]" - RUN sh -c "[[ ! -e src/_vendor/v.cc ]]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Makefile": "all:", - ".git/HEAD": "ref: foo", - "src/x.go": "package main", - "src/_vendor/v.go": "package main", - "src/_vendor/v.cc": "package main", - "src/v.cc": "package main", - "v.cc": "package main", - "dir/foo": "", - ".gitignore": "", - "README.md": "readme", - ".dockerignore": ` + RUN sh -c "[[ ! -e src/_vendor/v.cc ]]"`), + withFile("Makefile", "all:"), + withFile(".git/HEAD", "ref: foo"), + withFile("src/x.go", "package main"), + withFile("src/_vendor/v.go", "package main"), + withFile("src/_vendor/v.cc", "package main"), + withFile("src/v.cc", "package main"), + withFile("v.cc", "package main"), + withFile("dir/foo", ""), + withFile(".gitignore", ""), + withFile("README.md", "readme"), + withFile(".dockerignore", ` .git pkg .gitignore src/_vendor *.md **/*.cc -dir`, - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +dir`), + )) } func (s *DockerSuite) TestBuildDockerignoreCleanPaths(c *check.C) { name := "testbuilddockerignorecleanpaths" - dockerfile := ` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM busybox ADD . /tmp/ - RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "foo": "foo", - "foo2": "foo2", - "dir1/foo": "foo in dir1", - ".dockerignore": "./foo\ndir1//foo\n./dir1/../foo2", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (! ls /tmp/dir1/foo)"`), + withFile("foo", "foo"), + withFile("foo2", "foo2"), + withFile("dir1/foo", "foo in dir1"), + withFile(".dockerignore", "./foo\ndir1//foo\n./dir1/../foo2"), + )) } func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) { name := "testbuilddockerignoreexceptions" - dockerfile := ` - FROM busybox - ADD . /bla + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` + FROM busybox + ADD . /bla RUN sh -c "[[ -f /bla/src/x.go ]]" RUN sh -c "[[ -f /bla/Makefile ]]" RUN sh -c "[[ ! -e /bla/src/_vendor ]]" @@ -3215,22 +2425,21 @@ func (s *DockerSuite) TestBuildDockerignoreExceptions(c *check.C) { RUN sh -c "[[ -f /bla/dir/e-dir/foo ]]" RUN sh -c "[[ ! -e /bla/foo ]]" RUN sh -c "[[ ! -e /bla/.git ]]" - RUN sh -c "[[ -e /bla/dir/a.cc ]]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Makefile": "all:", - ".git/HEAD": "ref: foo", - "src/x.go": "package main", - "src/_vendor/v.go": "package main", - "dir/foo": "", - "dir/foo1": "", - "dir/dir/f1": "", - "dir/dir/foo": "", - "dir/e": "", - "dir/e-dir/foo": "", - ".gitignore": "", - "README.md": "readme", - "dir/a.cc": "hello", - ".dockerignore": ` + RUN sh -c "[[ -e /bla/dir/a.cc ]]"`), + withFile("Makefile", "all:"), + withFile(".git/HEAD", "ref: foo"), + withFile("src/x.go", "package main"), + withFile("src/_vendor/v.go", "package main"), + withFile("dir/foo", ""), + withFile("dir/foo1", ""), + withFile("dir/dir/f1", ""), + withFile("dir/dir/foo", ""), + withFile("dir/e", ""), + withFile("dir/e-dir/foo", ""), + withFile(".gitignore", ""), + withFile("README.md", "readme"), + withFile("dir/a.cc", "hello"), + withFile(".dockerignore", ` .git pkg .gitignore @@ -3240,93 +2449,58 @@ dir !dir/e* !dir/dir/foo **/*.cc -!**/*.cc`, - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +!**/*.cc`), + )) } func (s *DockerSuite) TestBuildDockerignoringDockerfile(c *check.C) { name := "testbuilddockerignoredockerfile" dockerfile := ` - FROM busybox + FROM busybox ADD . /tmp/ RUN sh -c "! ls /tmp/Dockerfile" RUN ls /tmp/.dockerignore` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": dockerfile, - ".dockerignore": "Dockerfile\n", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("Didn't ignore Dockerfile correctly:%s", err) - } - - // now try it with ./Dockerfile - ctx.Add(".dockerignore", "./Dockerfile\n") - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("Didn't ignore ./Dockerfile correctly:%s", err) - } - + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", "Dockerfile\n"), + )) + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", "./Dockerfile\n"), + )) } func (s *DockerSuite) TestBuildDockerignoringRenamedDockerfile(c *check.C) { name := "testbuilddockerignoredockerfile" dockerfile := ` - FROM busybox + FROM busybox ADD . /tmp/ RUN ls /tmp/Dockerfile RUN sh -c "! ls /tmp/MyDockerfile" RUN ls /tmp/.dockerignore` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": "Should not use me", - "MyDockerfile": dockerfile, - ".dockerignore": "MyDockerfile\n", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("Didn't ignore MyDockerfile correctly:%s", err) - } - - // now try it with ./MyDockerfile - ctx.Add(".dockerignore", "./MyDockerfile\n") - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("Didn't ignore ./MyDockerfile correctly:%s", err) - } - + buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c, + withFile("Dockerfile", "Should not use me"), + withFile("MyDockerfile", dockerfile), + withFile(".dockerignore", "MyDockerfile\n"), + )) + buildImageSuccessfully(c, name, withBuildFlags("-f", "MyDockerfile"), withBuildContext(c, + withFile("Dockerfile", "Should not use me"), + withFile("MyDockerfile", dockerfile), + withFile(".dockerignore", "./MyDockerfile\n"), + )) } func (s *DockerSuite) TestBuildDockerignoringDockerignore(c *check.C) { name := "testbuilddockerignoredockerignore" dockerfile := ` - FROM busybox + FROM busybox ADD . /tmp/ RUN sh -c "! ls /tmp/.dockerignore" RUN ls /tmp/Dockerfile` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": dockerfile, - ".dockerignore": ".dockerignore\n", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("Didn't ignore .dockerignore correctly:%s", err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", ".dockerignore\n"), + )) } func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) { @@ -3378,90 +2552,78 @@ func (s *DockerSuite) TestBuildDockerignoreTouchDockerfile(c *check.C) { if id1 != id2 { c.Fatalf("Didn't use the cache - 3") } - } func (s *DockerSuite) TestBuildDockerignoringWholeDir(c *check.C) { name := "testbuilddockerignorewholedir" + dockerfile := ` - FROM busybox + FROM busybox + COPY . / + RUN sh -c "[[ ! -e /.gitignore ]]" + RUN sh -c "[[ ! -e /Makefile ]]"` + + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", "*\n"), + withFile("Makefile", "all:"), + withFile(".gitignore", ""), + )) +} + +func (s *DockerSuite) TestBuildDockerignoringOnlyDotfiles(c *check.C) { + name := "testbuilddockerignorewholedir" + + dockerfile := ` + FROM busybox COPY . / RUN sh -c "[[ ! -e /.gitignore ]]" RUN sh -c "[[ -f /Makefile ]]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": "FROM scratch", - "Makefile": "all:", - ".gitignore": "", - ".dockerignore": ".*\n", - }) - c.Assert(err, check.IsNil) - defer ctx.Close() - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - c.Assert(ctx.Add(".dockerfile", "*"), check.IsNil) - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - - c.Assert(ctx.Add(".dockerfile", "."), check.IsNil) - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - - c.Assert(ctx.Add(".dockerfile", "?"), check.IsNil) - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", ".*"), + withFile("Makefile", "all:"), + withFile(".gitignore", ""), + )) } func (s *DockerSuite) TestBuildDockerignoringBadExclusion(c *check.C) { name := "testbuilddockerignorebadexclusion" - dockerfile := ` - FROM busybox + buildImageNew(name, withBuildContext(c, + withFile("Dockerfile", ` + FROM busybox COPY . / RUN sh -c "[[ ! -e /.gitignore ]]" - RUN sh -c "[[ -f /Makefile ]]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": "FROM scratch", - "Makefile": "all:", - ".gitignore": "", - ".dockerignore": "!\n", + RUN sh -c "[[ -f /Makefile ]]"`), + withFile("Makefile", "all:"), + withFile(".gitignore", ""), + withFile(".dockerignore", "!\n"), + )).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "Error checking context: 'Illegal exclusion pattern: !", }) - c.Assert(err, check.IsNil) - defer ctx.Close() - if _, err = buildImageFromContext(name, ctx, true); err == nil { - c.Fatalf("Build was supposed to fail but didn't") - } - - if err.Error() != "failed to build the image: Error checking context: 'Illegal exclusion pattern: !'.\n" { - c.Fatalf("Incorrect output, got:%q", err.Error()) - } } func (s *DockerSuite) TestBuildDockerignoringWildTopDir(c *check.C) { dockerfile := ` - FROM busybox + FROM busybox COPY . / RUN sh -c "[[ ! -e /.dockerignore ]]" RUN sh -c "[[ ! -e /Dockerfile ]]" RUN sh -c "[[ ! -e /file1 ]]" RUN sh -c "[[ ! -e /dir ]]"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": "FROM scratch", - "file1": "", - "dir/dfile1": "", - }) - c.Assert(err, check.IsNil) - defer ctx.Close() - // All of these should result in ignoring all files for _, variant := range []string{"**", "**/", "**/**", "*"} { - ctx.Add(".dockerignore", variant) - _, err = buildImageFromContext("noname", ctx, true) - c.Assert(err, check.IsNil, check.Commentf("variant: %s", variant)) + buildImageSuccessfully(c, "noname", withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("file1", ""), + withFile("dir/file1", ""), + withFile(".dockerignore", variant), + )) + + dockerCmd(c, "rmi", "noname") } } @@ -3492,31 +2654,7 @@ func (s *DockerSuite) TestBuildDockerignoringWildDirs(c *check.C) { RUN echo all done!` - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": "FROM scratch", - "file0": "", - "dir1/file0": "", - "dir1/dir2/file0": "", - - "file1": "", - "dir1/file1": "", - "dir1/dir2/file1": "", - - "dir1/file2": "", - "dir1/dir2/file2": "", // remains - - "dir1/dir2/file4": "", - "dir1/dir2/file5": "", - "dir1/dir2/file6": "", - "dir1/dir3/file7": "", - "dir1/dir3/file8": "", - "dir1/dir4/file9": "", - - "dir1/dir5/fileAA": "", - "dir1/dir5/fileAB": "", - "dir1/dir5/fileB": "", - - ".dockerignore": ` + dockerignore := ` **/file0 **/*file1 **/dir1/file2 @@ -3528,52 +2666,56 @@ dir1/dir3/** **/file?A **/file\?B **/dir5/file. -`, - }) - c.Assert(err, check.IsNil) - defer ctx.Close() +` - _, err = buildImageFromContext("noname", ctx, true) - c.Assert(err, check.IsNil) + buildImageSuccessfully(c, "noname", withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", dockerignore), + withFile("dir1/file0", ""), + withFile("dir1/dir2/file0", ""), + withFile("file1", ""), + withFile("dir1/file1", ""), + withFile("dir1/dir2/file1", ""), + withFile("dir1/file2", ""), + withFile("dir1/dir2/file2", ""), // remains + withFile("dir1/dir2/file4", ""), + withFile("dir1/dir2/file5", ""), + withFile("dir1/dir2/file6", ""), + withFile("dir1/dir3/file7", ""), + withFile("dir1/dir3/file8", ""), + withFile("dir1/dir4/file9", ""), + withFile("dir1/dir5/fileAA", ""), + withFile("dir1/dir5/fileAB", ""), + withFile("dir1/dir5/fileB", ""), + )) } func (s *DockerSuite) TestBuildLineBreak(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildlinebreak" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox RUN sh -c 'echo root:testpass \ > /tmp/passwd' RUN mkdir -p /var/run/sshd RUN sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]" -RUN sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`, - true) - if err != nil { - c.Fatal(err) - } +RUN sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`)) } func (s *DockerSuite) TestBuildEOLInLine(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildeolinline" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox RUN sh -c 'echo root:testpass > /tmp/passwd' RUN echo "foo \n bar"; echo "baz" RUN mkdir -p /var/run/sshd RUN sh -c "[ "$(cat /tmp/passwd)" = "root:testpass" ]" -RUN sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`, - true) - if err != nil { - c.Fatal(err) - } +RUN sh -c "[ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ]"`)) } func (s *DockerSuite) TestBuildCommentsShebangs(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildcomments" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox # This is an ordinary comment. RUN { echo '#!/bin/sh'; echo 'echo hello world'; } > /hello.sh RUN [ ! -x /hello.sh ] @@ -3581,18 +2723,13 @@ RUN [ ! -x /hello.sh ] RUN chmod +x /hello.sh RUN [ -x /hello.sh ] RUN [ "$(cat /hello.sh)" = $'#!/bin/sh\necho hello world' ] -RUN [ "$(/hello.sh)" = "hello world" ]`, - true) - if err != nil { - c.Fatal(err) - } +RUN [ "$(/hello.sh)" = "hello world" ]`)) } func (s *DockerSuite) TestBuildUsersAndGroups(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildusers" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox # Make sure our defaults work RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = '0:0/root:root' ] @@ -3641,13 +2778,10 @@ RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1002/do # make sure unknown uid/gid still works properly USER 1042:1043 -RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`, - true) - if err != nil { - c.Fatal(err) - } +RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1042:1043/1042:1043/1043:1043' ]`)) } +// FIXME(vdemeester) rename this test (and probably "merge" it with the one below TestBuildEnvUsage2) func (s *DockerSuite) TestBuildEnvUsage(c *check.C) { // /docker/world/hello is not owned by the correct user testRequires(c, NotUserNamespace) @@ -3664,7 +2798,7 @@ ENV BAZ $BAR ENV FOOPATH $PATH:$FOO RUN [ "$BAR" = "$BAZ" ] RUN [ "$FOOPATH" = "$PATH:/foo/baz" ] -ENV FROM hello/docker/world +ENV FROM hello/docker/world ENV TO /docker/world/hello ADD $FROM $TO RUN [ "$(cat $TO)" = "hello" ] @@ -3672,20 +2806,13 @@ ENV abc=def ENV ghi=$abc RUN [ "$ghi" = "def" ] ` - ctx, err := fakeContext(dockerfile, map[string]string{ - "hello/docker/world": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - _, err = buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("hello/docker/world", "hello"), + )) } +// FIXME(vdemeester) rename this test (and probably "merge" it with the one above TestBuildEnvUsage) func (s *DockerSuite) TestBuildEnvUsage2(c *check.C) { // /docker/world/hello is not owned by the correct user testRequires(c, NotUserNamespace) @@ -3749,18 +2876,10 @@ ENV eee4 'foo' RUN [ "$eee1,$eee2,$eee3,$eee4" = 'foo,foo,foo,foo' ] ` - ctx, err := fakeContext(dockerfile, map[string]string{ - "hello/docker/world": "hello", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - _, err = buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("hello/docker/world", "hello"), + )) } func (s *DockerSuite) TestBuildAddScript(c *check.C) { @@ -3772,18 +2891,11 @@ ADD test /test RUN ["chmod","+x","/test"] RUN ["/test"] RUN [ "$(cat /testfile)" = 'test!' ]` - ctx, err := fakeContext(dockerfile, map[string]string{ - "test": "#!/bin/sh\necho 'test!' > /testfile", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - _, err = buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("test", "#!/bin/sh\necho 'test!' > /testfile"), + )) } func (s *DockerSuite) TestBuildAddTar(c *check.C) { @@ -3898,20 +3010,13 @@ func (s *DockerSuite) TestBuildAddNonTar(c *check.C) { name := "testbuildaddnontar" // Should not try to extract test.tar - ctx, err := fakeContext(` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM busybox ADD test.tar / - RUN test -f /test.tar`, - map[string]string{"test.tar": "not_a_tar_file"}) - - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatalf("build failed for TestBuildAddNonTar") - } + RUN test -f /test.tar`), + withFile("test.tar", "not_a_tar_file"), + )) } func (s *DockerSuite) TestBuildAddTarXz(c *check.C) { @@ -4033,9 +3138,9 @@ func (s *DockerSuite) TestBuildFromGit(c *check.C) { name := "testbuildfromgit" git, err := newFakeGit("repo", map[string]string{ "Dockerfile": `FROM busybox - ADD first /first - RUN [ -f /first ] - MAINTAINER docker`, + ADD first /first + RUN [ -f /first ] + MAINTAINER docker`, "first": "test git data", }, true) if err != nil { @@ -4043,10 +3148,8 @@ func (s *DockerSuite) TestBuildFromGit(c *check.C) { } defer git.Close() - _, err = buildImageFromPath(name, git.RepoURL, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContextPath(git.RepoURL)) + res := inspectField(c, name, "Author") if res != "docker" { c.Fatalf("Maintainer should be docker, got %s", res) @@ -4067,11 +3170,8 @@ func (s *DockerSuite) TestBuildFromGitWithContext(c *check.C) { } defer git.Close() - u := fmt.Sprintf("%s#master:docker", git.RepoURL) - _, err = buildImageFromPath(name, u, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContextPath(fmt.Sprintf("%s#master:docker", git.RepoURL))) + res := inspectField(c, name, "Author") if res != "docker" { c.Fatalf("Maintainer should be docker, got %s", res) @@ -4089,14 +3189,9 @@ func (s *DockerSuite) TestBuildFromGitwithF(c *check.C) { } defer git.Close() - out, _, err := dockerCmdWithError("build", "-t", name, "--no-cache", "-f", "myApp/myDockerfile", git.RepoURL) - if err != nil { - c.Fatalf("Error on build. Out: %s\nErr: %v", out, err) - } - - if !strings.Contains(out, "hi from Dockerfile") { - c.Fatalf("Missing expected output, got:\n%s", out) - } + buildImageNew(name, withBuildFlags("-f", "myApp/myDockerfile"), withBuildContextPath(git.RepoURL)).Assert(c, icmd.Expected{ + Out: "hi from Dockerfile", + }) } func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) { @@ -4128,11 +3223,9 @@ func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) { defer server.Close() - _, err = buildImageFromPath(name, server.URL()+"/testT.tar", true) - c.Assert(err, check.IsNil) + buildImageSuccessfully(c, name, withBuildContextPath(server.URL()+"/testT.tar")) res := inspectField(c, name, "Author") - if res != "docker" { c.Fatalf("Maintainer should be docker, got %s", res) } @@ -4140,24 +3233,17 @@ func (s *DockerSuite) TestBuildFromRemoteTarball(c *check.C) { func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) { name := "testbuildcmdcleanuponentrypoint" - if _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - CMD ["test"] - ENTRYPOINT ["echo"]`, - true); err != nil { - c.Fatal(err) - } - if _, err := buildImage(name, - fmt.Sprintf(`FROM %s - ENTRYPOINT ["cat"]`, name), - true); err != nil { - c.Fatal(err) - } + + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + CMD ["test"] + ENTRYPOINT ["echo"]`)) + buildImageSuccessfully(c, name, withDockerfile(fmt.Sprintf(`FROM %s + ENTRYPOINT ["cat"]`, name))) + res := inspectField(c, name, "Config.Cmd") if res != "[]" { c.Fatalf("Cmd %s, expected nil", res) } - res = inspectField(c, name, "Config.Entrypoint") if expected := "[cat]"; res != expected { c.Fatalf("Entrypoint %s, expected %s", res, expected) @@ -4166,14 +3252,10 @@ func (s *DockerSuite) TestBuildCleanupCmdOnEntrypoint(c *check.C) { func (s *DockerSuite) TestBuildClearCmd(c *check.C) { name := "testbuildclearcmd" - _, err := buildImage(name, - `From `+minimalBaseImage()+` + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` ENTRYPOINT ["/bin/bash"] - CMD []`, - true) - if err != nil { - c.Fatal(err) - } + CMD []`)) + res := inspectFieldJSON(c, name, "Config.Cmd") if res != "[]" { c.Fatalf("Cmd %s, expected %s", res, "[]") @@ -4185,9 +3267,8 @@ func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildemptycmd" - if _, err := buildImage(name, "FROM "+minimalBaseImage()+"\nMAINTAINER quux\n", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n")) + res := inspectFieldJSON(c, name, "Config.Cmd") if res != "null" { c.Fatalf("Cmd %s, expected %s", res, "null") @@ -4196,43 +3277,31 @@ func (s *DockerSuite) TestBuildEmptyCmd(c *check.C) { func (s *DockerSuite) TestBuildOnBuildOutput(c *check.C) { name := "testbuildonbuildparent" - if _, err := buildImage(name, "FROM busybox\nONBUILD RUN echo foo\n", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nONBUILD RUN echo foo\n")) - _, out, err := buildImageWithOut(name, "FROM "+name+"\nMAINTAINER quux\n", true) - if err != nil { - c.Fatal(err) - } - - if !strings.Contains(out, "# Executing 1 build trigger") { - c.Fatal("failed to find the build trigger output", out) - } + buildImageNew(name, withDockerfile("FROM "+name+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{ + Out: "# Executing 1 build trigger", + }) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildInvalidTag(c *check.C) { name := "abcd:" + stringutils.GenerateRandomAlphaOnlyString(200) - _, out, err := buildImageWithOut(name, "FROM "+minimalBaseImage()+"\nMAINTAINER quux\n", true) - // if the error doesn't check for illegal tag name, or the image is built - // then this should fail - if !strings.Contains(out, "Error parsing reference") || strings.Contains(out, "Sending build context to Docker daemon") { - c.Fatalf("failed to stop before building. Error: %s, Output: %s", err, out) - } + buildImageNew(name, withDockerfile("FROM "+minimalBaseImage()+"\nMAINTAINER quux\n")).Assert(c, icmd.Expected{ + ExitCode: 125, + Err: "Error parsing reference", + }) } func (s *DockerSuite) TestBuildCmdShDashC(c *check.C) { name := "testbuildcmdshc" - if _, err := buildImage(name, "FROM busybox\nCMD echo cmd\n", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD echo cmd\n")) res := inspectFieldJSON(c, name, "Config.Cmd") - expected := `["/bin/sh","-c","echo cmd"]` if daemonPlatform == "windows" { expected = `["cmd","/S","/C","echo cmd"]` } - if res != expected { c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res) } @@ -4244,80 +3313,61 @@ func (s *DockerSuite) TestBuildCmdSpaces(c *check.C) { // the arg separator to make sure ["echo","hi"] and ["echo hi"] don't // look the same name := "testbuildcmdspaces" - var id1 string - var id2 string - var err error - if id1, err = buildImage(name, "FROM busybox\nCMD [\"echo hi\"]\n", true); err != nil { - c.Fatal(err) - } - - if id2, err = buildImage(name, "FROM busybox\nCMD [\"echo\", \"hi\"]\n", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo hi\"]\n")) + id1, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"hi\"]\n")) + id2, err := getIDByName(name) if id1 == id2 { c.Fatal("Should not have resulted in the same CMD") } // Now do the same with ENTRYPOINT - if id1, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo hi\"]\n", true); err != nil { - c.Fatal(err) - } - - if id2, err = buildImage(name, "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo hi\"]\n")) + id1, err = getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n")) + id2, err = getIDByName(name) if id1 == id2 { c.Fatal("Should not have resulted in the same ENTRYPOINT") } - } func (s *DockerSuite) TestBuildCmdJSONNoShDashC(c *check.C) { name := "testbuildcmdjson" - if _, err := buildImage(name, "FROM busybox\nCMD [\"echo\", \"cmd\"]", true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nCMD [\"echo\", \"cmd\"]")) res := inspectFieldJSON(c, name, "Config.Cmd") - expected := `["echo","cmd"]` - if res != expected { c.Fatalf("Expected value %s not in Config.Cmd: %s", expected, res) } - } -func (s *DockerSuite) TestBuildEntrypointInheritance(c *check.C) { - - if _, err := buildImage("parent", ` +func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChild(c *check.C) { + buildImageSuccessfully(c, "parent", withDockerfile(` FROM busybox ENTRYPOINT exit 130 - `, true); err != nil { - c.Fatal(err) - } + `)) - if _, status, _ := dockerCmdWithError("run", "parent"); status != 130 { - c.Fatalf("expected exit code 130 but received %d", status) - } + icmd.RunCommand(dockerBinary, "run", "parent").Assert(c, icmd.Expected{ + ExitCode: 130, + }) - if _, err := buildImage("child", ` + buildImageSuccessfully(c, "child", withDockerfile(` FROM parent ENTRYPOINT exit 5 - `, true); err != nil { - c.Fatal(err) - } - - if _, status, _ := dockerCmdWithError("run", "child"); status != 5 { - c.Fatalf("expected exit code 5 but received %d", status) - } + `)) + icmd.RunCommand(dockerBinary, "run", "child").Assert(c, icmd.Expected{ + ExitCode: 5, + }) } -func (s *DockerSuite) TestBuildEntrypointInheritanceInspect(c *check.C) { +func (s *DockerSuite) TestBuildEntrypointCanBeOverridenByChildInspect(c *check.C) { var ( name = "testbuildepinherit" name2 = "testbuildepinherit2" @@ -4328,40 +3378,23 @@ func (s *DockerSuite) TestBuildEntrypointInheritanceInspect(c *check.C) { expected = `["cmd","/S","/C","echo quux"]` } - if _, err := buildImage(name, "FROM busybox\nENTRYPOINT /foo/bar", true); err != nil { - c.Fatal(err) - } - - if _, err := buildImage(name2, fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name), true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nENTRYPOINT /foo/bar")) + buildImageSuccessfully(c, name2, withDockerfile(fmt.Sprintf("FROM %s\nENTRYPOINT echo quux", name))) res := inspectFieldJSON(c, name2, "Config.Entrypoint") - if res != expected { c.Fatalf("Expected value %s not in Config.Entrypoint: %s", expected, res) } - out, _ := dockerCmd(c, "run", name2) - - expected = "quux" - - if strings.TrimSpace(out) != expected { - c.Fatalf("Expected output is %s, got %s", expected, out) - } - + icmd.RunCommand(dockerBinary, "run", name2).Assert(c, icmd.Expected{ + Out: "quux", + }) } func (s *DockerSuite) TestBuildRunShEntrypoint(c *check.C) { name := "testbuildentrypoint" - _, err := buildImage(name, - `FROM busybox - ENTRYPOINT echo`, - true) - if err != nil { - c.Fatal(err) - } - + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + ENTRYPOINT echo`)) dockerCmd(c, "run", "--rm", name) } @@ -4369,7 +3402,7 @@ func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildexoticshellinterpolation" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM busybox ENV SOME_VAR a.b.c @@ -4387,11 +3420,7 @@ func (s *DockerSuite) TestBuildExoticShellInterpolation(c *check.C) { RUN [ "${SOME_VAR:+Version: ${SOME_VAR}}" = 'Version: a.b.c' ] RUN [ "${SOME_UNSET_VAR:+${SOME_VAR}}" = '' ] RUN [ "${SOME_UNSET_VAR:-${SOME_VAR:-d.e.f}}" = 'a.b.c' ] - `, false) - if err != nil { - c.Fatal(err) - } - + `)) } func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) { @@ -4401,18 +3430,17 @@ func (s *DockerSuite) TestBuildVerifySingleQuoteFails(c *check.C) { // as a "string" instead of "JSON array" and pass it on to "sh -c" and // it should barf on it. name := "testbuildsinglequotefails" - - if _, err := buildImage(name, - `FROM busybox - CMD [ '/bin/sh', '-c', 'echo hi' ]`, - true); err != nil { - c.Fatal(err) + expectedExitCode := 2 + if daemonPlatform == "windows" { + expectedExitCode = 127 } - if _, _, err := dockerCmdWithError("run", "--rm", name); err == nil { - c.Fatal("The image was not supposed to be able to run") - } + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + CMD [ '/bin/sh', '-c', 'echo hi' ]`)) + icmd.RunCommand(dockerBinary, "run", "--rm", name).Assert(c, icmd.Expected{ + ExitCode: expectedExitCode, + }) } func (s *DockerSuite) TestBuildVerboseOut(c *check.C) { @@ -4423,27 +3451,15 @@ func (s *DockerSuite) TestBuildVerboseOut(c *check.C) { expected = "\n123\r\n" } - _, out, err := buildImageWithOut(name, - `FROM busybox -RUN echo 123`, - false) - - if err != nil { - c.Fatal(err) - } - if !strings.Contains(out, expected) { - c.Fatalf("Output should contain %q: %q", "123", out) - } - + buildImageNew(name, withDockerfile(`FROM busybox +RUN echo 123`)).Assert(c, icmd.Expected{ + Out: expected, + }) } func (s *DockerSuite) TestBuildWithTabs(c *check.C) { name := "testbuildwithtabs" - _, err := buildImage(name, - "FROM busybox\nRUN echo\tone\t\ttwo", true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withDockerfile("FROM busybox\nRUN echo\tone\t\ttwo")) res := inspectFieldJSON(c, name, "ContainerConfig.Cmd") expected1 := `["/bin/sh","-c","echo\tone\t\ttwo"]` expected2 := `["/bin/sh","-c","echo\u0009one\u0009\u0009two"]` // syntactically equivalent, and what Go 1.3 generates @@ -4459,14 +3475,9 @@ func (s *DockerSuite) TestBuildWithTabs(c *check.C) { func (s *DockerSuite) TestBuildLabels(c *check.C) { name := "testbuildlabel" expected := `{"License":"GPL","Vendor":"Acme"}` - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox LABEL Vendor=Acme - LABEL License GPL`, - true) - if err != nil { - c.Fatal(err) - } + LABEL License GPL`)) res := inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -4476,46 +3487,45 @@ func (s *DockerSuite) TestBuildLabels(c *check.C) { func (s *DockerSuite) TestBuildLabelsCache(c *check.C) { name := "testbuildlabelcache" - id1, err := buildImage(name, - `FROM busybox - LABEL Vendor=Acme`, false) - if err != nil { - c.Fatalf("Build 1 should have worked: %v", err) - } - - id2, err := buildImage(name, - `FROM busybox - LABEL Vendor=Acme`, true) - if err != nil || id1 != id2 { + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + LABEL Vendor=Acme`)) + id1, err := getIDByName(name) + c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + LABEL Vendor=Acme`)) + id2, err := getIDByName(name) + c.Assert(err, checker.IsNil) + if id1 != id2 { c.Fatalf("Build 2 should have worked & used cache(%s,%s): %v", id1, id2, err) } - id2, err = buildImage(name, - `FROM busybox - LABEL Vendor=Acme1`, true) - if err != nil || id1 == id2 { + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + LABEL Vendor=Acme1`)) + id2, err = getIDByName(name) + c.Assert(err, checker.IsNil) + if id1 == id2 { c.Fatalf("Build 3 should have worked & NOT used cache(%s,%s): %v", id1, id2, err) } - id2, err = buildImage(name, - `FROM busybox - LABEL Vendor Acme`, true) // Note: " " and "=" should be same - if err != nil || id1 != id2 { + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + LABEL Vendor Acme`)) + id2, err = getIDByName(name) + c.Assert(err, checker.IsNil) + if id1 != id2 { c.Fatalf("Build 4 should have worked & used cache(%s,%s): %v", id1, id2, err) } // Now make sure the cache isn't used by mistake - id1, err = buildImage(name, - `FROM busybox - LABEL f1=b1 f2=b2`, false) - if err != nil { - c.Fatalf("Build 5 should have worked: %q", err) - } + buildImageSuccessfully(c, name, withoutCache, withDockerfile(`FROM busybox + LABEL f1=b1 f2=b2`)) + _, err = getIDByName(name) + c.Assert(err, checker.IsNil) - id2, err = buildImage(name, - `FROM busybox - LABEL f1="b1 f2=b2"`, true) - if err != nil || id1 == id2 { + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox + LABEL f1=b1 f2=b2`)) + id2, err = getIDByName(name) + c.Assert(err, checker.IsNil) + if id1 == id2 { c.Fatalf("Build 6 should have worked & NOT used the cache(%s,%s): %q", id1, id2, err) } @@ -4524,60 +3534,49 @@ func (s *DockerSuite) TestBuildLabelsCache(c *check.C) { func (s *DockerSuite) TestBuildNotVerboseSuccess(c *check.C) { // This test makes sure that -q works correctly when build is successful: // stdout has only the image ID (long image ID) and stderr is empty. - var stdout, stderr string - var err error outRegexp := regexp.MustCompile("^(sha256:|)[a-z0-9]{64}\\n$") + buildFlags := withBuildFlags("-q") tt := []struct { Name string - BuildFunc func(string) + BuildFunc func(string) *icmd.Result }{ { Name: "quiet_build_stdin_success", - BuildFunc: func(name string) { - _, stdout, stderr, err = buildImageWithStdoutStderr(name, "FROM busybox", true, "-q", "--force-rm", "--rm") + BuildFunc: func(name string) *icmd.Result { + return buildImageNew(name, buildFlags, withDockerfile("FROM busybox")) }, }, { Name: "quiet_build_ctx_success", - BuildFunc: func(name string) { - ctx, err := fakeContext("FROM busybox", map[string]string{ - "quiet_build_success_fctx": "test", - }) - if err != nil { - c.Fatalf("Failed to create context: %s", err.Error()) - } - defer ctx.Close() - _, stdout, stderr, err = buildImageFromContextWithStdoutStderr(name, ctx, true, "-q", "--force-rm", "--rm") + BuildFunc: func(name string) *icmd.Result { + return buildImageNew(name, buildFlags, withBuildContext(c, + withFile("Dockerfile", "FROM busybox"), + withFile("quiet_build_success_fctx", "test"), + )) }, }, { Name: "quiet_build_git_success", - BuildFunc: func(name string) { + BuildFunc: func(name string) *icmd.Result { git, err := newFakeGit("repo", map[string]string{ "Dockerfile": "FROM busybox", }, true) - if err != nil { - c.Fatalf("Failed to create the git repo: %s", err.Error()) - } - defer git.Close() - _, stdout, stderr, err = buildImageFromGitWithStdoutStderr(name, git, true, "-q", "--force-rm", "--rm") - + c.Assert(err, checker.IsNil) + return buildImageNew(name, buildFlags, withBuildContextPath(git.RepoURL)) }, }, } for _, te := range tt { - te.BuildFunc(te.Name) - if err != nil { - c.Fatalf("Test %s shouldn't fail, but got the following error: %s", te.Name, err.Error()) - } - if outRegexp.Find([]byte(stdout)) == nil { - c.Fatalf("Test %s expected stdout to match the [%v] regexp, but it is [%v]", te.Name, outRegexp, stdout) + result := te.BuildFunc(te.Name) + result.Assert(c, icmd.Success) + if outRegexp.Find([]byte(result.Stdout())) == nil { + c.Fatalf("Test %s expected stdout to match the [%v] regexp, but it is [%v]", te.Name, outRegexp, result.Stdout()) } - if stderr != "" { - c.Fatalf("Test %s expected stderr to be empty, but it is [%#v]", te.Name, stderr) + if result.Stderr() != "" { + c.Fatalf("Test %s expected stderr to be empty, but it is [%#v]", te.Name, result.Stderr()) } } @@ -4589,14 +3588,17 @@ func (s *DockerSuite) TestBuildNotVerboseFailureWithNonExistImage(c *check.C) { // and stderr output in verbose mode testRequires(c, Network) testName := "quiet_build_not_exists_image" - buildCmd := "FROM busybox11" - _, _, qstderr, qerr := buildImageWithStdoutStderr(testName, buildCmd, false, "-q", "--force-rm", "--rm") - _, vstdout, vstderr, verr := buildImageWithStdoutStderr(testName, buildCmd, false, "--force-rm", "--rm") - if verr == nil || qerr == nil { - c.Fatal(fmt.Errorf("Test [%s] expected to fail but didn't", testName)) - } - if qstderr != vstdout+vstderr { - c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", testName, qstderr, vstdout+vstderr)) + dockerfile := "FROM busybox11" + quietResult := buildImageNew(testName, withBuildFlags("-q"), withDockerfile(dockerfile)) + quietResult.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + result := buildImageNew(testName, withDockerfile(dockerfile)) + result.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + if quietResult.Stderr() != result.Combined() { + c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", testName, quietResult.Stderr(), result.Combined())) } } @@ -4604,22 +3606,25 @@ func (s *DockerSuite) TestBuildNotVerboseFailure(c *check.C) { // This test makes sure that -q works correctly when build fails by // comparing between the stderr output in quiet mode and in stdout // and stderr output in verbose mode - tt := []struct { - TestName string - BuildCmds string + testCases := []struct { + testName string + dockerfile string }{ {"quiet_build_no_from_at_the_beginning", "RUN whoami"}, {"quiet_build_unknown_instr", "FROMD busybox"}, } - for _, te := range tt { - _, _, qstderr, qerr := buildImageWithStdoutStderr(te.TestName, te.BuildCmds, false, "-q", "--force-rm", "--rm") - _, vstdout, vstderr, verr := buildImageWithStdoutStderr(te.TestName, te.BuildCmds, false, "--force-rm", "--rm") - if verr == nil || qerr == nil { - c.Fatal(fmt.Errorf("Test [%s] expected to fail but didn't", te.TestName)) - } - if qstderr != vstdout+vstderr { - c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", te.TestName, qstderr, vstdout+vstderr)) + for _, tc := range testCases { + quietResult := buildImageNew(tc.testName, withBuildFlags("-q"), withDockerfile(tc.dockerfile)) + quietResult.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + result := buildImageNew(tc.testName, withDockerfile(tc.dockerfile)) + result.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + if quietResult.Stderr() != result.Combined() { + c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", tc.testName, quietResult.Stderr(), result.Combined())) } } } @@ -4629,14 +3634,17 @@ func (s *DockerSuite) TestBuildNotVerboseFailureRemote(c *check.C) { // stderr in verbose mode are identical. // TODO(vdemeester) with cobra, stdout has a carriage return too much so this test should not check stdout URL := "http://something.invalid" - Name := "quiet_build_wrong_remote" - _, _, qstderr, qerr := buildImageWithStdoutStderr(Name, "", false, "-q", "--force-rm", "--rm", URL) - _, _, vstderr, verr := buildImageWithStdoutStderr(Name, "", false, "--force-rm", "--rm", URL) - if qerr == nil || verr == nil { - c.Fatal(fmt.Errorf("Test [%s] expected to fail but didn't", Name)) - } - if qstderr != vstderr { - c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", Name, qstderr, vstderr)) + name := "quiet_build_wrong_remote" + quietResult := buildImageNew(name, withBuildFlags("-q"), withBuildContextPath(URL)) + quietResult.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + result := buildImageNew(name, withBuildContextPath(URL)) + result.Assert(c, icmd.Expected{ + ExitCode: 1, + }) + if strings.TrimSpace(quietResult.Stderr()) != strings.TrimSpace(result.Combined()) { + c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", name, quietResult.Stderr(), result.Combined())) } } @@ -4644,26 +3652,22 @@ func (s *DockerSuite) TestBuildStderr(c *check.C) { // This test just makes sure that no non-error output goes // to stderr name := "testbuildstderr" - _, stdout, stderr, err := buildImageWithStdoutStderr(name, - "FROM busybox\nRUN echo one", true) - if err != nil { - c.Fatal(err) - } + result := buildImageNew(name, withDockerfile("FROM busybox\nRUN echo one")) + result.Assert(c, icmd.Success) // Windows to non-Windows should have a security warning - if runtime.GOOS == "windows" && daemonPlatform != "windows" && !strings.Contains(stdout, "SECURITY WARNING:") { - c.Fatalf("Stdout contains unexpected output: %q", stdout) + if runtime.GOOS == "windows" && daemonPlatform != "windows" && !strings.Contains(result.Stdout(), "SECURITY WARNING:") { + c.Fatalf("Stdout contains unexpected output: %q", result.Stdout()) } // Stderr should always be empty - if stderr != "" { - c.Fatalf("Stderr should have been empty, instead it's: %q", stderr) + if result.Stderr() != "" { + c.Fatalf("Stderr should have been empty, instead it's: %q", result.Stderr()) } } func (s *DockerSuite) TestBuildChownSingleFile(c *check.C) { - testRequires(c, UnixCli) // test uses chown: not available on windows - testRequires(c, DaemonIsLinux) + testRequires(c, UnixCli, DaemonIsLinux) // test uses chown: not available on windows name := "testbuildchownsinglefile" @@ -4747,28 +3751,18 @@ func (s *DockerSuite) TestBuildXZHost(c *check.C) { testRequires(c, DaemonIsLinux) name := "testbuildxzhost" - ctx, err := fakeContext(` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM busybox ADD xz /usr/local/sbin/ RUN chmod 755 /usr/local/sbin/xz ADD test.xz / -RUN [ ! -e /injected ]`, - map[string]string{ - "test.xz": "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00" + - "\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd" + - "\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21", - "xz": "#!/bin/sh\ntouch /injected", - }) - - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } - +RUN [ ! -e /injected ]`), + withFile("test.xz", "\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00"+ + "\x21\x01\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x3f\xfd"+ + "\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21"), + withFile("xz", "#!/bin/sh\ntouch /injected"), + )) } func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) { @@ -4785,22 +3779,14 @@ func (s *DockerSuite) TestBuildVolumesRetainContents(c *check.C) { volName = "C:/foo" } - ctx, err := fakeContext(` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM busybox COPY content /foo/file VOLUME `+volName+` -CMD cat /foo/file`, - map[string]string{ - "content": expected, - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err := buildImageFromContext(name, ctx, false); err != nil { - c.Fatal(err) - } +CMD cat /foo/file`), + withFile("content", expected), + )) out, _ := dockerCmd(c, "run", "--rm", name) if out != expected { @@ -4809,8 +3795,8 @@ CMD cat /foo/file`, } +// FIXME(vdemeester) part of this should be unit test, other part should be clearer func (s *DockerSuite) TestBuildRenamedDockerfile(c *check.C) { - ctx, err := fakeContext(`FROM busybox RUN echo from Dockerfile`, map[string]string{ @@ -4917,50 +3903,23 @@ func (s *DockerSuite) TestBuildFromMixedcaseDockerfile(c *check.C) { testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows testRequires(c, DaemonIsLinux) - ctx, err := fakeContext(`FROM busybox - RUN echo from dockerfile`, - map[string]string{ - "dockerfile": "FROM busybox\nRUN echo from dockerfile", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".") - if err != nil { - c.Fatalf("Failed to build: %s\n%s", out, err) - } - - if !strings.Contains(out, "from dockerfile") { - c.Fatalf("Missing proper output: %s", out) - } - -} - -func (s *DockerSuite) TestBuildWithTwoDockerfiles(c *check.C) { - testRequires(c, UnixCli) // Dockerfile overwrites dockerfile on windows - testRequires(c, DaemonIsLinux) - - ctx, err := fakeContext(`FROM busybox -RUN echo from Dockerfile`, - map[string]string{ - "dockerfile": "FROM busybox\nRUN echo from dockerfile", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-t", "test1", ".") - if err != nil { - c.Fatalf("Failed to build: %s\n%s", out, err) - } - - if !strings.Contains(out, "from Dockerfile") { - c.Fatalf("Missing proper output: %s", out) - } + // If Dockerfile is not present, use dockerfile + buildImageNew("test1", withBuildContext(c, + withFile("dockerfile", `FROM busybox + RUN echo from dockerfile`), + )).Assert(c, icmd.Expected{ + Out: "from dockerfile", + }) + // Prefer Dockerfile in place of dockerfile + buildImageNew("test1", withBuildContext(c, + withFile("dockerfile", `FROM busybox + RUN echo from dockerfile`), + withFile("Dockerfile", `FROM busybox + RUN echo from Dockerfile`), + )).Assert(c, icmd.Expected{ + Out: "from Dockerfile", + }) } func (s *DockerSuite) TestBuildFromURLWithF(c *check.C) { @@ -4983,15 +3942,16 @@ RUN echo from Dockerfile`, // Make sure that -f is ignored and that we don't use the Dockerfile // that's in the current dir - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "-f", "baz", "-t", "test1", server.URL()+"/baz") - if err != nil { - c.Fatalf("Failed to build: %s\n%s", out, err) - } + result := buildImageNew("test1", withBuildFlags("-f", "baz", server.URL()+"/baz"), func(cmd *icmd.Cmd) func() { + cmd.Dir = ctx.Dir + return nil + }) + result.Assert(c, icmd.Success) - if !strings.Contains(out, "from baz") || - strings.Contains(out, "/tmp/baz") || - !strings.Contains(out, "/tmp/Dockerfile") { - c.Fatalf("Missing proper output: %s", out) + if !strings.Contains(result.Combined(), "from baz") || + strings.Contains(result.Combined(), "/tmp/baz") || + !strings.Contains(result.Combined(), "/tmp/Dockerfile") { + c.Fatalf("Missing proper output: %s", result.Combined()) } } @@ -5008,21 +3968,20 @@ RUN echo "from Dockerfile"`, // Make sure that -f is ignored and that we don't use the Dockerfile // that's in the current dir - dockerCommand := exec.Command(dockerBinary, "build", "-f", "baz", "-t", "test1", "-") - dockerCommand.Dir = ctx.Dir - dockerCommand.Stdin = strings.NewReader(`FROM busybox + result := buildImageNew("test1", withBuildFlags("-f", "baz", "-"), func(cmd *icmd.Cmd) func() { + cmd.Dir = ctx.Dir + cmd.Stdin = strings.NewReader(`FROM busybox RUN echo "from baz" COPY * /tmp/ RUN sh -c "find /tmp/" # sh -c is needed on Windows to use the correct find`) - out, status, err := runCommandWithOutput(dockerCommand) - if err != nil || status != 0 { - c.Fatalf("Error building: %s", err) - } + return nil + }) + result.Assert(c, icmd.Success) - if !strings.Contains(out, "from baz") || - strings.Contains(out, "/tmp/baz") || - !strings.Contains(out, "/tmp/Dockerfile") { - c.Fatalf("Missing proper output: %s", out) + if !strings.Contains(result.Combined(), "from baz") || + strings.Contains(result.Combined(), "/tmp/baz") || + !strings.Contains(result.Combined(), "/tmp/Dockerfile") { + c.Fatalf("Missing proper output: %s", result.Combined()) } } @@ -5039,17 +3998,13 @@ func (s *DockerSuite) TestBuildFromOfficialNames(c *check.C) { } for idx, fromName := range fromNames { imgName := fmt.Sprintf("%s%d", name, idx) - _, err := buildImage(imgName, "FROM "+fromName, true) - if err != nil { - c.Errorf("Build failed using FROM %s: %s", fromName, err) - } - deleteImages(imgName) + buildImageSuccessfully(c, imgName, withDockerfile("FROM "+fromName)) + dockerCmd(c, "rmi", imgName) } } func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) { - testRequires(c, UnixCli) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2) - testRequires(c, DaemonIsLinux) + testRequires(c, UnixCli, DaemonIsLinux) // uses os.Symlink: not implemented in windows at the time of writing (go-1.4.2) name := "testbuilddockerfileoutsidecontext" tmpdir, err := ioutil.TempDir("", name) @@ -5103,6 +4058,7 @@ func (s *DockerSuite) TestBuildDockerfileOutsideContext(c *check.C) { } } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildSpaces(c *check.C) { // Test to make sure that leading/trailing spaces on a command // doesn't change the error msg we get @@ -5181,39 +4137,31 @@ func (s *DockerSuite) TestBuildSpacesWithQuotes(c *check.C) { RUN echo " \ foo "` - _, out, err := buildImageWithOut(name, dockerfile, false) - if err != nil { - c.Fatal("Build failed:", err) - } - - expecting := "\n foo \n" + expected := "\n foo \n" // Windows uses the builtin echo, which preserves quotes if daemonPlatform == "windows" { - expecting = "\" foo \"" - } - if !strings.Contains(out, expecting) { - c.Fatalf("Bad output: %q expecting to contain %q", out, expecting) + expected = "\" foo \"" } + buildImageNew(name, withDockerfile(dockerfile)).Assert(c, icmd.Expected{ + Out: expected, + }) } // #4393 func (s *DockerSuite) TestBuildVolumeFileExistsinContainer(c *check.C) { testRequires(c, DaemonIsLinux) // TODO Windows: This should error out - buildCmd := exec.Command(dockerBinary, "build", "-t", "docker-test-errcreatevolumewithfile", "-") - buildCmd.Stdin = strings.NewReader(` + buildImageNew("docker-test-errcreatevolumewithfile", withDockerfile(` FROM busybox RUN touch /foo VOLUME /foo - `) - - out, _, err := runCommandWithOutput(buildCmd) - if err == nil || !strings.Contains(out, "file exists") { - c.Fatalf("expected build to fail when file exists in container at requested volume path") - } - + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "file exists", + }) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildMissingArgs(c *check.C) { // Test to make sure that all Dockerfile commands (except the ones listed // in skipCmds) will generate an error if no args are provided. @@ -5243,7 +4191,6 @@ func (s *DockerSuite) TestBuildMissingArgs(c *check.C) { if _, ok := skipCmds[cmd]; ok { continue } - var dockerfile string if cmd == "FROM" { dockerfile = cmd @@ -5252,87 +4199,53 @@ func (s *DockerSuite) TestBuildMissingArgs(c *check.C) { dockerfile = "FROM busybox\n" + cmd } - ctx, err := fakeContext(dockerfile, map[string]string{}) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - var out string - if out, err = buildImageFromContext("args", ctx, true); err == nil { - c.Fatalf("%s was supposed to fail. Out:%s", cmd, out) - } - if !strings.Contains(err.Error(), cmd+" requires") { - c.Fatalf("%s returned the wrong type of error:%s", cmd, err) - } + buildImageNew("args", withDockerfile(dockerfile)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: cmd + " requires", + }) } } func (s *DockerSuite) TestBuildEmptyScratch(c *check.C) { testRequires(c, DaemonIsLinux) - _, out, err := buildImageWithOut("sc", "FROM scratch", true) - if err == nil { - c.Fatalf("Build was supposed to fail") - } - if !strings.Contains(out, "No image was generated") { - c.Fatalf("Wrong error message: %v", out) - } + buildImageNew("sc", withDockerfile("FROM scratch")).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "No image was generated", + }) } func (s *DockerSuite) TestBuildDotDotFile(c *check.C) { - ctx, err := fakeContext("FROM busybox\n", - map[string]string{ - "..gitme": "", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if _, err = buildImageFromContext("sc", ctx, false); err != nil { - c.Fatalf("Build was supposed to work: %s", err) - } + buildImageSuccessfully(c, "sc", withBuildContext(c, + withFile("Dockerfile", "FROM busybox\n"), + withFile("..gitme", ""), + )) } func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) { testRequires(c, DaemonIsLinux) // No hello-world Windows image name := "testbuildrunonejson" - ctx, err := fakeContext(`FROM hello-world:frozen -RUN [ "/hello" ]`, map[string]string{}) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-t", name, ".") - if err != nil { - c.Fatalf("failed to build the image: %s, %v", out, err) - } - - if !strings.Contains(out, "Hello from Docker") { - c.Fatalf("bad output: %s", out) - } - + buildImageNew(name, withDockerfile(`FROM hello-world:frozen +RUN [ "/hello" ]`)).Assert(c, icmd.Expected{ + Out: "Hello from Docker", + }) } func (s *DockerSuite) TestBuildEmptyStringVolume(c *check.C) { name := "testbuildemptystringvolume" - _, err := buildImage(name, ` + buildImageNew(name, withDockerfile(` FROM busybox ENV foo="" VOLUME $foo - `, false) - if err == nil { - c.Fatal("Should have failed to build") - } - + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + }) } func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) { - testRequires(c, SameHostDaemon) - testRequires(c, DaemonIsLinux) + testRequires(c, SameHostDaemon, DaemonIsLinux) cgroupParent := "test" data, err := ioutil.ReadFile("/proc/self/cgroup") @@ -5344,56 +4257,46 @@ func (s *DockerSuite) TestBuildContainerWithCgroupParent(c *check.C) { if !found { c.Fatalf("unable to find self memory cgroup path. CgroupsPath: %v", selfCgroupPaths) } - cmd := exec.Command(dockerBinary, "build", "--cgroup-parent", cgroupParent, "-") - cmd.Stdin = strings.NewReader(` + result := buildImageNew("buildcgroupparent", + withBuildFlags("--cgroup-parent", cgroupParent), + withDockerfile(` FROM busybox RUN cat /proc/self/cgroup -`) - - out, _, err := runCommandWithOutput(cmd) - if err != nil { - c.Fatalf("unexpected failure when running container with --cgroup-parent option - %s\n%v", string(out), err) - } - m, err := regexp.MatchString(fmt.Sprintf("memory:.*/%s/.*", cgroupParent), out) +`)) + result.Assert(c, icmd.Success) + m, err := regexp.MatchString(fmt.Sprintf("memory:.*/%s/.*", cgroupParent), result.Combined()) c.Assert(err, check.IsNil) if !m { - c.Fatalf("There is no expected memory cgroup with parent /%s/: %s", cgroupParent, out) + c.Fatalf("There is no expected memory cgroup with parent /%s/: %s", cgroupParent, result.Combined()) } } +// FIXME(vdemeester) could be a unit test func (s *DockerSuite) TestBuildNoDupOutput(c *check.C) { // Check to make sure our build output prints the Dockerfile cmd // property - there was a bug that caused it to be duplicated on the // Step X line name := "testbuildnodupoutput" - - _, out, err := buildImageWithOut(name, ` + result := buildImageNew(name, withDockerfile(` FROM busybox - RUN env`, false) - if err != nil { - c.Fatalf("Build should have worked: %q", err) - } - + RUN env`)) + result.Assert(c, icmd.Success) exp := "\nStep 2/2 : RUN env\n" - if !strings.Contains(out, exp) { - c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp) + if !strings.Contains(result.Combined(), exp) { + c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp) } } // GH15826 +// FIXME(vdemeester) could be a unit test func (s *DockerSuite) TestBuildStartsFromOne(c *check.C) { // Explicit check to ensure that build starts from step 1 rather than 0 name := "testbuildstartsfromone" - - _, out, err := buildImageWithOut(name, ` - FROM busybox`, false) - if err != nil { - c.Fatalf("Build should have worked: %q", err) - } - + result := buildImageNew(name, withDockerfile(`FROM busybox`)) + result.Assert(c, icmd.Success) exp := "\nStep 1/1 : FROM busybox\n" - if !strings.Contains(out, exp) { - c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", out, exp) + if !strings.Contains(result.Combined(), exp) { + c.Fatalf("Bad output\nGot:%s\n\nExpected to contain:%s\n", result.Combined(), exp) } } @@ -5401,23 +4304,21 @@ func (s *DockerSuite) TestBuildRUNErrMsg(c *check.C) { // Test to make sure the bad command is quoted with just "s and // not as a Go []string name := "testbuildbadrunerrmsg" - _, out, err := buildImageWithOut(name, ` - FROM busybox - RUN badEXE a1 \& a2 a3`, false) // tab between a2 and a3 - if err == nil { - c.Fatal("Should have failed to build") - } shell := "/bin/sh -c" - exitCode := "127" + exitCode := 127 if daemonPlatform == "windows" { shell = "cmd /S /C" // architectural - Windows has to start the container to determine the exe is bad, Linux does not - exitCode = "1" - } - exp := `The command '` + shell + ` badEXE a1 \& a2 a3' returned a non-zero code: ` + exitCode - if !strings.Contains(out, exp) { - c.Fatalf("RUN doesn't have the correct output:\nGot:%s\nExpected:%s", out, exp) + exitCode = 1 } + exp := fmt.Sprintf(`The command '%s badEXE a1 \& a2 a3' returned a non-zero code: %d`, shell, exitCode) + + buildImageNew(name, withDockerfile(` + FROM busybox + RUN badEXE a1 \& a2 a3`)).Assert(c, icmd.Expected{ + ExitCode: exitCode, + Err: exp, + }) } func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) { @@ -5429,26 +4330,15 @@ func (s *DockerTrustSuite) TestTrustedBuild(c *check.C) { name := "testtrustedbuild" - buildCmd := buildImageCmd(name, dockerFile, true) - trustedExecCmd(buildCmd) - out, _, err := runCommandWithOutput(buildCmd) - if err != nil { - c.Fatalf("Error running trusted build: %s\n%s", err, out) - } - - if !strings.Contains(out, fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7])) { - c.Fatalf("Unexpected output on trusted build:\n%s", out) - } + buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{ + Out: fmt.Sprintf("FROM %s@sha", repoName[:len(repoName)-7]), + }) // We should also have a tag reference for the image. - if out, exitCode := dockerCmd(c, "inspect", repoName); exitCode != 0 { - c.Fatalf("unexpected exit code inspecting image %q: %d: %s", repoName, exitCode, out) - } + dockerCmd(c, "inspect", repoName) // We should now be able to remove the tag reference. - if out, exitCode := dockerCmd(c, "rmi", repoName); exitCode != 0 { - c.Fatalf("unexpected exit code inspecting image %q: %d: %s", repoName, exitCode, out) - } + dockerCmd(c, "rmi", repoName) } func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) { @@ -5460,16 +4350,10 @@ func (s *DockerTrustSuite) TestTrustedBuildUntrustedTag(c *check.C) { name := "testtrustedbuilduntrustedtag" - buildCmd := buildImageCmd(name, dockerFile, true) - trustedExecCmd(buildCmd) - out, _, err := runCommandWithOutput(buildCmd) - if err == nil { - c.Fatalf("Expected error on trusted build with untrusted tag: %s\n%s", err, out) - } - - if !strings.Contains(out, "does not have trust data for") { - c.Fatalf("Unexpected output on trusted build with untrusted tag:\n%s", out) - } + buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "does not have trust data for", + }) } func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) { @@ -5504,9 +4388,7 @@ func (s *DockerTrustSuite) TestBuildContextDirIsSymlink(c *check.C) { // Executing the build with the symlink as the specified context should // *not* fail. - if out, exitStatus := dockerCmd(c, "build", contextSymlinkName); exitStatus != 0 { - c.Fatalf("build failed with exit status %d: %s", exitStatus, out) - } + dockerCmd(c, "build", contextSymlinkName) } func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) { @@ -5535,14 +4417,10 @@ func (s *DockerTrustSuite) TestTrustedBuildTagFromReleasesRole(c *check.C) { FROM %s RUN [] `, otherTag) - name := "testtrustedbuildreleasesrole" - - buildCmd := buildImageCmd(name, dockerFile, true) - trustedExecCmd(buildCmd) - out, _, err := runCommandWithOutput(buildCmd) - c.Assert(err, check.IsNil, check.Commentf("Trusted build failed: %s", out)) - c.Assert(out, checker.Contains, fmt.Sprintf("FROM %s@sha", repoName)) + buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{ + Out: fmt.Sprintf("FROM %s@sha", repoName), + }) } func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *check.C) { @@ -5573,50 +4451,37 @@ func (s *DockerTrustSuite) TestTrustedBuildTagIgnoresOtherDelegationRoles(c *che `, otherTag) name := "testtrustedbuildotherrole" - - buildCmd := buildImageCmd(name, dockerFile, true) - trustedExecCmd(buildCmd) - out, _, err := runCommandWithOutput(buildCmd) - c.Assert(err, check.NotNil, check.Commentf("Trusted build expected to fail: %s", out)) + buildImageNew(name, trustedBuild, withDockerfile(dockerFile)).Assert(c, icmd.Expected{ + ExitCode: 1, + }) } // Issue #15634: COPY fails when path starts with "null" func (s *DockerSuite) TestBuildNullStringInAddCopyVolume(c *check.C) { name := "testbuildnullstringinaddcopyvolume" - volName := "nullvolume" - if daemonPlatform == "windows" { volName = `C:\\nullvolume` } - ctx, err := fakeContext(` + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", ` FROM busybox ADD null / COPY nullfile / VOLUME `+volName+` - `, - map[string]string{ - "null": "test1", - "nullfile": "test2", - }, - ) - c.Assert(err, check.IsNil) - defer ctx.Close() - - _, err = buildImageFromContext(name, ctx, true) - c.Assert(err, check.IsNil) + `), + withFile("null", "test1"), + withFile("nullfile", "test2"), + )) } func (s *DockerSuite) TestBuildStopSignal(c *check.C) { testRequires(c, DaemonIsLinux) // Windows does not support STOPSIGNAL yet imgName := "test_build_stop_signal" - _, err := buildImage(imgName, - `FROM busybox - STOPSIGNAL SIGKILL`, - true) - c.Assert(err, check.IsNil) + buildImageSuccessfully(c, imgName, withDockerfile(`FROM busybox + STOPSIGNAL SIGKILL`)) res := inspectFieldJSON(c, imgName, "Config.StopSignal") if res != `"SIGKILL"` { c.Fatalf("Signal %s, expected SIGKILL", res) @@ -5624,7 +4489,6 @@ func (s *DockerSuite) TestBuildStopSignal(c *check.C) { containerName := "test-container-stop-signal" dockerCmd(c, "run", "-d", "--name", containerName, imgName, "top") - res = inspectFieldJSON(c, containerName, "Config.StopSignal") if res != `"SIGKILL"` { c.Fatalf("Signal %s, expected SIGKILL", res) @@ -5635,7 +4499,6 @@ func (s *DockerSuite) TestBuildBuildTimeArg(c *check.C) { imgName := "bldargtest" envKey := "foo" envVal := "bar" - args := []string{"--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)} var dockerfile string if daemonPlatform == "windows" { // Bugs in Windows busybox port - use the default base image and native cmd stuff @@ -5650,13 +4513,12 @@ func (s *DockerSuite) TestBuildBuildTimeArg(c *check.C) { CMD echo $%s`, envKey, envKey, envKey) } - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || !strings.Contains(out, envVal) { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envVal) - } + buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ).Assert(c, icmd.Expected{ + Out: envVal, + }) containerName := "bldargCont" out, _ := dockerCmd(c, "run", "--name", containerName, imgName) @@ -5671,18 +4533,14 @@ func (s *DockerSuite) TestBuildBuildTimeArgHistory(c *check.C) { envKey := "foo" envVal := "bar" envDef := "bar1" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox ARG %s=%s`, envKey, envDef) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || !strings.Contains(out, envVal) { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envVal) - } + buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ).Assert(c, icmd.Expected{ + Out: envVal, + }) out, _ := dockerCmd(c, "history", "--no-trunc", imgName) outputTabs := strings.Split(out, "\n")[1] @@ -5695,24 +4553,24 @@ func (s *DockerSuite) TestBuildBuildTimeArgCacheHit(c *check.C) { imgName := "bldargtest" envKey := "foo" envVal := "bar" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox ARG %s RUN echo $%s`, envKey, envKey) - - origImgID := "" - var err error - if origImgID, err = buildImage(imgName, dockerfile, true, args...); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + origImgID, err := getIDByName(imgName) + c.Assert(err, checker.IsNil) imgNameCache := "bldargtestcachehit" - if newImgID, err := buildImage(imgNameCache, dockerfile, true, args...); err != nil || newImgID != origImgID { - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgNameCache, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + newImgID, err := getIDByName(imgName) + c.Assert(err, checker.IsNil) + if newImgID != origImgID { c.Fatalf("build didn't use cache! expected image id: %q built image id: %q", origImgID, newImgID) } } @@ -5723,27 +4581,29 @@ func (s *DockerSuite) TestBuildBuildTimeArgCacheMissExtraArg(c *check.C) { envVal := "bar" extraEnvKey := "foo1" extraEnvVal := "bar1" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } - dockerfile := fmt.Sprintf(`FROM busybox ARG %s ARG %s RUN echo $%s`, envKey, extraEnvKey, envKey) - - origImgID := "" - var err error - if origImgID, err = buildImage(imgName, dockerfile, true, args...); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + origImgID, err := getIDByName(imgName) + c.Assert(err, checker.IsNil) imgNameCache := "bldargtestcachemiss" - args = append(args, "--build-arg", fmt.Sprintf("%s=%s", extraEnvKey, extraEnvVal)) - if newImgID, err := buildImage(imgNameCache, dockerfile, true, args...); err != nil || newImgID == origImgID { - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgNameCache, + withBuildFlags( + "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), + "--build-arg", fmt.Sprintf("%s=%s", extraEnvKey, extraEnvVal), + ), + withDockerfile(dockerfile), + ) + newImgID, err := getIDByName(imgNameCache) + c.Assert(err, checker.IsNil) + + if newImgID == origImgID { c.Fatalf("build used cache, expected a miss!") } } @@ -5753,28 +4613,24 @@ func (s *DockerSuite) TestBuildBuildTimeArgCacheMissSameArgDiffVal(c *check.C) { envKey := "foo" envVal := "bar" newEnvVal := "bar1" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } - dockerfile := fmt.Sprintf(`FROM busybox ARG %s RUN echo $%s`, envKey, envKey) - - origImgID := "" - var err error - if origImgID, err = buildImage(imgName, dockerfile, true, args...); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + origImgID, err := getIDByName(imgName) + c.Assert(err, checker.IsNil) imgNameCache := "bldargtestcachemiss" - args = []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, newEnvVal), - } - if newImgID, err := buildImage(imgNameCache, dockerfile, true, args...); err != nil || newImgID == origImgID { - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, imgNameCache, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, newEnvVal)), + withDockerfile(dockerfile), + ) + newImgID, err := getIDByName(imgNameCache) + c.Assert(err, checker.IsNil) + if newImgID == origImgID { c.Fatalf("build used cache, expected a miss!") } } @@ -5785,9 +4641,6 @@ func (s *DockerSuite) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv(c *check. envKey := "foo" envVal := "bar" envValOveride := "barOverride" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox ARG %s ENV %s %s @@ -5795,11 +4648,13 @@ func (s *DockerSuite) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv(c *check. CMD echo $%s `, envKey, envKey, envValOveride, envKey, envKey) - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Count(out, envValOveride) != 2 { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envValOveride) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if strings.Count(result.Combined(), envValOveride) != 2 { + c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride) } containerName := "bldargCont" @@ -5808,27 +4663,26 @@ func (s *DockerSuite) TestBuildBuildTimeArgOverrideArgDefinedBeforeEnv(c *check. } } +// FIXME(vdemeester) might be useful to merge with the one above ? func (s *DockerSuite) TestBuildBuildTimeArgOverrideEnvDefinedBeforeArg(c *check.C) { testRequires(c, DaemonIsLinux) // Windows does not support ARG imgName := "bldargtest" envKey := "foo" envVal := "bar" envValOveride := "barOverride" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox ENV %s %s ARG %s RUN echo $%s CMD echo $%s `, envKey, envValOveride, envKey, envKey, envKey) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Count(out, envValOveride) != 2 { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envValOveride) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if strings.Count(result.Combined(), envValOveride) != 2 { + c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride) } containerName := "bldargCont" @@ -5855,16 +4709,19 @@ func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) { userVal := "testUser" volVar := "VOL" volVal := "/testVol/" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", wdVar, wdVal), - "--build-arg", fmt.Sprintf("%s=%s", addVar, addVal), - "--build-arg", fmt.Sprintf("%s=%s", copyVar, copyVal), - "--build-arg", fmt.Sprintf("%s=%s", envVar, envVal), - "--build-arg", fmt.Sprintf("%s=%s", exposeVar, exposeVal), - "--build-arg", fmt.Sprintf("%s=%s", userVar, userVal), - "--build-arg", fmt.Sprintf("%s=%s", volVar, volVal), - } - ctx, err := fakeContext(fmt.Sprintf(`FROM busybox + + buildImageSuccessfully(c, imgName, + withBuildFlags( + "--build-arg", fmt.Sprintf("%s=%s", wdVar, wdVal), + "--build-arg", fmt.Sprintf("%s=%s", addVar, addVal), + "--build-arg", fmt.Sprintf("%s=%s", copyVar, copyVal), + "--build-arg", fmt.Sprintf("%s=%s", envVar, envVal), + "--build-arg", fmt.Sprintf("%s=%s", exposeVar, exposeVal), + "--build-arg", fmt.Sprintf("%s=%s", userVar, userVal), + "--build-arg", fmt.Sprintf("%s=%s", volVar, volVal), + ), + withBuildContext(c, + withFile("Dockerfile", fmt.Sprintf(`FROM busybox ARG %s WORKDIR ${%s} ARG %s @@ -5879,30 +4736,20 @@ func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) { USER $%s ARG %s VOLUME ${%s}`, - wdVar, wdVar, addVar, addVar, copyVar, copyVar, envVar, envVar, - envVar, exposeVar, exposeVar, userVar, userVar, volVar, volVar), - map[string]string{ - addVal: "some stuff", - copyVal: "some stuff", - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() + wdVar, wdVar, addVar, addVar, copyVar, copyVar, envVar, envVar, + envVar, exposeVar, exposeVar, userVar, userVar, volVar, volVar)), + withFile(addVal, "some stuff"), + withFile(copyVal, "some stuff"), + ), + ) - if _, err := buildImageFromContext(imgName, ctx, true, args...); err != nil { - c.Fatal(err) - } - - var resMap map[string]interface{} - var resArr []string - res := "" - res = inspectField(c, imgName, "Config.WorkingDir") + res := inspectField(c, imgName, "Config.WorkingDir") if res != filepath.ToSlash(filepath.Clean(wdVal)) { c.Fatalf("Config.WorkingDir value mismatch. Expected: %s, got: %s", filepath.ToSlash(filepath.Clean(wdVal)), res) } - inspectFieldAndMarshall(c, imgName, "Config.Env", &resArr) + var resArr []string + inspectFieldAndUnmarshall(c, imgName, "Config.Env", &resArr) found := false for _, v := range resArr { @@ -5916,7 +4763,8 @@ func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) { envVar, envVal, resArr) } - inspectFieldAndMarshall(c, imgName, "Config.ExposedPorts", &resMap) + var resMap map[string]interface{} + inspectFieldAndUnmarshall(c, imgName, "Config.ExposedPorts", &resMap) if _, ok := resMap[fmt.Sprintf("%s/tcp", exposeVal)]; !ok { c.Fatalf("Config.ExposedPorts value mismatch. Expected exposed port: %s/tcp, got: %v", exposeVal, resMap) } @@ -5926,7 +4774,7 @@ func (s *DockerSuite) TestBuildBuildTimeArgExpansion(c *check.C) { c.Fatalf("Config.User value mismatch. Expected: %s, got: %s", userVal, res) } - inspectFieldAndMarshall(c, imgName, "Config.Volumes", &resMap) + inspectFieldAndUnmarshall(c, imgName, "Config.Volumes", &resMap) if _, ok := resMap[volVal]; !ok { c.Fatalf("Config.Volumes value mismatch. Expected volume: %s, got: %v", volVal, resMap) } @@ -5939,21 +4787,19 @@ func (s *DockerSuite) TestBuildBuildTimeArgExpansionOverride(c *check.C) { envVal := "bar" envKey1 := "foo1" envValOveride := "barOverride" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox ARG %s ENV %s %s ENV %s ${%s} RUN echo $%s CMD echo $%s`, envKey, envKey, envValOveride, envKey1, envKey, envKey1, envKey1) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Count(out, envValOveride) != 2 { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envValOveride) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if strings.Count(result.Combined(), envValOveride) != 2 { + c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride) } containerName := "bldargCont" @@ -5967,19 +4813,17 @@ func (s *DockerSuite) TestBuildBuildTimeArgUntrustedDefinedAfterUse(c *check.C) imgName := "bldargtest" envKey := "foo" envVal := "bar" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox RUN echo $%s ARG %s CMD echo $%s`, envKey, envKey, envKey) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Contains(out, envVal) { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("able to access environment variable in output: %q expected to be missing", out) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if strings.Contains(result.Combined(), envVal) { + c.Fatalf("able to access environment variable in output: %q expected to be missing", result.Combined()) } containerName := "bldargCont" @@ -5993,20 +4837,18 @@ func (s *DockerSuite) TestBuildBuildTimeArgBuiltinArg(c *check.C) { imgName := "bldargtest" envKey := "HTTP_PROXY" envVal := "bar" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox RUN echo $%s CMD echo $%s`, envKey, envKey) - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || !strings.Contains(out, envVal) { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envVal) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if !strings.Contains(result.Combined(), envVal) { + c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envVal) } - containerName := "bldargCont" if out, _ := dockerCmd(c, "run", "--name", containerName, imgName); out != "\n" { c.Fatalf("run produced invalid output: %q, expected empty string", out) @@ -6019,20 +4861,18 @@ func (s *DockerSuite) TestBuildBuildTimeArgDefaultOverride(c *check.C) { envKey := "foo" envVal := "bar" envValOveride := "barOverride" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envValOveride), - } dockerfile := fmt.Sprintf(`FROM busybox ARG %s=%s ENV %s $%s RUN echo $%s CMD echo $%s`, envKey, envVal, envKey, envKey, envKey, envKey) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Count(out, envValOveride) != 1 { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("failed to access environment variable in output: %q expected: %q", out, envValOveride) + result := buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envValOveride)), + withDockerfile(dockerfile), + ) + result.Assert(c, icmd.Success) + if strings.Count(result.Combined(), envValOveride) != 1 { + c.Fatalf("failed to access environment variable in output: %q expected: %q", result.Combined(), envValOveride) } containerName := "bldargCont" @@ -6045,40 +4885,21 @@ func (s *DockerSuite) TestBuildBuildTimeArgUnconsumedArg(c *check.C) { imgName := "bldargtest" envKey := "foo" envVal := "bar" - args := []string{ - "--build-arg", fmt.Sprintf("%s=%s", envKey, envVal), - } dockerfile := fmt.Sprintf(`FROM busybox RUN echo $%s CMD echo $%s`, envKey, envKey) - warnStr := "[Warning] One or more build-args" - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); !strings.Contains(out, warnStr) { - c.Fatalf("build completed without warning: %q %q", out, err) - } else if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - + buildImageNew(imgName, + withBuildFlags("--build-arg", fmt.Sprintf("%s=%s", envKey, envVal)), + withDockerfile(dockerfile), + ).Assert(c, icmd.Expected{ + Out: warnStr, + }) } func (s *DockerSuite) TestBuildBuildTimeArgEnv(c *check.C) { testRequires(c, DaemonIsLinux) // Windows does not support ARG - args := []string{ - "build", - "--build-arg", fmt.Sprintf("FOO1=fromcmd"), - "--build-arg", fmt.Sprintf("FOO2="), - "--build-arg", fmt.Sprintf("FOO3"), // set in env - "--build-arg", fmt.Sprintf("FOO4"), // not set in env - "--build-arg", fmt.Sprintf("FOO5=fromcmd"), - // FOO6 is not set at all - "--build-arg", fmt.Sprintf("FOO7=fromcmd"), // should produce a warning - "--build-arg", fmt.Sprintf("FOO8="), // should produce a warning - "--build-arg", fmt.Sprintf("FOO9"), // should produce a warning - ".", - } - - dockerfile := fmt.Sprintf(`FROM busybox + dockerfile := `FROM busybox ARG FOO1=fromfile ARG FOO2=fromfile ARG FOO3=fromfile @@ -6096,30 +4917,36 @@ func (s *DockerSuite) TestBuildBuildTimeArgEnv(c *check.C) { RUN [ "$(env | grep FOO7)" == "" ] RUN [ "$(env | grep FOO8)" == "" ] RUN [ "$(env | grep FOO9)" == "" ] - `) - - ctx, err := fakeContext(dockerfile, nil) - c.Assert(err, check.IsNil) - defer ctx.Close() - - cmd := exec.Command(dockerBinary, args...) - cmd.Dir = ctx.Dir - cmd.Env = append(os.Environ(), - "FOO1=fromenv", - "FOO2=fromenv", - "FOO3=fromenv") - out, _, err := runCommandWithOutput(cmd) - if err != nil { - c.Fatal(err, out) - } + ` + result := buildImageNew("testbuildtimeargenv", + withBuildFlags( + "--build-arg", fmt.Sprintf("FOO1=fromcmd"), + "--build-arg", fmt.Sprintf("FOO2="), + "--build-arg", fmt.Sprintf("FOO3"), // set in env + "--build-arg", fmt.Sprintf("FOO4"), // not set in env + "--build-arg", fmt.Sprintf("FOO5=fromcmd"), + // FOO6 is not set at all + "--build-arg", fmt.Sprintf("FOO7=fromcmd"), // should produce a warning + "--build-arg", fmt.Sprintf("FOO8="), // should produce a warning + "--build-arg", fmt.Sprintf("FOO9"), // should produce a warning + ), + withEnvironmentVariales(append(os.Environ(), + "FOO1=fromenv", + "FOO2=fromenv", + "FOO3=fromenv")...), + withBuildContext(c, + withFile("Dockerfile", dockerfile), + ), + ) + result.Assert(c, icmd.Success) // Now check to make sure we got a warning msg about unused build-args - i := strings.Index(out, "[Warning]") + i := strings.Index(result.Combined(), "[Warning]") if i < 0 { - c.Fatalf("Missing the build-arg warning in %q", out) + c.Fatalf("Missing the build-arg warning in %q", result.Combined()) } - out = out[i:] // "out" should contain just the warning message now + out := result.Combined()[i:] // "out" should contain just the warning message now // These were specified on a --build-arg but no ARG was in the Dockerfile c.Assert(out, checker.Contains, "FOO7") @@ -6133,7 +4960,6 @@ func (s *DockerSuite) TestBuildBuildTimeArgQuotedValVariants(c *check.C) { envKey1 := "foo1" envKey2 := "foo2" envKey3 := "foo3" - args := []string{} dockerfile := fmt.Sprintf(`FROM busybox ARG %s="" ARG %s='' @@ -6146,10 +4972,7 @@ func (s *DockerSuite) TestBuildBuildTimeArgQuotedValVariants(c *check.C) { RUN [ "$%s" != "$%s" ]`, envKey, envKey1, envKey2, envKey3, envKey, envKey2, envKey, envKey3, envKey1, envKey2, envKey1, envKey3, envKey2, envKey3) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } + buildImageSuccessfully(c, imgName, withDockerfile(dockerfile)) } func (s *DockerSuite) TestBuildBuildTimeArgEmptyValVariants(c *check.C) { @@ -6158,7 +4981,6 @@ func (s *DockerSuite) TestBuildBuildTimeArgEmptyValVariants(c *check.C) { envKey := "foo" envKey1 := "foo1" envKey2 := "foo2" - args := []string{} dockerfile := fmt.Sprintf(`FROM busybox ARG %s= ARG %s="" @@ -6166,25 +4988,20 @@ func (s *DockerSuite) TestBuildBuildTimeArgEmptyValVariants(c *check.C) { RUN [ "$%s" == "$%s" ] RUN [ "$%s" == "$%s" ] RUN [ "$%s" == "$%s" ]`, envKey, envKey1, envKey2, envKey, envKey1, envKey1, envKey2, envKey, envKey2) - - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } + buildImageSuccessfully(c, imgName, withDockerfile(dockerfile)) } func (s *DockerSuite) TestBuildBuildTimeArgDefintionWithNoEnvInjection(c *check.C) { imgName := "bldargtest" envKey := "foo" - args := []string{} dockerfile := fmt.Sprintf(`FROM busybox ARG %s RUN env`, envKey) - if _, out, err := buildImageWithOut(imgName, dockerfile, true, args...); err != nil || strings.Count(out, envKey) != 1 { - if err != nil { - c.Fatalf("build failed to complete: %q %q", out, err) - } - c.Fatalf("unexpected number of occurrences of the arg in output: %q expected: 1", out) + result := buildImageNew(imgName, withDockerfile(dockerfile)) + result.Assert(c, icmd.Success) + if strings.Count(result.Combined(), envKey) != 1 { + c.Fatalf("unexpected number of occurrences of the arg in output: %q expected: 1", result.Combined()) } } @@ -6200,8 +5017,9 @@ func (s *DockerSuite) TestBuildNoNamedVolume(c *check.C) { VOLUME ` + volName + ` RUN ls /foo/oops ` - _, err := buildImage("test", dockerFile, false) - c.Assert(err, check.NotNil, check.Commentf("image build should have failed")) + buildImageNew("test", withDockerfile(dockerFile)).Assert(c, icmd.Expected{ + ExitCode: 1, + }) } func (s *DockerSuite) TestBuildTagEvent(c *check.C) { @@ -6210,8 +5028,7 @@ func (s *DockerSuite) TestBuildTagEvent(c *check.C) { dockerFile := `FROM busybox RUN echo events ` - _, err := buildImage("test", dockerFile, false) - c.Assert(err, check.IsNil) + buildImageSuccessfully(c, "test", withDockerfile(dockerFile)) until := daemonUnixTime(c) out, _ := dockerCmd(c, "events", "--since", since, "--until", until, "--filter", "type=image") @@ -6234,10 +5051,7 @@ func (s *DockerSuite) TestBuildMultipleTags(c *check.C) { FROM busybox MAINTAINER test-15780 ` - icmd.RunCmd(icmd.Cmd{ - Command: []string{dockerBinary, "build", "-t", "tag1", "-t", "tag2:v2", "-t", "tag1:latest", "-t", "tag1", "--no-cache", "-"}, - Stdin: strings.NewReader(dockerfile), - }).Assert(c, icmd.Success) + buildImageSuccessfully(c, "tag1", withBuildFlags("-t", "tag2:v2", "-t", "tag1:latest", "-t", "tag1"), withDockerfile(dockerfile)) id1, err := getIDByName("tag1") c.Assert(err, check.IsNil) @@ -6394,55 +5208,43 @@ func (s *DockerSuite) TestBuildCacheRootSource(c *check.C) { // #19375 func (s *DockerSuite) TestBuildFailsGitNotCallable(c *check.C) { - cmd := exec.Command(dockerBinary, "build", "github.com/docker/v1.10-migrator.git") - cmd.Env = append(cmd.Env, "PATH=") - out, _, err := runCommandWithOutput(cmd) - c.Assert(err, checker.NotNil) - c.Assert(out, checker.Contains, "unable to prepare context: unable to find 'git': ") + buildImageNew("gitnotcallable", withEnvironmentVariales("PATH="), + withBuildContextPath("github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "unable to prepare context: unable to find 'git': ", + }) - cmd = exec.Command(dockerBinary, "build", "https://github.com/docker/v1.10-migrator.git") - cmd.Env = append(cmd.Env, "PATH=") - out, _, err = runCommandWithOutput(cmd) - c.Assert(err, checker.NotNil) - c.Assert(out, checker.Contains, "unable to prepare context: unable to find 'git': ") + buildImageNew("gitnotcallable", withEnvironmentVariales("PATH="), + withBuildContextPath("https://github.com/docker/v1.10-migrator.git")).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "unable to prepare context: unable to find 'git': ", + }) } // TestBuildWorkdirWindowsPath tests that a Windows style path works as a workdir func (s *DockerSuite) TestBuildWorkdirWindowsPath(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildworkdirwindowspath" - - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM `+WindowsBaseImage+` RUN mkdir C:\\work WORKDIR C:\\work RUN if "%CD%" NEQ "C:\work" exit -1 - `, true) - - if err != nil { - c.Fatal(err) - } + `)) } func (s *DockerSuite) TestBuildLabel(c *check.C) { name := "testbuildlabel" testLabel := "foo" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel), + withDockerfile(` FROM `+minimalBaseImage()+` LABEL default foo -`, false, "--label", testLabel) - - c.Assert(err, checker.IsNil) - - res := inspectFieldJSON(c, name, "Config.Labels") +`)) var labels map[string]string - - if err := json.Unmarshal([]byte(res), &labels); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels) if _, ok := labels[testLabel]; !ok { c.Fatal("label not found in image") } @@ -6450,19 +5252,11 @@ func (s *DockerSuite) TestBuildLabel(c *check.C) { func (s *DockerSuite) TestBuildLabelOneNode(c *check.C) { name := "testbuildlabel" + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=bar"), + withDockerfile("FROM busybox")) - _, err := buildImage(name, "FROM busybox", false, "--label", "foo=bar") - - c.Assert(err, checker.IsNil) - - res, err := inspectImage(name, "json .Config.Labels") - c.Assert(err, checker.IsNil) var labels map[string]string - - if err := json.Unmarshal([]byte(res), &labels); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels) v, ok := labels["foo"] if !ok { c.Fatal("label `foo` not found in image") @@ -6474,28 +5268,18 @@ func (s *DockerSuite) TestBuildLabelCacheCommit(c *check.C) { name := "testbuildlabelcachecommit" testLabel := "foo" - if _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM `+minimalBaseImage()+` LABEL default foo - `, false); err != nil { - c.Fatal(err) - } - - _, err := buildImage(name, ` + `)) + buildImageSuccessfully(c, name, withBuildFlags("--label", testLabel), + withDockerfile(` FROM `+minimalBaseImage()+` LABEL default foo -`, true, "--label", testLabel) - - c.Assert(err, checker.IsNil) - - res := inspectFieldJSON(c, name, "Config.Labels") + `)) var labels map[string]string - - if err := json.Unmarshal([]byte(res), &labels); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels) if _, ok := labels[testLabel]; !ok { c.Fatal("label not found in image") } @@ -6507,30 +5291,19 @@ func (s *DockerSuite) TestBuildLabelMultiple(c *check.C) { "foo": "bar", "123": "456", } - labelArgs := []string{} - for k, v := range testLabels { labelArgs = append(labelArgs, "--label", k+"="+v) } - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withBuildFlags(labelArgs...), + withDockerfile(` FROM `+minimalBaseImage()+` LABEL default foo -`, false, labelArgs...) - - if err != nil { - c.Fatal("error building image with labels", err) - } - - res := inspectFieldJSON(c, name, "Config.Labels") +`)) var labels map[string]string - - if err := json.Unmarshal([]byte(res), &labels); err != nil { - c.Fatal(err) - } - + inspectFieldAndUnmarshall(c, name, "Config.Labels", &labels) for k, v := range testLabels { if x, ok := labels[k]; !ok || x != v { c.Fatalf("label %s=%s not found in image", k, v) @@ -6538,59 +5311,22 @@ func (s *DockerSuite) TestBuildLabelMultiple(c *check.C) { } } -func (s *DockerSuite) TestBuildLabelOverwrite(c *check.C) { - name := "testbuildlabeloverwrite" - testLabel := "foo" - testValue := "bar" - - _, err := buildImage(name, ` - FROM `+minimalBaseImage()+` - LABEL `+testLabel+`+ foo -`, false, []string{"--label", testLabel + "=" + testValue}...) - - if err != nil { - c.Fatal("error building image with labels", err) - } - - res := inspectFieldJSON(c, name, "Config.Labels") - - var labels map[string]string - - if err := json.Unmarshal([]byte(res), &labels); err != nil { - c.Fatal(err) - } - - v, ok := labels[testLabel] - if !ok { - c.Fatal("label not found in image") - } - - if v != testValue { - c.Fatal("label not overwritten") - } -} - func (s *DockerRegistryAuthHtpasswdSuite) TestBuildFromAuthenticatedRegistry(c *check.C) { dockerCmd(c, "login", "-u", s.reg.Username(), "-p", s.reg.Password(), privateRegistryURL) - baseImage := privateRegistryURL + "/baseimage" - _, err := buildImage(baseImage, ` + buildImageSuccessfully(c, baseImage, withDockerfile(` FROM busybox ENV env1 val1 - `, true) - - c.Assert(err, checker.IsNil) + `)) dockerCmd(c, "push", baseImage) dockerCmd(c, "rmi", baseImage) - _, err = buildImage(baseImage, fmt.Sprintf(` + buildImageSuccessfully(c, baseImage, withDockerfile(fmt.Sprintf(` FROM %s ENV env2 val2 - `, baseImage), true) - - c.Assert(err, checker.IsNil) + `, baseImage))) } func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C) { @@ -6628,11 +5364,10 @@ func (s *DockerRegistryAuthHtpasswdSuite) TestBuildWithExternalAuth(c *check.C) // make sure the image is pulled when building dockerCmd(c, "rmi", repoName) - buildCmd := exec.Command(dockerBinary, "--config", tmp, "build", "-") - buildCmd.Stdin = strings.NewReader(fmt.Sprintf("FROM %s", repoName)) - - out, _, err := runCommandWithOutput(buildCmd) - c.Assert(err, check.IsNil, check.Commentf(out)) + icmd.RunCmd(icmd.Cmd{ + Command: []string{dockerBinary, "--config", tmp, "build", "-"}, + Stdin: strings.NewReader(fmt.Sprintf("FROM %s", repoName)), + }).Assert(c, icmd.Success) } // Test cases in #22036 @@ -6640,12 +5375,9 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // Command line option labels will always override name := "scratchy" expected := `{"bar":"from-flag","foo":"from-flag"}` - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - LABEL foo=from-dockerfile`, - true, "--label", "foo=from-flag", "--label", "bar=from-flag") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"), + withDockerfile(`FROM `+minimalBaseImage()+` + LABEL foo=from-dockerfile`)) res := inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6653,12 +5385,8 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { name = "from" expected = `{"foo":"from-dockerfile"}` - _, err = buildImage(name, - `FROM `+minimalBaseImage()+` - LABEL foo from-dockerfile`, - true) - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + LABEL foo from-dockerfile`)) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6667,12 +5395,9 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // Command line option label will override even via `FROM` name = "new" expected = `{"bar":"from-dockerfile2","foo":"new"}` - _, err = buildImage(name, - `FROM from - LABEL bar from-dockerfile2`, - true, "--label", "foo=new") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=new"), + withDockerfile(`FROM from + LABEL bar from-dockerfile2`)) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6682,12 +5407,9 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // will be treated as --label foo="", --label bar="" name = "scratchy2" expected = `{"bar":"","foo":""}` - _, err = buildImage(name, - `FROM `+minimalBaseImage()+` - LABEL foo=from-dockerfile`, - true, "--label", "foo", "--label", "bar=") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo", "--label", "bar="), + withDockerfile(`FROM `+minimalBaseImage()+` + LABEL foo=from-dockerfile`)) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6698,12 +5420,9 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // This time is for inherited images name = "new2" expected = `{"bar":"","foo":""}` - _, err = buildImage(name, - `FROM from - LABEL bar from-dockerfile2`, - true, "--label", "foo=", "--label", "bar") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=", "--label", "bar"), + withDockerfile(`FROM from + LABEL bar from-dockerfile2`)) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6712,11 +5431,8 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // Command line option labels with only `FROM` name = "scratchy" expected = `{"bar":"from-flag","foo":"from-flag"}` - _, err = buildImage(name, - `FROM `+minimalBaseImage(), - true, "--label", "foo=from-flag", "--label", "bar=from-flag") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "foo=from-flag", "--label", "bar=from-flag"), + withDockerfile(`FROM `+minimalBaseImage())) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) @@ -6725,31 +5441,22 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { // Command line option labels with env var name = "scratchz" expected = `{"bar":"$PATH"}` - _, err = buildImage(name, - `FROM `+minimalBaseImage(), - true, "--label", "bar=$PATH") - c.Assert(err, check.IsNil) - + buildImageSuccessfully(c, name, withBuildFlags("--label", "bar=$PATH"), + withDockerfile(`FROM `+minimalBaseImage())) res = inspectFieldJSON(c, name, "Config.Labels") if res != expected { c.Fatalf("Labels %s, expected %s", res, expected) } - } // Test case for #22855 func (s *DockerSuite) TestBuildDeleteCommittedFile(c *check.C) { name := "test-delete-committed-file" - - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox RUN echo test > file RUN test -e file RUN rm file - RUN sh -c "! test -e file"`, false) - if err != nil { - c.Fatal(err) - } + RUN sh -c "! test -e file"`)) } // #20083 @@ -6766,13 +5473,14 @@ func (s *DockerSuite) TestBuildDockerignoreComment(c *check.C) { RUN sh -c "(ls -la /tmp/#1)" RUN sh -c "(! ls -la /tmp/#2)" RUN sh -c "(! ls /tmp/foo) && (! ls /tmp/foo2) && (ls /tmp/dir1/foo)"` - ctx, err := fakeContext(dockerfile, map[string]string{ - "foo": "foo", - "foo2": "foo2", - "dir1/foo": "foo in dir1", - "#1": "# file 1", - "#2": "# file 2", - ".dockerignore": `# Visual C++ cache files + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile("foo", "foo"), + withFile("foo2", "foo2"), + withFile("dir1/foo", "foo in dir1"), + withFile("#1", "# file 1"), + withFile("#2", "# file 2"), + withFile(".dockerignore", `# Visual C++ cache files # because we have git ;-) # The above comment is from #20083 foo @@ -6782,15 +5490,7 @@ foo2 #1 # The following is not considered as comment as # is not at the beginning #2 -`, - }) - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - if _, err := buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } +`))) } // Test case for #23221 @@ -6798,13 +5498,9 @@ func (s *DockerSuite) TestBuildWithUTF8BOM(c *check.C) { name := "test-with-utf8-bom" dockerfile := []byte(`FROM busybox`) bomDockerfile := append([]byte{0xEF, 0xBB, 0xBF}, dockerfile...) - ctx, err := fakeContextFromNewTempDir() - c.Assert(err, check.IsNil) - defer ctx.Close() - err = ctx.addFile("Dockerfile", bomDockerfile) - c.Assert(err, check.IsNil) - _, err = buildImageFromContext(name, ctx, true) - c.Assert(err, check.IsNil) + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", string(bomDockerfile)), + )) } // Test case for UTF-8 BOM in .dockerignore, related to #23221 @@ -6818,31 +5514,19 @@ func (s *DockerSuite) TestBuildWithUTF8BOMDockerignore(c *check.C) { RUN ls /tmp/.dockerignore` dockerignore := []byte("./Dockerfile\n") bomDockerignore := append([]byte{0xEF, 0xBB, 0xBF}, dockerignore...) - ctx, err := fakeContext(dockerfile, map[string]string{ - "Dockerfile": dockerfile, - }) - c.Assert(err, check.IsNil) - defer ctx.Close() - err = ctx.addFile(".dockerignore", bomDockerignore) - c.Assert(err, check.IsNil) - _, err = buildImageFromContext(name, ctx, true) - if err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", dockerfile), + withFile(".dockerignore", string(bomDockerignore)), + )) } // #22489 Shell test to confirm config gets updated correctly func (s *DockerSuite) TestBuildShellUpdatesConfig(c *check.C) { name := "testbuildshellupdatesconfig" + buildImageSuccessfully(c, name, withDockerfile(`FROM `+minimalBaseImage()+` + SHELL ["foo", "-bar"]`)) expected := `["foo","-bar","#(nop) ","SHELL [foo -bar]"]` - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` - SHELL ["foo", "-bar"]`, - true) - if err != nil { - c.Fatal(err) - } res := inspectFieldJSON(c, name, "ContainerConfig.Cmd") if res != expected { c.Fatalf("%s, expected %s", res, expected) @@ -6857,32 +5541,28 @@ func (s *DockerSuite) TestBuildShellUpdatesConfig(c *check.C) { func (s *DockerSuite) TestBuildShellMultiple(c *check.C) { name := "testbuildshellmultiple" - _, out, _, err := buildImageWithStdoutStderr(name, - `FROM busybox + result := buildImageNew(name, withDockerfile(`FROM busybox RUN echo defaultshell SHELL ["echo"] RUN echoshell SHELL ["ls"] RUN -l - CMD -l`, - true) - if err != nil { - c.Fatal(err) - } + CMD -l`)) + result.Assert(c, icmd.Success) // Must contain 'defaultshell' twice - if len(strings.Split(out, "defaultshell")) != 3 { - c.Fatalf("defaultshell should have appeared twice in %s", out) + if len(strings.Split(result.Combined(), "defaultshell")) != 3 { + c.Fatalf("defaultshell should have appeared twice in %s", result.Combined()) } // Must contain 'echoshell' twice - if len(strings.Split(out, "echoshell")) != 3 { - c.Fatalf("echoshell should have appeared twice in %s", out) + if len(strings.Split(result.Combined(), "echoshell")) != 3 { + c.Fatalf("echoshell should have appeared twice in %s", result.Combined()) } // Must contain "total " (part of ls -l) - if !strings.Contains(out, "total ") { - c.Fatalf("%s should have contained 'total '", out) + if !strings.Contains(result.Combined(), "total ") { + c.Fatalf("%s should have contained 'total '", result.Combined()) } // A container started from the image uses the shell-form CMD. @@ -6897,15 +5577,9 @@ func (s *DockerSuite) TestBuildShellMultiple(c *check.C) { func (s *DockerSuite) TestBuildShellEntrypoint(c *check.C) { name := "testbuildshellentrypoint" - _, err := buildImage(name, - `FROM busybox + buildImageSuccessfully(c, name, withDockerfile(`FROM busybox SHELL ["ls"] - ENTRYPOINT -l`, - true) - if err != nil { - c.Fatal(err) - } - + ENTRYPOINT -l`)) // A container started from the image uses the shell-form ENTRYPOINT. // Shell is ls. ENTRYPOINT is -l. So should contain 'total '. outrun, _ := dockerCmd(c, "run", "--rm", name) @@ -6917,43 +5591,26 @@ func (s *DockerSuite) TestBuildShellEntrypoint(c *check.C) { // #22489 Shell test to confirm shell is inherited in a subsequent build func (s *DockerSuite) TestBuildShellInherited(c *check.C) { name1 := "testbuildshellinherited1" - _, err := buildImage(name1, - `FROM busybox - SHELL ["ls"]`, - true) - if err != nil { - c.Fatal(err) - } - + buildImageSuccessfully(c, name1, withDockerfile(`FROM busybox + SHELL ["ls"]`)) name2 := "testbuildshellinherited2" - _, out, _, err := buildImageWithStdoutStderr(name2, - `FROM `+name1+` - RUN -l`, - true) - if err != nil { - c.Fatal(err) - } - - // ls -l has "total " followed by some number in it, ls without -l does not. - if !strings.Contains(out, "total ") { - c.Fatalf("Should have seen total in 'ls -l'.\n%s", out) - } + buildImageNew(name2, withDockerfile(`FROM `+name1+` + RUN -l`)).Assert(c, icmd.Expected{ + // ls -l has "total " followed by some number in it, ls without -l does not. + Out: "total ", + }) } // #22489 Shell test to confirm non-JSON doesn't work func (s *DockerSuite) TestBuildShellNotJSON(c *check.C) { name := "testbuildshellnotjson" - _, err := buildImage(name, - `FROM `+minimalBaseImage()+` + buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+` sHeLl exec -form`, // Casing explicit to ensure error is upper-cased. - true) - if err == nil { - c.Fatal("Image build should have failed") - } - if !strings.Contains(err.Error(), "SHELL requires the arguments to be in JSON form") { - c.Fatal("Error didn't indicate that arguments must be in JSON form") - } + )).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "SHELL requires the arguments to be in JSON form", + }) } // #22489 Windows shell test to confirm native is powershell if executing a PS command @@ -6961,17 +5618,11 @@ func (s *DockerSuite) TestBuildShellNotJSON(c *check.C) { func (s *DockerSuite) TestBuildShellWindowsPowershell(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildshellpowershell" - _, out, err := buildImageWithOut(name, - `FROM `+minimalBaseImage()+` + buildImageNew(name, withDockerfile(`FROM `+minimalBaseImage()+` SHELL ["powershell", "-command"] - RUN Write-Host John`, - true) - if err != nil { - c.Fatal(err) - } - if !strings.Contains(out, "\nJohn\n") { - c.Fatalf("Line with 'John' not found in output %q", out) - } + RUN Write-Host John`)).Assert(c, icmd.Expected{ + Out: "\nJohn\n", + }) } // Verify that escape is being correctly applied to words when escape directive is not \. @@ -6979,48 +5630,32 @@ func (s *DockerSuite) TestBuildShellWindowsPowershell(c *check.C) { func (s *DockerSuite) TestBuildEscapeNotBackslashWordTest(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildescapenotbackslashwordtesta" - _, out, err := buildImageWithOut(name, - `# escape= `+"`"+` + buildImageNew(name, withDockerfile(`# escape= `+"`"+` FROM `+minimalBaseImage()+` WORKDIR c:\windows - RUN dir /w`, - true) - if err != nil { - c.Fatal(err) - } - if !strings.Contains(strings.ToLower(out), "[system32]") { - c.Fatalf("Line with '[windows]' not found in output %q", out) - } + RUN dir /w`)).Assert(c, icmd.Expected{ + Out: "[System32]", + }) name = "testbuildescapenotbackslashwordtestb" - _, out, err = buildImageWithOut(name, - `# escape= `+"`"+` + buildImageNew(name, withDockerfile(`# escape= `+"`"+` FROM `+minimalBaseImage()+` SHELL ["powershell.exe"] WORKDIR c:\foo ADD Dockerfile c:\foo\ - RUN dir Dockerfile`, - true) - if err != nil { - c.Fatal(err) - } - if !strings.Contains(strings.ToLower(out), "-a----") { - c.Fatalf("Line with '-a----' not found in output %q", out) - } - + RUN dir Dockerfile`)).Assert(c, icmd.Expected{ + Out: "-a----", + }) } // #22868. Make sure shell-form CMD is marked as escaped in the config of the image func (s *DockerSuite) TestBuildCmdShellArgsEscaped(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildcmdshellescaped" - _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM `+minimalBaseImage()+` CMD "ipconfig" - `, true) - if err != nil { - c.Fatal(err) - } + `)) res := inspectFieldJSON(c, name, "Config.ArgsEscaped") if res != "true" { c.Fatalf("CMD did not update Config.ArgsEscaped on image: %v", res) @@ -7037,13 +5672,12 @@ func (s *DockerSuite) TestBuildCmdShellArgsEscaped(c *check.C) { // Test case for #24912. func (s *DockerSuite) TestBuildStepsWithProgress(c *check.C) { name := "testbuildstepswithprogress" - totalRun := 5 - _, out, err := buildImageWithOut(name, "FROM busybox\n"+strings.Repeat("RUN echo foo\n", totalRun), true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, fmt.Sprintf("Step 1/%d : FROM busybox", 1+totalRun)) + result := buildImageNew(name, withDockerfile("FROM busybox\n"+strings.Repeat("RUN echo foo\n", totalRun))) + result.Assert(c, icmd.Success) + c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step 1/%d : FROM busybox", 1+totalRun)) for i := 2; i <= 1+totalRun; i++ { - c.Assert(out, checker.Contains, fmt.Sprintf("Step %d/%d : RUN echo foo", i, 1+totalRun)) + c.Assert(result.Combined(), checker.Contains, fmt.Sprintf("Step %d/%d : RUN echo foo", i, 1+totalRun)) } } @@ -7051,18 +5685,18 @@ func (s *DockerSuite) TestBuildWithFailure(c *check.C) { name := "testbuildwithfailure" // First test case can only detect `nobody` in runtime so all steps will show up - buildCmd := "FROM busybox\nRUN nobody" - _, stdout, _, err := buildImageWithStdoutStderr(name, buildCmd, false, "--force-rm", "--rm") - c.Assert(err, checker.NotNil) - c.Assert(stdout, checker.Contains, "Step 1/2 : FROM busybox") - c.Assert(stdout, checker.Contains, "Step 2/2 : RUN nobody") + dockerfile := "FROM busybox\nRUN nobody" + result := buildImageNew(name, withDockerfile(dockerfile)) + c.Assert(result.Error, checker.NotNil) + c.Assert(result.Stdout(), checker.Contains, "Step 1/2 : FROM busybox") + c.Assert(result.Stdout(), checker.Contains, "Step 2/2 : RUN nobody") // Second test case `FFOM` should have been detected before build runs so no steps - buildCmd = "FFOM nobody\nRUN nobody" - _, stdout, _, err = buildImageWithStdoutStderr(name, buildCmd, false, "--force-rm", "--rm") - c.Assert(err, checker.NotNil) - c.Assert(stdout, checker.Not(checker.Contains), "Step 1/2 : FROM busybox") - c.Assert(stdout, checker.Not(checker.Contains), "Step 2/2 : RUN nobody") + dockerfile = "FFOM nobody\nRUN nobody" + result = buildImageNew(name, withDockerfile(dockerfile)) + c.Assert(result.Error, checker.NotNil) + c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 1/2 : FROM busybox") + c.Assert(result.Stdout(), checker.Not(checker.Contains), "Step 2/2 : RUN nobody") } func (s *DockerSuite) TestBuildCacheFrom(c *check.C) { @@ -7160,14 +5794,14 @@ func (s *DockerSuite) TestBuildCacheFrom(c *check.C) { func (s *DockerSuite) TestBuildNetNone(c *check.C) { testRequires(c, DaemonIsLinux) - name := "testbuildnetnone" - _, out, err := buildImageWithOut(name, ` + buildImageNew(name, withBuildFlags("--network=none"), withDockerfile(` FROM busybox RUN ping -c 1 8.8.8.8 - `, true, "--network=none") - c.Assert(err, checker.NotNil) - c.Assert(out, checker.Contains, "unreachable") + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Out: "unreachable", + }) } func (s *DockerSuite) TestBuildNetContainer(c *check.C) { @@ -7176,11 +5810,11 @@ func (s *DockerSuite) TestBuildNetContainer(c *check.C) { id, _ := dockerCmd(c, "run", "--hostname", "foobar", "-d", "busybox", "nc", "-ll", "-p", "1234", "-e", "hostname") name := "testbuildnetcontainer" - out, err := buildImage(name, ` + buildImageSuccessfully(c, name, withBuildFlags("--network=container:"+strings.TrimSpace(id)), + withDockerfile(` FROM busybox RUN nc localhost 1234 > /otherhost - `, true, "--network=container:"+strings.TrimSpace(id)) - c.Assert(err, checker.IsNil, check.Commentf("out: %v", out)) + `)) host, _ := dockerCmd(c, "run", "testbuildnetcontainer", "cat", "/otherhost") c.Assert(strings.TrimSpace(host), check.Equals, "foobar") @@ -7197,11 +5831,14 @@ func (s *DockerSuite) TestBuildSquashParent(c *check.C) { RUN rm /remove_me ` // build and get the ID that we can use later for history comparison - origID, err := buildImage("test", dockerFile, false) + name := "test" + buildImageSuccessfully(c, name, withDockerfile(dockerFile)) + origID, err := getIDByName(name) c.Assert(err, checker.IsNil) // build with squash - id, err := buildImage("test", dockerFile, true, "--squash") + buildImageSuccessfully(c, name, withBuildFlags("--squash"), withDockerfile(dockerFile)) + id, err := getIDByName(name) c.Assert(err, checker.IsNil) out, _ := dockerCmd(c, "run", "--rm", id, "/bin/sh", "-c", "cat /hello") @@ -7230,31 +5867,27 @@ func (s *DockerSuite) TestBuildSquashParent(c *check.C) { func (s *DockerSuite) TestBuildContChar(c *check.C) { name := "testbuildcontchar" - _, out, err := buildImageWithOut(name, - `FROM busybox\`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/1 : FROM busybox") + buildImageNew(name, withDockerfile(`FROM busybox\`)).Assert(c, icmd.Expected{ + Out: "Step 1/1 : FROM busybox", + }) - _, out, err = buildImageWithOut(name, - `FROM busybox - RUN echo hi \`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/2 : FROM busybox") - c.Assert(out, checker.Contains, "Step 2/2 : RUN echo hi\n") + result := buildImageNew(name, withDockerfile(`FROM busybox + RUN echo hi \`)) + result.Assert(c, icmd.Success) + c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox") + c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi\n") - _, out, err = buildImageWithOut(name, - `FROM busybox - RUN echo hi \\`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/2 : FROM busybox") - c.Assert(out, checker.Contains, "Step 2/2 : RUN echo hi \\\n") + result = buildImageNew(name, withDockerfile(`FROM busybox + RUN echo hi \\`)) + result.Assert(c, icmd.Success) + c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox") + c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\n") - _, out, err = buildImageWithOut(name, - `FROM busybox - RUN echo hi \\\`, true) - c.Assert(err, checker.IsNil) - c.Assert(out, checker.Contains, "Step 1/2 : FROM busybox") - c.Assert(out, checker.Contains, "Step 2/2 : RUN echo hi \\\\\n") + result = buildImageNew(name, withDockerfile(`FROM busybox + RUN echo hi \\\`)) + result.Assert(c, icmd.Success) + c.Assert(result.Combined(), checker.Contains, "Step 1/2 : FROM busybox") + c.Assert(result.Combined(), checker.Contains, "Step 2/2 : RUN echo hi \\\\\n") } // TestBuildOpaqueDirectory tests that a build succeeds which @@ -7262,7 +5895,6 @@ func (s *DockerSuite) TestBuildContChar(c *check.C) { // See https://github.com/docker/docker/issues/25244 func (s *DockerSuite) TestBuildOpaqueDirectory(c *check.C) { testRequires(c, DaemonIsLinux) - dockerFile := ` FROM busybox RUN mkdir /dir1 && touch /dir1/f1 @@ -7270,28 +5902,22 @@ func (s *DockerSuite) TestBuildOpaqueDirectory(c *check.C) { RUN touch /dir1/f3 RUN [ -f /dir1/f2 ] ` - // Test that build succeeds, last command fails if opaque directory // was not handled correctly - _, err := buildImage("testopaquedirectory", dockerFile, false) - c.Assert(err, checker.IsNil) + buildImageSuccessfully(c, "testopaquedirectory", withDockerfile(dockerFile)) } // Windows test for USER in dockerfile func (s *DockerSuite) TestBuildWindowsUser(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildwindowsuser" - _, out, err := buildImageWithOut(name, - `FROM `+WindowsBaseImage+` + buildImageNew(name, withDockerfile(`FROM `+WindowsBaseImage+` RUN net user user /add USER user RUN set username - `, - true) - if err != nil { - c.Fatal(err) - } - c.Assert(strings.ToLower(out), checker.Contains, "username=user") + `)).Assert(c, icmd.Expected{ + Out: "USERNAME=user", + }) } // Verifies if COPY file . when WORKDIR is set to a non-existing directory, @@ -7301,39 +5927,26 @@ func (s *DockerSuite) TestBuildWindowsUser(c *check.C) { // Note 27545 was reverted in 28505, but a new fix was added subsequently in 28514. func (s *DockerSuite) TestBuildCopyFileDotWithWorkdir(c *check.C) { name := "testbuildcopyfiledotwithworkdir" - ctx, err := fakeContext(`FROM busybox -WORKDIR /foo -COPY file . -RUN ["cat", "/foo/file"] -`, - map[string]string{}) - - if err != nil { - c.Fatal(err) - } - defer ctx.Close() - - if err := ctx.Add("file", "content"); err != nil { - c.Fatal(err) - } - - if _, err = buildImageFromContext(name, ctx, true); err != nil { - c.Fatal(err) - } + buildImageSuccessfully(c, name, withBuildContext(c, + withFile("Dockerfile", `FROM busybox +WORKDIR /foo +COPY file . +RUN ["cat", "/foo/file"] +`), + withFile("file", "content"), + )) } // Case-insensitive environment variables on Windows func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) { testRequires(c, DaemonIsWindows) name := "testbuildwindowsenvcaseinsensitive" - if _, err := buildImage(name, ` + buildImageSuccessfully(c, name, withDockerfile(` FROM `+WindowsBaseImage+` - ENV FOO=bar foo=bar - `, true); err != nil { - c.Fatal(err) - } + ENV FOO=bar foo=baz + `)) res := inspectFieldJSON(c, name, "Config.Env") - if res != `["foo=bar"]` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped. + if res != `["foo=baz"]` { // Should not have FOO=bar in it - takes the last one processed. And only one entry as deduped. c.Fatalf("Case insensitive environment variables on Windows failed. Got %s", res) } } @@ -7341,14 +5954,11 @@ func (s *DockerSuite) TestBuildWindowsEnvCaseInsensitive(c *check.C) { // Test case for 29667 func (s *DockerSuite) TestBuildWorkdirImageCmd(c *check.C) { image := "testworkdirimagecmd" - dockerfile := ` + buildImageSuccessfully(c, image, withDockerfile(` FROM busybox WORKDIR /foo/bar -` - out, err := buildImage(image, dockerfile, true) - c.Assert(err, checker.IsNil, check.Commentf("Output: %s", out)) - - out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image) +`)) + out, _ := dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image) // The Windows busybox image has a blank `cmd` lookingFor := `["sh"]` @@ -7358,13 +5968,11 @@ WORKDIR /foo/bar c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor) image = "testworkdirlabelimagecmd" - dockerfile = ` + buildImageSuccessfully(c, image, withDockerfile(` FROM busybox WORKDIR /foo/bar LABEL a=b -` - out, err = buildImage(image, dockerfile, true) - c.Assert(err, checker.IsNil, check.Commentf("Output: %s", out)) +`)) out, _ = dockerCmd(c, "inspect", "--format", "{{ json .Config.Cmd }}", image) c.Assert(strings.TrimSpace(out), checker.Equals, lookingFor) @@ -7373,47 +5981,46 @@ LABEL a=b // Test case for 28902/28909 func (s *DockerSuite) TestBuildWorkdirCmd(c *check.C) { testRequires(c, DaemonIsLinux) - + name := "testbuildworkdircmd" dockerFile := ` FROM busybox WORKDIR / ` - _, err := buildImage("testbuildworkdircmd", dockerFile, true) - c.Assert(err, checker.IsNil) - - _, out, err := buildImageWithOut("testbuildworkdircmd", dockerFile, true) - c.Assert(err, checker.IsNil) - c.Assert(strings.Count(out, "Using cache"), checker.Equals, 1) + buildImageSuccessfully(c, name, withDockerfile(dockerFile)) + result := buildImageNew(name, withDockerfile(dockerFile)) + result.Assert(c, icmd.Success) + c.Assert(strings.Count(result.Combined(), "Using cache"), checker.Equals, 1) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildLineErrorOnBuild(c *check.C) { name := "test_build_line_error_onbuild" - - _, err := buildImage(name, - `FROM busybox + buildImageNew(name, withDockerfile(`FROM busybox ONBUILD - `, true) - c.Assert(err.Error(), checker.Contains, "Dockerfile parse error line 2: ONBUILD requires at least one argument") + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "Dockerfile parse error line 2: ONBUILD requires at least one argument", + }) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildLineErrorUknownInstruction(c *check.C) { name := "test_build_line_error_unknown_instruction" - - _, err := buildImage(name, - `FROM busybox + buildImageNew(name, withDockerfile(`FROM busybox RUN echo hello world NOINSTRUCTION echo ba RUN echo hello ERROR - `, true) - c.Assert(err.Error(), checker.Contains, "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION") + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "Dockerfile parse error line 3: Unknown instruction: NOINSTRUCTION", + }) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) { name := "test_build_line_error_with_empty_lines" - - _, err := buildImage(name, - ` + buildImageNew(name, withDockerfile(` FROM busybox RUN echo hello world @@ -7421,19 +6028,22 @@ func (s *DockerSuite) TestBuildLineErrorWithEmptyLines(c *check.C) { NOINSTRUCTION echo ba CMD ["/bin/init"] - `, true) - c.Assert(err.Error(), checker.Contains, "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION") + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "Dockerfile parse error line 6: Unknown instruction: NOINSTRUCTION", + }) } +// FIXME(vdemeester) should be a unit test func (s *DockerSuite) TestBuildLineErrorWithComments(c *check.C) { name := "test_build_line_error_with_comments" - - _, err := buildImage(name, - `FROM busybox + buildImageNew(name, withDockerfile(`FROM busybox # This will print hello world # and then ba RUN echo hello world - RUM echo ba - `, true) - c.Assert(err.Error(), checker.Contains, "Dockerfile parse error line 5: Unknown instruction: RUM") + NOINSTRUCTION echo ba + `)).Assert(c, icmd.Expected{ + ExitCode: 1, + Err: "Dockerfile parse error line 5: Unknown instruction: NOINSTRUCTION", + }) } diff --git a/integration-cli/docker_cli_create_test.go b/integration-cli/docker_cli_create_test.go index d23d39c459..24ab376f58 100644 --- a/integration-cli/docker_cli_create_test.go +++ b/integration-cli/docker_cli_create_test.go @@ -195,7 +195,7 @@ func (s *DockerSuite) TestCreateLabels(c *check.C) { dockerCmd(c, "create", "--name", name, "-l", "k1=v1", "--label", "k2=v2", "busybox") actual := make(map[string]string) - inspectFieldAndMarshall(c, name, "Config.Labels", &actual) + inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual) if !reflect.DeepEqual(expected, actual) { c.Fatalf("Expected %s got %s", expected, actual) @@ -216,7 +216,7 @@ func (s *DockerSuite) TestCreateLabelFromImage(c *check.C) { dockerCmd(c, "create", "--name", name, "-l", "k2=x", "--label", "k3=v3", imageName) actual := make(map[string]string) - inspectFieldAndMarshall(c, name, "Config.Labels", &actual) + inspectFieldAndUnmarshall(c, name, "Config.Labels", &actual) if !reflect.DeepEqual(expected, actual) { c.Fatalf("Expected %s got %s", expected, actual) diff --git a/integration-cli/docker_cli_external_volume_driver_unix_test.go b/integration-cli/docker_cli_external_volume_driver_unix_test.go index 522242fa74..5c2cee724e 100644 --- a/integration-cli/docker_cli_external_volume_driver_unix_test.go +++ b/integration-cli/docker_cli_external_volume_driver_unix_test.go @@ -503,7 +503,7 @@ func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverWithDaemonRestart(c dockerCmd(c, "run", "--name=test", "-v", "abc1:/foo", "busybox", "true") var mounts []types.MountPoint - inspectFieldAndMarshall(c, "test", "Mounts", &mounts) + inspectFieldAndUnmarshall(c, "test", "Mounts", &mounts) c.Assert(mounts, checker.HasLen, 1) c.Assert(mounts[0].Driver, checker.Equals, volumePluginName) } diff --git a/integration-cli/docker_utils_test.go b/integration-cli/docker_utils_test.go index 3fd08077bf..a50fa5782f 100644 --- a/integration-cli/docker_utils_test.go +++ b/integration-cli/docker_utils_test.go @@ -305,17 +305,6 @@ func validateArgs(args ...string) error { return nil } -// find the State.ExitCode in container metadata -func findContainerExitCode(c *check.C, name string, vargs ...string) string { - args := append(vargs, "inspect", "--format='{{ .State.ExitCode }} {{ .State.Error }}'", name) - cmd := exec.Command(dockerBinary, args...) - out, _, err := runCommandWithOutput(cmd) - if err != nil { - c.Fatal(err, out) - } - return out -} - func findContainerIP(c *check.C, id string, network string) string { out, _ := dockerCmd(c, "inspect", fmt.Sprintf("--format='{{ .NetworkSettings.Networks.%s.IPAddress }}'", network), id) return strings.Trim(out, " \r\n'") @@ -582,7 +571,7 @@ COPY . /static`); err != nil { ctx: ctx}, nil } -func inspectFieldAndMarshall(c *check.C, name, field string, output interface{}) { +func inspectFieldAndUnmarshall(c *check.C, name, field string, output interface{}) { str := inspectFieldJSON(c, name, field) err := json.Unmarshal([]byte(str), output) if c != nil { @@ -592,12 +581,11 @@ func inspectFieldAndMarshall(c *check.C, name, field string, output interface{}) func inspectFilter(name, filter string) (string, error) { format := fmt.Sprintf("{{%s}}", filter) - inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name) - out, exitCode, err := runCommandWithOutput(inspectCmd) - if err != nil || exitCode != 0 { - return "", fmt.Errorf("failed to inspect %s: %s", name, out) + result := icmd.RunCommand(dockerBinary, "inspect", "-f", format, name) + if result.Error != nil || result.ExitCode != 0 { + return "", fmt.Errorf("failed to inspect %s: %s", name, result.Combined()) } - return strings.TrimSpace(out), nil + return strings.TrimSpace(result.Combined()), nil } func inspectFieldWithError(name, field string) (string, error) { @@ -687,10 +675,12 @@ func getIDByName(name string) (string, error) { return inspectFieldWithError(name, "Id") } +// Deprecated func buildImageCmd(name, dockerfile string, useCache bool, buildFlags ...string) *exec.Cmd { return daemon.BuildImageCmdWithHost(dockerBinary, name, dockerfile, "", useCache, buildFlags...) } +// Deprecated func buildImageWithOut(name, dockerfile string, useCache bool, buildFlags ...string) (string, string, error) { buildCmd := buildImageCmd(name, dockerfile, useCache, buildFlags...) out, exitCode, err := runCommandWithOutput(buildCmd) @@ -704,6 +694,7 @@ func buildImageWithOut(name, dockerfile string, useCache bool, buildFlags ...str return id, out, nil } +// Deprecated func buildImageWithStdoutStderr(name, dockerfile string, useCache bool, buildFlags ...string) (string, string, string, error) { buildCmd := buildImageCmd(name, dockerfile, useCache, buildFlags...) result := icmd.RunCmd(transformCmd(buildCmd)) @@ -719,11 +710,99 @@ func buildImageWithStdoutStderr(name, dockerfile string, useCache bool, buildFla return id, result.Stdout(), result.Stderr(), nil } +func buildImageSuccessfully(c *check.C, name string, cmdOperators ...func(*icmd.Cmd) func()) { + buildImageNew(name, cmdOperators...).Assert(c, icmd.Success) +} + +// FIXME(vdemeester) rename this buildImage once deprecated buildImage is no more +func buildImageNew(name string, cmdOperators ...func(*icmd.Cmd) func()) *icmd.Result { + cmd := icmd.Command(dockerBinary, "build", "-t", name) + for _, op := range cmdOperators { + deferFn := op(&cmd) + if deferFn != nil { + defer deferFn() + } + } + return icmd.RunCmd(cmd) +} + +func withBuildContextPath(path string) func(*icmd.Cmd) func() { + return func(cmd *icmd.Cmd) func() { + cmd.Command = append(cmd.Command, path) + return nil + } +} + +func withBuildContext(c *check.C, contextOperators ...func(*FakeContext) error) func(*icmd.Cmd) func() { + ctx, err := fakeContextFromNewTempDir() + if err != nil { + c.Fatalf("error creating build context : %v", err) + } + for _, op := range contextOperators { + if err := op(ctx); err != nil { + c.Fatal(err) + } + } + return func(cmd *icmd.Cmd) func() { + cmd.Dir = ctx.Dir + cmd.Command = append(cmd.Command, ".") + return closeBuildContext(c, ctx) + } +} + +func withBuildFlags(flags ...string) func(*icmd.Cmd) func() { + return func(cmd *icmd.Cmd) func() { + cmd.Command = append(cmd.Command, flags...) + return nil + } +} + +func withoutCache(cmd *icmd.Cmd) func() { + cmd.Command = append(cmd.Command, "--no-cache") + return nil +} + +func withFile(name, content string) func(*FakeContext) error { + return func(ctx *FakeContext) error { + return ctx.Add(name, content) + } +} + +func closeBuildContext(c *check.C, ctx *FakeContext) func() { + return func() { + if err := ctx.Close(); err != nil { + c.Fatal(err) + } + } +} + +func withDockerfile(dockerfile string) func(*icmd.Cmd) func() { + return func(cmd *icmd.Cmd) func() { + cmd.Command = append(cmd.Command, "-") + cmd.Stdin = strings.NewReader(dockerfile) + return nil + } +} + +func trustedBuild(cmd *icmd.Cmd) func() { + trustedCmd(cmd) + return nil +} + +func withEnvironmentVariales(envs ...string) func(cmd *icmd.Cmd) func() { + return func(cmd *icmd.Cmd) func() { + cmd.Env = envs + return nil + } +} + +// Deprecated func buildImage(name, dockerfile string, useCache bool, buildFlags ...string) (string, error) { id, _, err := buildImageWithOut(name, dockerfile, useCache, buildFlags...) return id, err } +// Deprecated func buildImageFromContext(name string, ctx *FakeContext, useCache bool, buildFlags ...string) (string, error) { id, _, err := buildImageFromContextWithOut(name, ctx, useCache, buildFlags...) if err != nil { @@ -732,6 +811,7 @@ func buildImageFromContext(name string, ctx *FakeContext, useCache bool, buildFl return id, nil } +// Deprecated func buildImageFromContextWithOut(name string, ctx *FakeContext, useCache bool, buildFlags ...string) (string, string, error) { args := []string{"build", "-t", name} if !useCache { @@ -754,6 +834,7 @@ func buildImageFromContextWithOut(name string, ctx *FakeContext, useCache bool, return id, out, nil } +// Deprecated func buildImageFromContextWithStdoutStderr(name string, ctx *FakeContext, useCache bool, buildFlags ...string) (string, string, string, error) { args := []string{"build", "-t", name} if !useCache { @@ -778,6 +859,7 @@ func buildImageFromContextWithStdoutStderr(name string, ctx *FakeContext, useCac return id, result.Stdout(), result.Stderr(), nil } +// Deprecated func buildImageFromGitWithStdoutStderr(name string, ctx *fakeGit, useCache bool, buildFlags ...string) (string, string, string, error) { args := []string{"build", "-t", name} if !useCache { @@ -800,6 +882,7 @@ func buildImageFromGitWithStdoutStderr(name string, ctx *fakeGit, useCache bool, return id, result.Stdout(), result.Stderr(), nil } +// Deprecated func buildImageFromPath(name, path string, useCache bool, buildFlags ...string) (string, error) { args := []string{"build", "-t", name} if !useCache {