Tizen_4.0 base
[platform/upstream/docker-engine.git] / integration-cli / environment / clean.go
1 package environment
2
3 import (
4         "encoding/json"
5         "fmt"
6         "net/http"
7         "regexp"
8         "strings"
9
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"
14 )
15
16 type testingT interface {
17         logT
18         Fatalf(string, ...interface{})
19 }
20
21 type logT interface {
22         Logf(string, ...interface{})
23 }
24
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)
31         }
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" {
37                 // TODO FIXME
38                 //deleteAllPlugins(t, dockerBinary)
39         }
40 }
41
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)
46         }
47 }
48
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())
53 }
54
55 var alreadyExists = regexp.MustCompile(`Error response from daemon: removal of container (\w+) is already in progress`)
56
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()) {
66                                 return
67                         }
68                         t.Fatalf("error removing containers %v : %v (%s)", containers, result.Error, result.Combined())
69                 }
70         }
71 }
72
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())
77 }
78
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 {
85                 if l == "" {
86                         continue
87                 }
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{}{}
94                                 } else {
95                                         imgMap[fields[3]] = struct{}{}
96                                 }
97                                 // continue
98                         } else {
99                                 imgMap[imgTag] = struct{}{}
100                         }
101                 }
102         }
103         if len(imgMap) != 0 {
104                 imgs := make([]string, 0, len(imgMap))
105                 for k := range imgMap {
106                         imgs = append(imgs, k)
107                 }
108                 icmd.RunCommand(dockerBinary, append([]string{"rmi", "-f"}, imgs...)...).Assert(t, icmd.Success)
109         }
110 }
111
112 func deleteAllVolumes(t testingT, dockerBinary string) {
113         volumes, err := getAllVolumes()
114         if err != nil {
115                 t.Fatalf("%v", err)
116         }
117         var errs []string
118         for _, v := range volumes {
119                 status, b, err := request.SockRequest("DELETE", "/volumes/"+v.Name, nil, request.DaemonHost())
120                 if err != nil {
121                         errs = append(errs, err.Error())
122                         continue
123                 }
124                 if status != http.StatusNoContent {
125                         errs = append(errs, fmt.Sprintf("error deleting volume %s: %s", v.Name, string(b)))
126                 }
127         }
128         if len(errs) > 0 {
129                 t.Fatalf("%v", strings.Join(errs, "\n"))
130         }
131 }
132
133 func getAllVolumes() ([]*types.Volume, error) {
134         var volumes volumetypes.VolumesListOKBody
135         _, b, err := request.SockRequest("GET", "/volumes", nil, request.DaemonHost())
136         if err != nil {
137                 return nil, err
138         }
139         if err := json.Unmarshal(b, &volumes); err != nil {
140                 return nil, err
141         }
142         return volumes.Volumes, nil
143 }
144
145 func deleteAllNetworks(t testingT, dockerBinary string, daemonPlatform string) {
146         networks, err := getAllNetworks()
147         if err != nil {
148                 t.Fatalf("%v", err)
149         }
150         var errs []string
151         for _, n := range networks {
152                 if n.Name == "bridge" || n.Name == "none" || n.Name == "host" {
153                         continue
154                 }
155                 if daemonPlatform == "windows" && strings.ToLower(n.Name) == "nat" {
156                         // nat is a pre-defined network on Windows and cannot be removed
157                         continue
158                 }
159                 status, b, err := request.SockRequest("DELETE", "/networks/"+n.Name, nil, request.DaemonHost())
160                 if err != nil {
161                         errs = append(errs, err.Error())
162                         continue
163                 }
164                 if status != http.StatusNoContent {
165                         errs = append(errs, fmt.Sprintf("error deleting network %s: %s", n.Name, string(b)))
166                 }
167         }
168         if len(errs) > 0 {
169                 t.Fatalf("%v", strings.Join(errs, "\n"))
170         }
171 }
172
173 func getAllNetworks() ([]types.NetworkResource, error) {
174         var networks []types.NetworkResource
175         _, b, err := request.SockRequest("GET", "/networks", nil, request.DaemonHost())
176         if err != nil {
177                 return nil, err
178         }
179         if err := json.Unmarshal(b, &networks); err != nil {
180                 return nil, err
181         }
182         return networks, nil
183 }
184
185 func deleteAllPlugins(t testingT, dockerBinary string) {
186         plugins, err := getAllPlugins()
187         if err != nil {
188                 t.Fatalf("%v", err)
189         }
190         var errs []string
191         for _, p := range plugins {
192                 pluginName := p.Name
193                 status, b, err := request.SockRequest("DELETE", "/plugins/"+pluginName+"?force=1", nil, request.DaemonHost())
194                 if err != nil {
195                         errs = append(errs, err.Error())
196                         continue
197                 }
198                 if status != http.StatusOK {
199                         errs = append(errs, fmt.Sprintf("error deleting plugin %s: %s", p.Name, string(b)))
200                 }
201         }
202         if len(errs) > 0 {
203                 t.Fatalf("%v", strings.Join(errs, "\n"))
204         }
205 }
206
207 func getAllPlugins() (types.PluginsListResponse, error) {
208         var plugins types.PluginsListResponse
209         _, b, err := request.SockRequest("GET", "/plugins", nil, request.DaemonHost())
210         if err != nil {
211                 return nil, err
212         }
213         if err := json.Unmarshal(b, &plugins); err != nil {
214                 return nil, err
215         }
216         return plugins, nil
217 }