github.com/jwhonce/docker@v0.6.7-0.20190327063223-da823cf3a5a3/internal/test/environment/protect.go (about) 1 package environment // import "github.com/docker/docker/internal/test/environment" 2 3 import ( 4 "context" 5 6 "github.com/docker/docker/api/types" 7 "github.com/docker/docker/api/types/filters" 8 dclient "github.com/docker/docker/client" 9 "github.com/docker/docker/internal/test" 10 "gotest.tools/assert" 11 ) 12 13 var frozenImages = []string{"busybox:latest", "busybox:glibc", "hello-world:frozen", "debian:jessie"} 14 15 type protectedElements struct { 16 containers map[string]struct{} 17 images map[string]struct{} 18 networks map[string]struct{} 19 plugins map[string]struct{} 20 volumes map[string]struct{} 21 } 22 23 func newProtectedElements() protectedElements { 24 return protectedElements{ 25 containers: map[string]struct{}{}, 26 images: map[string]struct{}{}, 27 networks: map[string]struct{}{}, 28 plugins: map[string]struct{}{}, 29 volumes: map[string]struct{}{}, 30 } 31 } 32 33 // ProtectAll protects the existing environment (containers, images, networks, 34 // volumes, and, on Linux, plugins) from being cleaned up at the end of test 35 // runs 36 func ProtectAll(t assert.TestingT, testEnv *Execution) { 37 if ht, ok := t.(test.HelperT); ok { 38 ht.Helper() 39 } 40 ProtectContainers(t, testEnv) 41 ProtectImages(t, testEnv) 42 ProtectNetworks(t, testEnv) 43 ProtectVolumes(t, testEnv) 44 if testEnv.OSType == "linux" { 45 ProtectPlugins(t, testEnv) 46 } 47 } 48 49 // ProtectContainer adds the specified container(s) to be protected in case of 50 // clean 51 func (e *Execution) ProtectContainer(t assert.TestingT, containers ...string) { 52 if ht, ok := t.(test.HelperT); ok { 53 ht.Helper() 54 } 55 for _, container := range containers { 56 e.protectedElements.containers[container] = struct{}{} 57 } 58 } 59 60 // ProtectContainers protects existing containers from being cleaned up at the 61 // end of test runs 62 func ProtectContainers(t assert.TestingT, testEnv *Execution) { 63 if ht, ok := t.(test.HelperT); ok { 64 ht.Helper() 65 } 66 containers := getExistingContainers(t, testEnv) 67 testEnv.ProtectContainer(t, containers...) 68 } 69 70 func getExistingContainers(t assert.TestingT, testEnv *Execution) []string { 71 if ht, ok := t.(test.HelperT); ok { 72 ht.Helper() 73 } 74 client := testEnv.APIClient() 75 containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{ 76 All: true, 77 }) 78 assert.NilError(t, err, "failed to list containers") 79 80 var containers []string 81 for _, container := range containerList { 82 containers = append(containers, container.ID) 83 } 84 return containers 85 } 86 87 // ProtectImage adds the specified image(s) to be protected in case of clean 88 func (e *Execution) ProtectImage(t assert.TestingT, images ...string) { 89 if ht, ok := t.(test.HelperT); ok { 90 ht.Helper() 91 } 92 for _, image := range images { 93 e.protectedElements.images[image] = struct{}{} 94 } 95 } 96 97 // ProtectImages protects existing images and on linux frozen images from being 98 // cleaned up at the end of test runs 99 func ProtectImages(t assert.TestingT, testEnv *Execution) { 100 if ht, ok := t.(test.HelperT); ok { 101 ht.Helper() 102 } 103 images := getExistingImages(t, testEnv) 104 105 if testEnv.OSType == "linux" { 106 images = append(images, frozenImages...) 107 } 108 testEnv.ProtectImage(t, images...) 109 } 110 111 func getExistingImages(t assert.TestingT, testEnv *Execution) []string { 112 if ht, ok := t.(test.HelperT); ok { 113 ht.Helper() 114 } 115 client := testEnv.APIClient() 116 filter := filters.NewArgs() 117 filter.Add("dangling", "false") 118 imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ 119 All: true, 120 Filters: filter, 121 }) 122 assert.NilError(t, err, "failed to list images") 123 124 var images []string 125 for _, image := range imageList { 126 images = append(images, tagsFromImageSummary(image)...) 127 } 128 return images 129 } 130 131 func tagsFromImageSummary(image types.ImageSummary) []string { 132 var result []string 133 for _, tag := range image.RepoTags { 134 if tag != "<none>:<none>" { 135 result = append(result, tag) 136 } 137 } 138 for _, digest := range image.RepoDigests { 139 if digest != "<none>@<none>" { 140 result = append(result, digest) 141 } 142 } 143 return result 144 } 145 146 // ProtectNetwork adds the specified network(s) to be protected in case of 147 // clean 148 func (e *Execution) ProtectNetwork(t assert.TestingT, networks ...string) { 149 if ht, ok := t.(test.HelperT); ok { 150 ht.Helper() 151 } 152 for _, network := range networks { 153 e.protectedElements.networks[network] = struct{}{} 154 } 155 } 156 157 // ProtectNetworks protects existing networks from being cleaned up at the end 158 // of test runs 159 func ProtectNetworks(t assert.TestingT, testEnv *Execution) { 160 if ht, ok := t.(test.HelperT); ok { 161 ht.Helper() 162 } 163 networks := getExistingNetworks(t, testEnv) 164 testEnv.ProtectNetwork(t, networks...) 165 } 166 167 func getExistingNetworks(t assert.TestingT, testEnv *Execution) []string { 168 if ht, ok := t.(test.HelperT); ok { 169 ht.Helper() 170 } 171 client := testEnv.APIClient() 172 networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{}) 173 assert.NilError(t, err, "failed to list networks") 174 175 var networks []string 176 for _, network := range networkList { 177 networks = append(networks, network.ID) 178 } 179 return networks 180 } 181 182 // ProtectPlugin adds the specified plugin(s) to be protected in case of clean 183 func (e *Execution) ProtectPlugin(t assert.TestingT, plugins ...string) { 184 if ht, ok := t.(test.HelperT); ok { 185 ht.Helper() 186 } 187 for _, plugin := range plugins { 188 e.protectedElements.plugins[plugin] = struct{}{} 189 } 190 } 191 192 // ProtectPlugins protects existing plugins from being cleaned up at the end of 193 // test runs 194 func ProtectPlugins(t assert.TestingT, testEnv *Execution) { 195 if ht, ok := t.(test.HelperT); ok { 196 ht.Helper() 197 } 198 plugins := getExistingPlugins(t, testEnv) 199 testEnv.ProtectPlugin(t, plugins...) 200 } 201 202 func getExistingPlugins(t assert.TestingT, testEnv *Execution) []string { 203 if ht, ok := t.(test.HelperT); ok { 204 ht.Helper() 205 } 206 client := testEnv.APIClient() 207 pluginList, err := client.PluginList(context.Background(), filters.Args{}) 208 // Docker EE does not allow cluster-wide plugin management. 209 if dclient.IsErrNotImplemented(err) { 210 return []string{} 211 } 212 assert.NilError(t, err, "failed to list plugins") 213 214 var plugins []string 215 for _, plugin := range pluginList { 216 plugins = append(plugins, plugin.Name) 217 } 218 return plugins 219 } 220 221 // ProtectVolume adds the specified volume(s) to be protected in case of clean 222 func (e *Execution) ProtectVolume(t assert.TestingT, volumes ...string) { 223 if ht, ok := t.(test.HelperT); ok { 224 ht.Helper() 225 } 226 for _, volume := range volumes { 227 e.protectedElements.volumes[volume] = struct{}{} 228 } 229 } 230 231 // ProtectVolumes protects existing volumes from being cleaned up at the end of 232 // test runs 233 func ProtectVolumes(t assert.TestingT, testEnv *Execution) { 234 if ht, ok := t.(test.HelperT); ok { 235 ht.Helper() 236 } 237 volumes := getExistingVolumes(t, testEnv) 238 testEnv.ProtectVolume(t, volumes...) 239 } 240 241 func getExistingVolumes(t assert.TestingT, testEnv *Execution) []string { 242 if ht, ok := t.(test.HelperT); ok { 243 ht.Helper() 244 } 245 client := testEnv.APIClient() 246 volumeList, err := client.VolumeList(context.Background(), filters.Args{}) 247 assert.NilError(t, err, "failed to list volumes") 248 249 var volumes []string 250 for _, volume := range volumeList.Volumes { 251 volumes = append(volumes, volume.Name) 252 } 253 return volumes 254 }