docker_utils.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. // deprecated, use dockerCmd instead
  78. func cmd(t *testing.T, args ...string) (string, int, error) {
  79. return dockerCmd(t, args...)
  80. }
  81. func dockerCmd(t *testing.T, args ...string) (string, int, error) {
  82. out, status, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
  83. errorOut(err, t, fmt.Sprintf("'%s' failed with errors: %v (%v)", strings.Join(args, " "), err, out))
  84. return out, status, err
  85. }
  86. // execute a docker command in a directory
  87. func dockerCmdInDir(t *testing.T, path string, args ...string) (string, int, error) {
  88. dockerCommand := exec.Command(dockerBinary, args...)
  89. dockerCommand.Dir = path
  90. out, status, err := runCommandWithOutput(dockerCommand)
  91. errorOut(err, t, fmt.Sprintf("'%s' failed with errors: %v (%v)", strings.Join(args, " "), err, out))
  92. return out, status, err
  93. }
  94. func findContainerIp(t *testing.T, id string) string {
  95. cmd := exec.Command(dockerBinary, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
  96. out, _, err := runCommandWithOutput(cmd)
  97. if err != nil {
  98. t.Fatal(err, out)
  99. }
  100. return strings.Trim(out, " \r\n'")
  101. }
  102. func getContainerCount() (int, error) {
  103. const containers = "Containers:"
  104. cmd := exec.Command(dockerBinary, "info")
  105. out, _, err := runCommandWithOutput(cmd)
  106. if err != nil {
  107. return 0, err
  108. }
  109. lines := strings.Split(out, "\n")
  110. for _, line := range lines {
  111. if strings.Contains(line, containers) {
  112. output := stripTrailingCharacters(line)
  113. output = strings.TrimLeft(output, containers)
  114. output = strings.Trim(output, " ")
  115. containerCount, err := strconv.Atoi(output)
  116. if err != nil {
  117. return 0, err
  118. }
  119. return containerCount, nil
  120. }
  121. }
  122. return 0, fmt.Errorf("couldn't find the Container count in the output")
  123. }
  124. type FakeContext struct {
  125. Dir string
  126. }
  127. func (f *FakeContext) Add(file, content string) error {
  128. filepath := path.Join(f.Dir, file)
  129. dirpath := path.Dir(filepath)
  130. if dirpath != "." {
  131. if err := os.MkdirAll(dirpath, 0755); err != nil {
  132. return err
  133. }
  134. }
  135. return ioutil.WriteFile(filepath, []byte(content), 0644)
  136. }
  137. func (f *FakeContext) Delete(file string) error {
  138. filepath := path.Join(f.Dir, file)
  139. return os.RemoveAll(filepath)
  140. }
  141. func (f *FakeContext) Close() error {
  142. return os.RemoveAll(f.Dir)
  143. }
  144. func fakeContext(dockerfile string, files map[string]string) (*FakeContext, error) {
  145. tmp, err := ioutil.TempDir("", "fake-context")
  146. if err != nil {
  147. return nil, err
  148. }
  149. ctx := &FakeContext{tmp}
  150. for file, content := range files {
  151. if err := ctx.Add(file, content); err != nil {
  152. ctx.Close()
  153. return nil, err
  154. }
  155. }
  156. if err := ctx.Add("Dockerfile", dockerfile); err != nil {
  157. ctx.Close()
  158. return nil, err
  159. }
  160. return ctx, nil
  161. }
  162. type FakeStorage struct {
  163. *FakeContext
  164. *httptest.Server
  165. }
  166. func (f *FakeStorage) Close() error {
  167. f.Server.Close()
  168. return f.FakeContext.Close()
  169. }
  170. func fakeStorage(files map[string]string) (*FakeStorage, error) {
  171. tmp, err := ioutil.TempDir("", "fake-storage")
  172. if err != nil {
  173. return nil, err
  174. }
  175. ctx := &FakeContext{tmp}
  176. for file, content := range files {
  177. if err := ctx.Add(file, content); err != nil {
  178. ctx.Close()
  179. return nil, err
  180. }
  181. }
  182. handler := http.FileServer(http.Dir(ctx.Dir))
  183. server := httptest.NewServer(handler)
  184. return &FakeStorage{
  185. FakeContext: ctx,
  186. Server: server,
  187. }, nil
  188. }
  189. func inspectField(name, field string) (string, error) {
  190. format := fmt.Sprintf("{{.%s}}", field)
  191. inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name)
  192. out, exitCode, err := runCommandWithOutput(inspectCmd)
  193. if err != nil || exitCode != 0 {
  194. return "", fmt.Errorf("failed to inspect %s: %s", name, out)
  195. }
  196. return strings.TrimSpace(out), nil
  197. }
  198. func inspectFieldJSON(name, field string) (string, error) {
  199. format := fmt.Sprintf("{{json .%s}}", field)
  200. inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name)
  201. out, exitCode, err := runCommandWithOutput(inspectCmd)
  202. if err != nil || exitCode != 0 {
  203. return "", fmt.Errorf("failed to inspect %s: %s", name, out)
  204. }
  205. return strings.TrimSpace(out), nil
  206. }
  207. func getIDByName(name string) (string, error) {
  208. return inspectField(name, "Id")
  209. }
  210. func buildImage(name, dockerfile string, useCache bool) (string, error) {
  211. args := []string{"build", "-t", name}
  212. if !useCache {
  213. args = append(args, "--no-cache")
  214. }
  215. args = append(args, "-")
  216. buildCmd := exec.Command(dockerBinary, args...)
  217. buildCmd.Stdin = strings.NewReader(dockerfile)
  218. out, exitCode, err := runCommandWithOutput(buildCmd)
  219. if err != nil || exitCode != 0 {
  220. return "", fmt.Errorf("failed to build the image: %s", out)
  221. }
  222. return getIDByName(name)
  223. }
  224. func buildImageFromContext(name string, ctx *FakeContext, useCache bool) (string, error) {
  225. args := []string{"build", "-t", name}
  226. if !useCache {
  227. args = append(args, "--no-cache")
  228. }
  229. args = append(args, ".")
  230. buildCmd := exec.Command(dockerBinary, args...)
  231. buildCmd.Dir = ctx.Dir
  232. out, exitCode, err := runCommandWithOutput(buildCmd)
  233. if err != nil || exitCode != 0 {
  234. return "", fmt.Errorf("failed to build the image: %s", out)
  235. }
  236. return getIDByName(name)
  237. }