docker_utils.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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 cmd(t *testing.T, args ...string) (string, int, error) {
  60. out, status, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
  61. errorOut(err, t, fmt.Sprintf("'%s' failed with errors: %v (%v)", strings.Join(args, " "), err, out))
  62. return out, status, err
  63. }
  64. func findContainerIp(t *testing.T, id string) string {
  65. cmd := exec.Command(dockerBinary, "inspect", "--format='{{ .NetworkSettings.IPAddress }}'", id)
  66. out, _, err := runCommandWithOutput(cmd)
  67. if err != nil {
  68. t.Fatal(err, out)
  69. }
  70. return strings.Trim(out, " \r\n'")
  71. }
  72. func getContainerCount() (int, error) {
  73. const containers = "Containers:"
  74. cmd := exec.Command(dockerBinary, "info")
  75. out, _, err := runCommandWithOutput(cmd)
  76. if err != nil {
  77. return 0, err
  78. }
  79. lines := strings.Split(out, "\n")
  80. for _, line := range lines {
  81. if strings.Contains(line, containers) {
  82. output := stripTrailingCharacters(line)
  83. output = strings.TrimLeft(output, containers)
  84. output = strings.Trim(output, " ")
  85. containerCount, err := strconv.Atoi(output)
  86. if err != nil {
  87. return 0, err
  88. }
  89. return containerCount, nil
  90. }
  91. }
  92. return 0, fmt.Errorf("couldn't find the Container count in the output")
  93. }
  94. type FakeContext struct {
  95. Dir string
  96. }
  97. func (f *FakeContext) Add(file, content string) error {
  98. filepath := path.Join(f.Dir, file)
  99. dirpath := path.Dir(filepath)
  100. if dirpath != "." {
  101. if err := os.MkdirAll(dirpath, 0755); err != nil {
  102. return err
  103. }
  104. }
  105. return ioutil.WriteFile(filepath, []byte(content), 0644)
  106. }
  107. func (f *FakeContext) Delete(file string) error {
  108. filepath := path.Join(f.Dir, file)
  109. return os.RemoveAll(filepath)
  110. }
  111. func (f *FakeContext) Close() error {
  112. return os.RemoveAll(f.Dir)
  113. }
  114. func fakeContext(dockerfile string, files map[string]string) (*FakeContext, error) {
  115. tmp, err := ioutil.TempDir("", "fake-context")
  116. if err != nil {
  117. return nil, err
  118. }
  119. ctx := &FakeContext{tmp}
  120. for file, content := range files {
  121. if err := ctx.Add(file, content); err != nil {
  122. ctx.Close()
  123. return nil, err
  124. }
  125. }
  126. if err := ctx.Add("Dockerfile", dockerfile); err != nil {
  127. ctx.Close()
  128. return nil, err
  129. }
  130. return ctx, nil
  131. }
  132. type FakeStorage struct {
  133. *FakeContext
  134. *httptest.Server
  135. }
  136. func (f *FakeStorage) Close() error {
  137. f.Server.Close()
  138. return f.FakeContext.Close()
  139. }
  140. func fakeStorage(files map[string]string) (*FakeStorage, error) {
  141. tmp, err := ioutil.TempDir("", "fake-storage")
  142. if err != nil {
  143. return nil, err
  144. }
  145. ctx := &FakeContext{tmp}
  146. for file, content := range files {
  147. if err := ctx.Add(file, content); err != nil {
  148. ctx.Close()
  149. return nil, err
  150. }
  151. }
  152. handler := http.FileServer(http.Dir(ctx.Dir))
  153. server := httptest.NewServer(handler)
  154. return &FakeStorage{
  155. FakeContext: ctx,
  156. Server: server,
  157. }, nil
  158. }
  159. func inspectField(name, field string) (string, error) {
  160. format := fmt.Sprintf("{{.%s}}", field)
  161. inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name)
  162. out, exitCode, err := runCommandWithOutput(inspectCmd)
  163. if err != nil || exitCode != 0 {
  164. return "", fmt.Errorf("failed to inspect %s: %s", name, out)
  165. }
  166. return strings.TrimSpace(out), nil
  167. }
  168. func getIDByName(name string) (string, error) {
  169. return inspectField(name, "Id")
  170. }
  171. func buildImage(name, dockerfile string, useCache bool) (string, error) {
  172. args := []string{"build", "-t", name}
  173. if !useCache {
  174. args = append(args, "--no-cache")
  175. }
  176. args = append(args, "-")
  177. buildCmd := exec.Command(dockerBinary, args...)
  178. buildCmd.Stdin = strings.NewReader(dockerfile)
  179. out, exitCode, err := runCommandWithOutput(buildCmd)
  180. if err != nil || exitCode != 0 {
  181. return "", fmt.Errorf("failed to build the image: %s", out)
  182. }
  183. return getIDByName(name)
  184. }
  185. func buildImageFromContext(name string, ctx *FakeContext, useCache bool) (string, error) {
  186. args := []string{"build", "-t", name}
  187. if !useCache {
  188. args = append(args, "--no-cache")
  189. }
  190. args = append(args, ".")
  191. buildCmd := exec.Command(dockerBinary, args...)
  192. buildCmd.Dir = ctx.Dir
  193. out, exitCode, err := runCommandWithOutput(buildCmd)
  194. if err != nil || exitCode != 0 {
  195. return "", fmt.Errorf("failed to build the image: %s", out)
  196. }
  197. return getIDByName(name)
  198. }