clean.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package environment
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/docker/docker/api/types"
  8. volumetypes "github.com/docker/docker/api/types/volume"
  9. "github.com/docker/docker/integration-cli/request"
  10. icmd "github.com/docker/docker/pkg/testutil/cmd"
  11. )
  12. type testingT interface {
  13. logT
  14. Fatalf(string, ...interface{})
  15. }
  16. type logT interface {
  17. Logf(string, ...interface{})
  18. }
  19. // Clean the environment, preserving protected objects (images, containers, ...)
  20. // and removing everything else. It's meant to run after any tests so that they don't
  21. // depend on each others.
  22. func (e *Execution) Clean(t testingT, dockerBinary string) {
  23. if (e.DaemonPlatform() != "windows") || (e.DaemonPlatform() == "windows" && e.Isolation() == "hyperv") {
  24. unpauseAllContainers(t, dockerBinary)
  25. }
  26. deleteAllContainers(t, dockerBinary)
  27. deleteAllImages(t, dockerBinary, e.protectedElements.images)
  28. deleteAllVolumes(t, dockerBinary)
  29. deleteAllNetworks(t, dockerBinary, e.DaemonPlatform())
  30. if e.DaemonPlatform() == "linux" {
  31. deleteAllPlugins(t, dockerBinary)
  32. }
  33. }
  34. func unpauseAllContainers(t testingT, dockerBinary string) {
  35. containers := getPausedContainers(t, dockerBinary)
  36. if len(containers) > 0 {
  37. icmd.RunCommand(dockerBinary, append([]string{"unpause"}, containers...)...).Assert(t, icmd.Success)
  38. }
  39. }
  40. func getPausedContainers(t testingT, dockerBinary string) []string {
  41. result := icmd.RunCommand(dockerBinary, "ps", "-f", "status=paused", "-q", "-a")
  42. result.Assert(t, icmd.Success)
  43. return strings.Fields(result.Combined())
  44. }
  45. func deleteAllContainers(t testingT, dockerBinary string) {
  46. containers := getAllContainers(t, dockerBinary)
  47. if len(containers) > 0 {
  48. result := icmd.RunCommand(dockerBinary, append([]string{"rm", "-fv"}, containers...)...)
  49. if result.Error != nil {
  50. // If the error is "No such container: ..." this means the container doesn't exists anymore,
  51. // we can safely ignore that one.
  52. if strings.Contains(result.Stderr(), "No such container") {
  53. return
  54. }
  55. t.Fatalf("error removing containers %v : %v (%s)", containers, result.Error, result.Combined())
  56. }
  57. }
  58. }
  59. func getAllContainers(t testingT, dockerBinary string) []string {
  60. result := icmd.RunCommand(dockerBinary, "ps", "-q", "-a")
  61. result.Assert(t, icmd.Success)
  62. return strings.Fields(result.Combined())
  63. }
  64. func deleteAllImages(t testingT, dockerBinary string, protectedImages map[string]struct{}) {
  65. result := icmd.RunCommand(dockerBinary, "images", "--digests")
  66. result.Assert(t, icmd.Success)
  67. lines := strings.Split(string(result.Combined()), "\n")[1:]
  68. imgMap := map[string]struct{}{}
  69. for _, l := range lines {
  70. if l == "" {
  71. continue
  72. }
  73. fields := strings.Fields(l)
  74. imgTag := fields[0] + ":" + fields[1]
  75. if _, ok := protectedImages[imgTag]; !ok {
  76. if fields[0] == "<none>" || fields[1] == "<none>" {
  77. if fields[2] != "<none>" {
  78. imgMap[fields[0]+"@"+fields[2]] = struct{}{}
  79. } else {
  80. imgMap[fields[3]] = struct{}{}
  81. }
  82. // continue
  83. } else {
  84. imgMap[imgTag] = struct{}{}
  85. }
  86. }
  87. }
  88. if len(imgMap) != 0 {
  89. imgs := make([]string, 0, len(imgMap))
  90. for k := range imgMap {
  91. imgs = append(imgs, k)
  92. }
  93. icmd.RunCommand(dockerBinary, append([]string{"rmi", "-f"}, imgs...)...).Assert(t, icmd.Success)
  94. }
  95. }
  96. func deleteAllVolumes(t testingT, dockerBinary string) {
  97. volumes, err := getAllVolumes()
  98. if err != nil {
  99. t.Fatalf("%v", err)
  100. }
  101. var errs []string
  102. for _, v := range volumes {
  103. status, b, err := request.SockRequest("DELETE", "/volumes/"+v.Name, nil, request.DaemonHost())
  104. if err != nil {
  105. errs = append(errs, err.Error())
  106. continue
  107. }
  108. if status != http.StatusNoContent {
  109. errs = append(errs, fmt.Sprintf("error deleting volume %s: %s", v.Name, string(b)))
  110. }
  111. }
  112. if len(errs) > 0 {
  113. t.Fatalf("%v", strings.Join(errs, "\n"))
  114. }
  115. }
  116. func getAllVolumes() ([]*types.Volume, error) {
  117. var volumes volumetypes.VolumesListOKBody
  118. _, b, err := request.SockRequest("GET", "/volumes", nil, request.DaemonHost())
  119. if err != nil {
  120. return nil, err
  121. }
  122. if err := json.Unmarshal(b, &volumes); err != nil {
  123. return nil, err
  124. }
  125. return volumes.Volumes, nil
  126. }
  127. func deleteAllNetworks(t testingT, dockerBinary string, daemonPlatform string) {
  128. networks, err := getAllNetworks()
  129. if err != nil {
  130. t.Fatalf("%v", err)
  131. }
  132. var errs []string
  133. for _, n := range networks {
  134. if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
  135. continue
  136. }
  137. if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
  138. // nat is a pre-defined network on Windows and cannot be removed
  139. continue
  140. }
  141. status, b, err := request.SockRequest("DELETE", "/networks/"+n.Name, nil, request.DaemonHost())
  142. if err != nil {
  143. errs = append(errs, err.Error())
  144. continue
  145. }
  146. if status != http.StatusNoContent {
  147. errs = append(errs, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
  148. }
  149. }
  150. if len(errs) > 0 {
  151. t.Fatalf("%v", strings.Join(errs, "\n"))
  152. }
  153. }
  154. func getAllNetworks() ([]types.NetworkResource, error) {
  155. var networks []types.NetworkResource
  156. _, b, err := request.SockRequest("GET", "/networks", nil, request.DaemonHost())
  157. if err != nil {
  158. return nil, err
  159. }
  160. if err := json.Unmarshal(b, &networks); err != nil {
  161. return nil, err
  162. }
  163. return networks, nil
  164. }
  165. func deleteAllPlugins(t testingT, dockerBinary string) {
  166. plugins, err := getAllPlugins()
  167. if err != nil {
  168. t.Fatalf("%v", err)
  169. }
  170. var errs []string
  171. for _, p := range plugins {
  172. pluginName := p.Name
  173. status, b, err := request.SockRequest("DELETE", "/plugins/"+pluginName+"?force=1", nil, request.DaemonHost())
  174. if err != nil {
  175. errs = append(errs, err.Error())
  176. continue
  177. }
  178. if status != http.StatusOK {
  179. errs = append(errs, fmt.Sprintf("error deleting plugin %s: %s", p.Name, string(b)))
  180. }
  181. }
  182. if len(errs) > 0 {
  183. t.Fatalf("%v", strings.Join(errs, "\n"))
  184. }
  185. }
  186. func getAllPlugins() (types.PluginsListResponse, error) {
  187. var plugins types.PluginsListResponse
  188. _, b, err := request.SockRequest("GET", "/plugins", nil, request.DaemonHost())
  189. if err != nil {
  190. return nil, err
  191. }
  192. if err := json.Unmarshal(b, &plugins); err != nil {
  193. return nil, err
  194. }
  195. return plugins, nil
  196. }