зеркало из https://github.com/microsoft/docker.git
Merge pull request #6143 from LK4D4/move_some_more_tests_to_cli
Move some more tests to integration cli
This commit is contained in:
Коммит
f65fadbda0
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -10,25 +11,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func checkSimpleBuild(t *testing.T, dockerfile, name, inspectFormat, expected string) {
|
|
||||||
buildCmd := exec.Command(dockerBinary, "build", "-t", name, "-")
|
|
||||||
buildCmd.Stdin = strings.NewReader(dockerfile)
|
|
||||||
out, exitCode, err := runCommandWithOutput(buildCmd)
|
|
||||||
errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
|
|
||||||
if err != nil || exitCode != 0 {
|
|
||||||
t.Fatal("failed to build the image")
|
|
||||||
}
|
|
||||||
inspectCmd := exec.Command(dockerBinary, "inspect", "-f", inspectFormat, name)
|
|
||||||
out, exitCode, err = runCommandWithOutput(inspectCmd)
|
|
||||||
if err != nil || exitCode != 0 {
|
|
||||||
t.Fatalf("failed to inspect the image: %s", out)
|
|
||||||
}
|
|
||||||
out = strings.TrimSpace(out)
|
|
||||||
if out != expected {
|
|
||||||
t.Fatalf("From format %s expected %s, got %s", inspectFormat, expected, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildCacheADD(t *testing.T) {
|
func TestBuildCacheADD(t *testing.T) {
|
||||||
buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "1")
|
buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "1")
|
||||||
buildCmd := exec.Command(dockerBinary, "build", "-t", "testcacheadd1", ".")
|
buildCmd := exec.Command(dockerBinary, "build", "-t", "testcacheadd1", ".")
|
||||||
|
@ -606,129 +588,516 @@ func TestBuildRm(t *testing.T) {
|
||||||
logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
|
logDone("build - ensure --rm doesn't leave containers behind and that --rm=true is the default")
|
||||||
logDone("build - ensure --rm=false overrides the default")
|
logDone("build - ensure --rm=false overrides the default")
|
||||||
}
|
}
|
||||||
|
func TestBuildWithVolumes(t *testing.T) {
|
||||||
func TestBuildWithVolume(t *testing.T) {
|
name := "testbuildvolumes"
|
||||||
checkSimpleBuild(t,
|
expected := "map[/test1:map[] /test2:map[]]"
|
||||||
`
|
defer deleteImages(name)
|
||||||
FROM scratch
|
_, err := buildImage(name,
|
||||||
VOLUME /test
|
`FROM scratch
|
||||||
`,
|
VOLUME /test1
|
||||||
"testbuildimg",
|
VOLUME /test2`,
|
||||||
"{{json .Config.Volumes}}",
|
true)
|
||||||
`{"/test":{}}`)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
deleteImages("testbuildimg")
|
}
|
||||||
logDone("build - with volume")
|
res, err := inspectField(name, "Config.Volumes")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Volumes %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
|
logDone("build - with volumes")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildMaintainer(t *testing.T) {
|
func TestBuildMaintainer(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildmaintainer"
|
||||||
`
|
expected := "dockerio"
|
||||||
FROM scratch
|
defer deleteImages(name)
|
||||||
MAINTAINER dockerio
|
_, err := buildImage(name,
|
||||||
`,
|
`FROM scratch
|
||||||
"testbuildimg",
|
MAINTAINER dockerio`,
|
||||||
"{{json .Author}}",
|
true)
|
||||||
`"dockerio"`)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
deleteImages("testbuildimg")
|
}
|
||||||
|
res, err := inspectField(name, "Author")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Maintainer %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - maintainer")
|
logDone("build - maintainer")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildUser(t *testing.T) {
|
func TestBuildUser(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuilduser"
|
||||||
`
|
expected := "dockerio"
|
||||||
FROM busybox
|
defer deleteImages(name)
|
||||||
|
_, err := buildImage(name,
|
||||||
|
`FROM busybox
|
||||||
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
RUN echo 'dockerio:x:1001:1001::/bin:/bin/false' >> /etc/passwd
|
||||||
USER dockerio
|
USER dockerio
|
||||||
RUN [ $(whoami) = 'dockerio' ]
|
RUN [ $(whoami) = 'dockerio' ]`,
|
||||||
`,
|
true)
|
||||||
"testbuildimg",
|
if err != nil {
|
||||||
"{{json .Config.User}}",
|
t.Fatal(err)
|
||||||
`"dockerio"`)
|
}
|
||||||
|
res, err := inspectField(name, "Config.User")
|
||||||
deleteImages("testbuildimg")
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("User %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - user")
|
logDone("build - user")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildRelativeWorkdir(t *testing.T) {
|
func TestBuildRelativeWorkdir(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildrelativeworkdir"
|
||||||
`
|
expected := "/test2/test3"
|
||||||
FROM busybox
|
defer deleteImages(name)
|
||||||
|
_, err := buildImage(name,
|
||||||
|
`FROM busybox
|
||||||
RUN [ "$PWD" = '/' ]
|
RUN [ "$PWD" = '/' ]
|
||||||
WORKDIR test1
|
WORKDIR test1
|
||||||
RUN [ "$PWD" = '/test1' ]
|
RUN [ "$PWD" = '/test1' ]
|
||||||
WORKDIR /test2
|
WORKDIR /test2
|
||||||
RUN [ "$PWD" = '/test2' ]
|
RUN [ "$PWD" = '/test2' ]
|
||||||
WORKDIR test3
|
WORKDIR test3
|
||||||
RUN [ "$PWD" = '/test2/test3' ]
|
RUN [ "$PWD" = '/test2/test3' ]`,
|
||||||
`,
|
true)
|
||||||
"testbuildimg",
|
if err != nil {
|
||||||
"{{json .Config.WorkingDir}}",
|
t.Fatal(err)
|
||||||
`"/test2/test3"`)
|
}
|
||||||
|
res, err := inspectField(name, "Config.WorkingDir")
|
||||||
deleteImages("testbuildimg")
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Workdir %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - relative workdir")
|
logDone("build - relative workdir")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildEnv(t *testing.T) {
|
func TestBuildEnv(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildenv"
|
||||||
`
|
expected := "[HOME=/ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=4243]"
|
||||||
FROM busybox
|
defer deleteImages(name)
|
||||||
|
_, err := buildImage(name,
|
||||||
|
`FROM busybox
|
||||||
ENV PORT 4243
|
ENV PORT 4243
|
||||||
RUN [ $(env | grep PORT) = 'PORT=4243' ]
|
RUN [ $(env | grep PORT) = 'PORT=4243' ]`,
|
||||||
`,
|
true)
|
||||||
"testbuildimg",
|
if err != nil {
|
||||||
"{{json .Config.Env}}",
|
t.Fatal(err)
|
||||||
`["HOME=/","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","PORT=4243"]`)
|
}
|
||||||
|
res, err := inspectField(name, "Config.Env")
|
||||||
deleteImages("testbuildimg")
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Env %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - env")
|
logDone("build - env")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildCmd(t *testing.T) {
|
func TestBuildCmd(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildcmd"
|
||||||
`
|
expected := "[/bin/echo Hello World]"
|
||||||
FROM scratch
|
defer deleteImages(name)
|
||||||
CMD ["/bin/echo", "Hello World"]
|
_, err := buildImage(name,
|
||||||
`,
|
`FROM scratch
|
||||||
"testbuildimg",
|
CMD ["/bin/echo", "Hello World"]`,
|
||||||
"{{json .Config.Cmd}}",
|
true)
|
||||||
`["/bin/echo","Hello World"]`)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
deleteImages("testbuildimg")
|
}
|
||||||
|
res, err := inspectField(name, "Config.Cmd")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Cmd %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - cmd")
|
logDone("build - cmd")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildExpose(t *testing.T) {
|
func TestBuildExpose(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildexpose"
|
||||||
`
|
expected := "map[4243/tcp:map[]]"
|
||||||
FROM scratch
|
defer deleteImages(name)
|
||||||
EXPOSE 4243
|
_, err := buildImage(name,
|
||||||
`,
|
`FROM scratch
|
||||||
|
EXPOSE 4243`,
|
||||||
"testbuildimg",
|
true)
|
||||||
"{{json .Config.ExposedPorts}}",
|
if err != nil {
|
||||||
`{"4243/tcp":{}}`)
|
t.Fatal(err)
|
||||||
|
}
|
||||||
deleteImages("testbuildimg")
|
res, err := inspectField(name, "Config.ExposedPorts")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Exposed ports %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - expose")
|
logDone("build - expose")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuildEntrypoint(t *testing.T) {
|
func TestBuildEntrypoint(t *testing.T) {
|
||||||
checkSimpleBuild(t,
|
name := "testbuildentrypoint"
|
||||||
`
|
expected := "[/bin/echo]"
|
||||||
FROM scratch
|
defer deleteImages(name)
|
||||||
ENTRYPOINT ["/bin/echo"]
|
_, err := buildImage(name,
|
||||||
`,
|
`FROM scratch
|
||||||
"testbuildimg",
|
ENTRYPOINT ["/bin/echo"]`,
|
||||||
"{{json .Config.Entrypoint}}",
|
true)
|
||||||
`["/bin/echo"]`)
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
deleteImages("testbuildimg")
|
}
|
||||||
|
res, err := inspectField(name, "Config.Entrypoint")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if res != expected {
|
||||||
|
t.Fatalf("Entrypoint %s, expected %s", res, expected)
|
||||||
|
}
|
||||||
logDone("build - entrypoint")
|
logDone("build - entrypoint")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: TestCaching
|
func TestBuildWithCache(t *testing.T) {
|
||||||
|
name := "testbuildwithcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
id1, err := buildImage(name,
|
||||||
|
`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
EXPOSE 5432
|
||||||
|
ENTRYPOINT ["/bin/echo"]`,
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImage(name,
|
||||||
|
`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
EXPOSE 5432
|
||||||
|
ENTRYPOINT ["/bin/echo"]`,
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 != id2 {
|
||||||
|
t.Fatal("The cache should have been used but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - with cache")
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: TestADDCacheInvalidation
|
func TestBuildWithoutCache(t *testing.T) {
|
||||||
|
name := "testbuildwithoutcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
id1, err := buildImage(name,
|
||||||
|
`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
EXPOSE 5432
|
||||||
|
ENTRYPOINT ["/bin/echo"]`,
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImage(name,
|
||||||
|
`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
EXPOSE 5432
|
||||||
|
ENTRYPOINT ["/bin/echo"]`,
|
||||||
|
false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - without cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDLocalFileWithCache(t *testing.T) {
|
||||||
|
name := "testbuildaddlocalfilewithcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
dockerfile := `
|
||||||
|
FROM busybox
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD foo /usr/lib/bla/bar
|
||||||
|
RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
|
||||||
|
ctx, err := fakeContext(dockerfile, map[string]string{
|
||||||
|
"foo": "hello",
|
||||||
|
})
|
||||||
|
defer ctx.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 != id2 {
|
||||||
|
t.Fatal("The cache should have been used but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add local file with cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDLocalFileWithoutCache(t *testing.T) {
|
||||||
|
name := "testbuildaddlocalfilewithoutcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
dockerfile := `
|
||||||
|
FROM busybox
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD foo /usr/lib/bla/bar
|
||||||
|
RUN [ "$(cat /usr/lib/bla/bar)" = "hello" ]`
|
||||||
|
ctx, err := fakeContext(dockerfile, map[string]string{
|
||||||
|
"foo": "hello",
|
||||||
|
})
|
||||||
|
defer ctx.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add local file without cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDCurrentDirWithCache(t *testing.T) {
|
||||||
|
name := "testbuildaddcurrentdirwithcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
dockerfile := `
|
||||||
|
FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD . /usr/lib/bla`
|
||||||
|
ctx, err := fakeContext(dockerfile, map[string]string{
|
||||||
|
"foo": "hello",
|
||||||
|
})
|
||||||
|
defer ctx.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Check that adding file invalidate cache of "ADD ."
|
||||||
|
if err := ctx.Add("bar", "hello2"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
// Check that changing file invalidate cache of "ADD ."
|
||||||
|
if err := ctx.Add("foo", "hello1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id3, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id2 == id3 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
// Check that changing file to same content invalidate cache of "ADD ."
|
||||||
|
time.Sleep(1 * time.Second) // wait second because of mtime precision
|
||||||
|
if err := ctx.Add("foo", "hello1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id4, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id3 == id4 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
id5, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id4 != id5 {
|
||||||
|
t.Fatal("The cache should have been used but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add current directory with cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDCurrentDirWithoutCache(t *testing.T) {
|
||||||
|
name := "testbuildaddcurrentdirwithoutcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
dockerfile := `
|
||||||
|
FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD . /usr/lib/bla`
|
||||||
|
ctx, err := fakeContext(dockerfile, map[string]string{
|
||||||
|
"foo": "hello",
|
||||||
|
})
|
||||||
|
defer ctx.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add current directory without cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDRemoteFileWithCache(t *testing.T) {
|
||||||
|
name := "testbuildaddremotefilewithcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
server, err := fakeStorage(map[string]string{
|
||||||
|
"baz": "hello",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer server.Close()
|
||||||
|
id1, err := buildImage(name,
|
||||||
|
fmt.Sprintf(`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD %s/baz /usr/lib/baz/quux`, server.URL),
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImage(name,
|
||||||
|
fmt.Sprintf(`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD %s/baz /usr/lib/baz/quux`, server.URL),
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 != id2 {
|
||||||
|
t.Fatal("The cache should have been used but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add remote file with cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
|
||||||
|
name := "testbuildaddremotefilewithoutcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
server, err := fakeStorage(map[string]string{
|
||||||
|
"baz": "hello",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer server.Close()
|
||||||
|
id1, err := buildImage(name,
|
||||||
|
fmt.Sprintf(`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD %s/baz /usr/lib/baz/quux`, server.URL),
|
||||||
|
true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImage(name,
|
||||||
|
fmt.Sprintf(`FROM scratch
|
||||||
|
MAINTAINER dockerio
|
||||||
|
ADD %s/baz /usr/lib/baz/quux`, server.URL),
|
||||||
|
false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add remote file without cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
|
||||||
|
name := "testbuildaddlocalandremotefilewithcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
server, err := fakeStorage(map[string]string{
|
||||||
|
"baz": "hello",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer server.Close()
|
||||||
|
ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
|
||||||
|
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 {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ctx.Close()
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 != id2 {
|
||||||
|
t.Fatal("The cache should have been used but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add local and remote file with cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
|
||||||
|
name := "testbuildaddlocalandremotefilewithoutcache"
|
||||||
|
defer deleteImages(name)
|
||||||
|
server, err := fakeStorage(map[string]string{
|
||||||
|
"baz": "hello",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer server.Close()
|
||||||
|
ctx, err := fakeContext(fmt.Sprintf(`FROM scratch
|
||||||
|
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 {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer ctx.Close()
|
||||||
|
id1, err := buildImageFromContext(name, ctx, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
id2, err := buildImageFromContext(name, ctx, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if id1 == id2 {
|
||||||
|
t.Fatal("The cache should have been invalided but hasn't.")
|
||||||
|
}
|
||||||
|
logDone("build - add local and remote file without cache")
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,12 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -97,3 +102,120 @@ func getContainerCount() (int, error) {
|
||||||
}
|
}
|
||||||
return 0, fmt.Errorf("couldn't find the Container count in the output")
|
return 0, fmt.Errorf("couldn't find the Container count in the output")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FakeContext struct {
|
||||||
|
Dir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeContext) Add(file, content string) error {
|
||||||
|
filepath := path.Join(f.Dir, file)
|
||||||
|
dirpath := path.Dir(filepath)
|
||||||
|
if dirpath != "." {
|
||||||
|
if err := os.MkdirAll(dirpath, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(filepath, []byte(content), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeContext) Delete(file string) error {
|
||||||
|
filepath := path.Join(f.Dir, file)
|
||||||
|
return os.RemoveAll(filepath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeContext) Close() error {
|
||||||
|
return os.RemoveAll(f.Dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fakeContext(dockerfile string, files map[string]string) (*FakeContext, error) {
|
||||||
|
tmp, err := ioutil.TempDir("", "fake-context")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx := &FakeContext{tmp}
|
||||||
|
for file, content := range files {
|
||||||
|
if err := ctx.Add(file, content); err != nil {
|
||||||
|
ctx.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := ctx.Add("Dockerfile", dockerfile); err != nil {
|
||||||
|
ctx.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ctx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FakeStorage struct {
|
||||||
|
*FakeContext
|
||||||
|
*httptest.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeStorage) Close() error {
|
||||||
|
f.Server.Close()
|
||||||
|
return f.FakeContext.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func fakeStorage(files map[string]string) (*FakeStorage, error) {
|
||||||
|
tmp, err := ioutil.TempDir("", "fake-storage")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ctx := &FakeContext{tmp}
|
||||||
|
for file, content := range files {
|
||||||
|
if err := ctx.Add(file, content); err != nil {
|
||||||
|
ctx.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler := http.FileServer(http.Dir(ctx.Dir))
|
||||||
|
server := httptest.NewServer(handler)
|
||||||
|
return &FakeStorage{
|
||||||
|
FakeContext: ctx,
|
||||||
|
Server: server,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func inspectField(name, field string) (string, error) {
|
||||||
|
format := fmt.Sprintf("{{.%s}}", field)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(out), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getIDByName(name string) (string, error) {
|
||||||
|
return inspectField(name, "Id")
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildImage(name, dockerfile string, useCache bool) (string, error) {
|
||||||
|
args := []string{"build", "-t", name}
|
||||||
|
if !useCache {
|
||||||
|
args = append(args, "--no-cache")
|
||||||
|
}
|
||||||
|
args = append(args, "-")
|
||||||
|
buildCmd := exec.Command(dockerBinary, args...)
|
||||||
|
buildCmd.Stdin = strings.NewReader(dockerfile)
|
||||||
|
out, exitCode, err := runCommandWithOutput(buildCmd)
|
||||||
|
if err != nil || exitCode != 0 {
|
||||||
|
return "", fmt.Errorf("failed to build the image: %s", out)
|
||||||
|
}
|
||||||
|
return getIDByName(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildImageFromContext(name string, ctx *FakeContext, useCache bool) (string, error) {
|
||||||
|
args := []string{"build", "-t", name}
|
||||||
|
if !useCache {
|
||||||
|
args = append(args, "--no-cache")
|
||||||
|
}
|
||||||
|
args = append(args, ".")
|
||||||
|
buildCmd := exec.Command(dockerBinary, args...)
|
||||||
|
buildCmd.Dir = ctx.Dir
|
||||||
|
out, exitCode, err := runCommandWithOutput(buildCmd)
|
||||||
|
if err != nil || exitCode != 0 {
|
||||||
|
return "", fmt.Errorf("failed to build the image: %s", out)
|
||||||
|
}
|
||||||
|
return getIDByName(name)
|
||||||
|
}
|
||||||
|
|
|
@ -445,226 +445,6 @@ func TestBuildEntrypointRunCleanup(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCacheBehavior(t *testing.T, template testContextTemplate, expectHit bool) (imageId string) {
|
|
||||||
eng := NewTestEngine(t)
|
|
||||||
defer nuke(mkDaemonFromEngine(eng, t))
|
|
||||||
|
|
||||||
img, err := buildImage(template, t, eng, true)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
imageId = img.ID
|
|
||||||
|
|
||||||
img, err = buildImage(template, t, eng, expectHit)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hit := imageId == img.ID; hit != expectHit {
|
|
||||||
t.Fatalf("Cache misbehavior, got hit=%t, expected hit=%t: (first: %s, second %s)", hit, expectHit, imageId, img.ID)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCacheBehaviorFromEngime(t *testing.T, template testContextTemplate, expectHit bool, eng *engine.Engine) (imageId string) {
|
|
||||||
img, err := buildImage(template, t, eng, true)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
imageId = img.ID
|
|
||||||
|
|
||||||
img, err = buildImage(template, t, eng, expectHit)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if hit := imageId == img.ID; hit != expectHit {
|
|
||||||
t.Fatalf("Cache misbehavior, got hit=%t, expected hit=%t: (first: %s, second %s)", hit, expectHit, imageId, img.ID)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildImageWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
`,
|
|
||||||
nil, nil}
|
|
||||||
checkCacheBehavior(t, template, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildExposeWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
expose 80
|
|
||||||
run echo hello
|
|
||||||
`,
|
|
||||||
nil, nil}
|
|
||||||
checkCacheBehavior(t, template, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildImageWithoutCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
`,
|
|
||||||
nil, nil}
|
|
||||||
checkCacheBehavior(t, template, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDLocalFileWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add foo /usr/lib/bla/bar
|
|
||||||
run [ "$(cat /usr/lib/bla/bar)" = "hello" ]
|
|
||||||
run echo "second"
|
|
||||||
add . /src/
|
|
||||||
run [ "$(cat /src/foo)" = "hello" ]
|
|
||||||
`,
|
|
||||||
[][2]string{
|
|
||||||
{"foo", "hello"},
|
|
||||||
},
|
|
||||||
nil}
|
|
||||||
eng := NewTestEngine(t)
|
|
||||||
defer nuke(mkDaemonFromEngine(eng, t))
|
|
||||||
|
|
||||||
id1 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
template.files = append(template.files, [2]string{"bar", "hello2"})
|
|
||||||
id2 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id1 == id2 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
id3 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id2 != id3 {
|
|
||||||
t.Fatal("The cache should have been used but hasn't.")
|
|
||||||
}
|
|
||||||
template.files[1][1] = "hello3"
|
|
||||||
id4 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id3 == id4 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
template.dockerfile += `
|
|
||||||
add ./bar /src2/
|
|
||||||
run ls /src2/bar
|
|
||||||
`
|
|
||||||
id5 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id4 == id5 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
template.files[1][1] = "hello4"
|
|
||||||
id6 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id5 == id6 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
|
|
||||||
template.dockerfile += `
|
|
||||||
add bar /src2/bar2
|
|
||||||
add /bar /src2/bar3
|
|
||||||
run ls /src2/bar2 /src2/bar3
|
|
||||||
`
|
|
||||||
id7 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id6 == id7 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
template.files[1][1] = "hello5"
|
|
||||||
id8 := checkCacheBehaviorFromEngime(t, template, true, eng)
|
|
||||||
if id7 == id8 {
|
|
||||||
t.Fatal("The cache should have been invalided but hasn't.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDLocalFileWithoutCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add foo /usr/lib/bla/bar
|
|
||||||
run echo "second"
|
|
||||||
`,
|
|
||||||
[][2]string{{"foo", "hello"}},
|
|
||||||
nil}
|
|
||||||
checkCacheBehavior(t, template, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDCurrentDirectoryWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
add . /usr/lib/bla
|
|
||||||
`,
|
|
||||||
nil, nil}
|
|
||||||
checkCacheBehavior(t, template, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDCurrentDirectoryWithoutCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
add . /usr/lib/bla
|
|
||||||
`,
|
|
||||||
nil, nil}
|
|
||||||
checkCacheBehavior(t, template, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDRemoteFileWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add http://{SERVERADDR}/baz /usr/lib/baz/quux
|
|
||||||
run echo "second"
|
|
||||||
`,
|
|
||||||
nil,
|
|
||||||
[][2]string{{"/baz", "world!"}}}
|
|
||||||
checkCacheBehavior(t, template, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDRemoteFileWithoutCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add http://{SERVERADDR}/baz /usr/lib/baz/quux
|
|
||||||
run echo "second"
|
|
||||||
`,
|
|
||||||
nil,
|
|
||||||
[][2]string{{"/baz", "world!"}}}
|
|
||||||
checkCacheBehavior(t, template, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDLocalAndRemoteFilesWithCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add foo /usr/lib/bla/bar
|
|
||||||
add http://{SERVERADDR}/baz /usr/lib/baz/quux
|
|
||||||
run echo "second"
|
|
||||||
`,
|
|
||||||
[][2]string{{"foo", "hello"}},
|
|
||||||
[][2]string{{"/baz", "world!"}}}
|
|
||||||
checkCacheBehavior(t, template, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildADDLocalAndRemoteFilesWithoutCache(t *testing.T) {
|
|
||||||
template := testContextTemplate{`
|
|
||||||
from {IMAGE}
|
|
||||||
maintainer dockerio
|
|
||||||
run echo "first"
|
|
||||||
add foo /usr/lib/bla/bar
|
|
||||||
add http://{SERVERADDR}/baz /usr/lib/baz/quux
|
|
||||||
run echo "second"
|
|
||||||
`,
|
|
||||||
[][2]string{{"foo", "hello"}},
|
|
||||||
[][2]string{{"/baz", "world!"}}}
|
|
||||||
checkCacheBehavior(t, template, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestForbiddenContextPath(t *testing.T) {
|
func TestForbiddenContextPath(t *testing.T) {
|
||||||
eng := NewTestEngine(t)
|
eng := NewTestEngine(t)
|
||||||
defer nuke(mkDaemonFromEngine(eng, t))
|
defer nuke(mkDaemonFromEngine(eng, t))
|
||||||
|
|
Загрузка…
Ссылка в новой задаче