10 "github.com/docker/docker/api/types"
11 volumetypes "github.com/docker/docker/api/types/volume"
12 "github.com/docker/docker/integration-cli/request"
13 icmd "github.com/docker/docker/pkg/testutil/cmd"
16 type testingT interface {
18 Fatalf(string, ...interface{})
22 Logf(string, ...interface{})
25 // Clean the environment, preserving protected objects (images, containers, ...)
26 // and removing everything else. It's meant to run after any tests so that they don't
27 // depend on each others.
28 func (e *Execution) Clean(t testingT, dockerBinary string) {
29 if (e.DaemonPlatform() != "windows") || (e.DaemonPlatform() == "windows" && e.Isolation() == "hyperv") {
30 unpauseAllContainers(t, dockerBinary)
32 deleteAllContainers(t, dockerBinary)
33 deleteAllImages(t, dockerBinary, e.protectedElements.images)
34 deleteAllVolumes(t, dockerBinary)
35 deleteAllNetworks(t, dockerBinary, e.DaemonPlatform())
36 if e.DaemonPlatform() == "linux" {
38 //deleteAllPlugins(t, dockerBinary)
42 func unpauseAllContainers(t testingT, dockerBinary string) {
43 containers := getPausedContainers(t, dockerBinary)
44 if len(containers) > 0 {
45 icmd.RunCommand(dockerBinary, append([]string{"unpause"}, containers...)...).Assert(t, icmd.Success)
49 func getPausedContainers(t testingT, dockerBinary string) []string {
50 result := icmd.RunCommand(dockerBinary, "ps", "-f", "status=paused", "-q", "-a")
51 result.Assert(t, icmd.Success)
52 return strings.Fields(result.Combined())
55 var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`)
57 func deleteAllContainers(t testingT, dockerBinary string) {
58 containers := getAllContainers(t, dockerBinary)
59 if len(containers) > 0 {
60 result := icmd.RunCommand(dockerBinary, append([]string{"rm", "-fv"}, containers...)...)
61 if result.Error != nil {
62 // If the error is "No such container: ..." this means the container doesn't exists anymore,
63 // or if it is "... removal of container ... is already in progress" it will be removed eventually.
64 // We can safely ignore those.
65 if strings.Contains(result.Stderr(), "No such container") || alreadyExists.MatchString(result.Stderr()) {
68 t.Fatalf("error removing containers %v : %v (%s)", containers, result.Error, result.Combined())
73 func getAllContainers(t testingT, dockerBinary string) []string {
74 result := icmd.RunCommand(dockerBinary, "ps", "-q", "-a")
75 result.Assert(t, icmd.Success)
76 return strings.Fields(result.Combined())
79 func deleteAllImages(t testingT, dockerBinary string, protectedImages map[string]struct{}) {
80 result := icmd.RunCommand(dockerBinary, "images", "--digests")
81 result.Assert(t, icmd.Success)
82 lines := strings.Split(string(result.Combined()), "\n")[1:]
83 imgMap := map[string]struct{}{}
84 for _, l := range lines {
88 fields := strings.Fields(l)
89 imgTag := fields[0] + ":" + fields[1]
90 if _, ok := protectedImages[imgTag]; !ok {
91 if fields[0] == "<none>" || fields[1] == "<none>" {
92 if fields[2] != "<none>" {
93 imgMap[fields[0]+"@"+fields[2]] = struct{}{}
95 imgMap[fields[3]] = struct{}{}
99 imgMap[imgTag] = struct{}{}
103 if len(imgMap) != 0 {
104 imgs := make([]string, 0, len(imgMap))
105 for k := range imgMap {
106 imgs = append(imgs, k)
108 icmd.RunCommand(dockerBinary, append([]string{"rmi", "-f"}, imgs...)...).Assert(t, icmd.Success)
112 func deleteAllVolumes(t testingT, dockerBinary string) {
113 volumes, err := getAllVolumes()
118 for _, v := range volumes {
119 status, b, err := request.SockRequest("DELETE", "/volumes/"+v.Name, nil, request.DaemonHost())
121 errs = append(errs, err.Error())
124 if status != http.StatusNoContent {
125 errs = append(errs, fmt.Sprintf("error deleting volume %s: %s", v.Name, string(b)))
129 t.Fatalf("%v", strings.Join(errs, "\n"))
133 func getAllVolumes() ([]*types.Volume, error) {
134 var volumes volumetypes.VolumesListOKBody
135 _, b, err := request.SockRequest("GET", "/volumes", nil, request.DaemonHost())
139 if err := json.Unmarshal(b, &volumes); err != nil {
142 return volumes.Volumes, nil
145 func deleteAllNetworks(t testingT, dockerBinary string, daemonPlatform string) {
146 networks, err := getAllNetworks()
151 for _, n := range networks {
152 if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
155 if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
156 // nat is a pre-defined network on Windows and cannot be removed
159 status, b, err := request.SockRequest("DELETE", "/networks/"+n.Name, nil, request.DaemonHost())
161 errs = append(errs, err.Error())
164 if status != http.StatusNoContent {
165 errs = append(errs, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
169 t.Fatalf("%v", strings.Join(errs, "\n"))
173 func getAllNetworks() ([]types.NetworkResource, error) {
174 var networks []types.NetworkResource
175 _, b, err := request.SockRequest("GET", "/networks", nil, request.DaemonHost())
179 if err := json.Unmarshal(b, &networks); err != nil {
185 func deleteAllPlugins(t testingT, dockerBinary string) {
186 plugins, err := getAllPlugins()
191 for _, p := range plugins {
193 status, b, err := request.SockRequest("DELETE", "/plugins/"+pluginName+"?force=1", nil, request.DaemonHost())
195 errs = append(errs, err.Error())
198 if status != http.StatusOK {
199 errs = append(errs, fmt.Sprintf("error deleting plugin %s: %s", p.Name, string(b)))
203 t.Fatalf("%v", strings.Join(errs, "\n"))
207 func getAllPlugins() (types.PluginsListResponse, error) {
208 var plugins types.PluginsListResponse
209 _, b, err := request.SockRequest("GET", "/plugins", nil, request.DaemonHost())
213 if err := json.Unmarshal(b, &plugins); err != nil {