docker_utils.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "net/http/httptest"
  7. "os"
  8. "os/exec"
  9. "path"
  10. "strconv"
  11. "strings"
  12. "testing"
  13. )
  14. func deleteContainer(container string) error {
  15. container = strings.Replace(container, "\n", " ", -1)
  16. container = strings.Trim(container, " ")
  17. killArgs := fmt.Sprintf("kill %v", container)
  18. killSplitArgs := strings.Split(killArgs, " ")
  19. killCmd := exec.Command(dockerBinary, killSplitArgs...)
  20. runCommand(killCmd)
  21. rmArgs := fmt.Sprintf("rm %v", container)
  22. rmSplitArgs := strings.Split(rmArgs, " ")
  23. rmCmd := exec.Command(dockerBinary, rmSplitArgs...)
  24. exitCode, err := runCommand(rmCmd)
  25. // set error manually if not set
  26. if exitCode != 0 && err == nil {
  27. err = fmt.Errorf("failed to remove container: `docker rm` exit is non-zero")
  28. }
  29. return err
  30. }
  31. func getAllContainers() (string, error) {
  32. getContainersCmd := exec.Command(dockerBinary, "ps", "-q", "-a")
  33. out, exitCode, err := runCommandWithOutput(getContainersCmd)
  34. if exitCode != 0 && err == nil {
  35. err = fmt.Errorf("failed to get a list of containers: %v\n", out)
  36. }
  37. return out, err
  38. }
  39. func deleteAllContainers() error {
  40. containers, err := getAllContainers()
  41. if err != nil {
  42. fmt.Println(containers)
  43. return err
  44. }
  45. if err = deleteContainer(containers); err != nil {
  46. return err
  47. }
  48. return nil
  49. }
  50. func deleteImages(images string) error {
  51. rmiCmd := exec.Command(dockerBinary, "rmi", images)
  52. exitCode, err := runCommand(rmiCmd)
  53. // set error manually if not set
  54. if exitCode != 0 && err == nil {
  55. err = fmt.Errorf("failed to remove image: `docker rmi` exit is non-zero")
  56. }
  57. return err
  58. }
  59. func imageExists(image string) error {
  60. inspectCmd := exec.Command(dockerBinary, "inspect", image)
  61. exitCode, err := runCommand(inspectCmd)
  62. if exitCode != 0 && err == nil {
  63. err = fmt.Errorf("couldn't find image '%s'", image)
  64. }
  65. return err
  66. }
  67. func pullImageIfNotExist(image string) (err error) {
  68. if err := imageExists(image); err != nil {
  69. pullCmd := exec.Command(dockerBinary, "pull", image)
  70. _, exitCode, err := runCommandWithOutput(pullCmd)
  71. if err != nil || exitCode != 0 {
  72. err = fmt.Errorf("image '%s' wasn't found locally and it couldn't be pulled: %s", image, err)
  73. }
  74. }
  75. return
  76. }
  77. func cmd(t *testing.T, args ...string) (string, int, error) {
  78. out, status, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
  79. errorOut(err, t, fmt.Sprintf("'%s' failed with errors: %v (%v)", strings.Join(args, " "), err, out))
  80. return out, status, err
  81. }
  82. func findContainerIp(t *testing.T, id string) string {
  83. cmd := exec.Command(dockerBinary, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
  84. out, _, err := runCommandWithOutput(cmd)
  85. if err != nil {
  86. t.Fatal(err, out)
  87. }
  88. return strings.Trim(out, " \r\n'")
  89. }
  90. func getContainerCount() (int, error) {
  91. const containers = "Containers:"
  92. cmd := exec.Command(dockerBinary, "info")
  93. out, _, err := runCommandWithOutput(cmd)
  94. if err != nil {
  95. return 0, err
  96. }
  97. lines := strings.Split(out, "\n")
  98. for _, line := range lines {
  99. if strings.Contains(line, containers) {
  100. output := stripTrailingCharacters(line)
  101. output = strings.TrimLeft(output, containers)
  102. output = strings.Trim(output, " ")
  103. containerCount, err := strconv.Atoi(output)
  104. if err != nil {
  105. return 0, err
  106. }
  107. return containerCount, nil
  108. }
  109. }
  110. return 0, fmt.Errorf("couldn't find the Container count in the output")
  111. }
  112. type FakeContext struct {
  113. Dir string
  114. }
  115. func (f *FakeContext) Add(file, content string) error {
  116. filepath := path.Join(f.Dir, file)
  117. dirpath := path.Dir(filepath)
  118. if dirpath != "." {
  119. if err := os.MkdirAll(dirpath, 0755); err != nil {
  120. return err
  121. }
  122. }
  123. return ioutil.WriteFile(filepath, []byte(content), 0644)
  124. }
  125. func (f *FakeContext) Delete(file string) error {
  126. filepath := path.Join(f.Dir, file)
  127. return os.RemoveAll(filepath)
  128. }
  129. func (f *FakeContext) Close() error {
  130. return os.RemoveAll(f.Dir)
  131. }
  132. func fakeContext(dockerfile string, files map[string]string) (*FakeContext, error) {
  133. tmp, err := ioutil.TempDir("", "fake-context")
  134. if err != nil {
  135. return nil, err
  136. }
  137. ctx := &FakeContext{tmp}
  138. for file, content := range files {
  139. if err := ctx.Add(file, content); err != nil {
  140. ctx.Close()
  141. return nil, err
  142. }
  143. }
  144. if err := ctx.Add("Dockerfile", dockerfile); err != nil {
  145. ctx.Close()
  146. return nil, err
  147. }
  148. return ctx, nil
  149. }
  150. type FakeStorage struct {
  151. *FakeContext
  152. *httptest.Server
  153. }
  154. func (f *FakeStorage) Close() error {
  155. f.Server.Close()
  156. return f.FakeContext.Close()
  157. }
  158. func fakeStorage(files map[string]string) (*FakeStorage, error) {
  159. tmp, err := ioutil.TempDir("", "fake-storage")
  160. if err != nil {
  161. return nil, err
  162. }
  163. ctx := &FakeContext{tmp}
  164. for file, content := range files {
  165. if err := ctx.Add(file, content); err != nil {
  166. ctx.Close()
  167. return nil, err
  168. }
  169. }
  170. handler := http.FileServer(http.Dir(ctx.Dir))
  171. server := httptest.NewServer(handler)
  172. return &FakeStorage{
  173. FakeContext: ctx,
  174. Server: server,
  175. }, nil
  176. }
  177. func inspectField(name, field string) (string, error) {
  178. format := fmt.Sprintf("{{.%s}}", field)
  179. inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name)
  180. out, exitCode, err := runCommandWithOutput(inspectCmd)
  181. if err != nil || exitCode != 0 {
  182. return "", fmt.Errorf("failed to inspect %s: %s", name, out)
  183. }
  184. return strings.TrimSpace(out), nil
  185. }
  186. func getIDByName(name string) (string, error) {
  187. return inspectField(name, "Id")
  188. }
  189. func buildImage(name, dockerfile string, useCache bool) (string, error) {
  190. args := []string{"build", "-t", name}
  191. if !useCache {
  192. args = append(args, "--no-cache")
  193. }
  194. args = append(args, "-")
  195. buildCmd := exec.Command(dockerBinary, args...)
  196. buildCmd.Stdin = strings.NewReader(dockerfile)
  197. out, exitCode, err := runCommandWithOutput(buildCmd)
  198. if err != nil || exitCode != 0 {
  199. return "", fmt.Errorf("failed to build the image: %s", out)
  200. }
  201. return getIDByName(name)
  202. }
  203. func buildImageFromContext(name string, ctx *FakeContext, useCache bool) (string, error) {
  204. args := []string{"build", "-t", name}
  205. if !useCache {
  206. args = append(args, "--no-cache")
  207. }
  208. args = append(args, ".")
  209. buildCmd := exec.Command(dockerBinary, args...)
  210. buildCmd.Dir = ctx.Dir
  211. out, exitCode, err := runCommandWithOutput(buildCmd)
  212. if err != nil || exitCode != 0 {
  213. return "", fmt.Errorf("failed to build the image: %s", out)
  214. }
  215. return getIDByName(name)
  216. }