docker_cli_build_test.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. )
  10. func TestBuildCacheADD(t *testing.T) {
  11. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "1")
  12. buildCmd := exec.Command(dockerBinary, "build", "-t", "testcacheadd1", ".")
  13. buildCmd.Dir = buildDirectory
  14. exitCode, err := runCommand(buildCmd)
  15. errorOut(err, t, fmt.Sprintf("build failed to complete: %v", err))
  16. if err != nil || exitCode != 0 {
  17. t.Fatal("failed to build the image")
  18. }
  19. buildDirectory = filepath.Join(workingDirectory, "build_tests", "TestBuildCacheADD", "2")
  20. buildCmd = exec.Command(dockerBinary, "build", "-t", "testcacheadd2", ".")
  21. buildCmd.Dir = buildDirectory
  22. out, exitCode, err := runCommandWithOutput(buildCmd)
  23. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  24. if err != nil || exitCode != 0 {
  25. t.Fatal("failed to build the image")
  26. }
  27. if strings.Contains(out, "Using cache") {
  28. t.Fatal("2nd build used cache on ADD, it shouldn't")
  29. }
  30. deleteImages("testcacheadd1")
  31. deleteImages("testcacheadd2")
  32. logDone("build - build two images with ADD")
  33. }
  34. func TestBuildSixtySteps(t *testing.T) {
  35. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildSixtySteps")
  36. buildCmd := exec.Command(dockerBinary, "build", "-t", "foobuildsixtysteps", ".")
  37. buildCmd.Dir = buildDirectory
  38. out, exitCode, err := runCommandWithOutput(buildCmd)
  39. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  40. if err != nil || exitCode != 0 {
  41. t.Fatal("failed to build the image")
  42. }
  43. deleteImages("foobuildsixtysteps")
  44. logDone("build - build an image with sixty build steps")
  45. }
  46. func TestAddSingleFileToRoot(t *testing.T) {
  47. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  48. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToRoot")
  49. buildCmd.Dir = buildDirectory
  50. out, exitCode, err := runCommandWithOutput(buildCmd)
  51. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  52. if err != nil || exitCode != 0 {
  53. t.Fatal("failed to build the image")
  54. }
  55. deleteImages("testaddimg")
  56. logDone("build - add single file to root")
  57. }
  58. func TestAddSingleFileToExistDir(t *testing.T) {
  59. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  60. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToExistDir")
  61. buildCmd.Dir = buildDirectory
  62. out, exitCode, err := runCommandWithOutput(buildCmd)
  63. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  64. if err != nil || exitCode != 0 {
  65. t.Fatal("failed to build the image")
  66. }
  67. deleteImages("testaddimg")
  68. logDone("build - add single file to existing dir")
  69. }
  70. func TestAddSingleFileToNonExistDir(t *testing.T) {
  71. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  72. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToNonExistDir")
  73. buildCmd.Dir = buildDirectory
  74. out, exitCode, err := runCommandWithOutput(buildCmd)
  75. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  76. if err != nil || exitCode != 0 {
  77. t.Fatal("failed to build the image")
  78. }
  79. deleteImages("testaddimg")
  80. logDone("build - add single file to non-existing dir")
  81. }
  82. func TestAddDirContentToRoot(t *testing.T) {
  83. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  84. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToRoot")
  85. buildCmd.Dir = buildDirectory
  86. out, exitCode, err := runCommandWithOutput(buildCmd)
  87. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  88. if err != nil || exitCode != 0 {
  89. t.Fatal("failed to build the image")
  90. }
  91. deleteImages("testaddimg")
  92. logDone("build - add directory contents to root")
  93. }
  94. func TestAddDirContentToExistDir(t *testing.T) {
  95. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  96. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToExistDir")
  97. buildCmd.Dir = buildDirectory
  98. out, exitCode, err := runCommandWithOutput(buildCmd)
  99. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  100. if err != nil || exitCode != 0 {
  101. t.Fatal("failed to build the image")
  102. }
  103. deleteImages("testaddimg")
  104. logDone("build - add directory contents to existing dir")
  105. }
  106. func TestAddWholeDirToRoot(t *testing.T) {
  107. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  108. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "WholeDirToRoot")
  109. buildCmd.Dir = buildDirectory
  110. out, exitCode, err := runCommandWithOutput(buildCmd)
  111. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  112. if err != nil || exitCode != 0 {
  113. t.Fatal("failed to build the image")
  114. }
  115. deleteImages("testaddimg")
  116. logDone("build - add whole directory to root")
  117. }
  118. func TestAddEtcToRoot(t *testing.T) {
  119. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  120. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "EtcToRoot")
  121. buildCmd.Dir = buildDirectory
  122. out, exitCode, err := runCommandWithOutput(buildCmd)
  123. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  124. if err != nil || exitCode != 0 {
  125. t.Fatal("failed to build the image")
  126. }
  127. deleteImages("testaddimg")
  128. logDone("build - add etc directory to root")
  129. }
  130. // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  131. // when we can't access files in the context.
  132. func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  133. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildWithInaccessibleFilesInContext")
  134. {
  135. // This is used to ensure we detect inaccessible files early during build in the cli client
  136. pathToInaccessibleFileBuildDirectory := filepath.Join(buildDirectory, "inaccessiblefile")
  137. pathToFileWithoutReadAccess := filepath.Join(pathToInaccessibleFileBuildDirectory, "fileWithoutReadAccess")
  138. err := os.Chown(pathToFileWithoutReadAccess, 0, 0)
  139. errorOut(err, t, fmt.Sprintf("failed to chown file to root: %s", err))
  140. err = os.Chmod(pathToFileWithoutReadAccess, 0700)
  141. errorOut(err, t, fmt.Sprintf("failed to chmod file to 700: %s", err))
  142. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  143. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  144. buildCmd.Dir = pathToInaccessibleFileBuildDirectory
  145. out, exitCode, err := runCommandWithOutput(buildCmd)
  146. if err == nil || exitCode == 0 {
  147. t.Fatalf("build should have failed: %s %s", err, out)
  148. }
  149. // check if we've detected the failure before we started building
  150. if !strings.Contains(out, "no permission to read from ") {
  151. t.Fatalf("output should've contained the string: no permission to read from ")
  152. }
  153. if !strings.Contains(out, "Error checking context is accessible") {
  154. t.Fatalf("output should've contained the string: Error checking context is accessible")
  155. }
  156. }
  157. {
  158. // This is used to ensure we detect inaccessible directories early during build in the cli client
  159. pathToInaccessibleDirectoryBuildDirectory := filepath.Join(buildDirectory, "inaccessibledirectory")
  160. pathToDirectoryWithoutReadAccess := filepath.Join(pathToInaccessibleDirectoryBuildDirectory, "directoryWeCantStat")
  161. pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  162. err := os.Chown(pathToDirectoryWithoutReadAccess, 0, 0)
  163. errorOut(err, t, fmt.Sprintf("failed to chown directory to root: %s", err))
  164. err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444)
  165. errorOut(err, t, fmt.Sprintf("failed to chmod directory to 755: %s", err))
  166. err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700)
  167. errorOut(err, t, fmt.Sprintf("failed to chmod file to 444: %s", err))
  168. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  169. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  170. buildCmd.Dir = pathToInaccessibleDirectoryBuildDirectory
  171. out, exitCode, err := runCommandWithOutput(buildCmd)
  172. if err == nil || exitCode == 0 {
  173. t.Fatalf("build should have failed: %s %s", err, out)
  174. }
  175. // check if we've detected the failure before we started building
  176. if !strings.Contains(out, "can't stat") {
  177. t.Fatalf("output should've contained the string: can't access %s", out)
  178. }
  179. if !strings.Contains(out, "Error checking context is accessible") {
  180. t.Fatalf("output should've contained the string: Error checking context is accessible")
  181. }
  182. }
  183. {
  184. // This is used to ensure we don't follow links when checking if everything in the context is accessible
  185. // This test doesn't require that we run commands as an unprivileged user
  186. pathToDirectoryWhichContainsLinks := filepath.Join(buildDirectory, "linksdirectory")
  187. buildCmd := exec.Command(dockerBinary, "build", "-t", "testlinksok", ".")
  188. buildCmd.Dir = pathToDirectoryWhichContainsLinks
  189. out, exitCode, err := runCommandWithOutput(buildCmd)
  190. if err != nil || exitCode != 0 {
  191. t.Fatalf("build should have worked: %s %s", err, out)
  192. }
  193. deleteImages("testlinksok")
  194. }
  195. deleteImages("inaccessiblefiles")
  196. logDone("build - ADD from context with inaccessible files must fail")
  197. logDone("build - ADD from context with accessible links must work")
  198. }
  199. // TODO: TestCaching
  200. // TODO: TestADDCacheInvalidation