2014-02-25 20:17:48 +04:00
package main
import (
2014-07-21 23:10:47 +04:00
"archive/tar"
2015-03-11 01:10:00 +03:00
"bufio"
2014-11-13 06:14:15 +03:00
"bytes"
2014-10-25 22:29:18 +04:00
"encoding/json"
2014-02-25 20:17:48 +04:00
"fmt"
2014-07-21 23:10:47 +04:00
"io/ioutil"
2014-05-13 22:49:12 +04:00
"os"
2014-02-25 20:17:48 +04:00
"os/exec"
"path/filepath"
2014-12-04 04:52:06 +03:00
"reflect"
2014-10-14 00:14:35 +04:00
"regexp"
2015-02-18 10:20:20 +03:00
"runtime"
2014-11-13 06:14:15 +03:00
"strconv"
2014-05-13 22:49:12 +04:00
"strings"
2015-03-11 01:10:00 +03:00
"sync"
2014-11-13 06:14:15 +03:00
"text/template"
2014-05-23 02:12:41 +04:00
"time"
2014-05-10 02:26:41 +04:00
2015-02-12 08:18:48 +03:00
"github.com/docker/docker/builder/command"
2014-09-30 10:23:36 +04:00
"github.com/docker/docker/pkg/archive"
2015-03-24 14:25:26 +03:00
"github.com/docker/docker/pkg/stringutils"
2015-04-18 19:46:47 +03:00
"github.com/go-check/check"
2014-02-25 20:17:48 +04:00
)
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildJSONEmptyRun ( c * check . C ) {
2015-01-09 04:00:00 +03:00
name := "testbuildjsonemptyrun"
defer deleteImages ( name )
_ , err := buildImage (
name ,
`
FROM busybox
RUN [ ]
` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "error when dealing with a RUN statement with empty JSON array" )
2015-01-09 04:00:00 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyWhitespace ( c * check . C ) {
2015-01-08 22:30:08 +03:00
name := "testbuildemptywhitespace"
defer deleteImages ( name )
_ , err := buildImage (
name ,
`
FROM busybox
2015-02-04 20:34:25 +03:00
COPY
2015-01-08 22:30:08 +03:00
quux \
bar
` ,
true )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "no error when dealing with a COPY statement with no content on the same line" )
2015-01-08 22:30:08 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildShCmdJSONEntrypoint ( c * check . C ) {
2014-10-28 00:15:28 +03:00
name := "testbuildshcmdjsonentrypoint"
defer deleteImages ( name )
_ , err := buildImage (
name ,
`
FROM busybox
ENTRYPOINT [ "/bin/echo" ]
CMD echo test
` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-28 00:15:28 +03:00
}
out , _ , err := runCommandWithOutput (
exec . Command (
dockerBinary ,
"run" ,
2014-11-17 19:05:49 +03:00
"--rm" ,
2014-10-28 00:15:28 +03:00
name ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-28 00:15:28 +03:00
}
if strings . TrimSpace ( out ) != "/bin/sh -c echo test" {
2015-04-18 19:46:47 +03:00
c . Fatal ( "CMD did not contain /bin/sh -c" )
2014-10-28 00:15:28 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementUser ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM scratch
ENV user foo
USER $ { user }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
res , err := inspectFieldJSON ( name , "Config.User" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
if res != ` "foo" ` {
2015-04-18 19:46:47 +03:00
c . Fatal ( "User foo from environment not in Config.User on image" )
2014-10-25 22:29:18 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementVolume ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM scratch
ENV volume / quux
VOLUME $ { volume }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Volumes" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
var volumes map [ string ] interface { }
if err := json . Unmarshal ( [ ] byte ( res ) , & volumes ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
if _ , ok := volumes [ "/quux" ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Volume /quux from environment not in Config.Volumes on image" )
2014-10-25 22:29:18 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementExpose ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM scratch
ENV port 80
EXPOSE $ { port }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
res , err := inspectFieldJSON ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
var exposedPorts map [ string ] interface { }
if err := json . Unmarshal ( [ ] byte ( res ) , & exposedPorts ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
if _ , ok := exposedPorts [ "80/tcp" ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Exposed port 80 from environment not in Config.ExposedPorts on image" )
2014-10-25 22:29:18 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementWorkdir ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM busybox
ENV MYWORKDIR / work
RUN mkdir $ { MYWORKDIR }
WORKDIR $ { MYWORKDIR }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementAddCopy ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
ctx , err := fakeContext ( `
FROM scratch
ENV baz foo
ENV quux bar
ENV dot .
2015-01-29 05:28:48 +03:00
ENV fee fff
ENV gee ggg
2014-10-25 22:29:18 +04:00
ADD $ { baz } $ { dot }
COPY $ { quux } $ { dot }
2015-01-29 05:28:48 +03:00
ADD $ { zzz : - $ { fee } } $ { dot }
COPY $ { zzz : - $ { gee } } $ { dot }
2014-10-25 22:29:18 +04:00
` ,
map [ string ] string {
"foo" : "test1" ,
"bar" : "test2" ,
2015-01-29 05:28:48 +03:00
"fff" : "test3" ,
"ggg" : "test4" ,
2014-10-25 22:29:18 +04:00
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-25 22:29:18 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvironmentReplacementEnv ( c * check . C ) {
2014-10-25 22:29:18 +04:00
name := "testbuildenvironmentreplacement"
defer deleteImages ( name )
_ , err := buildImage ( name ,
`
2015-01-29 05:28:48 +03:00
FROM busybox
ENV foo zzz
2014-10-25 22:29:18 +04:00
ENV bar $ { foo }
2015-01-29 05:28:48 +03:00
ENV abc1 = ' $ foo '
ENV env1 = $ foo env2 = $ { foo } env3 = "$foo" env4 = "${foo}"
RUN [ "$abc1" = ' $ foo ' ] && ( echo "$abc1" | grep - q foo )
ENV abc2 = "\$foo"
RUN [ "$abc2" = ' $ foo ' ] && ( echo "$abc2" | grep - q foo )
ENV abc3 ' $ foo '
RUN [ "$abc3" = ' $ foo ' ] && ( echo "$abc3" | grep - q foo )
ENV abc4 "\$foo"
RUN [ "$abc4" = ' $ foo ' ] && ( echo "$abc4" | grep - q foo )
2014-10-25 22:29:18 +04:00
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Env" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
envResult := [ ] string { }
if err = unmarshalJSON ( [ ] byte ( res ) , & envResult ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 22:29:18 +04:00
}
found := false
2015-01-29 05:28:48 +03:00
envCount := 0
2014-10-25 22:29:18 +04:00
for _ , env := range envResult {
parts := strings . SplitN ( env , "=" , 2 )
if parts [ 0 ] == "bar" {
found = true
2015-01-29 05:28:48 +03:00
if parts [ 1 ] != "zzz" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Could not find replaced var for env `bar`: got %q instead of `zzz`" , parts [ 1 ] )
2015-01-29 05:28:48 +03:00
}
} else if strings . HasPrefix ( parts [ 0 ] , "env" ) {
envCount ++
if parts [ 1 ] != "zzz" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s should be 'foo' but instead its %q" , parts [ 0 ] , parts [ 1 ] )
2014-10-25 22:29:18 +04:00
}
2015-01-29 05:28:48 +03:00
} else if strings . HasPrefix ( parts [ 0 ] , "env" ) {
envCount ++
if parts [ 1 ] != "foo" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s should be 'foo' but instead its %q" , parts [ 0 ] , parts [ 1 ] )
2015-01-29 05:28:48 +03:00
}
2014-10-25 22:29:18 +04:00
}
}
if ! found {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Never found the `bar` env variable" )
2014-10-25 22:29:18 +04:00
}
2015-01-29 05:28:48 +03:00
if envCount != 4 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't find all env vars - only saw %d\n%s" , envCount , envResult )
2015-01-29 05:28:48 +03:00
}
2014-10-25 22:29:18 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildHandleEscapes ( c * check . C ) {
2014-10-25 21:58:57 +04:00
name := "testbuildhandleescapes"
defer deleteImages ( name )
_ , err := buildImage ( name ,
`
FROM scratch
ENV FOO bar
VOLUME $ { FOO }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
var result map [ string ] map [ string ] struct { }
res , err := inspectFieldJSON ( name , "Config.Volumes" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
if err = unmarshalJSON ( [ ] byte ( res ) , & result ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
if _ , ok := result [ "bar" ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Could not find volume bar set from env foo in volumes table" )
2014-10-25 21:58:57 +04:00
}
2014-11-17 19:05:49 +03:00
deleteImages ( name )
2014-10-25 21:58:57 +04:00
_ , err = buildImage ( name ,
`
FROM scratch
ENV FOO bar
VOLUME \ $ { FOO }
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
res , err = inspectFieldJSON ( name , "Config.Volumes" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
if err = unmarshalJSON ( [ ] byte ( res ) , & result ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
if _ , ok := result [ "${FOO}" ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Could not find volume ${FOO} set from env foo in volumes table" )
2014-10-25 21:58:57 +04:00
}
2014-11-17 19:05:49 +03:00
deleteImages ( name )
2014-10-25 21:58:57 +04:00
// 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
res , err = inspectFieldJSON ( name , "Config.Volumes" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
if err = unmarshalJSON ( [ ] byte ( res ) , & result ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-25 21:58:57 +04:00
}
2015-01-29 05:28:48 +03:00
if _ , ok := result [ ` \\\$ { FOO} ` ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Fatal ( ` Could not find volume \\\$ { FOO} set from env foo in volumes table ` , result )
2014-10-25 21:58:57 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildLowercase ( c * check . C ) {
2014-10-21 23:26:20 +04:00
name := "testbuildonbuildlowercase"
name2 := "testbuildonbuildlowercase2"
defer deleteImages ( name , name2 )
_ , err := buildImage ( name ,
`
FROM busybox
onbuild run echo quux
` , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-21 23:26:20 +04:00
}
_ , out , err := buildImageWithOut ( name2 , fmt . Sprintf ( `
FROM % s
` , name ) , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-21 23:26:20 +04:00
}
if ! strings . Contains ( out , "quux" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Did not receive the expected echo text, got %s" , out )
2014-10-21 23:26:20 +04:00
}
if strings . Contains ( out , "ONBUILD ONBUILD" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Got an ONBUILD ONBUILD error with no error: got %s" , out )
2014-10-21 23:26:20 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvEscapes ( c * check . C ) {
2014-10-17 23:15:07 +04:00
name := "testbuildenvescapes"
defer deleteImages ( name )
_ , err := buildImage ( name ,
`
FROM busybox
ENV TEST foo
CMD echo \ $
` ,
true )
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "-t" , name ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-17 23:15:07 +04:00
}
if strings . TrimSpace ( out ) != "$" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q" , strings . TrimSpace ( out ) )
2014-10-17 23:15:07 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvOverwrite ( c * check . C ) {
2014-10-17 23:15:07 +04:00
name := "testbuildenvoverwrite"
defer deleteImages ( name )
_ , err := buildImage ( name ,
`
FROM busybox
ENV TEST foo
2014-10-25 22:29:18 +04:00
CMD echo $ { TEST }
2014-10-17 23:15:07 +04:00
` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-17 23:15:07 +04:00
}
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "-e" , "TEST=bar" , "-t" , name ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-17 23:15:07 +04:00
}
if strings . TrimSpace ( out ) != "bar" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q" , strings . TrimSpace ( out ) )
2014-10-17 23:15:07 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenMaintainerInSourceImage ( c * check . C ) {
2014-10-14 00:14:35 +04:00
name := "testbuildonbuildforbiddenmaintainerinsourceimage"
2014-11-17 19:05:49 +03:00
defer deleteImages ( "onbuild" )
2014-10-14 00:14:35 +04:00
defer deleteImages ( name )
2014-11-17 19:05:49 +03:00
2014-10-14 00:14:35 +04:00
createCmd := exec . Command ( dockerBinary , "create" , "busybox" , "true" )
out , _ , _ , err := runCommandWithStdoutStderr ( createCmd )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( out , err )
2014-10-15 00:51:12 +04:00
}
2014-10-14 00:14:35 +04:00
2015-04-06 16:21:18 +03:00
cleanedContainerID := strings . TrimSpace ( out )
2014-10-14 00:14:35 +04:00
commitCmd := exec . Command ( dockerBinary , "commit" , "--run" , "{\"OnBuild\":[\"MAINTAINER docker.io\"]}" , cleanedContainerID , "onbuild" )
if _ , err := runCommand ( commitCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
_ , err = buildImage ( name ,
` FROM onbuild ` ,
true )
if err != nil {
if ! strings . Contains ( err . Error ( ) , "maintainer isn't allowed as an ONBUILD trigger" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about MAINTAINER and ONBUILD in source image" , err )
2014-10-14 00:14:35 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-10-14 00:14:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenFromInSourceImage ( c * check . C ) {
2014-10-14 00:14:35 +04:00
name := "testbuildonbuildforbiddenfrominsourceimage"
2014-11-17 19:05:49 +03:00
defer deleteImages ( "onbuild" )
2014-10-14 00:14:35 +04:00
defer deleteImages ( name )
2014-11-17 19:05:49 +03:00
2014-10-14 00:14:35 +04:00
createCmd := exec . Command ( dockerBinary , "create" , "busybox" , "true" )
out , _ , _ , err := runCommandWithStdoutStderr ( createCmd )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( out , err )
2014-10-15 00:51:12 +04:00
}
2014-10-14 00:14:35 +04:00
2015-04-06 16:21:18 +03:00
cleanedContainerID := strings . TrimSpace ( out )
2014-10-14 00:14:35 +04:00
commitCmd := exec . Command ( dockerBinary , "commit" , "--run" , "{\"OnBuild\":[\"FROM busybox\"]}" , cleanedContainerID , "onbuild" )
if _ , err := runCommand ( commitCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
_ , err = buildImage ( name ,
` FROM onbuild ` ,
true )
if err != nil {
if ! strings . Contains ( err . Error ( ) , "from isn't allowed as an ONBUILD trigger" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about FROM and ONBUILD in source image" , err )
2014-10-14 00:14:35 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-10-14 00:14:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenChainedInSourceImage ( c * check . C ) {
2014-10-14 00:14:35 +04:00
name := "testbuildonbuildforbiddenchainedinsourceimage"
2014-11-17 19:05:49 +03:00
defer deleteImages ( "onbuild" )
2014-10-14 00:14:35 +04:00
defer deleteImages ( name )
2014-11-17 19:05:49 +03:00
2014-10-14 00:14:35 +04:00
createCmd := exec . Command ( dockerBinary , "create" , "busybox" , "true" )
out , _ , _ , err := runCommandWithStdoutStderr ( createCmd )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( out , err )
2014-10-15 00:51:12 +04:00
}
2014-10-14 00:14:35 +04:00
2015-04-06 16:21:18 +03:00
cleanedContainerID := strings . TrimSpace ( out )
2014-10-14 00:14:35 +04:00
commitCmd := exec . Command ( dockerBinary , "commit" , "--run" , "{\"OnBuild\":[\"ONBUILD RUN ls\"]}" , cleanedContainerID , "onbuild" )
if _ , err := runCommand ( commitCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
_ , err = buildImage ( name ,
` FROM onbuild ` ,
true )
if err != nil {
if ! strings . Contains ( err . Error ( ) , "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about chaining ONBUILD in source image" , err )
2014-10-14 00:14:35 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-10-14 00:14:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildCmdEntrypointJSON ( c * check . C ) {
2014-10-14 00:14:35 +04:00
name1 := "onbuildcmd"
name2 := "onbuildgenerated"
defer deleteImages ( name2 )
defer deleteImages ( name1 )
_ , err := buildImage ( name1 , `
FROM busybox
ONBUILD CMD [ "hello world" ]
ONBUILD ENTRYPOINT [ "echo" ]
ONBUILD RUN [ "true" ] ` ,
false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
_ , err = buildImage ( name2 , fmt . Sprintf ( ` FROM %s ` , name1 ) , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "-t" , name2 ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
if ! regexp . MustCompile ( ` (?m)^hello world ` ) . MatchString ( out ) {
2015-04-18 19:46:47 +03:00
c . Fatal ( "did not get echo output from onbuild" , out )
2014-10-14 00:14:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildEntrypointJSON ( c * check . C ) {
2014-10-14 00:14:35 +04:00
name1 := "onbuildcmd"
name2 := "onbuildgenerated"
defer deleteImages ( name2 )
defer deleteImages ( name1 )
_ , err := buildImage ( name1 , `
FROM busybox
ONBUILD ENTRYPOINT [ "echo" ] ` ,
false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
_ , err = buildImage ( name2 , fmt . Sprintf ( "FROM %s\nCMD [\"hello world\"]\n" , name1 ) , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "-t" , name2 ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 00:14:35 +04:00
}
if ! regexp . MustCompile ( ` (?m)^hello world ` ) . MatchString ( out ) {
2015-04-18 19:46:47 +03:00
c . Fatal ( "got malformed output from onbuild" , out )
2014-10-14 00:14:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCacheADD ( c * check . C ) {
2014-08-18 14:13:43 +04:00
name := "testbuildtwoimageswithadd"
defer deleteImages ( name )
server , err := fakeStorage ( map [ string ] string {
"robots.txt" : "hello" ,
"index.html" : "world" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 01:29:19 +04:00
}
2014-08-18 14:13:43 +04:00
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-08-18 14:13:43 +04:00
if _ , err := buildImage ( name ,
fmt . Sprintf ( ` FROM scratch
2015-02-19 13:01:27 +03:00
ADD % s / robots . txt / ` , server . URL ( ) ) ,
2014-08-18 14:13:43 +04:00
true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-08-18 14:13:43 +04:00
}
2014-11-17 19:05:49 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-17 19:05:49 +03:00
}
deleteImages ( name )
2014-10-06 21:04:10 +04:00
_ , out , err := buildImageWithOut ( name ,
2014-08-18 14:13:43 +04:00
fmt . Sprintf ( ` FROM scratch
2015-02-19 13:01:27 +03:00
ADD % s / index . html / ` , server . URL ( ) ) ,
2014-08-18 14:13:43 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 01:29:19 +04:00
}
if strings . Contains ( out , "Using cache" ) {
2015-04-18 19:46:47 +03:00
c . Fatal ( "2nd build used cache on ADD, it shouldn't" )
2014-05-21 01:29:19 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildLastModified ( c * check . C ) {
2015-03-04 20:14:58 +03:00
name := "testbuildlastmodified"
defer deleteImages ( name )
server , err := fakeStorage ( map [ string ] string {
"file" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-04 20:14:58 +03:00
}
defer server . Close ( )
var out , out2 string
dFmt := ` FROM busybox
ADD % s / file /
RUN ls - le / file `
2015-03-10 02:56:51 +03:00
dockerfile := fmt . Sprintf ( dFmt , server . URL ( ) )
2015-03-04 20:14:58 +03:00
if _ , out , err = buildImageWithOut ( name , dockerfile , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-04 20:14:58 +03:00
}
originMTime := regexp . MustCompile ( ` root.*/file.*\n ` ) . FindString ( out )
// Make sure our regexp is correct
if strings . Index ( originMTime , "/file" ) < 0 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing ls info on 'file':\n%s" , out )
2015-03-04 20:14:58 +03:00
}
// Build it again and make sure the mtime of the file didn't change.
// Wait a few seconds to make sure the time changed enough to notice
time . Sleep ( 2 * time . Second )
if _ , out2 , err = buildImageWithOut ( name , dockerfile , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-04 20:14:58 +03:00
}
newMTime := regexp . MustCompile ( ` root.*/file.*\n ` ) . FindString ( out2 )
if newMTime != originMTime {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "MTime changed:\nOrigin:%s\nNew:%s" , originMTime , newMTime )
2015-03-04 20:14:58 +03:00
}
// Now 'touch' the file and make sure the timestamp DID change this time
// Create a new fakeStorage instead of just using Add() to help windows
server , err = fakeStorage ( map [ string ] string {
"file" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-04 20:14:58 +03:00
}
defer server . Close ( )
2015-03-10 02:56:51 +03:00
dockerfile = fmt . Sprintf ( dFmt , server . URL ( ) )
2015-03-04 20:14:58 +03:00
if _ , out2 , err = buildImageWithOut ( name , dockerfile , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-04 20:14:58 +03:00
}
newMTime = regexp . MustCompile ( ` root.*/file.*\n ` ) . FindString ( out2 )
if newMTime == originMTime {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "MTime didn't change:\nOrigin:%s\nNew:%s" , originMTime , newMTime )
2015-03-04 20:14:58 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildSixtySteps ( c * check . C ) {
2014-09-22 18:18:19 +04:00
name := "foobuildsixtysteps"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\n" + strings . Repeat ( "ADD foo /\n" , 60 ) ,
map [ string ] string {
"foo" : "test1" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 18:18:19 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 18:18:19 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-02-25 20:17:48 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddSingleFileToRoot ( c * check . C ) {
2014-09-22 18:23:20 +04:00
name := "testaddimg"
defer deleteImages ( name )
2015-03-04 05:40:16 +03:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
2014-09-22 18:23:20 +04:00
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_file /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 05:40:16 +03:00
RUN [ $ ( ls - l / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ,
2014-09-22 18:23:20 +04:00
map [ string ] string {
"test_file" : "test1" ,
} )
2014-05-21 22:29:11 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 22:29:11 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 18:23:20 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-04-09 18:21:22 +04:00
}
}
2014-05-23 02:12:41 +04:00
// Issue #3960: "ADD src ." hangs
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddSingleFileToWorkdir ( c * check . C ) {
2014-09-22 18:51:42 +04:00
name := "testaddsinglefiletoworkdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
ADD test_file . ` ,
map [ string ] string {
"test_file" : "test1" ,
} )
2014-05-23 02:12:41 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-23 02:12:41 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 18:51:42 +04:00
done := make ( chan struct { } )
go func ( ) {
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 18:51:42 +04:00
}
close ( done )
} ( )
select {
case <- time . After ( 5 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build with adding to workdir timed out" )
2014-09-22 18:51:42 +04:00
case <- done :
2014-05-23 02:12:41 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddSingleFileToExistDir ( c * check . C ) {
2014-09-22 19:24:14 +04:00
name := "testaddsinglefiletoexistdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 19:24:14 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 19:24:14 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-04-09 18:21:22 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyAddMultipleFiles ( c * check . C ) {
2015-02-26 05:08:17 +03:00
server , err := fakeStorage ( map [ string ] string {
"robots.txt" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-26 05:08:17 +03:00
}
defer server . Close ( )
2014-10-02 22:33:12 +04:00
name := "testcopymultiplefilestofile"
defer deleteImages ( name )
2015-02-26 05:08:17 +03:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
2014-10-02 22:33:12 +04:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
RUN chown - R dockerio . dockerio / exists
COPY test_file1 test_file2 / exists /
2015-02-26 05:08:17 +03:00
ADD test_file3 test_file4 % s / robots . txt / exists /
2014-10-02 22:33:12 +04:00
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 ' ]
2014-09-16 20:58:20 +04:00
2014-10-02 22:33:12 +04:00
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 ' ]
2014-09-16 20:58:20 +04:00
2014-10-02 22:33:12 +04:00
RUN [ $ ( ls - l / exists / exists_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ]
2015-02-19 13:01:27 +03:00
` , server . URL ( ) ) ,
2014-10-02 22:33:12 +04:00
map [ string ] string {
"test_file1" : "test1" ,
"test_file2" : "test2" ,
"test_file3" : "test3" ,
"test_file4" : "test4" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-02 22:33:12 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-02 22:33:12 +04:00
}
2014-09-16 20:58:20 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddMultipleFilesToFile ( c * check . C ) {
2014-09-16 20:58:20 +04:00
name := "testaddmultiplefilestofile"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
ADD file1 . txt file2 . txt test
2014-12-27 03:30:34 +03:00
` ,
2014-09-16 20:58:20 +04:00
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-16 20:58:20 +04:00
}
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-09-16 20:58:20 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildJSONAddMultipleFilesToFile ( c * check . C ) {
2014-12-27 03:30:34 +03:00
name := "testjsonaddmultiplefilestofile"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
ADD [ "file1.txt" , "file2.txt" , "test" ]
` ,
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-27 03:30:34 +03:00
}
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-12-27 03:30:34 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddMultipleFilesToFileWild ( c * check . C ) {
2014-09-22 17:41:02 +04:00
name := "testaddmultiplefilestofilewild"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
ADD file * . txt test
2014-12-27 03:30:34 +03:00
` ,
2014-09-22 17:41:02 +04:00
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-09-22 17:41:02 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildJSONAddMultipleFilesToFileWild ( c * check . C ) {
2014-12-27 03:30:34 +03:00
name := "testjsonaddmultiplefilestofilewild"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
ADD [ "file*.txt" , "test" ]
` ,
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-27 03:30:34 +03:00
}
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-12-27 03:30:34 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyMultipleFilesToFile ( c * check . C ) {
2014-09-16 20:58:20 +04:00
name := "testcopymultiplefilestofile"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
COPY file1 . txt file2 . txt test
2014-12-27 03:30:34 +03:00
` ,
2014-09-16 20:58:20 +04:00
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-16 20:58:20 +04:00
}
expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-09-16 20:58:20 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildJSONCopyMultipleFilesToFile ( c * check . C ) {
2014-12-27 03:30:34 +03:00
name := "testjsoncopymultiplefilestofile"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
COPY [ "file1.txt" , "file2.txt" , "test" ]
` ,
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-27 03:30:34 +03:00
}
expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-12-27 03:30:34 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddFileWithWhitespace ( c * check . C ) {
2014-10-06 14:15:09 +04:00
name := "testaddfilewithwhitespace"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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" ]
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" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyFileWithWhitespace ( c * check . C ) {
2014-10-06 14:15:09 +04:00
name := "testcopyfilewithwhitespace"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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 ' ] ` ,
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" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddMultipleFilesToFileWithWhitespace ( c * check . C ) {
2014-10-06 14:15:09 +04:00
name := "testaddmultiplefilestofilewithwhitespace"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
ADD [ "test file1" , "test file2" , "test" ]
2014-12-27 03:30:34 +03:00
` ,
2014-10-06 14:15:09 +04:00
map [ string ] string {
"test file1" : "test1" ,
"test file2" : "test2" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
expected := "When using ADD with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-10-06 14:15:09 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyMultipleFilesToFileWithWhitespace ( c * check . C ) {
2014-10-06 14:15:09 +04:00
name := "testcopymultiplefilestofilewithwhitespace"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
COPY [ "test file1" , "test file2" , "test" ]
` ,
map [ string ] string {
"test file1" : "test1" ,
"test file2" : "test2" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 14:15:09 +04:00
}
expected := "When using COPY with more than one source file, the destination must be a directory and end with a /"
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain %q) got:\n%v" , expected , err )
2014-10-06 14:15:09 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyWildcard ( c * check . C ) {
2014-09-22 17:41:02 +04:00
name := "testcopywildcard"
defer deleteImages ( name )
server , err := fakeStorage ( map [ string ] string {
"robots.txt" : "hello" ,
"index.html" : "world" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-09-22 17:41:02 +04:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
COPY file * . txt / tmp /
RUN ls / tmp / file1 . txt / tmp / file2 . txt
RUN mkdir / tmp1
COPY dir * / tmp1 /
RUN ls / tmp1 / dirt / tmp1 / nested_file / tmp1 / nested_dir / nest_nest_file
RUN mkdir / tmp2
ADD dir / * dir % s / robots . txt / tmp2 /
RUN ls / tmp2 / nest_nest_file / tmp2 / robots . txt
2015-02-19 13:01:27 +03:00
` , server . URL ( ) ) ,
2014-09-22 17:41:02 +04:00
map [ string ] string {
"file1.txt" : "test1" ,
"file2.txt" : "test2" ,
"dir/nested_file" : "nested file" ,
"dir/nested_dir/nest_nest_file" : "2 times nested" ,
"dirt" : "dirty" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
// Now make sure we use a cache the 2nd time
id2 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "didn't use the cache" )
2014-09-22 17:41:02 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyWildcardNoFind ( c * check . C ) {
2014-09-22 17:41:02 +04:00
name := "testcopywildcardnofind"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
COPY file * . txt / tmp /
` , nil )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
_ , err = buildImageFromContext ( name , ctx , true )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "should have failed to find a file" )
2014-09-22 17:41:02 +04:00
}
if ! strings . Contains ( err . Error ( ) , "No source files were specified" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about no source files" , err )
2014-09-22 17:41:02 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyWildcardCache ( c * check . C ) {
2014-09-22 17:41:02 +04:00
name := "testcopywildcardcache"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
2014-09-30 00:35:09 +04:00
COPY file1 . txt / tmp / ` ,
2014-09-22 17:41:02 +04:00
map [ string ] string {
"file1.txt" : "test1" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
2014-09-30 00:35:09 +04:00
// Now make sure we use a cache the 2nd time even with wild cards.
// Use the same context so the file is the same and the checksum will match
ctx . Add ( "Dockerfile" , ` FROM busybox
COPY file * . txt / tmp / ` )
2014-09-22 17:41:02 +04:00
2014-09-30 00:35:09 +04:00
id2 , err := buildImageFromContext ( name , ctx , true )
2014-09-22 17:41:02 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 17:41:02 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "didn't use the cache" )
2014-09-22 17:41:02 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddSingleFileToNonExistingDir ( c * check . C ) {
2014-10-14 22:47:01 +04:00
name := "testaddsinglefiletononexistingdir"
2014-09-22 19:41:13 +04:00
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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_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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 19:41:13 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 19:41:13 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-04-09 18:21:22 +04:00
}
2014-10-14 22:17:41 +04:00
2014-04-09 18:21:22 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddDirContentToRoot ( c * check . C ) {
2014-09-22 20:47:01 +04:00
name := "testadddircontenttoroot"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 20:47:01 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 20:47:01 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-04-09 18:21:22 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddDirContentToExistingDir ( c * check . C ) {
2014-10-14 22:47:01 +04:00
name := "testadddircontenttoexistingdir"
2014-09-22 21:21:39 +04:00
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 21:21:39 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 21:21:39 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-04-09 18:21:22 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddWholeDirToRoot ( c * check . C ) {
2014-09-22 21:36:43 +04:00
name := "testaddwholedirtoroot"
defer deleteImages ( name )
2015-03-04 05:40:16 +03:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
2014-09-22 21:36:43 +04:00
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 / test_dir
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 ' ]
2015-03-04 05:40:16 +03:00
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ,
2014-09-22 21:36:43 +04:00
map [ string ] string {
"test_dir/test_file" : "test1" ,
} )
2014-09-17 20:34:45 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 22:29:11 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 21:36:43 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 22:29:11 +04:00
}
2014-04-09 18:21:22 +04:00
}
2014-09-22 21:26:51 +04:00
// Testing #5941
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddEtcToRoot ( c * check . C ) {
2014-09-22 21:26:51 +04:00
name := "testaddetctoroot"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
ADD . / ` ,
map [ string ] string {
"etc/test_file" : "test1" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-22 21:26:51 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-09-22 21:26:51 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-21 00:39:46 +04:00
}
}
2014-12-03 05:45:07 +03:00
// Testing #9401
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddPreservesFilesSpecialBits ( c * check . C ) {
2014-12-03 05:45:07 +03:00
name := "testaddpreservesfilesspecialbits"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 05:45:07 +03:00
}
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 05:45:07 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopySingleFileToRoot ( c * check . C ) {
2014-10-14 21:07:04 +04:00
name := "testcopysinglefiletoroot"
defer deleteImages ( name )
2015-03-04 05:40:16 +03:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
2014-10-14 21:07:04 +04:00
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_file /
RUN [ $ ( ls - l / test_file | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
2015-03-04 05:40:16 +03:00
RUN [ $ ( ls - l / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ,
2014-10-14 21:07:04 +04:00
map [ string ] string {
"test_file" : "test1" ,
} )
2014-05-28 21:53:16 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:07:04 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
// Issue #3960: "ADD src ." hangs - adapted for COPY
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopySingleFileToWorkdir ( c * check . C ) {
2014-10-14 21:12:11 +04:00
name := "testcopysinglefiletoworkdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
COPY test_file . ` ,
map [ string ] string {
"test_file" : "test1" ,
} )
2014-05-28 21:53:16 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:12:11 +04:00
done := make ( chan struct { } )
go func ( ) {
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:12:11 +04:00
}
close ( done )
} ( )
select {
case <- time . After ( 5 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build with adding to workdir timed out" )
2014-10-14 21:12:11 +04:00
case <- done :
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopySingleFileToExistDir ( c * check . C ) {
2014-10-14 21:15:45 +04:00
name := "testcopysinglefiletoexistdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:15:45 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:15:45 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopySingleFileToNonExistDir ( c * check . C ) {
2014-10-14 21:19:45 +04:00
name := "testcopysinglefiletononexistdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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_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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:19:45 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:19:45 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyDirContentToRoot ( c * check . C ) {
2014-10-14 21:22:06 +04:00
name := "testcopydircontenttoroot"
defer deleteImages ( name )
ctx , err := fakeContext ( ` 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:22:06 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:22:06 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyDirContentToExistDir ( c * check . C ) {
2014-10-14 21:26:20 +04:00
name := "testcopydircontenttoexistdir"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM busybox
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
RUN mkdir / exists
RUN touch / exists / exists_file
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:26:20 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:26:20 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyWholeDirToRoot ( c * check . C ) {
2014-10-14 21:29:22 +04:00
name := "testcopywholedirtoroot"
defer deleteImages ( name )
2015-03-04 05:40:16 +03:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM busybox
2014-10-14 21:29:22 +04:00
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 / test_dir
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 ' ]
2015-03-04 05:40:16 +03:00
RUN [ $ ( ls - l / test_dir / test_file | awk ' { print $ 1 } ' ) = ' % s ' ]
RUN [ $ ( ls - l / exists | awk ' { print $ 3 ":" $ 4 } ' ) = ' dockerio : dockerio ' ] ` , expectedFileChmod ) ,
2014-10-14 21:29:22 +04:00
map [ string ] string {
"test_dir/test_file" : "test1" ,
} )
2014-09-17 20:34:45 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:29:22 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyEtcToRoot ( c * check . C ) {
2014-10-14 21:32:00 +04:00
name := "testcopyetctoroot"
defer deleteImages ( name )
ctx , err := fakeContext ( ` FROM scratch
COPY . / ` ,
map [ string ] string {
"etc/test_file" : "test1" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 21:32:00 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-10-14 21:32:00 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyDisallowRemote ( c * check . C ) {
2014-10-14 21:37:05 +04:00
name := "testcopydisallowremote"
defer deleteImages ( name )
_ , out , err := buildImageWithOut ( name , ` FROM scratch
COPY https : //index.docker.io/robots.txt /`,
true )
if err == nil || ! strings . Contains ( out , "Source can't be a URL for COPY" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error should be about disallowed remote source, got err: %s, out: %q" , err , out )
2014-05-28 21:53:16 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddBadLinks ( c * check . C ) {
2014-11-27 23:14:15 +03:00
const (
dockerfile = `
FROM scratch
ADD links . tar /
ADD foo . txt / symlink /
`
targetFile = "foo.txt"
)
var (
name = "test-link-absolute"
)
defer deleteImages ( name )
ctx , err := fakeContext ( dockerfile , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
defer ctx . Close ( )
tempDir , err := ioutil . TempDir ( "" , "test-link-absolute-temp-" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to create temporary directory: %s" , tempDir )
2014-11-27 23:14:15 +03:00
}
defer os . RemoveAll ( tempDir )
2015-02-18 10:20:20 +03:00
var symlinkTarget string
if runtime . GOOS == "windows" {
var driveLetter string
if abs , err := filepath . Abs ( tempDir ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-18 10:20:20 +03:00
} else {
driveLetter = abs [ : 1 ]
}
tempDirWithoutDrive := tempDir [ 2 : ]
symlinkTarget = fmt . Sprintf ( ` %s:\..\..\..\..\..\..\..\..\..\..\..\..%s ` , driveLetter , tempDirWithoutDrive )
} else {
symlinkTarget = fmt . Sprintf ( "/../../../../../../../../../../../..%s" , tempDir )
}
2014-11-27 23:14:15 +03:00
tarPath := filepath . Join ( ctx . Dir , "links.tar" )
nonExistingFile := filepath . Join ( tempDir , targetFile )
fooPath := filepath . Join ( ctx . Dir , targetFile )
tarOut , err := os . Create ( tarPath )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
tarWriter := tar . NewWriter ( tarOut )
header := & tar . Header {
Name : "symlink" ,
Typeflag : tar . TypeSymlink ,
Linkname : symlinkTarget ,
Mode : 0755 ,
Uid : 0 ,
Gid : 0 ,
}
err = tarWriter . WriteHeader ( header )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
tarWriter . Close ( )
tarOut . Close ( )
foo , err := os . Create ( fooPath )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
defer foo . Close ( )
if _ , err := foo . WriteString ( "test" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:14:15 +03:00
}
if _ , err := os . Stat ( nonExistingFile ) ; err == nil || err != nil && ! os . IsNotExist ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s shouldn't have been written and it shouldn't exist" , nonExistingFile )
2014-11-27 23:14:15 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddBadLinksVolume ( c * check . C ) {
2014-11-27 23:39:43 +03:00
const (
dockerfileTemplate = `
FROM busybox
RUN ln - s / . . / . . / . . / . . / . . / . . / . . / . . / % s / x
VOLUME / x
ADD foo . txt / x / `
targetFile = "foo.txt"
)
var (
name = "test-link-absolute-volume"
dockerfile = ""
)
defer deleteImages ( name )
tempDir , err := ioutil . TempDir ( "" , "test-link-absolute-volume-temp-" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to create temporary directory: %s" , tempDir )
2014-11-27 23:39:43 +03:00
}
defer os . RemoveAll ( tempDir )
dockerfile = fmt . Sprintf ( dockerfileTemplate , tempDir )
nonExistingFile := filepath . Join ( tempDir , targetFile )
ctx , err := fakeContext ( dockerfile , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:39:43 +03:00
}
defer ctx . Close ( )
fooPath := filepath . Join ( ctx . Dir , targetFile )
foo , err := os . Create ( fooPath )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:39:43 +03:00
}
defer foo . Close ( )
if _ , err := foo . WriteString ( "test" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:39:43 +03:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-27 23:39:43 +03:00
}
if _ , err := os . Stat ( nonExistingFile ) ; err == nil || err != nil && ! os . IsNotExist ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s shouldn't have been written and it shouldn't exist" , nonExistingFile )
2014-11-27 23:39:43 +03:00
}
}
2014-05-13 22:49:12 +04:00
// Issue #5270 - ensure we throw a better error than "unexpected EOF"
// when we can't access files in the context.
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithInaccessibleFilesInContext ( c * check . C ) {
testRequires ( c , UnixCli ) // test uses chown/chmod: not available on windows
2015-02-20 12:37:27 +03:00
2014-05-13 22:49:12 +04:00
{
2014-09-24 16:42:17 +04:00
name := "testbuildinaccessiblefiles"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nADD . /foo/" , map [ string ] string { "fileWithoutReadAccess" : "foo" } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:42:17 +04:00
}
defer ctx . Close ( )
2014-05-13 22:49:12 +04:00
// This is used to ensure we detect inaccessible files early during build in the cli client
2014-09-24 16:42:17 +04:00
pathToFileWithoutReadAccess := filepath . Join ( ctx . Dir , "fileWithoutReadAccess" )
2014-05-13 22:49:12 +04:00
2014-10-15 00:51:12 +04:00
if err = os . Chown ( pathToFileWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chown file to root: %s" , err )
2014-10-15 00:51:12 +04:00
}
if err = os . Chmod ( pathToFileWithoutReadAccess , 0700 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chmod file to 700: %s" , err )
2014-10-15 00:51:12 +04:00
}
2014-09-24 16:42:17 +04:00
buildCmd := exec . Command ( "su" , "unprivilegeduser" , "-c" , fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) )
buildCmd . Dir = ctx . Dir
2014-10-15 00:51:12 +04:00
out , _ , err := runCommandWithOutput ( buildCmd )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build should have failed: %s %s" , err , out )
2014-05-13 22:49:12 +04:00
}
// check if we've detected the failure before we started building
if ! strings . Contains ( out , "no permission to read from " ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "output should've contained the string: no permission to read from but contained: %s" , out )
2014-05-13 22:49:12 +04:00
}
if ! strings . Contains ( out , "Error checking context is accessible" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "output should've contained the string: Error checking context is accessible" )
2014-05-13 22:49:12 +04:00
}
}
{
2014-09-24 16:42:17 +04:00
name := "testbuildinaccessibledirectory"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nADD . /foo/" , map [ string ] string { "directoryWeCantStat/bar" : "foo" } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:42:17 +04:00
}
defer ctx . Close ( )
2014-05-13 22:49:12 +04:00
// This is used to ensure we detect inaccessible directories early during build in the cli client
2014-09-24 16:42:17 +04:00
pathToDirectoryWithoutReadAccess := filepath . Join ( ctx . Dir , "directoryWeCantStat" )
2014-05-13 22:49:12 +04:00
pathToFileInDirectoryWithoutReadAccess := filepath . Join ( pathToDirectoryWithoutReadAccess , "bar" )
2014-10-15 00:51:12 +04:00
if err = os . Chown ( pathToDirectoryWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chown directory to root: %s" , err )
2014-10-15 00:51:12 +04:00
}
if err = os . Chmod ( pathToDirectoryWithoutReadAccess , 0444 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chmod directory to 444: %s" , err )
2014-10-15 00:51:12 +04:00
}
if err = os . Chmod ( pathToFileInDirectoryWithoutReadAccess , 0700 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chmod file to 700: %s" , err )
2014-10-15 00:51:12 +04:00
}
2014-05-13 22:49:12 +04:00
2014-09-24 16:42:17 +04:00
buildCmd := exec . Command ( "su" , "unprivilegeduser" , "-c" , fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) )
buildCmd . Dir = ctx . Dir
2014-10-15 00:51:12 +04:00
out , _ , err := runCommandWithOutput ( buildCmd )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build should have failed: %s %s" , err , out )
2014-05-13 22:49:12 +04:00
}
// check if we've detected the failure before we started building
if ! strings . Contains ( out , "can't stat" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "output should've contained the string: can't access %s" , out )
2014-05-13 22:49:12 +04:00
}
if ! strings . Contains ( out , "Error checking context is accessible" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "output should've contained the string: Error checking context is accessible" )
2014-05-13 22:49:12 +04:00
}
}
{
2014-09-24 16:42:17 +04:00
name := "testlinksok"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nADD . /foo/" , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:42:17 +04:00
}
defer ctx . Close ( )
2014-11-17 19:05:49 +03:00
target := "../../../../../../../../../../../../../../../../../../../azA"
if err := os . Symlink ( filepath . Join ( ctx . Dir , "g" ) , target ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:42:17 +04:00
}
2014-11-17 19:05:49 +03:00
defer os . Remove ( target )
2014-05-13 22:49:12 +04:00
// This is used to ensure we don't follow links when checking if everything in the context is accessible
// This test doesn't require that we run commands as an unprivileged user
2014-09-24 16:42:17 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-13 22:49:12 +04:00
}
2014-07-07 16:23:07 +04:00
}
{
2014-09-24 16:42:17 +04:00
name := "testbuildignoredinaccessible"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nADD . /foo/" ,
map [ string ] string {
"directoryWeCantStat/bar" : "foo" ,
".dockerignore" : "directoryWeCantStat" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:42:17 +04:00
}
defer ctx . Close ( )
2014-07-07 16:23:07 +04:00
// This is used to ensure we don't try to add inaccessible files when they are ignored by a .dockerignore pattern
2014-09-24 16:42:17 +04:00
pathToDirectoryWithoutReadAccess := filepath . Join ( ctx . Dir , "directoryWeCantStat" )
2014-07-07 16:23:07 +04:00
pathToFileInDirectoryWithoutReadAccess := filepath . Join ( pathToDirectoryWithoutReadAccess , "bar" )
2014-10-15 00:51:12 +04:00
if err = os . Chown ( pathToDirectoryWithoutReadAccess , 0 , 0 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chown directory to root: %s" , err )
2014-10-15 00:51:12 +04:00
}
if err = os . Chmod ( pathToDirectoryWithoutReadAccess , 0444 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chmod directory to 755: %s" , err )
2014-10-15 00:51:12 +04:00
}
if err = os . Chmod ( pathToFileInDirectoryWithoutReadAccess , 0700 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to chmod file to 444: %s" , err )
2014-10-15 00:51:12 +04:00
}
2014-07-07 16:23:07 +04:00
2014-09-24 16:42:17 +04:00
buildCmd := exec . Command ( "su" , "unprivilegeduser" , "-c" , fmt . Sprintf ( "%s build -t %s ." , dockerBinary , name ) )
buildCmd . Dir = ctx . Dir
2014-10-15 00:51:12 +04:00
if out , _ , err := runCommandWithOutput ( buildCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build should have worked: %s %s" , err , out )
2014-07-07 16:23:07 +04:00
}
2014-05-13 22:49:12 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildForceRm ( c * check . C ) {
2014-05-19 20:46:25 +04:00
containerCountBefore , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 20:46:25 +04:00
}
2014-09-24 12:29:27 +04:00
name := "testbuildforcerm"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nRUN true\nRUN thiswillfail" , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 12:29:27 +04:00
}
defer ctx . Close ( )
2014-05-19 20:46:25 +04:00
2014-09-24 12:29:27 +04:00
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , name , "--force-rm" , "." )
buildCmd . Dir = ctx . Dir
2014-10-15 00:51:12 +04:00
if out , _ , err := runCommandWithOutput ( buildCmd ) ; err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to build the image: %s, %v" , out , err )
2014-05-19 20:46:25 +04:00
}
containerCountAfter , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 20:46:25 +04:00
}
if containerCountBefore != containerCountAfter {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "--force-rm shouldn't have left containers behind" )
2014-05-19 20:46:25 +04:00
}
}
2015-03-11 01:10:00 +03:00
// Test that an infinite sleep during a build is killed if the client disconnects.
// This test is fairly hairy because there are lots of ways to race.
// Strategy:
// * Monitor the output of docker events starting from before
// * Run a 1-year-long sleep from a docker build.
// * When docker events sees container start, close the "docker build" command
// * Wait for docker events to emit a dying event.
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCancelationKillsSleep ( c * check . C ) {
2015-04-06 17:28:39 +03:00
var wg sync . WaitGroup
defer wg . Wait ( )
2015-03-11 01:10:00 +03:00
name := "testbuildcancelation"
defer deleteImages ( name )
// (Note: one year, will never finish)
ctx , err := fakeContext ( "FROM busybox\nRUN sleep 31536000" , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-11 01:10:00 +03:00
}
defer ctx . Close ( )
finish := make ( chan struct { } )
defer close ( finish )
eventStart := make ( chan struct { } )
eventDie := make ( chan struct { } )
2015-04-06 17:28:39 +03:00
containerID := make ( chan string )
2015-03-11 01:10:00 +03:00
2015-04-18 19:46:47 +03:00
startEpoch := daemonTime ( c ) . Unix ( )
2015-03-11 01:10:00 +03:00
wg . Add ( 1 )
2015-04-06 17:28:39 +03:00
// Goroutine responsible for watching start/die events from `docker events`
2015-03-11 01:10:00 +03:00
go func ( ) {
defer wg . Done ( )
// Watch for events since epoch.
2015-04-06 17:28:39 +03:00
eventsCmd := exec . Command (
dockerBinary , "events" ,
"--since" , strconv . FormatInt ( startEpoch , 10 ) )
2015-03-11 01:10:00 +03:00
stdout , err := eventsCmd . StdoutPipe ( )
err = eventsCmd . Start ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to start 'docker events': %s" , err )
2015-03-11 01:10:00 +03:00
}
go func ( ) {
<- finish
eventsCmd . Process . Kill ( )
} ( )
2015-04-06 17:28:39 +03:00
cid := <- containerID
2015-04-01 17:08:00 +03:00
2015-04-06 17:28:39 +03:00
matchStart := regexp . MustCompile ( cid + ` (.*) start$ ` )
matchDie := regexp . MustCompile ( cid + ` (.*) die$ ` )
2015-03-11 01:10:00 +03:00
//
// Read lines of `docker events` looking for container start and stop.
//
scanner := bufio . NewScanner ( stdout )
for scanner . Scan ( ) {
2015-04-06 17:28:39 +03:00
switch {
case matchStart . MatchString ( scanner . Text ( ) ) :
2015-03-11 01:10:00 +03:00
close ( eventStart )
2015-04-06 17:28:39 +03:00
case matchDie . MatchString ( scanner . Text ( ) ) :
2015-03-11 01:10:00 +03:00
close ( eventDie )
}
}
err = eventsCmd . Wait ( )
if err != nil && ! IsKilled ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "docker events had bad exit status: %s" , err )
2015-03-11 01:10:00 +03:00
}
} ( )
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , name , "." )
buildCmd . Dir = ctx . Dir
2015-04-06 17:28:39 +03:00
stdoutBuild , err := buildCmd . StdoutPipe ( )
2015-03-11 01:10:00 +03:00
err = buildCmd . Start ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to run build: %s" , err )
2015-03-11 01:10:00 +03:00
}
2015-04-06 17:28:39 +03:00
matchCID := regexp . MustCompile ( "Running in " )
scanner := bufio . NewScanner ( stdoutBuild )
for scanner . Scan ( ) {
line := scanner . Text ( )
if ok := matchCID . MatchString ( line ) ; ok {
containerID <- line [ len ( line ) - 12 : ]
break
}
}
2015-03-11 01:10:00 +03:00
select {
2015-04-06 17:28:39 +03:00
case <- time . After ( 5 * time . Second ) :
2015-04-18 19:46:47 +03:00
c . Fatal ( "failed to observe build container start in timely fashion" )
2015-03-11 01:10:00 +03:00
case <- eventStart :
// Proceeds from here when we see the container fly past in the
// output of "docker events".
// Now we know the container is running.
}
// Send a kill to the `docker build` command.
// Causes the underlying build to be cancelled due to socket close.
err = buildCmd . Process . Kill ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "error killing build command: %s" , err )
2015-03-11 01:10:00 +03:00
}
// Get the exit status of `docker build`, check it exited because killed.
err = buildCmd . Wait ( )
if err != nil && ! IsKilled ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "wait failed during build run: %T %s" , err , err )
2015-03-11 01:10:00 +03:00
}
select {
2015-04-06 17:28:39 +03:00
case <- time . After ( 5 * time . Second ) :
2015-03-11 01:10:00 +03:00
// If we don't get here in a timely fashion, it wasn't killed.
2015-04-18 19:46:47 +03:00
c . Fatal ( "container cancel did not succeed" )
2015-03-11 01:10:00 +03:00
case <- eventDie :
// We saw the container shut down in the `docker events` stream,
// as expected.
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRm ( c * check . C ) {
2014-09-24 13:15:55 +04:00
name := "testbuildrm"
defer deleteImages ( name )
ctx , err := fakeContext ( "FROM scratch\nADD foo /\nADD foo /" , map [ string ] string { "foo" : "bar" } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 13:15:55 +04:00
}
defer ctx . Close ( )
2014-05-19 22:21:25 +04:00
{
containerCountBefore , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "--rm" , "-t" , name , "." )
2014-05-19 22:21:25 +04:00
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "failed to build the image" , out )
2014-05-19 22:21:25 +04:00
}
containerCountAfter , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
if containerCountBefore != containerCountAfter {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "-rm shouldn't have left containers behind" )
2014-05-19 22:21:25 +04:00
}
2014-09-24 13:15:55 +04:00
deleteImages ( name )
2014-05-19 22:21:25 +04:00
}
{
containerCountBefore , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , name , "." )
2014-05-19 22:21:25 +04:00
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "failed to build the image" , out )
2014-05-19 22:21:25 +04:00
}
containerCountAfter , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
if containerCountBefore != containerCountAfter {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "--rm shouldn't have left containers behind" )
2014-05-19 22:21:25 +04:00
}
2014-09-24 13:15:55 +04:00
deleteImages ( name )
2014-05-19 22:21:25 +04:00
}
{
containerCountBefore , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "--rm=false" , "-t" , name , "." )
2014-05-19 22:21:25 +04:00
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "failed to build the image" , out )
2014-05-19 22:21:25 +04:00
}
containerCountAfter , err := getContainerCount ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to get the container count: %s" , err )
2014-05-19 22:21:25 +04:00
}
if containerCountBefore == containerCountAfter {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "--rm=false should have left containers behind" )
2014-05-19 22:21:25 +04:00
}
2014-09-24 13:15:55 +04:00
deleteImages ( name )
2014-05-19 22:21:25 +04:00
}
}
2014-06-17 10:04:25 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithVolumes ( c * check . C ) {
2014-07-09 00:27:58 +04:00
var (
result map [ string ] map [ string ] struct { }
name = "testbuildvolumes"
emptyMap = make ( map [ string ] struct { } )
2014-09-11 17:27:51 +04:00
expected = map [ string ] map [ string ] struct { } {
"/test1" : emptyMap ,
"/test2" : emptyMap ,
"/test3" : emptyMap ,
"/test4" : emptyMap ,
"/test5" : emptyMap ,
"/test6" : emptyMap ,
"[/test7" : emptyMap ,
"/test8]" : emptyMap ,
}
2014-07-09 00:27:58 +04:00
)
2014-05-31 16:43:32 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
VOLUME / test1
2014-09-11 17:27:51 +04:00
VOLUME / test2
VOLUME / test3 / test4
VOLUME [ "/test5" , "/test6" ]
VOLUME [ / test7 / test8 ]
` ,
2014-05-31 16:43:32 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
2014-07-09 00:27:58 +04:00
res , err := inspectFieldJSON ( name , "Config.Volumes" )
2014-05-31 16:43:32 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
2014-07-09 00:27:58 +04:00
err = unmarshalJSON ( [ ] byte ( res ) , & result )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
2014-07-09 00:27:58 +04:00
2014-12-04 04:52:06 +03:00
equal := reflect . DeepEqual ( & result , & expected )
2014-07-09 00:27:58 +04:00
if ! equal {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Volumes %s, expected %s" , result , expected )
2014-07-09 00:27:58 +04:00
}
2014-05-22 23:16:27 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildMaintainer ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildmaintainer"
expected := "dockerio"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
MAINTAINER dockerio ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Author" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Maintainer %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-25 22:26:50 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildUser ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuilduser"
expected := "dockerio"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
2014-05-25 22:28:14 +04:00
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
USER dockerio
2014-05-31 16:43:32 +04:00
RUN [ $ ( whoami ) = ' dockerio ' ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.User" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "User %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-25 22:28:14 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRelativeWorkdir ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildrelativeworkdir"
expected := "/test2/test3"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
2014-05-25 22:41:47 +04:00
RUN [ "$PWD" = '/' ]
WORKDIR test1
RUN [ "$PWD" = ' / test1 ' ]
WORKDIR / test2
RUN [ "$PWD" = ' / test2 ' ]
WORKDIR test3
2014-05-31 16:43:32 +04:00
RUN [ "$PWD" = ' / test2 / test3 ' ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.WorkingDir" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Workdir %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-25 22:41:47 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWorkdirWithEnvVariables ( c * check . C ) {
2014-07-15 21:17:20 +04:00
name := "testbuildworkdirwithenvvariables"
2015-01-29 05:28:48 +03:00
expected := "/test1/test2"
2014-07-15 21:17:20 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
ENV DIRPATH / test1
ENV SUBDIRNAME test2
WORKDIR $ DIRPATH
WORKDIR $ SUBDIRNAME / $ MISSING_VAR ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-15 21:17:20 +04:00
}
res , err := inspectField ( name , "Config.WorkingDir" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-15 21:17:20 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Workdir %s, expected %s" , res , expected )
2014-07-15 21:17:20 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRelativeCopy ( c * check . C ) {
2014-12-12 21:32:11 +03:00
name := "testbuildrelativecopy"
defer deleteImages ( name )
dockerfile := `
FROM busybox
WORKDIR / test1
WORKDIR test2
RUN [ "$PWD" = ' / test1 / test2 ' ]
COPY foo . /
RUN [ "$(cat /test1/test2/foo)" = ' hello ' ]
ADD foo . / bar / baz
RUN [ "$(cat /test1/test2/bar/baz)" = ' hello ' ]
COPY foo . / bar / baz2
RUN [ "$(cat /test1/test2/bar/baz2)" = ' hello ' ]
WORKDIR . .
COPY foo . /
RUN [ "$(cat /test1/foo)" = ' hello ' ]
COPY foo / test3 /
RUN [ "$(cat /test3/foo)" = ' hello ' ]
WORKDIR / test4
COPY . .
RUN [ "$(cat /test4/foo)" = ' hello ' ]
WORKDIR / test5 / test6
COPY foo . . /
RUN [ "$(cat /test5/foo)" = ' hello ' ]
`
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"foo" : "hello" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-12 21:32:11 +03:00
}
_ , err = buildImageFromContext ( name , ctx , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-12 21:32:11 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnv ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildenv"
2014-08-13 14:07:41 +04:00
expected := "[PATH=/test:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PORT=2375]"
2014-05-31 16:43:32 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
2014-08-13 14:07:41 +04:00
ENV PATH / test : $ PATH
2014-06-03 23:44:20 +04:00
ENV PORT 2375
RUN [ $ ( env | grep PORT ) = ' PORT = 2375 ' ] ` ,
2014-05-31 16:43:32 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.Env" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Env %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-26 23:09:33 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildContextCleanup ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-19 07:06:23 +03:00
2014-09-02 18:35:25 +04:00
name := "testbuildcontextcleanup"
defer deleteImages ( name )
entries , err := ioutil . ReadDir ( "/var/lib/docker/tmp" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-02 18:35:25 +04:00
}
_ , err = buildImage ( name ,
` FROM scratch
ENTRYPOINT [ "/bin/echo" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-02 18:35:25 +04:00
}
entriesFinal , err := ioutil . ReadDir ( "/var/lib/docker/tmp" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-02 18:35:25 +04:00
}
if err = compareDirectoryEntries ( entries , entriesFinal ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "context should have been deleted, but wasn't" )
2014-09-02 18:35:25 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildContextCleanupFailedBuild ( c * check . C ) {
testRequires ( c , SameHostDaemon )
2015-02-19 07:06:23 +03:00
2014-09-15 17:01:23 +04:00
name := "testbuildcontextcleanup"
defer deleteImages ( name )
entries , err := ioutil . ReadDir ( "/var/lib/docker/tmp" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-15 17:01:23 +04:00
}
_ , err = buildImage ( name ,
` FROM scratch
RUN / non / existing / command ` ,
true )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected build to fail, but it didn't" )
2014-09-15 17:01:23 +04:00
}
entriesFinal , err := ioutil . ReadDir ( "/var/lib/docker/tmp" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to list contents of tmp dir: %s" , err )
2014-09-15 17:01:23 +04:00
}
if err = compareDirectoryEntries ( entries , entriesFinal ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "context should have been deleted, but wasn't" )
2014-09-15 17:01:23 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCmd ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildcmd"
2015-03-26 22:43:00 +03:00
expected := "{[/bin/echo Hello World]}"
2014-05-31 16:43:32 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
CMD [ "/bin/echo" , "Hello World" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Cmd %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-26 23:15:40 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExpose ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildexpose"
2015-03-26 22:43:00 +03:00
expected := "map[2375/tcp:{}]"
2014-05-31 16:43:32 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
2014-06-03 23:44:20 +04:00
EXPOSE 2375 ` ,
2014-05-31 16:43:32 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Exposed ports %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-05-26 23:23:46 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExposeMorePorts ( c * check . C ) {
2014-11-13 06:14:15 +03:00
// start building docker file with a large number of ports
portList := make ( [ ] string , 50 )
line := make ( [ ] string , 100 )
expectedPorts := make ( [ ] int , len ( portList ) * len ( line ) )
for i := 0 ; i < len ( portList ) ; i ++ {
for j := 0 ; j < len ( line ) ; j ++ {
p := i * len ( line ) + j + 1
line [ j ] = strconv . Itoa ( p )
expectedPorts [ p - 1 ] = p
}
if i == len ( portList ) - 1 {
portList [ i ] = strings . Join ( line , " " )
} else {
portList [ i ] = strings . Join ( line , " " ) + ` \ `
}
}
dockerfile := ` FROM scratch
EXPOSE { { range . } } { { . } }
{ { end } } `
tmpl := template . Must ( template . New ( "dockerfile" ) . Parse ( dockerfile ) )
buf := bytes . NewBuffer ( nil )
tmpl . Execute ( buf , portList )
name := "testbuildexpose"
defer deleteImages ( name )
_ , err := buildImage ( name , buf . String ( ) , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-13 06:14:15 +03:00
}
// check if all the ports are saved inside Config.ExposedPorts
res , err := inspectFieldJSON ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-13 06:14:15 +03:00
}
var exposedPorts map [ string ] interface { }
if err := json . Unmarshal ( [ ] byte ( res ) , & exposedPorts ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-13 06:14:15 +03:00
}
for _ , p := range expectedPorts {
ep := fmt . Sprintf ( "%d/tcp" , p )
if _ , ok := exposedPorts [ ep ] ; ! ok {
2015-04-18 19:46:47 +03:00
c . Errorf ( "Port(%s) is not exposed" , ep )
2014-11-13 06:14:15 +03:00
} else {
delete ( exposedPorts , ep )
}
}
if len ( exposedPorts ) != 0 {
2015-04-18 19:46:47 +03:00
c . Errorf ( "Unexpected extra exposed ports %v" , exposedPorts )
2014-11-13 06:14:15 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExposeOrder ( c * check . C ) {
2014-11-12 17:13:47 +03:00
buildID := func ( name , exposed string ) string {
_ , err := buildImage ( name , fmt . Sprintf ( ` FROM scratch
EXPOSE % s ` , exposed ) , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-12 17:13:47 +03:00
}
id , err := inspectField ( name , "Id" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-11-12 17:13:47 +03:00
}
return id
}
id1 := buildID ( "testbuildexpose1" , "80 2375" )
id2 := buildID ( "testbuildexpose2" , "2375 80" )
defer deleteImages ( "testbuildexpose1" , "testbuildexpose2" )
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Errorf ( "EXPOSE should invalidate the cache only when ports actually changed" )
2014-11-12 17:13:47 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExposeUpperCaseProto ( c * check . C ) {
2015-02-08 02:04:22 +03:00
name := "testbuildexposeuppercaseproto"
2015-03-26 22:43:00 +03:00
expected := "map[5678/udp:{}]"
2015-02-08 02:04:22 +03:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
EXPOSE 5678 / UDP ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-08 02:04:22 +03:00
}
res , err := inspectField ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-08 02:04:22 +03:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Exposed ports %s, expected %s" , res , expected )
2015-02-08 02:04:22 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExposeHostPort ( c * check . C ) {
2015-03-05 05:09:50 +03:00
// start building docker file with ip:hostPort:containerPort
name := "testbuildexpose"
2015-03-26 22:43:00 +03:00
expected := "map[5678/tcp:{}]"
2015-03-05 05:09:50 +03:00
defer deleteImages ( name )
_ , out , err := buildImageWithOut ( name ,
` FROM scratch
EXPOSE 192.168 .1 .2 : 2375 : 5678 ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-05 05:09:50 +03:00
}
if ! strings . Contains ( out , "to map host ports to container ports (ip:hostPort:containerPort) is deprecated." ) {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Missing warning message" )
2015-03-05 05:09:50 +03:00
}
res , err := inspectField ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-05 05:09:50 +03:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Exposed ports %s, expected %s" , res , expected )
2015-03-05 05:09:50 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyEntrypointInheritance ( c * check . C ) {
2014-10-24 04:23:25 +04:00
name := "testbuildentrypointinheritance"
name2 := "testbuildentrypointinheritance2"
defer deleteImages ( name , name2 )
_ , err := buildImage ( name ,
` FROM busybox
ENTRYPOINT [ "/bin/echo" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 04:23:25 +04:00
}
res , err := inspectField ( name , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 04:23:25 +04:00
}
2015-03-26 22:43:00 +03:00
expected := "{[/bin/echo]}"
2014-10-24 04:23:25 +04:00
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-10-24 04:23:25 +04:00
}
_ , err = buildImage ( name2 ,
fmt . Sprintf ( ` FROM % s
ENTRYPOINT [ ] ` , name ) ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 04:23:25 +04:00
}
res , err = inspectField ( name2 , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 04:23:25 +04:00
}
2015-03-26 22:43:00 +03:00
expected = "{[]}"
2014-10-24 04:23:25 +04:00
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-10-24 04:23:25 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyEntrypoint ( c * check . C ) {
2014-05-31 16:43:32 +04:00
name := "testbuildentrypoint"
defer deleteImages ( name )
2015-03-26 22:43:00 +03:00
expected := "{[]}"
2014-09-03 23:17:17 +04:00
2014-05-31 16:43:32 +04:00
_ , err := buildImage ( name ,
2014-09-03 23:17:17 +04:00
` FROM busybox
ENTRYPOINT [ ] ` ,
2014-05-31 16:43:32 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
res , err := inspectField ( name , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-05-31 16:43:32 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-05-31 16:43:32 +04:00
}
2014-09-02 00:33:06 +04:00
2014-09-03 23:17:17 +04:00
}
2014-09-02 00:33:06 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEntrypoint ( c * check . C ) {
2014-09-03 23:17:17 +04:00
name := "testbuildentrypoint"
2015-03-26 22:43:00 +03:00
expected := "{[/bin/echo]}"
2014-09-03 23:17:17 +04:00
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
ENTRYPOINT [ "/bin/echo" ] ` ,
2014-09-02 00:33:06 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-02 00:33:06 +04:00
}
2014-09-03 23:17:17 +04:00
res , err := inspectField ( name , "Config.Entrypoint" )
2014-09-02 00:33:06 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-02 00:33:06 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-09-02 00:33:06 +04:00
}
2014-05-27 08:36:00 +04:00
}
2014-06-17 10:04:25 +04:00
// #6445 ensure ONBUILD triggers aren't committed to grandchildren
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildLimitedInheritence ( c * check . C ) {
2014-07-29 17:01:56 +04:00
var (
out2 , out3 string
)
{
name1 := "testonbuildtrigger1"
dockerfile1 := `
2014-06-17 10:04:25 +04:00
FROM busybox
RUN echo "GRANDPARENT"
ONBUILD RUN echo "ONBUILD PARENT"
2014-07-29 17:01:56 +04:00
`
ctx , err := fakeContext ( dockerfile1 , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-29 17:01:56 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-06-17 10:04:25 +04:00
2015-04-18 19:46:47 +03:00
out1 , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , name1 , "." )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete: %s, %v" , out1 , err )
2014-10-15 00:51:12 +04:00
}
2014-07-29 17:01:56 +04:00
defer deleteImages ( name1 )
2014-06-17 10:04:25 +04:00
}
2014-07-29 17:01:56 +04:00
{
name2 := "testonbuildtrigger2"
dockerfile2 := `
FROM testonbuildtrigger1
`
ctx , err := fakeContext ( dockerfile2 , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-29 17:01:56 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-06-17 10:04:25 +04:00
2015-04-18 19:46:47 +03:00
out2 , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , name2 , "." )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete: %s, %v" , out2 , err )
2014-10-15 00:51:12 +04:00
}
2014-07-29 17:01:56 +04:00
defer deleteImages ( name2 )
2014-06-17 10:04:25 +04:00
}
2014-07-29 17:01:56 +04:00
{
name3 := "testonbuildtrigger3"
dockerfile3 := `
FROM testonbuildtrigger2
`
ctx , err := fakeContext ( dockerfile3 , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-29 17:01:56 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-06-17 10:04:25 +04:00
2015-04-18 19:46:47 +03:00
out3 , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , name3 , "." )
2014-10-15 00:51:12 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete: %s, %v" , out3 , err )
2014-10-15 00:51:12 +04:00
}
2014-07-29 17:01:56 +04:00
defer deleteImages ( name3 )
}
2014-06-17 10:04:25 +04:00
// ONBUILD should be run in second build.
if ! strings . Contains ( out2 , "ONBUILD PARENT" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "ONBUILD instruction did not run in child of ONBUILD parent" )
2014-06-17 10:04:25 +04:00
}
// ONBUILD should *not* be run in third build.
if strings . Contains ( out3 , "ONBUILD PARENT" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "ONBUILD instruction ran in grandchild of ONBUILD parent" )
2014-06-17 10:04:25 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildwithcache"
defer deleteImages ( name )
id1 , err := buildImage ( name ,
` FROM scratch
MAINTAINER dockerio
EXPOSE 5432
ENTRYPOINT [ "/bin/echo" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id2 , err := buildImage ( name ,
` FROM scratch
MAINTAINER dockerio
EXPOSE 5432
ENTRYPOINT [ "/bin/echo" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2014-02-25 20:17:48 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithoutCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildwithoutcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildwithoutcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
id1 , err := buildImage ( name ,
` FROM scratch
MAINTAINER dockerio
EXPOSE 5432
ENTRYPOINT [ "/bin/echo" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImage ( name2 ,
2014-06-01 00:49:50 +04:00
` FROM scratch
MAINTAINER dockerio
EXPOSE 5432
ENTRYPOINT [ "/bin/echo" ] ` ,
false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildConditionalCache ( c * check . C ) {
2015-01-08 17:56:30 +03:00
name := "testbuildconditionalcache"
name2 := "testbuildconditionalcache2"
defer deleteImages ( name , name2 )
dockerfile := `
FROM busybox
ADD foo / tmp / `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"foo" : "hello" ,
} )
2015-02-25 11:53:43 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-25 11:53:43 +03:00
}
defer ctx . Close ( )
2015-01-08 17:56:30 +03:00
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error building #1: %s" , err )
2015-01-08 17:56:30 +03:00
}
if err := ctx . Add ( "foo" , "bye" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error modifying foo: %s" , err )
2015-01-08 17:56:30 +03:00
}
id2 , err := buildImageFromContext ( name , ctx , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error building #2: %s" , err )
2015-01-08 17:56:30 +03:00
}
if id2 == id1 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Should not have used the cache" )
2015-01-08 17:56:30 +03:00
}
id3 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error building #3: %s" , err )
2015-01-08 17:56:30 +03:00
}
if id3 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Should have used the cache" )
2015-01-08 17:56:30 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDLocalFileWithCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddlocalfilewithcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddlocalfilewithcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , true )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDMultipleLocalFileWithCache ( c * check . C ) {
2014-09-16 20:58:20 +04:00
name := "testbuildaddmultiplelocalfilewithcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddmultiplelocalfilewithcache2"
defer deleteImages ( name , name2 )
2014-09-16 20:58:20 +04:00
dockerfile := `
FROM busybox
MAINTAINER dockerio
ADD foo Dockerfile / usr / lib / bla /
RUN [ "$(cat /usr/lib/bla/foo)" = "hello" ] `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"foo" : "hello" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-16 20:58:20 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-16 20:58:20 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , true )
2014-09-16 20:58:20 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-16 20:58:20 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-09-16 20:58:20 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDLocalFileWithoutCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddlocalfilewithoutcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddlocalfilewithoutcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , false )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCopyDirButNotFile ( c * check . C ) {
2014-09-23 23:08:42 +04:00
name := "testbuildcopydirbutnotfile"
2014-11-17 19:05:49 +03:00
name2 := "testbuildcopydirbutnotfile2"
defer deleteImages ( name , name2 )
2014-09-23 23:08:42 +04:00
dockerfile := `
FROM scratch
COPY dir / tmp / `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"dir/foo" : "hello" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 23:08:42 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 23:08:42 +04:00
}
// Check that adding file with similar name doesn't mess with cache
if err := ctx . Add ( "dir_file" , "hello2" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 23:08:42 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , true )
2014-09-23 23:08:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 23:08:42 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but wasn't" )
2014-09-23 23:08:42 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDCurrentDirWithCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddcurrentdirwithcache"
2014-11-17 19:05:49 +03:00
name2 := name + "2"
name3 := name + "3"
name4 := name + "4"
name5 := name + "5"
defer deleteImages ( name , name2 , name3 , name4 , name5 )
2014-06-01 00:49:50 +04:00
dockerfile := `
FROM scratch
MAINTAINER dockerio
ADD . / usr / lib / bla `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"foo" : "hello" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
// Check that adding file invalidate cache of "ADD ."
if err := ctx . Add ( "bar" , "hello2" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , true )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
// Check that changing file invalidate cache of "ADD ."
if err := ctx . Add ( "foo" , "hello1" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id3 , err := buildImageFromContext ( name3 , ctx , true )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id2 == id3 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
// 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id4 , err := buildImageFromContext ( name4 , ctx , true )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id3 == id4 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id5 , err := buildImageFromContext ( name5 , ctx , true )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id4 != id5 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDCurrentDirWithoutCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddcurrentdirwithoutcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddcurrentdirwithoutcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
dockerfile := `
FROM scratch
MAINTAINER dockerio
ADD . / usr / lib / bla `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"foo" : "hello" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , false )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDRemoteFileWithCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddremotefilewithcache"
defer deleteImages ( name )
server , err := fakeStorage ( map [ string ] string {
"baz" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-06-01 00:49:50 +04:00
id1 , err := buildImage ( name ,
fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id2 , err := buildImage ( name ,
fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDRemoteFileWithoutCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddremotefilewithoutcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddremotefilewithoutcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
server , err := fakeStorage ( map [ string ] string {
"baz" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-06-01 00:49:50 +04:00
id1 , err := buildImage ( name ,
fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImage ( name2 ,
2014-06-01 00:49:50 +04:00
fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDRemoteFileMTime ( c * check . C ) {
2014-10-22 22:16:42 +04:00
name := "testbuildaddremotefilemtime"
2014-11-17 19:05:49 +03:00
name2 := name + "2"
name3 := name + "3"
name4 := name + "4"
defer deleteImages ( name , name2 , name3 , name4 )
2014-10-22 22:16:42 +04:00
2015-02-19 13:01:27 +03:00
files := map [ string ] string { "baz" : "hello" }
server , err := fakeStorage ( files )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
defer server . Close ( )
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) , nil )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
defer ctx . Close ( )
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , true )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but wasn't - #1" )
2014-10-22 22:16:42 +04:00
}
2015-02-19 13:01:27 +03:00
// Now create a different server withsame contents (causes different mtim)
2014-10-22 22:16:42 +04:00
// This time the cache should not be used
2015-02-19 13:01:27 +03:00
// allow some time for clock to pass as mtime precision is only 1s
time . Sleep ( 2 * time . Second )
server2 , err := fakeStorage ( files )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
2015-02-19 13:01:27 +03:00
defer server2 . Close ( )
2014-10-22 22:16:42 +04:00
2015-02-19 13:01:27 +03:00
ctx2 , err := fakeContext ( fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
ADD % s / baz / usr / lib / baz / quux ` , server2 . URL ( ) ) , nil )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-19 13:01:27 +03:00
}
defer ctx2 . Close ( )
id3 , err := buildImageFromContext ( name3 , ctx2 , true )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
if id1 == id3 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should not have been used but was" )
2014-10-22 22:16:42 +04:00
}
// And for good measure do it again and make sure cache is used this time
2015-02-19 13:01:27 +03:00
id4 , err := buildImageFromContext ( name4 , ctx2 , true )
2014-10-22 22:16:42 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-22 22:16:42 +04:00
}
if id3 != id4 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but wasn't - #2" )
2014-10-22 22:16:42 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDLocalAndRemoteFilesWithCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddlocalandremotefilewithcache"
defer deleteImages ( name )
server , err := fakeStorage ( map [ string ] string {
"baz" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-06-01 00:49:50 +04:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
ADD foo / usr / lib / bla / bar
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
map [ string ] string {
"foo" : "hello world" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer ctx . Close ( )
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
id2 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been used but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func testContextTar ( c * check . C , compression archive . Compression ) {
2014-09-24 16:55:52 +04:00
ctx , err := fakeContext (
` FROM busybox
ADD foo / foo
CMD [ "cat" , "/foo" ] ` ,
map [ string ] string {
"foo" : "bar" ,
} ,
)
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 16:55:52 +04:00
}
context , err := archive . Tar ( ctx . Dir , compression )
2014-05-10 02:26:41 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to build context tar: %v" , err )
2014-05-10 02:26:41 +04:00
}
2014-09-24 16:55:52 +04:00
name := "contexttar"
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , name , "-" )
defer deleteImages ( name )
2014-05-10 02:26:41 +04:00
buildCmd . Stdin = context
2014-10-15 00:51:12 +04:00
if out , _ , err := runCommandWithOutput ( buildCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete: %v %v" , out , err )
2014-05-10 02:26:41 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildContextTarGzip ( c * check . C ) {
testContextTar ( c , archive . Gzip )
2014-05-10 02:26:41 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildContextTarNoCompression ( c * check . C ) {
testContextTar ( c , archive . Uncompressed )
2014-05-10 02:26:41 +04:00
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildNoContext ( c * check . C ) {
2014-05-10 02:26:41 +04:00
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , "nocontext" , "-" )
buildCmd . Stdin = strings . NewReader ( "FROM busybox\nCMD echo ok\n" )
2014-10-15 00:51:12 +04:00
if out , _ , err := runCommandWithOutput ( buildCmd ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete: %v %v" , out , err )
2014-05-10 02:26:41 +04:00
}
2015-04-18 19:46:47 +03:00
if out , _ := dockerCmd ( c , "run" , "--rm" , "nocontext" ) ; out != "ok\n" {
c . Fatalf ( "run produced invalid output: %q, expected %q" , out , "ok" )
2014-05-10 02:26:41 +04:00
}
deleteImages ( "nocontext" )
}
2014-06-03 01:46:28 +04:00
// TODO: TestCaching
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDLocalAndRemoteFilesWithoutCache ( c * check . C ) {
2014-06-01 00:49:50 +04:00
name := "testbuildaddlocalandremotefilewithoutcache"
2014-11-17 19:05:49 +03:00
name2 := "testbuildaddlocalandremotefilewithoutcache2"
defer deleteImages ( name , name2 )
2014-06-01 00:49:50 +04:00
server , err := fakeStorage ( map [ string ] string {
"baz" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer server . Close ( )
2015-02-19 13:01:27 +03:00
2014-06-01 00:49:50 +04:00
ctx , err := fakeContext ( fmt . Sprintf ( ` FROM scratch
MAINTAINER dockerio
ADD foo / usr / lib / bla / bar
2015-02-19 13:01:27 +03:00
ADD % s / baz / usr / lib / baz / quux ` , server . URL ( ) ) ,
2014-06-01 00:49:50 +04:00
map [ string ] string {
"foo" : "hello world" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
defer ctx . Close ( )
id1 , err := buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
2014-11-17 19:05:49 +03:00
id2 , err := buildImageFromContext ( name2 , ctx , false )
2014-06-01 00:49:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-01 00:49:50 +04:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The cache should have been invalided but hasn't." )
2014-06-01 00:49:50 +04:00
}
}
2014-06-03 01:46:28 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithVolumeOwnership ( c * check . C ) {
2014-06-03 01:46:28 +04:00
name := "testbuildimg"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox : latest
RUN mkdir / test && chown daemon : daemon / test && chmod 0600 / test
VOLUME / test ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-03 01:46:28 +04:00
}
cmd := exec . Command ( dockerBinary , "run" , "--rm" , "testbuildimg" , "ls" , "-la" , "/test" )
out , _ , err := runCommandWithOutput ( cmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( out , err )
2014-06-03 01:46:28 +04:00
}
if expected := "drw-------" ; ! strings . Contains ( out , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected %s received %s" , expected , out )
2014-06-03 01:46:28 +04:00
}
if expected := "daemon daemon" ; ! strings . Contains ( out , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected %s received %s" , expected , out )
2014-06-03 01:46:28 +04:00
}
}
2014-06-17 10:08:14 +04:00
// testing #1405 - config.Cmd does not get cleaned up if
// utilizing cache
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEntrypointRunCleanup ( c * check . C ) {
2014-06-17 10:08:14 +04:00
name := "testbuildcmdcleanup"
defer deleteImages ( name )
if _ , err := buildImage ( name ,
` FROM busybox
RUN echo "hello" ` ,
true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:08:14 +04:00
}
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:08:14 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:08:14 +04:00
}
res , err := inspectField ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:08:14 +04:00
}
2014-07-08 21:37:20 +04:00
// Cmd must be cleaned up
2015-03-26 22:43:00 +03:00
if res != "<nil>" {
c . Fatalf ( "Cmd %s, expected nil" , res )
2014-06-17 10:08:14 +04:00
}
}
2014-06-17 10:26:42 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildForbiddenContextPath ( c * check . C ) {
2014-06-17 10:26:42 +04:00
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:26:42 +04:00
}
2014-08-06 22:24:00 +04:00
expected := "Forbidden path outside the build context: ../../ "
if _ , err := buildImageFromContext ( name , ctx , true ) ; err == nil || ! strings . Contains ( err . Error ( ) , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error: (should contain \"%s\") got:\n%v" , expected , err )
2014-06-17 10:26:42 +04:00
}
2014-08-06 22:24:00 +04:00
2014-06-17 10:26:42 +04:00
}
2014-06-17 10:35:29 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildADDFileNotFound ( c * check . C ) {
2014-06-17 10:35:29 +04:00
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:35:29 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
if ! strings . Contains ( err . Error ( ) , "foo: no such file or directory" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about missing foo file or directory" , err )
2014-06-17 10:35:29 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 10:35:29 +04:00
}
}
2014-06-17 10:50:51 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildInheritance ( c * check . C ) {
2014-06-17 10:50:51 +04:00
name := "testbuildinheritance"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM scratch
EXPOSE 2375 ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:50:51 +04:00
}
ports1 , err := inspectField ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:50:51 +04:00
}
_ , err = buildImage ( name ,
fmt . Sprintf ( ` FROM % s
ENTRYPOINT [ "/bin/echo" ] ` , name ) ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:50:51 +04:00
}
res , err := inspectField ( name , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:50:51 +04:00
}
2015-03-26 22:43:00 +03:00
if expected := "{[/bin/echo]}" ; res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-06-17 10:50:51 +04:00
}
ports2 , err := inspectField ( name , "Config.ExposedPorts" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 10:50:51 +04:00
}
if ports1 != ports2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Ports must be same: %s != %s" , ports1 , ports2 )
2014-06-17 10:50:51 +04:00
}
}
2014-06-17 10:57:32 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFails ( c * check . C ) {
2014-06-17 10:57:32 +04:00
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" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about non-zero code 23" , err )
2014-06-17 10:57:32 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 10:57:32 +04:00
}
}
2014-06-17 11:04:07 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFailsDockerfileEmpty ( c * check . C ) {
2014-06-17 11:04:07 +04:00
name := "testbuildfails"
defer deleteImages ( name )
_ , err := buildImage ( name , ` ` , true )
if err != nil {
2015-03-23 22:20:43 +03:00
if ! strings . Contains ( err . Error ( ) , "The Dockerfile (Dockerfile) cannot be empty" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about empty Dockerfile" , err )
2014-06-17 11:04:07 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 11:04:07 +04:00
}
}
2014-06-17 11:14:45 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuild ( c * check . C ) {
2014-06-17 11:14:45 +04:00
name := "testbuildonbuild"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
ONBUILD RUN touch foobar ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 11:14:45 +04:00
}
_ , err = buildImage ( name ,
fmt . Sprintf ( ` FROM % s
RUN [ - f foobar ] ` , name ) ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 11:14:45 +04:00
}
}
2014-06-17 11:24:47 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenChained ( c * check . C ) {
2014-06-17 11:24:47 +04:00
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" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about chaining ONBUILD" , err )
2014-06-17 11:24:47 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 11:24:47 +04:00
}
}
2014-06-17 11:36:45 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenFrom ( c * check . C ) {
2014-06-17 11:36:45 +04:00
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" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about FROM forbidden" , err )
2014-06-17 11:36:45 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 11:36:45 +04:00
}
}
2014-06-17 11:39:47 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildForbiddenMaintainer ( c * check . C ) {
2014-06-17 11:39:47 +04:00
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" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error %v, must be about MAINTAINER forbidden" , err )
2014-06-17 11:39:47 +04:00
}
} else {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Error must not be nil" )
2014-06-17 11:39:47 +04:00
}
}
2014-06-17 11:49:07 +04:00
// gh #2446
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddToSymlinkDest ( c * check . C ) {
2014-06-17 11:49:07 +04:00
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 11:49:07 +04:00
}
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-17 11:49:07 +04:00
}
}
2014-06-25 10:54:53 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEscapeWhitespace ( c * check . C ) {
2014-06-25 10:54:53 +04:00
name := "testbuildescaping"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM busybox
MAINTAINER " Docker \
IO < io @ \
docker . com > "
` , true )
res , err := inspectField ( name , "Author" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-06-25 10:54:53 +04:00
}
2014-12-11 15:56:21 +03:00
if res != "\"Docker IO <io@docker.com>\"" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Parsed string did not match the escaped string. Got: %q" , res )
2014-06-25 10:54:53 +04:00
}
}
2014-02-15 22:38:48 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildVerifyIntString ( c * check . C ) {
2014-12-11 15:56:21 +03:00
// Verify that strings that look like ints are still passed as strings
name := "testbuildstringing"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM busybox
MAINTAINER 123
` , true )
out , rc , err := runCommandWithOutput ( exec . Command ( dockerBinary , "inspect" , name ) )
if rc != 0 || err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Unexcepted error from inspect: rc: %v err: %v" , rc , err )
2014-12-11 15:56:21 +03:00
}
if ! strings . Contains ( out , "\"123\"" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Output does not contain the int as a string:\n%s" , out )
2014-12-11 15:56:21 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignore ( c * check . C ) {
2014-02-15 22:38:48 +04:00
name := "testbuilddockerignore"
defer deleteImages ( name )
dockerfile := `
FROM busybox
ADD . / bla
RUN [ [ - f / bla / src / x . go ] ]
RUN [ [ - f / bla / Makefile ] ]
RUN [ [ ! - e / bla / src / _vendor ] ]
RUN [ [ ! - e / bla / . gitignore ] ]
RUN [ [ ! - e / bla / README . md ] ]
RUN [ [ ! - e / bla / . git ] ] `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"Makefile" : "all:" ,
".git/HEAD" : "ref: foo" ,
"src/x.go" : "package main" ,
"src/_vendor/v.go" : "package main" ,
".gitignore" : "" ,
"README.md" : "readme" ,
".dockerignore" : ".git\npkg\n.gitignore\nsrc/_vendor\n*.md" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-02-15 22:38:48 +04:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-02-15 22:38:48 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoreCleanPaths ( c * check . C ) {
2014-10-24 01:54:35 +04:00
name := "testbuilddockerignorecleanpaths"
defer deleteImages ( name )
dockerfile := `
FROM busybox
ADD . / tmp /
RUN ( ! 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 01:54:35 +04:00
}
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 01:54:35 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoringDockerfile ( c * check . C ) {
2014-02-15 22:38:48 +04:00
name := "testbuilddockerignoredockerfile"
defer deleteImages ( name )
dockerfile := `
2014-10-24 01:30:11 +04:00
FROM busybox
ADD . / tmp /
RUN ! ls / tmp / Dockerfile
RUN ls / tmp / . dockerignore `
2014-02-15 22:38:48 +04:00
ctx , err := fakeContext ( dockerfile , map [ string ] string {
2014-10-24 01:30:11 +04:00
"Dockerfile" : dockerfile ,
2014-02-15 22:38:48 +04:00
".dockerignore" : "Dockerfile\n" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-02-15 22:38:48 +04:00
}
2015-02-25 11:53:43 +03:00
defer ctx . Close ( )
2014-10-24 01:30:11 +04:00
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't ignore Dockerfile correctly:%s" , err )
2014-02-15 22:38:48 +04:00
}
2014-10-24 01:54:35 +04:00
// now try it with ./Dockerfile
ctx . Add ( ".dockerignore" , "./Dockerfile\n" )
2014-10-24 01:30:11 +04:00
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't ignore ./Dockerfile correctly:%s" , err )
2014-10-24 01:54:35 +04:00
}
2014-02-15 22:38:48 +04:00
}
2014-07-06 15:36:34 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoringRenamedDockerfile ( c * check . C ) {
2014-09-11 18:42:17 +04:00
name := "testbuilddockerignoredockerfile"
defer deleteImages ( name )
dockerfile := `
FROM busybox
ADD . / tmp /
RUN ls / tmp / Dockerfile
RUN ! 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-11 18:42:17 +04:00
}
2015-02-25 11:53:43 +03:00
defer ctx . Close ( )
2014-09-11 18:42:17 +04:00
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't ignore MyDockerfile correctly:%s" , err )
2014-09-11 18:42:17 +04:00
}
// now try it with ./MyDockerfile
ctx . Add ( ".dockerignore" , "./MyDockerfile\n" )
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't ignore ./MyDockerfile correctly:%s" , err )
2014-09-11 18:42:17 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoringDockerignore ( c * check . C ) {
2014-10-24 01:30:11 +04:00
name := "testbuilddockerignoredockerignore"
defer deleteImages ( name )
dockerfile := `
FROM busybox
ADD . / tmp /
RUN ! ls / tmp / . dockerignore
RUN ls / tmp / Dockerfile `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
".dockerignore" : ".dockerignore\n" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 01:30:11 +04:00
}
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't ignore .dockerignore correctly:%s" , err )
2014-10-24 01:30:11 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoreTouchDockerfile ( c * check . C ) {
2014-10-24 01:30:11 +04:00
var id1 string
var id2 string
name := "testbuilddockerignoretouchdockerfile"
defer deleteImages ( name )
dockerfile := `
FROM busybox
ADD . / tmp / `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"Dockerfile" : dockerfile ,
".dockerignore" : "Dockerfile\n" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-24 01:30:11 +04:00
}
if id1 , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't build it correctly:%s" , err )
2014-10-24 01:30:11 +04:00
}
if id2 , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't build it correctly:%s" , err )
2014-10-24 01:30:11 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't use the cache - 1" )
2014-10-24 01:30:11 +04:00
}
// Now make sure touching Dockerfile doesn't invalidate the cache
if err = ctx . Add ( "Dockerfile" , dockerfile + "\n# hi" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't add Dockerfile: %s" , err )
2014-10-24 01:30:11 +04:00
}
if id2 , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't build it correctly:%s" , err )
2014-10-24 01:30:11 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't use the cache - 2" )
2014-10-24 01:30:11 +04:00
}
// One more time but just 'touch' it instead of changing the content
if err = ctx . Add ( "Dockerfile" , dockerfile + "\n# hi" ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't add Dockerfile: %s" , err )
2014-10-24 01:30:11 +04:00
}
if id2 , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't build it correctly:%s" , err )
2014-10-24 01:30:11 +04:00
}
if id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Didn't use the cache - 3" )
2014-10-24 01:30:11 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDockerignoringWholeDir ( c * check . C ) {
2014-07-18 09:35:54 +04:00
name := "testbuilddockerignorewholedir"
defer deleteImages ( name )
dockerfile := `
FROM busybox
COPY . /
RUN [ [ ! - e / . gitignore ] ]
RUN [ [ - f / Makefile ] ] `
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"Dockerfile" : "FROM scratch" ,
"Makefile" : "all:" ,
".dockerignore" : ".*\n" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-18 09:35:54 +04:00
}
if _ , err = buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-18 09:35:54 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildLineBreak ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildlinebreak"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
RUN sh - c ' echo root : testpass \
> / tmp / passwd '
RUN mkdir - p / var / run / sshd
RUN [ "$(cat /tmp/passwd)" = "root:testpass" ]
RUN [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEOLInLine ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildeolinline"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
RUN sh - c ' echo root : testpass > / tmp / passwd '
RUN echo "foo \n bar" ; echo "baz"
RUN mkdir - p / var / run / sshd
RUN [ "$(cat /tmp/passwd)" = "root:testpass" ]
RUN [ "$(ls -d /var/run/sshd)" = "/var/run/sshd" ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCommentsShebangs ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildcomments"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
# This is an ordinary comment .
RUN { echo ' # ! / bin / sh ' ; echo ' echo hello world ' ; } > / hello . sh
RUN [ ! - x / hello . sh ]
# comment with line break \
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildUsersAndGroups ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildusers"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
# Make sure our defaults work
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)" = ' 0 : 0 / root : root ' ]
# TODO decide if "args.user = strconv.Itoa(syscall.Getuid())" is acceptable behavior for changeUser in sysvinit instead of "return nil" when "USER" isn ' t specified ( so that we get the proper group list even if that is the empty list , even in the default case of not supplying an explicit USER to run as , which implies USER 0 )
USER root
RUN [ "$(id -G):$(id -Gn)" = ' 0 10 : root wheel ' ]
# Setup dockerio user and group
RUN echo ' dockerio : x : 1001 : 1001 : : / bin : / bin / false ' >> / etc / passwd
RUN echo ' dockerio : x : 1001 : ' >> / etc / group
# Make sure we can switch to our user and all the information is exactly as we expect it to be
USER dockerio
RUN id - G
RUN id - Gn
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
# Switch back to root and double check that worked exactly as we might expect it to
USER root
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 0 : 0 / root : root / 0 10 : root wheel ' ]
# Add a "supplementary" group for our dockerio user
RUN echo ' supplementary : x : 1002 : dockerio ' >> / etc / group
# ... and then go verify that we get it like we expect
USER dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 1002 : dockerio supplementary ' ]
USER 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 1002 : dockerio supplementary ' ]
# super test the new "user:group" syntax
USER dockerio : dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER 1001 : dockerio
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER dockerio : 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER 1001 : 1001
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1001 / dockerio : dockerio / 1001 : dockerio ' ]
USER dockerio : supplementary
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER dockerio : 1002
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER 1001 : supplementary
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
USER 1001 : 1002
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = ' 1001 : 1002 / dockerio : supplementary / 1002 : supplementary ' ]
# 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvUsage ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildenvusage"
defer deleteImages ( name )
dockerfile := ` FROM busybox
2014-10-25 22:29:18 +04:00
ENV HOME / root
2014-08-13 14:07:41 +04:00
ENV PATH $ HOME / bin : $ PATH
ENV PATH / tmp : $ PATH
RUN [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
2014-07-06 15:36:34 +04:00
ENV FOO / foo / baz
ENV BAR / bar
ENV BAZ $ BAR
ENV FOOPATH $ PATH : $ FOO
RUN [ "$BAR" = "$BAZ" ]
RUN [ "$FOOPATH" = "$PATH:/foo/baz" ]
ENV FROM hello / docker / world
ENV TO / docker / world / hello
ADD $ FROM $ TO
2014-08-13 14:07:41 +04:00
RUN [ "$(cat $TO)" = "hello" ]
2015-02-20 03:27:20 +03:00
ENV abc = def
ENV ghi = $ abc
RUN [ "$ghi" = "def" ]
2014-08-13 14:07:41 +04:00
`
2014-07-06 15:36:34 +04:00
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"hello/docker/world" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-07-06 15:36:34 +04:00
_ , err = buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEnvUsage2 ( c * check . C ) {
2014-09-26 06:28:24 +04:00
name := "testbuildenvusage2"
defer deleteImages ( name )
dockerfile := ` FROM busybox
ENV abc = def
RUN [ "$abc" = "def" ]
ENV def = "hello world"
RUN [ "$def" = "hello world" ]
ENV def = hello \ world
RUN [ "$def" = "hello world" ]
ENV v1 = abc v2 = "hi there"
RUN [ "$v1" = "abc" ]
RUN [ "$v2" = "hi there" ]
ENV v3 = ' boogie nights ' v4 = "with'quotes too"
RUN [ "$v3" = "boogie nights" ]
RUN [ "$v4" = "with'quotes too" ]
ENV abc = zzz FROM = hello / docker / world
ENV abc = zzz TO = / docker / world / hello
ADD $ FROM $ TO
RUN [ "$(cat $TO)" = "hello" ]
ENV abc "zzz"
2015-01-29 05:28:48 +03:00
RUN [ $ abc = "zzz" ]
2014-09-26 06:28:24 +04:00
ENV abc ' yyy '
2015-01-29 05:28:48 +03:00
RUN [ $ abc = ' yyy ' ]
2014-09-26 06:28:24 +04:00
ENV abc =
RUN [ "$abc" = "" ]
2015-02-20 03:27:20 +03:00
# use grep to make sure if the builder substitutes \ $ foo by mistake
# we don ' t get a false positive
ENV abc = \ $ foo
RUN [ "$abc" = "\$foo" ] && ( echo "$abc" | grep foo )
ENV abc \ $ foo
RUN [ "$abc" = "\$foo" ] && ( echo "$abc" | grep foo )
ENV abc = \ ' foo \ '
RUN [ "$abc" = "'foo'" ]
ENV abc = \ "foo\"
RUN [ "$abc" = "\"foo\"" ]
ENV abc "foo"
2015-01-29 05:28:48 +03:00
RUN [ "$abc" = "foo" ]
2015-02-20 03:27:20 +03:00
ENV abc ' foo '
2015-01-29 05:28:48 +03:00
RUN [ "$abc" = ' foo ' ]
2015-02-20 03:27:20 +03:00
ENV abc \ ' foo \ '
2015-01-29 05:28:48 +03:00
RUN [ "$abc" = "'foo'" ]
2015-02-20 03:27:20 +03:00
ENV abc \ "foo\"
2015-01-29 05:28:48 +03:00
RUN [ "$abc" = ' "foo" ' ]
2015-01-29 05:28:48 +03:00
ENV abc = ABC
RUN [ "$abc" = "ABC" ]
ENV def = $ { abc : - DEF }
RUN [ "$def" = "ABC" ]
ENV def = $ { ccc : - DEF }
RUN [ "$def" = "DEF" ]
ENV def = $ { ccc : - $ { def } xx }
RUN [ "$def" = "DEFxx" ]
ENV def = $ { def : + ALT }
RUN [ "$def" = "ALT" ]
ENV def = $ { def : + $ { abc } : }
RUN [ "$def" = "ABC:" ]
ENV def = $ { ccc : - \ $ abc : }
RUN [ "$def" = ' $ abc : ' ]
ENV def = $ { ccc : - \ $ { abc } : }
RUN [ "$def" = ' $ { abc : } ' ]
ENV mypath = $ { mypath : + $ mypath : } / home
RUN [ "$mypath" = ' / home ' ]
ENV mypath = $ { mypath : + $ mypath : } / away
RUN [ "$mypath" = ' / home : / away ' ]
2015-01-29 05:28:48 +03:00
ENV e1 = bar
ENV e2 = $ e1
ENV e3 = $ e11
ENV e4 = \ $ e1
ENV e5 = \ $ e11
RUN [ "$e0,$e1,$e2,$e3,$e4,$e5" = ' , bar , bar , , $ e1 , $ e11 ' ]
ENV ee1 bar
ENV ee2 $ ee1
ENV ee3 $ ee11
ENV ee4 \ $ ee1
ENV ee5 \ $ ee11
RUN [ "$ee1,$ee2,$ee3,$ee4,$ee5" = ' bar , bar , , $ ee1 , $ ee11 ' ]
ENV eee1 = "foo"
ENV eee2 = ' foo '
ENV eee3 "foo"
ENV eee4 ' foo '
RUN [ "$eee1,$eee2,$eee3,$eee4" = ' foo , foo , foo , foo ' ]
2014-09-26 06:28:24 +04:00
`
ctx , err := fakeContext ( dockerfile , map [ string ] string {
"hello/docker/world" : "hello" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-26 06:28:24 +04:00
}
2015-02-25 11:53:43 +03:00
defer ctx . Close ( )
2014-09-26 06:28:24 +04:00
_ , err = buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-26 06:28:24 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddScript ( c * check . C ) {
2014-07-06 15:36:34 +04:00
name := "testbuildaddscript"
defer deleteImages ( name )
dockerfile := `
FROM busybox
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-07-06 15:36:34 +04:00
_ , err = buildImageFromContext ( name , ctx , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-06 15:36:34 +04:00
}
}
2014-07-08 23:34:04 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddTar ( c * check . C ) {
2014-07-09 13:39:38 +04:00
name := "testbuildaddtar"
defer deleteImages ( name )
2014-07-08 23:34:04 +04:00
2014-07-21 23:10:47 +04:00
ctx := func ( ) * FakeContext {
2014-07-22 02:02:31 +04:00
dockerfile := `
FROM busybox
ADD test . tar /
RUN cat / test / foo | grep Hi
ADD test . tar / test . tar
RUN cat / test . tar / test / foo | grep Hi
ADD test . tar / unlikely - to - exist
RUN cat / unlikely - to - exist / test / foo | grep Hi
ADD test . tar / unlikely - to - exist - trailing - slash /
RUN cat / unlikely - to - exist - trailing - slash / test / foo | grep Hi
RUN mkdir / existing - directory
ADD test . tar / existing - directory
RUN cat / existing - directory / test / foo | grep Hi
ADD test . tar / existing - directory - trailing - slash /
RUN cat / existing - directory - trailing - slash / test / foo | grep Hi `
2014-07-21 23:10:47 +04:00
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-07-08 23:34:04 +04:00
}
2014-07-21 23:10:47 +04:00
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-07-21 23:10:47 +04:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-07-21 23:10:47 +04:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-07-08 23:34:04 +04:00
}
2014-07-22 02:02:31 +04:00
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-07-21 23:10:47 +04:00
}
2015-03-10 06:53:28 +03:00
return fakeContextFromDir ( tmpDir )
2014-07-21 23:10:47 +04:00
} ( )
2014-11-20 20:38:41 +03:00
defer ctx . Close ( )
2014-07-21 23:10:47 +04:00
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete for TestBuildAddTar: %v" , err )
2014-07-08 23:34:04 +04:00
}
2014-07-21 22:55:43 +04:00
2014-07-08 23:34:04 +04:00
}
2014-07-24 11:19:16 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddTarXz ( c * check . C ) {
2014-12-08 23:40:27 +03:00
name := "testbuildaddtarxz"
defer deleteImages ( name )
ctx := func ( ) * FakeContext {
dockerfile := `
FROM busybox
ADD test . tar . xz /
RUN cat / test / foo | grep Hi `
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-12-08 23:40:27 +03:00
}
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-12-08 23:40:27 +03:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-12-08 23:40:27 +03:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-12-08 23:40:27 +03:00
}
2015-02-13 02:42:27 +03:00
xzCompressCmd := exec . Command ( "xz" , "-k" , "test.tar" )
2014-12-08 23:40:27 +03:00
xzCompressCmd . Dir = tmpDir
out , _ , err := runCommandWithOutput ( xzCompressCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2014-12-08 23:40:27 +03:00
}
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-12-08 23:40:27 +03:00
}
2015-03-10 06:53:28 +03:00
return fakeContextFromDir ( tmpDir )
2014-12-08 23:40:27 +03:00
} ( )
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete for TestBuildAddTarXz: %v" , err )
2014-12-08 23:40:27 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildAddTarXzGz ( c * check . C ) {
2014-12-08 23:40:27 +03:00
name := "testbuildaddtarxzgz"
defer deleteImages ( name )
ctx := func ( ) * FakeContext {
dockerfile := `
FROM busybox
ADD test . tar . xz . gz /
RUN ls / test . tar . xz . gz `
tmpDir , err := ioutil . TempDir ( "" , "fake-context" )
testTar , err := os . Create ( filepath . Join ( tmpDir , "test.tar" ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to create test.tar archive: %v" , err )
2014-12-08 23:40:27 +03:00
}
defer testTar . Close ( )
tw := tar . NewWriter ( testTar )
if err := tw . WriteHeader ( & tar . Header {
Name : "test/foo" ,
Size : 2 ,
} ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file header: %v" , err )
2014-12-08 23:40:27 +03:00
}
if _ , err := tw . Write ( [ ] byte ( "Hi" ) ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to write tar file content: %v" , err )
2014-12-08 23:40:27 +03:00
}
if err := tw . Close ( ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to close tar archive: %v" , err )
2014-12-08 23:40:27 +03:00
}
2015-02-13 02:42:27 +03:00
xzCompressCmd := exec . Command ( "xz" , "-k" , "test.tar" )
2014-12-08 23:40:27 +03:00
xzCompressCmd . Dir = tmpDir
out , _ , err := runCommandWithOutput ( xzCompressCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2014-12-08 23:40:27 +03:00
}
gzipCompressCmd := exec . Command ( "gzip" , "test.tar.xz" )
gzipCompressCmd . Dir = tmpDir
out , _ , err = runCommandWithOutput ( gzipCompressCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2014-12-08 23:40:27 +03:00
}
if err := ioutil . WriteFile ( filepath . Join ( tmpDir , "Dockerfile" ) , [ ] byte ( dockerfile ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to open destination dockerfile: %v" , err )
2014-12-08 23:40:27 +03:00
}
2015-03-10 06:53:28 +03:00
return fakeContextFromDir ( tmpDir )
2014-12-08 23:40:27 +03:00
} ( )
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "build failed to complete for TestBuildAddTarXz: %v" , err )
2014-12-08 23:40:27 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFromGIT ( c * check . C ) {
2014-07-24 11:19:16 +04:00
name := "testbuildfromgit"
defer deleteImages ( name )
git , err := fakeGIT ( "repo" , map [ string ] string {
"Dockerfile" : ` FROM busybox
ADD first / first
RUN [ - f / first ]
MAINTAINER docker ` ,
"first" : "test git data" ,
2015-03-10 06:53:28 +03:00
} , true )
2014-07-24 11:19:16 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-24 11:19:16 +04:00
}
defer git . Close ( )
_ , err = buildImageFromPath ( name , git . RepoURL , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-24 11:19:16 +04:00
}
res , err := inspectField ( name , "Author" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-24 11:19:16 +04:00
}
if res != "docker" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Maintainer should be docker, got %s" , res )
2014-07-24 11:19:16 +04:00
}
}
2014-07-08 21:37:20 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCleanupCmdOnEntrypoint ( c * check . C ) {
2014-07-08 21:37:20 +04:00
name := "testbuildcmdcleanuponentrypoint"
defer deleteImages ( name )
if _ , err := buildImage ( name ,
` FROM scratch
CMD [ "test" ]
ENTRYPOINT [ "echo" ] ` ,
true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-08 21:37:20 +04:00
}
if _ , err := buildImage ( name ,
fmt . Sprintf ( ` FROM % s
ENTRYPOINT [ "cat" ] ` , name ) ,
true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-08 21:37:20 +04:00
}
res , err := inspectField ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-08 21:37:20 +04:00
}
2015-03-26 22:43:00 +03:00
if res != "<nil>" {
c . Fatalf ( "Cmd %s, expected nil" , res )
2014-07-08 21:37:20 +04:00
}
2015-03-26 22:43:00 +03:00
2014-07-08 21:37:20 +04:00
res , err = inspectField ( name , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-07-08 21:37:20 +04:00
}
2015-03-26 22:43:00 +03:00
if expected := "{[cat]}" ; res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Entrypoint %s, expected %s" , res , expected )
2014-07-08 21:37:20 +04:00
}
}
2014-08-30 15:34:09 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildClearCmd ( c * check . C ) {
2014-08-30 15:34:09 +04:00
name := "testbuildclearcmd"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` From scratch
ENTRYPOINT [ "/bin/bash" ]
CMD [ ] ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-08-30 15:34:09 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-08-30 15:34:09 +04:00
}
if res != "[]" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Cmd %s, expected %s" , res , "[]" )
2014-08-30 15:34:09 +04:00
}
}
2014-09-23 10:18:46 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyCmd ( c * check . C ) {
2014-09-23 10:18:46 +04:00
name := "testbuildemptycmd"
defer deleteImages ( name )
if _ , err := buildImage ( name , "FROM scratch\nMAINTAINER quux\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 10:18:46 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-23 10:18:46 +04:00
}
if res != "null" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Cmd %s, expected %s" , res , "null" )
2014-09-23 10:18:46 +04:00
}
}
2014-09-24 00:31:42 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildOnBuildOutput ( c * check . C ) {
2014-09-24 00:31:42 +04:00
name := "testbuildonbuildparent"
defer deleteImages ( name )
if _ , err := buildImage ( name , "FROM busybox\nONBUILD RUN echo foo\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 00:31:42 +04:00
}
childname := "testbuildonbuildchild"
defer deleteImages ( childname )
_ , out , err := buildImageWithOut ( name , "FROM " + name + "\nMAINTAINER quux\n" , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-24 00:31:42 +04:00
}
2014-10-14 00:14:35 +04:00
if ! strings . Contains ( out , "Trigger 0, RUN echo foo" ) {
2015-04-18 19:46:47 +03:00
c . Fatal ( "failed to find the ONBUILD output" , out )
2014-09-24 00:31:42 +04:00
}
}
2014-09-29 13:52:13 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildInvalidTag ( c * check . C ) {
2015-03-24 14:25:26 +03:00
name := "abcd:" + stringutils . GenerateRandomAlphaOnlyString ( 200 )
2014-09-29 13:52:13 +04:00
defer deleteImages ( name )
_ , out , err := buildImageWithOut ( name , "FROM scratch\nMAINTAINER quux\n" , true )
// if the error doesnt check for illegal tag name, or the image is built
// then this should fail
2014-10-08 06:07:51 +04:00
if ! strings . Contains ( out , "Illegal tag name" ) || strings . Contains ( out , "Sending build context to Docker daemon" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to stop before building. Error: %s, Output: %s" , err , out )
2014-09-29 13:52:13 +04:00
}
}
2014-09-29 21:23:10 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCmdShDashC ( c * check . C ) {
2014-09-29 21:23:10 +04:00
name := "testbuildcmdshc"
defer deleteImages ( name )
if _ , err := buildImage ( name , "FROM busybox\nCMD echo cmd\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-29 21:23:10 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , res )
2014-09-29 21:23:10 +04:00
}
expected := ` ["/bin/sh","-c","echo cmd"] `
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected value %s not in Config.Cmd: %s" , expected , res )
2014-09-29 21:23:10 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCmdSpaces ( c * check . C ) {
2015-01-15 22:34:59 +03:00
// Test to make sure that when we strcat arrays we take into account
// the arg separator to make sure ["echo","hi"] and ["echo hi"] don't
// look the same
name := "testbuildcmdspaces"
defer deleteImages ( name )
var id1 string
var id2 string
var err error
if id1 , err = buildImage ( name , "FROM busybox\nCMD [\"echo hi\"]\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-15 22:34:59 +03:00
}
if id2 , err = buildImage ( name , "FROM busybox\nCMD [\"echo\", \"hi\"]\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-15 22:34:59 +03:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Should not have resulted in the same CMD" )
2015-01-15 22:34:59 +03:00
}
// Now do the same with ENTRYPOINT
if id1 , err = buildImage ( name , "FROM busybox\nENTRYPOINT [\"echo hi\"]\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-15 22:34:59 +03:00
}
if id2 , err = buildImage ( name , "FROM busybox\nENTRYPOINT [\"echo\", \"hi\"]\n" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-15 22:34:59 +03:00
}
if id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Should not have resulted in the same ENTRYPOINT" )
2015-01-15 22:34:59 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildCmdJSONNoShDashC ( c * check . C ) {
2014-09-29 21:23:10 +04:00
name := "testbuildcmdjson"
defer deleteImages ( name )
if _ , err := buildImage ( name , "FROM busybox\nCMD [\"echo\", \"cmd\"]" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-29 21:23:10 +04:00
}
res , err := inspectFieldJSON ( name , "Config.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , res )
2014-09-29 21:23:10 +04:00
}
expected := ` ["echo","cmd"] `
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected value %s not in Config.Cmd: %s" , expected , res )
2014-09-29 21:23:10 +04:00
}
}
2014-10-07 07:14:25 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildErrorInvalidInstruction ( c * check . C ) {
2014-10-07 07:14:25 +04:00
name := "testbuildignoreinvalidinstruction"
defer deleteImages ( name )
out , _ , err := buildImageWithOut ( name , "FROM busybox\nfoo bar" , true )
2015-02-05 18:23:25 +03:00
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Should have failed: %s" , out )
2014-10-07 07:14:25 +04:00
}
}
2014-10-08 02:39:50 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEntrypointInheritance ( c * check . C ) {
2014-10-08 02:39:50 +04:00
defer deleteImages ( "parent" , "child" )
if _ , err := buildImage ( "parent" , `
FROM busybox
ENTRYPOINT exit 130
` , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-08 02:39:50 +04:00
}
status , _ := runCommand ( exec . Command ( dockerBinary , "run" , "parent" ) )
if status != 130 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected exit code 130 but received %d" , status )
2014-10-08 02:39:50 +04:00
}
if _ , err := buildImage ( "child" , `
FROM parent
ENTRYPOINT exit 5
` , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-08 02:39:50 +04:00
}
status , _ = runCommand ( exec . Command ( dockerBinary , "run" , "child" ) )
if status != 5 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected exit code 5 but received %d" , status )
2014-10-08 02:39:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEntrypointInheritanceInspect ( c * check . C ) {
2014-10-08 02:39:50 +04:00
var (
name = "testbuildepinherit"
name2 = "testbuildepinherit2"
expected = ` ["/bin/sh","-c","echo quux"] `
)
defer deleteImages ( name , name2 )
if _ , err := buildImage ( name , "FROM busybox\nENTRYPOINT /foo/bar" , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-08 02:39:50 +04:00
}
if _ , err := buildImage ( name2 , fmt . Sprintf ( "FROM %s\nENTRYPOINT echo quux" , name ) , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-08 02:39:50 +04:00
}
res , err := inspectFieldJSON ( name2 , "Config.Entrypoint" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , res )
2014-10-08 02:39:50 +04:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected value %s not in Config.Entrypoint: %s" , expected , res )
2014-10-08 02:39:50 +04:00
}
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "-t" , name2 ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2014-10-08 02:39:50 +04:00
}
expected = "quux"
if strings . TrimSpace ( out ) != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected output is %s, got %s" , expected , out )
2014-10-08 02:39:50 +04:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRunShEntrypoint ( c * check . C ) {
2014-10-08 02:39:50 +04:00
name := "testbuildentrypoint"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
ENTRYPOINT / bin / echo ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-08 02:39:50 +04:00
}
2014-11-17 19:05:49 +03:00
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "--rm" , name ) )
2014-10-08 02:39:50 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2014-10-08 02:39:50 +04:00
}
}
2014-10-14 10:58:55 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildExoticShellInterpolation ( c * check . C ) {
2014-10-14 10:58:55 +04:00
name := "testbuildexoticshellinterpolation"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM busybox
2014-12-16 18:06:45 +03:00
2014-10-14 10:58:55 +04:00
ENV SOME_VAR a . b . c
RUN [ "$SOME_VAR" = ' a . b . c ' ]
RUN [ "${SOME_VAR}" = ' a . b . c ' ]
RUN [ "${SOME_VAR%.*}" = ' a . b ' ]
RUN [ "${SOME_VAR%%.*}" = 'a' ]
RUN [ "${SOME_VAR#*.}" = ' b . c ' ]
RUN [ "${SOME_VAR##*.}" = 'c' ]
RUN [ "${SOME_VAR/c/d}" = ' a . b . d ' ]
RUN [ "${#SOME_VAR}" = '5' ]
RUN [ "${SOME_UNSET_VAR:-$SOME_VAR}" = ' a . b . 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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-14 10:58:55 +04:00
}
}
2014-10-09 07:34:20 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildVerifySingleQuoteFails ( c * check . C ) {
2014-10-09 07:34:20 +04:00
// This testcase is supposed to generate an error because the
// JSON array we're passing in on the CMD uses single quotes instead
// of double quotes (per the JSON spec). This means we interpret it
// as a "string" insead of "JSON array" and pass it on to "sh -c" and
// it should barf on it.
name := "testbuildsinglequotefails"
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
CMD [ ' / bin / sh ' , ' - c ' , ' echo hi ' ] ` ,
true )
2014-11-17 19:05:49 +03:00
_ , _ , err = runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "--rm" , name ) )
2014-10-09 07:34:20 +04:00
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "The image was not supposed to be able to run" )
2014-10-09 07:34:20 +04:00
}
}
2014-10-06 20:41:22 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildVerboseOut ( c * check . C ) {
2014-10-06 20:41:22 +04:00
name := "testbuildverboseout"
defer deleteImages ( name )
_ , out , err := buildImageWithOut ( name ,
` FROM busybox
RUN echo 123 ` ,
false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-06 20:41:22 +04:00
}
if ! strings . Contains ( out , "\n123\n" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Output should contain %q: %q" , "123" , out )
2014-10-06 20:41:22 +04:00
}
}
2014-10-09 01:55:02 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithTabs ( c * check . C ) {
2014-10-09 01:55:02 +04:00
name := "testbuildwithtabs"
defer deleteImages ( name )
_ , err := buildImage ( name ,
"FROM busybox\nRUN echo\tone\t\ttwo" , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-09 01:55:02 +04:00
}
res , err := inspectFieldJSON ( name , "ContainerConfig.Cmd" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-10-09 01:55:02 +04:00
}
2015-01-20 22:11:59 +03:00
expected1 := ` ["/bin/sh","-c","echo\tone\t\ttwo"] `
expected2 := ` ["/bin/sh","-c","echo\u0009one\u0009\u0009two"] ` // syntactically equivalent, and what Go 1.3 generates
if res != expected1 && res != expected2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing tabs.\nGot: %s\nExp: %s or %s" , res , expected1 , expected2 )
2014-10-09 01:55:02 +04:00
}
}
2014-12-05 01:06:40 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildLabels ( c * check . C ) {
2015-02-17 18:20:06 +03:00
name := "testbuildlabel"
expected := ` { "License":"GPL","Vendor":"Acme"} `
defer deleteImages ( name )
_ , err := buildImage ( name ,
` FROM busybox
LABEL Vendor = Acme
LABEL License GPL ` ,
true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 18:20:06 +03:00
}
res , err := inspectFieldJSON ( name , "Config.Labels" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 18:20:06 +03:00
}
if res != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Labels %s, expected %s" , res , expected )
2015-02-17 18:20:06 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildLabelsCache ( c * check . C ) {
2015-03-19 20:06:06 +03:00
name := "testbuildlabelcache"
defer deleteImages ( name )
id1 , err := buildImage ( name ,
` FROM busybox
LABEL Vendor = Acme ` , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 1 should have worked: %v" , err )
2015-03-19 20:06:06 +03:00
}
id2 , err := buildImage ( name ,
` FROM busybox
LABEL Vendor = Acme ` , true )
if err != nil || id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 2 should have worked & used cache(%s,%s): %v" , id1 , id2 , err )
2015-03-19 20:06:06 +03:00
}
id2 , err = buildImage ( name ,
` FROM busybox
LABEL Vendor = Acme1 ` , true )
if err != nil || id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 3 should have worked & NOT used cache(%s,%s): %v" , id1 , id2 , err )
2015-03-19 20:06:06 +03:00
}
id2 , err = buildImage ( name ,
` FROM busybox
LABEL Vendor Acme ` , true ) // Note: " " and "=" should be same
if err != nil || id1 != id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 4 should have worked & used cache(%s,%s): %v" , id1 , id2 , err )
2015-03-20 15:14:31 +03:00
}
// 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 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 5 should have worked: %q" , err )
2015-03-20 15:14:31 +03:00
}
id2 , err = buildImage ( name ,
` FROM busybox
LABEL f1 = "b1 f2=b2" ` , true )
if err != nil || id1 == id2 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 6 should have worked & NOT used the cache(%s,%s): %q" , id1 , id2 , err )
2015-03-19 20:06:06 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildStderr ( c * check . C ) {
2014-12-05 01:06:40 +03:00
// This test just makes sure that no non-error output goes
// to stderr
name := "testbuildstderr"
defer deleteImages ( name )
_ , _ , stderr , err := buildImageWithStdoutStderr ( name ,
"FROM busybox\nRUN echo one" , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-05 01:06:40 +03:00
}
2015-03-16 09:59:10 +03:00
if runtime . GOOS == "windows" {
// stderr might contain a security warning on windows
lines := strings . Split ( stderr , "\n" )
for _ , v := range lines {
if v != "" && ! strings . Contains ( v , "SECURITY WARNING:" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Stderr contains unexpected output line: %q" , v )
2015-03-16 09:59:10 +03:00
}
}
} else {
if stderr != "" {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Stderr should have been empty, instead its: %q" , stderr )
2015-03-16 09:59:10 +03:00
}
2014-12-05 01:06:40 +03:00
}
}
2014-12-10 22:09:03 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildChownSingleFile ( c * check . C ) {
testRequires ( c , UnixCli ) // test uses chown: not available on windows
2015-02-20 12:37:27 +03:00
2014-12-10 22:09:03 +03:00
name := "testbuildchownsinglefile"
defer deleteImages ( name )
ctx , err := fakeContext ( `
FROM busybox
COPY test /
RUN ls - l / test
RUN [ $ ( ls - l / test | awk ' { print $ 3 ":" $ 4 } ' ) = ' root : root ' ]
` , map [ string ] string {
"test" : "test" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-10 22:09:03 +03:00
}
defer ctx . Close ( )
if err := os . Chown ( filepath . Join ( ctx . Dir , "test" ) , 4242 , 4242 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-10 22:09:03 +03:00
}
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-10 22:09:03 +03:00
}
}
2014-12-03 22:04:51 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildSymlinkBreakout ( c * check . C ) {
2014-12-03 22:04:51 +03:00
name := "testbuildsymlinkbreakout"
tmpdir , err := ioutil . TempDir ( "" , name )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
defer os . RemoveAll ( tmpdir )
ctx := filepath . Join ( tmpdir , "context" )
if err := os . MkdirAll ( ctx , 0755 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
if err := ioutil . WriteFile ( filepath . Join ( ctx , "Dockerfile" ) , [ ] byte ( `
from busybox
add symlink . tar /
add inject / symlink /
` ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
inject := filepath . Join ( ctx , "inject" )
if err := ioutil . WriteFile ( inject , nil , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
f , err := os . Create ( filepath . Join ( ctx , "symlink.tar" ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
w := tar . NewWriter ( f )
w . WriteHeader ( & tar . Header {
Name : "symlink2" ,
Typeflag : tar . TypeSymlink ,
Linkname : "/../../../../../../../../../../../../../../" ,
Uid : os . Getuid ( ) ,
Gid : os . Getgid ( ) ,
} )
w . WriteHeader ( & tar . Header {
Name : "symlink" ,
Typeflag : tar . TypeSymlink ,
Linkname : filepath . Join ( "symlink2" , tmpdir ) ,
Uid : os . Getuid ( ) ,
Gid : os . Getgid ( ) ,
} )
w . Close ( )
f . Close ( )
2015-03-10 06:53:28 +03:00
if _ , err := buildImageFromContext ( name , fakeContextFromDir ( ctx ) , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-03 22:04:51 +03:00
}
if _ , err := os . Lstat ( filepath . Join ( tmpdir , "inject" ) ) ; err == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "symlink breakout - inject" )
2014-12-03 22:04:51 +03:00
} else if ! os . IsNotExist ( err ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "unexpected error: %v" , err )
2014-12-03 22:04:51 +03:00
}
}
2014-12-09 01:33:46 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildXZHost ( c * check . C ) {
2014-12-09 01:33:46 +03:00
name := "testbuildxzhost"
defer deleteImages ( name )
ctx , err := fakeContext ( `
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 {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-09 01:33:46 +03:00
}
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , true ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-09 01:33:46 +03:00
}
}
2014-12-12 22:15:31 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildVolumesRetainContents ( c * check . C ) {
2014-12-12 22:15:31 +03:00
var (
name = "testbuildvolumescontent"
expected = "some text"
)
defer deleteImages ( name )
ctx , err := fakeContext ( `
FROM busybox
COPY content / foo / file
VOLUME / foo
CMD cat / foo / file ` ,
map [ string ] string {
"content" : expected ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-12 22:15:31 +03:00
}
defer ctx . Close ( )
if _ , err := buildImageFromContext ( name , ctx , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-12 22:15:31 +03:00
}
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "run" , "--rm" , name ) )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-12-12 22:15:31 +03:00
}
if out != expected {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected file contents for /foo/file to be %q but received %q" , expected , out )
2014-12-12 22:15:31 +03:00
}
}
2014-09-11 18:42:17 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRenamedDockerfile ( c * check . C ) {
2014-09-11 18:42:17 +04:00
ctx , err := fakeContext ( ` FROM busybox
RUN echo from Dockerfile ` ,
map [ string ] string {
"Dockerfile" : "FROM busybox\nRUN echo from Dockerfile" ,
"files/Dockerfile" : "FROM busybox\nRUN echo from files/Dockerfile" ,
"files/dFile" : "FROM busybox\nRUN echo from files/dFile" ,
"dFile" : "FROM busybox\nRUN echo from dFile" ,
2015-02-04 17:07:37 +03:00
"files/dFile2" : "FROM busybox\nRUN echo from files/dFile2" ,
2014-09-11 18:42:17 +04:00
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , "test1" , "." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Failed to build: %s\n%s" , out , err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test1 should have used Dockerfile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , "-f" , filepath . Join ( "files" , "Dockerfile" ) , "-t" , "test2" , "." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from files/Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test2 should have used files/Dockerfile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , fmt . Sprintf ( "--file=%s" , filepath . Join ( "files" , "dFile" ) ) , "-t" , "test3" , "." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from files/dFile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test3 should have used files/dFile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , "--file=dFile" , "-t" , "test4" , "." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from dFile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test4 should have used dFile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-02-18 10:59:13 +03:00
dirWithNoDockerfile , _ := ioutil . TempDir ( os . TempDir ( ) , "test5" )
nonDockerfileFile := filepath . Join ( dirWithNoDockerfile , "notDockerfile" )
if _ , err = os . Create ( nonDockerfileFile ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-18 10:59:13 +03:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , ctx . Dir , "build" , fmt . Sprintf ( "--file=%s" , nonDockerfileFile ) , "-t" , "test5" , "." )
2015-02-18 10:59:13 +03:00
2014-09-11 18:42:17 +04:00
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test5 was supposed to fail to find passwd" )
2014-09-11 18:42:17 +04:00
}
2015-02-18 10:59:13 +03:00
if expected := fmt . Sprintf ( "The Dockerfile (%s) must be within the build context (.)" , strings . Replace ( nonDockerfileFile , ` \ ` , ` \\ ` , - 1 ) ) ; ! strings . Contains ( out , expected ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "wrong error messsage:%v\nexpected to contain=%v" , out , expected )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , filepath . Join ( ctx . Dir , "files" ) , "build" , "-f" , filepath . Join ( ".." , "Dockerfile" ) , "-t" , "test6" , ".." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test6 failed: %s" , err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test6 should have used root Dockerfile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , filepath . Join ( ctx . Dir , "files" ) , "build" , "-f" , filepath . Join ( ctx . Dir , "files" , "Dockerfile" ) , "-t" , "test7" , ".." )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test7 failed: %s" , err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from files/Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test7 should have used files Dockerfile, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , filepath . Join ( ctx . Dir , "files" ) , "build" , "-f" , filepath . Join ( ".." , "Dockerfile" ) , "-t" , "test8" , "." )
2014-09-11 18:42:17 +04:00
if err == nil || ! strings . Contains ( out , "must be within the build context" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test8 should have failed with Dockerfile out of context: %s" , err )
2014-09-11 18:42:17 +04:00
}
2015-02-04 17:07:37 +03:00
tmpDir := os . TempDir ( )
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , tmpDir , "build" , "-t" , "test9" , ctx . Dir )
2014-09-11 18:42:17 +04:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test9 - failed: %s" , err )
2014-09-11 18:42:17 +04:00
}
if ! strings . Contains ( out , "from Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test9 should have used root Dockerfile, output:%s" , out )
2015-02-04 17:07:37 +03:00
}
2015-04-18 19:46:47 +03:00
out , _ , err = dockerCmdInDir ( c , filepath . Join ( ctx . Dir , "files" ) , "build" , "-f" , "dFile2" , "-t" , "test10" , "." )
2015-02-04 17:07:37 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test10 should have worked: %s" , err )
2015-02-04 17:07:37 +03:00
}
if ! strings . Contains ( out , "from files/dFile2" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "test10 should have used files/dFile2, output:%s" , out )
2014-09-11 18:42:17 +04:00
}
}
2014-10-07 05:54:52 +04:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFromMixedcaseDockerfile ( c * check . C ) {
testRequires ( c , UnixCli ) // Dockerfile overwrites dockerfile on windows
2015-02-17 21:25:36 +03:00
defer deleteImages ( "test1" )
ctx , err := fakeContext ( ` FROM busybox
RUN echo from dockerfile ` ,
map [ string ] string {
"dockerfile" : "FROM busybox\nRUN echo from dockerfile" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 21:25:36 +03:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , "test1" , "." )
2015-02-17 21:25:36 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Failed to build: %s\n%s" , out , err )
2015-02-17 21:25:36 +03:00
}
if ! strings . Contains ( out , "from dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing proper output: %s" , out )
2015-02-17 21:25:36 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildWithTwoDockerfiles ( c * check . C ) {
testRequires ( c , UnixCli ) // Dockerfile overwrites dockerfile on windows
2015-02-17 21:25:36 +03:00
defer deleteImages ( "test1" )
ctx , err := fakeContext ( ` FROM busybox
RUN echo from Dockerfile ` ,
map [ string ] string {
"dockerfile" : "FROM busybox\nRUN echo from dockerfile" ,
} )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 21:25:36 +03:00
}
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-t" , "test1" , "." )
2015-02-17 21:25:36 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Failed to build: %s\n%s" , out , err )
2015-02-17 21:25:36 +03:00
}
if ! strings . Contains ( out , "from Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing proper output: %s" , out )
2015-02-17 21:25:36 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFromURLWithF ( c * check . C ) {
2015-02-17 21:25:36 +03:00
defer deleteImages ( "test1" )
server , err := fakeStorage ( map [ string ] string { "baz" : ` FROM busybox
RUN echo from baz
COPY * / tmp /
RUN find / tmp / ` } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 21:25:36 +03:00
}
defer server . Close ( )
ctx , err := fakeContext ( ` FROM busybox
RUN echo from Dockerfile ` ,
map [ string ] string { } )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 21:25:36 +03:00
}
// Make sure that -f is ignored and that we don't use the Dockerfile
// that's in the current dir
2015-04-18 19:46:47 +03:00
out , _ , err := dockerCmdInDir ( c , ctx . Dir , "build" , "-f" , "baz" , "-t" , "test1" , server . URL ( ) + "/baz" )
2015-02-17 21:25:36 +03:00
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Failed to build: %s\n%s" , out , err )
2015-02-17 21:25:36 +03:00
}
if ! strings . Contains ( out , "from baz" ) ||
strings . Contains ( out , "/tmp/baz" ) ||
! strings . Contains ( out , "/tmp/Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing proper output: %s" , out )
2015-02-17 21:25:36 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFromStdinWithF ( c * check . C ) {
2015-02-17 21:25:36 +03:00
defer deleteImages ( "test1" )
ctx , err := fakeContext ( ` FROM busybox
RUN echo from Dockerfile ` ,
map [ string ] string { } )
defer ctx . Close ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 21:25:36 +03:00
}
// 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
RUN echo from baz
COPY * / tmp /
RUN find / tmp / ` )
out , status , err := runCommandWithOutput ( dockerCommand )
if err != nil || status != 0 {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Error building: %s" , err )
2015-02-17 21:25:36 +03:00
}
if ! strings . Contains ( out , "from baz" ) ||
strings . Contains ( out , "/tmp/baz" ) ||
! strings . Contains ( out , "/tmp/Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Missing proper output: %s" , out )
2015-02-17 21:25:36 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildFromOfficialNames ( c * check . C ) {
2014-10-07 05:54:52 +04:00
name := "testbuildfromofficial"
fromNames := [ ] string {
"busybox" ,
"docker.io/busybox" ,
"index.docker.io/busybox" ,
"library/busybox" ,
"docker.io/library/busybox" ,
"index.docker.io/library/busybox" ,
}
for idx , fromName := range fromNames {
imgName := fmt . Sprintf ( "%s%d" , name , idx )
_ , err := buildImage ( imgName , "FROM " + fromName , true )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Errorf ( "Build failed using FROM %s: %s" , fromName , err )
2014-10-07 05:54:52 +04:00
}
deleteImages ( imgName )
}
}
2015-02-03 00:17:12 +03:00
2015-04-18 19:46:47 +03:00
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)
2015-02-20 12:37:27 +03:00
2015-02-03 00:17:12 +03:00
name := "testbuilddockerfileoutsidecontext"
tmpdir , err := ioutil . TempDir ( "" , name )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
defer os . RemoveAll ( tmpdir )
ctx := filepath . Join ( tmpdir , "context" )
if err := os . MkdirAll ( ctx , 0755 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
2015-02-04 17:07:37 +03:00
if err := ioutil . WriteFile ( filepath . Join ( ctx , "Dockerfile" ) , [ ] byte ( "FROM scratch\nENV X Y" ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
wd , err := os . Getwd ( )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
defer os . Chdir ( wd )
if err := os . Chdir ( ctx ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
2015-02-04 17:07:37 +03:00
if err := ioutil . WriteFile ( filepath . Join ( tmpdir , "outsideDockerfile" ) , [ ] byte ( "FROM scratch\nENV x y" ) , 0644 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
2015-02-17 03:59:41 +03:00
if err := os . Symlink ( filepath . Join ( ".." , "outsideDockerfile" ) , filepath . Join ( ctx , "dockerfile1" ) ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
if err := os . Symlink ( filepath . Join ( tmpdir , "outsideDockerfile" ) , filepath . Join ( ctx , "dockerfile2" ) ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-03 00:17:12 +03:00
}
2015-02-17 03:59:41 +03:00
2015-02-03 00:17:12 +03:00
for _ , dockerfilePath := range [ ] string {
2015-02-17 03:59:41 +03:00
filepath . Join ( ".." , "outsideDockerfile" ) ,
2015-02-03 00:17:12 +03:00
filepath . Join ( ctx , "dockerfile1" ) ,
filepath . Join ( ctx , "dockerfile2" ) ,
} {
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "build" , "-t" , name , "--no-cache" , "-f" , dockerfilePath , "." ) )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected error with %s. Out: %s" , dockerfilePath , out )
2015-02-03 00:17:12 +03:00
}
2015-02-04 17:07:37 +03:00
if ! strings . Contains ( out , "must be within the build context" ) && ! strings . Contains ( out , "Cannot locate Dockerfile" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Unexpected error with %s. Out: %s" , dockerfilePath , out )
2015-02-04 17:07:37 +03:00
}
2015-02-03 00:17:12 +03:00
deleteImages ( name )
}
os . Chdir ( tmpdir )
// Path to Dockerfile should be resolved relative to working directory, not relative to context.
// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
out , _ , err := runCommandWithOutput ( exec . Command ( dockerBinary , "build" , "-t" , name , "--no-cache" , "-f" , "Dockerfile" , ctx ) )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Expected error. Out: %s" , out )
2015-02-03 00:17:12 +03:00
}
deleteImages ( name )
}
2015-01-15 17:49:48 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildSpaces ( c * check . C ) {
2015-01-15 17:49:48 +03:00
// Test to make sure that leading/trailing spaces on a command
// doesn't change the error msg we get
var (
err1 error
err2 error
)
name := "testspaces"
defer deleteImages ( name )
2015-02-08 06:30:44 +03:00
ctx , err := fakeContext ( "FROM busybox\nCOPY\n" ,
2015-01-15 17:49:48 +03:00
map [ string ] string {
2015-02-08 06:30:44 +03:00
"Dockerfile" : "FROM busybox\nCOPY\n" ,
2015-01-15 17:49:48 +03:00
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-01-15 17:49:48 +03:00
}
defer ctx . Close ( )
if _ , err1 = buildImageFromContext ( name , ctx , false ) ; err1 == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build 1 was supposed to fail, but didn't" )
2015-01-15 17:49:48 +03:00
}
2015-02-08 06:30:44 +03:00
ctx . Add ( "Dockerfile" , "FROM busybox\nCOPY " )
2015-01-15 17:49:48 +03:00
if _ , err2 = buildImageFromContext ( name , ctx , false ) ; err2 == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build 2 was supposed to fail, but didn't" )
2015-01-15 17:49:48 +03:00
}
2015-03-21 22:43:14 +03:00
removeLogTimestamps := func ( s string ) string {
return regexp . MustCompile ( ` time="(.*?)" ` ) . ReplaceAllString ( s , ` time=[TIMESTAMP] ` )
}
2015-01-15 17:49:48 +03:00
// Skip over the times
2015-03-21 22:43:14 +03:00
e1 := removeLogTimestamps ( err1 . Error ( ) )
e2 := removeLogTimestamps ( err2 . Error ( ) )
2015-01-15 17:49:48 +03:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 2's error wasn't the same as build 1's\n1:%s\n2:%s" , err1 , err2 )
2015-01-15 17:49:48 +03:00
}
2015-02-08 06:30:44 +03:00
ctx . Add ( "Dockerfile" , "FROM busybox\n COPY" )
2015-01-15 17:49:48 +03:00
if _ , err2 = buildImageFromContext ( name , ctx , false ) ; err2 == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build 3 was supposed to fail, but didn't" )
2015-01-15 17:49:48 +03:00
}
// Skip over the times
2015-03-21 22:43:14 +03:00
e1 = removeLogTimestamps ( err1 . Error ( ) )
e2 = removeLogTimestamps ( err2 . Error ( ) )
2015-01-15 17:49:48 +03:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 3's error wasn't the same as build 1's\n1:%s\n3:%s" , err1 , err2 )
2015-01-15 17:49:48 +03:00
}
2015-02-08 06:30:44 +03:00
ctx . Add ( "Dockerfile" , "FROM busybox\n COPY " )
2015-01-15 17:49:48 +03:00
if _ , err2 = buildImageFromContext ( name , ctx , false ) ; err2 == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build 4 was supposed to fail, but didn't" )
2015-01-15 17:49:48 +03:00
}
// Skip over the times
2015-03-21 22:43:14 +03:00
e1 = removeLogTimestamps ( err1 . Error ( ) )
e2 = removeLogTimestamps ( err2 . Error ( ) )
2015-01-15 17:49:48 +03:00
// Ignore whitespace since that's what were verifying doesn't change stuff
if strings . Replace ( e1 , " " , "" , - 1 ) != strings . Replace ( e2 , " " , "" , - 1 ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build 4's error wasn't the same as build 1's\n1:%s\n4:%s" , err1 , err2 )
2015-01-15 17:49:48 +03:00
}
}
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildSpacesWithQuotes ( c * check . C ) {
2015-01-15 17:49:48 +03:00
// Test to make sure that spaces in quotes aren't lost
name := "testspacesquotes"
defer deleteImages ( name )
dockerfile := ` FROM busybox
RUN echo " \
foo " `
_ , out , err := buildImageWithOut ( name , dockerfile , false )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Build failed:" , err )
2015-01-15 17:49:48 +03:00
}
expecting := "\n foo \n"
if ! strings . Contains ( out , expecting ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Bad output: %q expecting to contian %q" , out , expecting )
2015-01-15 17:49:48 +03:00
}
}
2015-01-15 06:30:28 +03:00
// #4393
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildVolumeFileExistsinContainer ( c * check . C ) {
2015-01-15 06:30:28 +03:00
buildCmd := exec . Command ( dockerBinary , "build" , "-t" , "docker-test-errcreatevolumewithfile" , "-" )
buildCmd . Stdin = strings . NewReader ( `
FROM busybox
RUN touch / foo
VOLUME / foo
` )
out , _ , err := runCommandWithOutput ( buildCmd )
if err == nil || ! strings . Contains ( out , "file exists" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "expected build to fail when file exists in container at requested volume path" )
2015-01-15 06:30:28 +03:00
}
}
2015-02-04 20:34:25 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildMissingArgs ( c * check . C ) {
2015-02-08 06:30:44 +03:00
// Test to make sure that all Dockerfile commands (except the ones listed
// in skipCmds) will generate an error if no args are provided.
// Note: INSERT is deprecated so we exclude it because of that.
skipCmds := map [ string ] struct { } {
"CMD" : { } ,
"RUN" : { } ,
"ENTRYPOINT" : { } ,
"INSERT" : { } ,
2015-02-04 20:34:25 +03:00
}
2015-02-20 13:38:55 +03:00
for cmd := range command . Commands {
2015-02-08 06:30:44 +03:00
cmd = strings . ToUpper ( cmd )
if _ , ok := skipCmds [ cmd ] ; ok {
continue
}
2015-02-12 08:18:48 +03:00
var dockerfile string
2015-02-04 20:34:25 +03:00
if cmd == "FROM" {
dockerfile = cmd
} else {
// Add FROM to make sure we don't complain about it missing
dockerfile = "FROM busybox\n" + cmd
}
ctx , err := fakeContext ( dockerfile , map [ string ] string { } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-04 20:34:25 +03:00
}
defer ctx . Close ( )
var out string
if out , err = buildImageFromContext ( "args" , ctx , true ) ; err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s was supposed to fail. Out:%s" , cmd , out )
2015-02-04 20:34:25 +03:00
}
if ! strings . Contains ( err . Error ( ) , cmd + " requires" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "%s returned the wrong type of error:%s" , cmd , err )
2015-02-04 20:34:25 +03:00
}
}
}
2015-02-10 22:10:10 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyScratch ( c * check . C ) {
2015-02-10 22:10:10 +03:00
defer deleteImages ( "sc" )
_ , out , err := buildImageWithOut ( "sc" , "FROM scratch" , true )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build was supposed to fail" )
2015-02-10 22:10:10 +03:00
}
if ! strings . Contains ( out , "No image was generated" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Wrong error message: %v" , out )
2015-02-10 22:10:10 +03:00
}
}
2015-02-17 05:38:52 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildDotDotFile ( c * check . C ) {
2015-02-17 05:38:52 +03:00
defer deleteImages ( "sc" )
ctx , err := fakeContext ( "FROM busybox\n" ,
map [ string ] string {
"..gitme" : "" ,
} )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-17 05:38:52 +03:00
}
defer ctx . Close ( )
if _ , err = buildImageFromContext ( "sc" , ctx , false ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Build was supposed to work: %s" , err )
2015-02-17 05:38:52 +03:00
}
}
2015-02-21 00:26:11 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildNotVerbose ( c * check . C ) {
2015-02-21 00:26:11 +03:00
defer deleteImages ( "verbose" )
ctx , err := fakeContext ( "FROM busybox\nENV abc=hi\nRUN echo $abc there" , map [ string ] string { } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-21 00:26:11 +03:00
}
defer ctx . Close ( )
// First do it w/verbose - baseline
buildCmd := exec . Command ( dockerBinary , "build" , "--no-cache" , "-t" , "verbose" , "." )
buildCmd . Dir = ctx . Dir
out , _ , err := runCommandWithOutput ( buildCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to build the image w/o -q: %s, %v" , out , err )
2015-02-21 00:26:11 +03:00
}
if ! strings . Contains ( out , "hi there" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "missing output:%s\n" , out )
2015-02-21 00:26:11 +03:00
}
// Now do it w/o verbose
buildCmd = exec . Command ( dockerBinary , "build" , "--no-cache" , "-q" , "-t" , "verbose" , "." )
buildCmd . Dir = ctx . Dir
out , _ , err = runCommandWithOutput ( buildCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to build the image w/ -q: %s, %v" , out , err )
2015-02-21 00:26:11 +03:00
}
if strings . Contains ( out , "hi there" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "Bad output, should not contain 'hi there':%s" , out )
2015-02-21 00:26:11 +03:00
}
}
2015-03-10 00:44:14 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildRUNoneJSON ( c * check . C ) {
2015-03-10 00:44:14 +03:00
name := "testbuildrunonejson"
2015-03-24 01:16:13 +03:00
defer deleteImages ( name , "hello-world" )
2015-03-10 00:44:14 +03:00
2015-03-16 22:22:00 +03:00
ctx , err := fakeContext ( ` FROM hello - world : frozen
2015-03-10 00:44:14 +03:00
RUN [ "/hello" ] ` , map [ string ] string { } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-03-10 00:44:14 +03:00
}
defer ctx . Close ( )
buildCmd := exec . Command ( dockerBinary , "build" , "--no-cache" , "-t" , name , "." )
buildCmd . Dir = ctx . Dir
out , _ , err := runCommandWithOutput ( buildCmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "failed to build the image: %s, %v" , out , err )
2015-03-10 00:44:14 +03:00
}
if ! strings . Contains ( out , "Hello from Docker" ) {
2015-04-18 19:46:47 +03:00
c . Fatalf ( "bad output: %s" , out )
2015-03-10 00:44:14 +03:00
}
}
2015-02-06 17:33:01 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildResourceConstraintsAreUsed ( c * check . C ) {
2015-02-06 17:33:01 +03:00
name := "testbuildresourceconstraints"
2015-03-24 01:16:13 +03:00
defer deleteImages ( name , "hello-world" )
2015-02-06 17:33:01 +03:00
ctx , err := fakeContext ( `
FROM hello - world : frozen
RUN [ "/hello" ]
` , map [ string ] string { } )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-06 17:33:01 +03:00
}
2015-04-24 03:54:08 +03:00
cmd := exec . Command ( dockerBinary , "build" , "--no-cache" , "--rm=false" , "--memory=64m" , "--memory-swap=-1" , "--cpuset-cpus=0" , "--cpuset-mems=0" , "--cpu-shares=100" , "--cpu-quota=8000" , "-t" , name , "." )
2015-02-06 17:33:01 +03:00
cmd . Dir = ctx . Dir
out , _ , err := runCommandWithOutput ( cmd )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , out )
2015-02-06 17:33:01 +03:00
}
2015-04-18 19:46:47 +03:00
out , _ = dockerCmd ( c , "ps" , "-lq" )
2015-02-06 17:33:01 +03:00
2015-04-06 16:21:18 +03:00
cID := strings . TrimSpace ( out )
2015-02-06 17:33:01 +03:00
type hostConfig struct {
2015-04-23 04:28:07 +03:00
Memory int64
MemorySwap int64
2015-02-06 17:33:01 +03:00
CpusetCpus string
2015-04-14 05:00:48 +03:00
CpusetMems string
2015-04-23 04:28:07 +03:00
CpuShares int64
2015-04-24 03:54:08 +03:00
CpuQuota int64
2015-02-06 17:33:01 +03:00
}
cfg , err := inspectFieldJSON ( cID , "HostConfig" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-06 17:33:01 +03:00
}
var c1 hostConfig
if err := json . Unmarshal ( [ ] byte ( cfg ) , & c1 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , cfg )
2015-02-06 17:33:01 +03:00
}
2015-04-24 03:54:08 +03:00
if c1 . Memory != 67108864 || c1 . MemorySwap != - 1 || c1 . CpusetCpus != "0" || c1 . CpusetMems != "0" || c1 . CpuShares != 100 || c1 . CpuQuota != 8000 {
c . Fatalf ( "resource constraints not set properly:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d" ,
c1 . Memory , c1 . MemorySwap , c1 . CpusetCpus , c1 . CpusetMems , c1 . CpuShares , c1 . CpuQuota )
2015-02-06 17:33:01 +03:00
}
// Make sure constraints aren't saved to image
2015-04-18 19:46:47 +03:00
_ , _ = dockerCmd ( c , "run" , "--name=test" , name )
2015-04-14 08:16:19 +03:00
2015-02-06 17:33:01 +03:00
cfg , err = inspectFieldJSON ( "test" , "HostConfig" )
if err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err )
2015-02-06 17:33:01 +03:00
}
var c2 hostConfig
if err := json . Unmarshal ( [ ] byte ( cfg ) , & c2 ) ; err != nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( err , cfg )
2015-02-06 17:33:01 +03:00
}
2015-04-24 03:54:08 +03:00
if c2 . Memory == 67108864 || c2 . MemorySwap == - 1 || c2 . CpusetCpus == "0" || c2 . CpusetMems == "0" || c2 . CpuShares == 100 || c2 . CpuQuota == 8000 {
c . Fatalf ( "resource constraints leaked from build:\nMemory: %d, MemSwap: %d, CpusetCpus: %s, CpusetMems: %s, CpuShares: %d, CpuQuota: %d" ,
c2 . Memory , c2 . MemorySwap , c2 . CpusetCpus , c2 . CpusetMems , c2 . CpuShares , c2 . CpuQuota )
2015-02-06 17:33:01 +03:00
}
}
2015-03-21 07:39:49 +03:00
2015-04-18 19:46:47 +03:00
func ( s * DockerSuite ) TestBuildEmptyStringVolume ( c * check . C ) {
2015-03-21 07:39:49 +03:00
name := "testbuildemptystringvolume"
defer deleteImages ( name )
_ , err := buildImage ( name , `
FROM busybox
ENV foo = ""
VOLUME $ foo
` , false )
if err == nil {
2015-04-18 19:46:47 +03:00
c . Fatal ( "Should have failed to build" )
2015-03-21 07:39:49 +03:00
}
}