docker_cli_build_test.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "path/filepath"
  7. "strings"
  8. "testing"
  9. )
  10. func TestBuildSixtySteps(t *testing.T) {
  11. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildSixtySteps")
  12. buildCmd := exec.Command(dockerBinary, "build", "-t", "foobuildsixtysteps", ".")
  13. buildCmd.Dir = buildDirectory
  14. out, exitCode, err := runCommandWithOutput(buildCmd)
  15. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  16. if err != nil || exitCode != 0 {
  17. t.Fatal("failed to build the image")
  18. }
  19. deleteImages("foobuildsixtysteps")
  20. logDone("build - build an image with sixty build steps")
  21. }
  22. func TestAddSingleFileToRoot(t *testing.T) {
  23. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  24. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToRoot")
  25. buildCmd.Dir = buildDirectory
  26. out, exitCode, err := runCommandWithOutput(buildCmd)
  27. errorOut(err, t, fmt.Sprintf("build failed to complete: %v %v", out, err))
  28. if err != nil || exitCode != 0 {
  29. t.Fatal("failed to build the image")
  30. }
  31. deleteImages("testaddimg")
  32. logDone("build - add single file to root")
  33. }
  34. func TestAddSingleFileToExistDir(t *testing.T) {
  35. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  36. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToExistDir")
  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("testaddimg")
  44. logDone("build - add single file to existing dir")
  45. }
  46. func TestAddSingleFileToNonExistDir(t *testing.T) {
  47. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  48. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "SingleFileToNonExistDir")
  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 non-existing dir")
  57. }
  58. func TestAddDirContentToRoot(t *testing.T) {
  59. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  60. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToRoot")
  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 directory contents to root")
  69. }
  70. func TestAddDirContentToExistDir(t *testing.T) {
  71. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  72. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "DirContentToExistDir")
  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 directory contents to existing dir")
  81. }
  82. func TestAddWholeDirToRoot(t *testing.T) {
  83. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestAdd")
  84. buildCmd := exec.Command(dockerBinary, "build", "-t", "testaddimg", "WholeDirToRoot")
  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 whole directory to root")
  93. }
  94. // Issue #5270 - ensure we throw a better error than "unexpected EOF"
  95. // when we can't access files in the context.
  96. func TestBuildWithInaccessibleFilesInContext(t *testing.T) {
  97. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildWithInaccessibleFilesInContext")
  98. addUserCmd := exec.Command("adduser", "unprivilegeduser")
  99. out, _, err := runCommandWithOutput(addUserCmd)
  100. errorOut(err, t, fmt.Sprintf("failed to add user: %v %v", out, err))
  101. {
  102. // This is used to ensure we detect inaccessible files early during build in the cli client
  103. pathToInaccessibleFileBuildDirectory := filepath.Join(buildDirectory, "inaccessiblefile")
  104. pathToFileWithoutReadAccess := filepath.Join(pathToInaccessibleFileBuildDirectory, "fileWithoutReadAccess")
  105. err = os.Chown(pathToFileWithoutReadAccess, 0, 0)
  106. errorOut(err, t, fmt.Sprintf("failed to chown file to root: %s", err))
  107. err = os.Chmod(pathToFileWithoutReadAccess, 0700)
  108. errorOut(err, t, fmt.Sprintf("failed to chmod file to 700: %s", err))
  109. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  110. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  111. buildCmd.Dir = pathToInaccessibleFileBuildDirectory
  112. out, exitCode, err := runCommandWithOutput(buildCmd)
  113. if err == nil || exitCode == 0 {
  114. t.Fatalf("build should have failed: %s %s", err, out)
  115. }
  116. // check if we've detected the failure before we started building
  117. if !strings.Contains(out, "no permission to read from ") {
  118. t.Fatalf("output should've contained the string: no permission to read from ")
  119. }
  120. if !strings.Contains(out, "Error checking context is accessible") {
  121. t.Fatalf("output should've contained the string: Error checking context is accessible")
  122. }
  123. }
  124. {
  125. // This is used to ensure we detect inaccessible directories early during build in the cli client
  126. pathToInaccessibleDirectoryBuildDirectory := filepath.Join(buildDirectory, "inaccessibledirectory")
  127. pathToDirectoryWithoutReadAccess := filepath.Join(pathToInaccessibleDirectoryBuildDirectory, "directoryWeCantStat")
  128. pathToFileInDirectoryWithoutReadAccess := filepath.Join(pathToDirectoryWithoutReadAccess, "bar")
  129. err = os.Chown(pathToDirectoryWithoutReadAccess, 0, 0)
  130. errorOut(err, t, fmt.Sprintf("failed to chown directory to root: %s", err))
  131. err = os.Chmod(pathToDirectoryWithoutReadAccess, 0444)
  132. errorOut(err, t, fmt.Sprintf("failed to chmod directory to 755: %s", err))
  133. err = os.Chmod(pathToFileInDirectoryWithoutReadAccess, 0700)
  134. errorOut(err, t, fmt.Sprintf("failed to chmod file to 444: %s", err))
  135. buildCommandStatement := fmt.Sprintf("%s build -t inaccessiblefiles .", dockerBinary)
  136. buildCmd := exec.Command("su", "unprivilegeduser", "-c", buildCommandStatement)
  137. buildCmd.Dir = pathToInaccessibleDirectoryBuildDirectory
  138. out, exitCode, err := runCommandWithOutput(buildCmd)
  139. if err == nil || exitCode == 0 {
  140. t.Fatalf("build should have failed: %s %s", err, out)
  141. }
  142. // check if we've detected the failure before we started building
  143. if !strings.Contains(out, "can't stat") {
  144. t.Fatalf("output should've contained the string: can't access %s", out)
  145. }
  146. if !strings.Contains(out, "Error checking context is accessible") {
  147. t.Fatalf("output should've contained the string: Error checking context is accessible")
  148. }
  149. }
  150. {
  151. // This is used to ensure we don't follow links when checking if everything in the context is accessible
  152. // This test doesn't require that we run commands as an unprivileged user
  153. pathToDirectoryWhichContainsLinks := filepath.Join(buildDirectory, "linksdirectory")
  154. buildCmd := exec.Command(dockerBinary, "build", "-t", "testlinksok", ".")
  155. buildCmd.Dir = pathToDirectoryWhichContainsLinks
  156. out, exitCode, err := runCommandWithOutput(buildCmd)
  157. if err != nil || exitCode != 0 {
  158. t.Fatalf("build should have worked: %s %s", err, out)
  159. }
  160. deleteImages("testlinksok")
  161. }
  162. deleteImages("inaccessiblefiles")
  163. logDone("build - ADD from context with inaccessible files must fail")
  164. logDone("build - ADD from context with accessible links must work")
  165. }
  166. func TestBuildForceRm(t *testing.T) {
  167. containerCountBefore, err := getContainerCount()
  168. if err != nil {
  169. t.Fatalf("failed to get the container count: %s", err)
  170. }
  171. buildDirectory := filepath.Join(workingDirectory, "build_tests", "TestBuildForceRm")
  172. buildCmd := exec.Command(dockerBinary, "build", "--force-rm", ".")
  173. buildCmd.Dir = buildDirectory
  174. _, exitCode, err := runCommandWithOutput(buildCmd)
  175. if err == nil || exitCode == 0 {
  176. t.Fatal("failed to build the image")
  177. }
  178. containerCountAfter, err := getContainerCount()
  179. if err != nil {
  180. t.Fatalf("failed to get the container count: %s", err)
  181. }
  182. if containerCountBefore != containerCountAfter {
  183. t.Fatalf("--force-rm shouldn't have left containers behind")
  184. }
  185. logDone("build - ensure --force-rm doesn't leave containers behind")
  186. }
  187. // TODO: TestCaching
  188. // TODO: TestADDCacheInvalidation