docker_utils.go 5.4 KB

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