diff --git a/components/engine/integration-cli/docker_cli_build_test.go b/components/engine/integration-cli/docker_cli_build_test.go index f000235843..0837088322 100644 --- a/components/engine/integration-cli/docker_cli_build_test.go +++ b/components/engine/integration-cli/docker_cli_build_test.go @@ -1133,3 +1133,251 @@ func TestBuildWithVolumeOwnership(t *testing.T) { logDone("build - volume ownership") } + +// testing #1405 - config.Cmd does not get cleaned up if +// utilizing cache +func TestBuildEntrypointRunCleanup(t *testing.T) { + name := "testbuildcmdcleanup" + defer deleteImages(name) + if _, err := buildImage(name, + `FROM busybox + RUN echo "hello"`, + true); err != nil { + t.Fatal(err) + } + + ctx, err := fakeContext(`FROM busybox + RUN echo "hello" + ADD foo /foo + ENTRYPOINT ["/bin/echo"]`, + map[string]string{ + "foo": "hello", + }) + defer ctx.Close() + if err != nil { + t.Fatal(err) + } + if _, err := buildImageFromContext(name, ctx, true); err != nil { + t.Fatal(err) + } + res, err := inspectField(name, "Config.Cmd") + if err != nil { + t.Fatal(err) + } + // Cmd inherited from busybox, maybe will be fixed in #5147 + if expected := "[/bin/sh]"; res != expected { + t.Fatalf("Cmd %s, expected %s", res, expected) + } + logDone("build - cleanup cmd after RUN") +} + +func TestBuldForbiddenContextPath(t *testing.T) { + name := "testbuildforbidpath" + defer deleteImages(name) + ctx, err := fakeContext(`FROM scratch + ADD ../../ test/ + `, + map[string]string{ + "test.txt": "test1", + "other.txt": "other", + }) + + defer ctx.Close() + if err != nil { + t.Fatal(err) + } + if _, err := buildImageFromContext(name, ctx, true); err != nil { + if !strings.Contains(err.Error(), "Forbidden path outside the build context: ../../ (/)") { + t.Fatal("Wrong error, must be about forbidden ../../ path") + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - forbidden context path") +} + +func TestBuildADDFileNotFound(t *testing.T) { + name := "testbuildaddnotfound" + defer deleteImages(name) + ctx, err := fakeContext(`FROM scratch + ADD foo /usr/local/bar`, + map[string]string{"bar": "hello"}) + defer ctx.Close() + if err != nil { + t.Fatal(err) + } + if _, err := buildImageFromContext(name, ctx, true); err != nil { + if !strings.Contains(err.Error(), "foo: no such file or directory") { + t.Fatalf("Wrong error %v, must be about missing foo file or directory", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - add file not found") +} + +func TestBuildInheritance(t *testing.T) { + name := "testbuildinheritance" + defer deleteImages(name) + + _, err := buildImage(name, + `FROM scratch + EXPOSE 2375`, + true) + if err != nil { + t.Fatal(err) + } + ports1, err := inspectField(name, "Config.ExposedPorts") + if err != nil { + t.Fatal(err) + } + + _, err = buildImage(name, + fmt.Sprintf(`FROM %s + ENTRYPOINT ["/bin/echo"]`, name), + true) + if err != nil { + t.Fatal(err) + } + + res, err := inspectField(name, "Config.Entrypoint") + if err != nil { + t.Fatal(err) + } + if expected := "[/bin/echo]"; res != expected { + t.Fatalf("Entrypoint %s, expected %s", res, expected) + } + ports2, err := inspectField(name, "Config.ExposedPorts") + if err != nil { + t.Fatal(err) + } + if ports1 != ports2 { + t.Fatalf("Ports must be same: %s != %s", ports1, ports2) + } + logDone("build - inheritance") +} + +func TestBuildFails(t *testing.T) { + name := "testbuildfails" + defer deleteImages(name) + _, 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") { + t.Fatalf("Wrong error %v, must be about non-zero code 23", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - fails") +} + +func TestBuildFailsDockerfileEmpty(t *testing.T) { + name := "testbuildfails" + defer deleteImages(name) + _, err := buildImage(name, ``, true) + if err != nil { + if !strings.Contains(err.Error(), "Dockerfile cannot be empty") { + t.Fatalf("Wrong error %v, must be about empty Dockerfile", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - fails with empty dockerfile") +} + +func TestBuildOnBuild(t *testing.T) { + name := "testbuildonbuild" + defer deleteImages(name) + _, err := buildImage(name, + `FROM busybox + ONBUILD RUN touch foobar`, + true) + if err != nil { + t.Fatal(err) + } + _, err = buildImage(name, + fmt.Sprintf(`FROM %s + RUN [ -f foobar ]`, name), + true) + if err != nil { + t.Fatal(err) + } + logDone("build - onbuild") +} + +func TestBuildOnBuildForbiddenChained(t *testing.T) { + name := "testbuildonbuildforbiddenchained" + defer deleteImages(name) + _, err := buildImage(name, + `FROM busybox + ONBUILD ONBUILD RUN touch foobar`, + true) + if err != nil { + if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") { + t.Fatalf("Wrong error %v, must be about chaining ONBUILD", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - onbuild forbidden chained") +} + +func TestBuildOnBuildForbiddenFrom(t *testing.T) { + name := "testbuildonbuildforbiddenfrom" + defer deleteImages(name) + _, err := buildImage(name, + `FROM busybox + ONBUILD FROM scratch`, + true) + if err != nil { + if !strings.Contains(err.Error(), "FROM isn't allowed as an ONBUILD trigger") { + t.Fatalf("Wrong error %v, must be about FROM forbidden", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - onbuild forbidden from") +} + +func TestBuildOnBuildForbiddenMaintainer(t *testing.T) { + name := "testbuildonbuildforbiddenmaintainer" + defer deleteImages(name) + _, err := buildImage(name, + `FROM busybox + ONBUILD MAINTAINER docker.io`, + true) + if err != nil { + if !strings.Contains(err.Error(), "MAINTAINER isn't allowed as an ONBUILD trigger") { + t.Fatalf("Wrong error %v, must be about MAINTAINER forbidden", err) + } + } else { + t.Fatal("Error must not be nil") + } + logDone("build - onbuild forbidden maintainer") +} + +// gh #2446 +func TestBuildAddToSymlinkDest(t *testing.T) { + name := "testbuildaddtosymlinkdest" + defer deleteImages(name) + ctx, err := fakeContext(`FROM busybox + RUN mkdir /foo + RUN ln -s /foo /bar + ADD foo /bar/ + RUN [ -f /bar/foo ] + RUN [ -f /foo/foo ]`, + map[string]string{ + "foo": "hello", + }) + if err != nil { + t.Fatal(err) + } + defer ctx.Close() + if _, err := buildImageFromContext(name, ctx, true); err != nil { + t.Fatal(err) + } + logDone("build - add to symlink destination") +} diff --git a/components/engine/integration/buildfile_test.go b/components/engine/integration/buildfile_test.go index 8c02cf043c..147ae353a2 100644 --- a/components/engine/integration/buildfile_test.go +++ b/components/engine/integration/buildfile_test.go @@ -14,7 +14,6 @@ import ( "github.com/dotcloud/docker/archive" "github.com/dotcloud/docker/engine" "github.com/dotcloud/docker/image" - "github.com/dotcloud/docker/nat" "github.com/dotcloud/docker/server" "github.com/dotcloud/docker/utils" ) @@ -413,267 +412,3 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u err = json.NewDecoder(buffer).Decode(image) return image, err } - -// testing #1405 - config.Cmd does not get cleaned up if -// utilizing cache -func TestBuildEntrypointRunCleanup(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - - img, err := buildImage(testContextTemplate{` - from {IMAGE} - run echo "hello" - `, - nil, nil}, t, eng, true) - if err != nil { - t.Fatal(err) - } - - img, err = buildImage(testContextTemplate{` - from {IMAGE} - run echo "hello" - add foo /foo - entrypoint ["/bin/echo"] - `, - [][2]string{{"foo", "HEYO"}}, nil}, t, eng, true) - if err != nil { - t.Fatal(err) - } - - if len(img.Config.Cmd) != 0 { - t.Fail() - } -} - -func TestForbiddenContextPath(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - srv := mkServerFromEngine(eng, t) - - context := testContextTemplate{` - from {IMAGE} - maintainer dockerio - add ../../ test/ - `, - [][2]string{{"test.txt", "test1"}, {"other.txt", "other"}}, nil} - - httpServer, err := mkTestingFileServer(context.remoteFiles) - if err != nil { - t.Fatal(err) - } - defer httpServer.Close() - - idx := strings.LastIndex(httpServer.URL, ":") - if idx < 0 { - t.Fatalf("could not get port from test http server address %s", httpServer.URL) - } - port := httpServer.URL[idx+1:] - - iIP := eng.Hack_GetGlobalVar("httpapi.bridgeIP") - if iIP == nil { - t.Fatal("Legacy bridgeIP field not set in engine") - } - ip, ok := iIP.(net.IP) - if !ok { - panic("Legacy bridgeIP field in engine does not cast to net.IP") - } - dockerfile := constructDockerfile(context.dockerfile, ip, port) - - buildfile := server.NewBuildFile(srv, ioutil.Discard, ioutil.Discard, false, true, false, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil) - _, err = buildfile.Build(context.Archive(dockerfile, t)) - - if err == nil { - t.Log("Error should not be nil") - t.Fail() - } - - if err.Error() != "Forbidden path outside the build context: ../../ (/)" { - t.Logf("Error message is not expected: %s", err.Error()) - t.Fail() - } -} - -func TestBuildADDFileNotFound(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - - context := testContextTemplate{` - from {IMAGE} - add foo /usr/local/bar - `, - nil, nil} - - httpServer, err := mkTestingFileServer(context.remoteFiles) - if err != nil { - t.Fatal(err) - } - defer httpServer.Close() - - idx := strings.LastIndex(httpServer.URL, ":") - if idx < 0 { - t.Fatalf("could not get port from test http server address %s", httpServer.URL) - } - port := httpServer.URL[idx+1:] - - iIP := eng.Hack_GetGlobalVar("httpapi.bridgeIP") - if iIP == nil { - t.Fatal("Legacy bridgeIP field not set in engine") - } - ip, ok := iIP.(net.IP) - if !ok { - panic("Legacy bridgeIP field in engine does not cast to net.IP") - } - dockerfile := constructDockerfile(context.dockerfile, ip, port) - - buildfile := server.NewBuildFile(mkServerFromEngine(eng, t), ioutil.Discard, ioutil.Discard, false, true, false, false, ioutil.Discard, utils.NewStreamFormatter(false), nil, nil) - _, err = buildfile.Build(context.Archive(dockerfile, t)) - - if err == nil { - t.Log("Error should not be nil") - t.Fail() - } - - if err.Error() != "foo: no such file or directory" { - t.Logf("Error message is not expected: %s", err.Error()) - t.Fail() - } -} - -func TestBuildInheritance(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - - img, err := buildImage(testContextTemplate{` - from {IMAGE} - expose 2375 - `, - nil, nil}, t, eng, true) - - if err != nil { - t.Fatal(err) - } - - img2, _ := buildImage(testContextTemplate{fmt.Sprintf(` - from %s - entrypoint ["/bin/echo"] - `, img.ID), - nil, nil}, t, eng, true) - - if err != nil { - t.Fatal(err) - } - - // from child - if img2.Config.Entrypoint[0] != "/bin/echo" { - t.Fail() - } - - // from parent - if _, exists := img.Config.ExposedPorts[nat.NewPort("tcp", "2375")]; !exists { - t.Fail() - } -} - -func TestBuildFails(t *testing.T) { - _, err := buildImage(testContextTemplate{` - from {IMAGE} - run sh -c "exit 23" - `, - nil, nil}, t, nil, true) - - if err == nil { - t.Fatal("Error should not be nil") - } - - sterr, ok := err.(*utils.JSONError) - if !ok { - t.Fatalf("Error should be utils.JSONError") - } - if sterr.Code != 23 { - t.Fatalf("StatusCode %d unexpected, should be 23", sterr.Code) - } -} - -func TestBuildFailsDockerfileEmpty(t *testing.T) { - _, err := buildImage(testContextTemplate{``, nil, nil}, t, nil, true) - - if err != server.ErrDockerfileEmpty { - t.Fatal("Expected: %v, got: %v", server.ErrDockerfileEmpty, err) - } -} - -func TestBuildOnBuildTrigger(t *testing.T) { - _, err := buildImage(testContextTemplate{` - from {IMAGE} - onbuild run echo here is the trigger - onbuild run touch foobar - `, - nil, nil, - }, - t, nil, true, - ) - if err != nil { - t.Fatal(err) - } - // FIXME: test that the 'foobar' file was created in the final build. -} - -func TestBuildOnBuildForbiddenChainedTrigger(t *testing.T) { - _, err := buildImage(testContextTemplate{` - from {IMAGE} - onbuild onbuild run echo test - `, - nil, nil, - }, - t, nil, true, - ) - if err == nil { - t.Fatal("Error should not be nil") - } -} - -func TestBuildOnBuildForbiddenFromTrigger(t *testing.T) { - _, err := buildImage(testContextTemplate{` - from {IMAGE} - onbuild from {IMAGE} - `, - nil, nil, - }, - t, nil, true, - ) - if err == nil { - t.Fatal("Error should not be nil") - } -} - -func TestBuildOnBuildForbiddenMaintainerTrigger(t *testing.T) { - _, err := buildImage(testContextTemplate{` - from {IMAGE} - onbuild maintainer test - `, - nil, nil, - }, - t, nil, true, - ) - if err == nil { - t.Fatal("Error should not be nil") - } -} - -// gh #2446 -func TestBuildAddToSymlinkDest(t *testing.T) { - eng := NewTestEngine(t) - defer nuke(mkDaemonFromEngine(eng, t)) - - _, err := buildImage(testContextTemplate{` - from {IMAGE} - run mkdir /foo - run ln -s /foo /bar - add foo /bar/ - run stat /bar/foo - `, - [][2]string{{"foo", "HEYO"}}, nil}, t, eng, true) - if err != nil { - t.Fatal(err) - } -}