github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/testutil/environment/protect.go (about) 1 package environment 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/demonoid81/moby/api/types" 8 "github.com/demonoid81/moby/api/types/filters" 9 dclient "github.com/demonoid81/moby/client" 10 "gotest.tools/v3/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 testing.TB, testEnv *Execution) { 37 t.Helper() 38 ProtectContainers(t, testEnv) 39 ProtectImages(t, testEnv) 40 ProtectNetworks(t, testEnv) 41 ProtectVolumes(t, testEnv) 42 if testEnv.OSType == "linux" { 43 ProtectPlugins(t, testEnv) 44 } 45 } 46 47 // ProtectContainer adds the specified container(s) to be protected in case of 48 // clean 49 func (e *Execution) ProtectContainer(t testing.TB, containers ...string) { 50 t.Helper() 51 for _, container := range containers { 52 e.protectedElements.containers[container] = struct{}{} 53 } 54 } 55 56 // ProtectContainers protects existing containers from being cleaned up at the 57 // end of test runs 58 func ProtectContainers(t testing.TB, testEnv *Execution) { 59 t.Helper() 60 containers := getExistingContainers(t, testEnv) 61 testEnv.ProtectContainer(t, containers...) 62 } 63 64 func getExistingContainers(t testing.TB, testEnv *Execution) []string { 65 t.Helper() 66 client := testEnv.APIClient() 67 containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{ 68 All: true, 69 }) 70 assert.NilError(t, err, "failed to list containers") 71 72 var containers []string 73 for _, container := range containerList { 74 containers = append(containers, container.ID) 75 } 76 return containers 77 } 78 79 // ProtectImage adds the specified image(s) to be protected in case of clean 80 func (e *Execution) ProtectImage(t testing.TB, images ...string) { 81 t.Helper() 82 for _, image := range images { 83 e.protectedElements.images[image] = struct{}{} 84 } 85 } 86 87 // ProtectImages protects existing images and on linux frozen images from being 88 // cleaned up at the end of test runs 89 func ProtectImages(t testing.TB, testEnv *Execution) { 90 t.Helper() 91 images := getExistingImages(t, testEnv) 92 93 if testEnv.OSType == "linux" { 94 images = append(images, frozenImages...) 95 } 96 testEnv.ProtectImage(t, images...) 97 } 98 99 func getExistingImages(t testing.TB, testEnv *Execution) []string { 100 t.Helper() 101 client := testEnv.APIClient() 102 filter := filters.NewArgs() 103 filter.Add("dangling", "false") 104 imageList, err := client.ImageList(context.Background(), types.ImageListOptions{ 105 All: true, 106 Filters: filter, 107 }) 108 assert.NilError(t, err, "failed to list images") 109 110 var images []string 111 for _, image := range imageList { 112 images = append(images, tagsFromImageSummary(image)...) 113 } 114 return images 115 } 116 117 func tagsFromImageSummary(image types.ImageSummary) []string { 118 var result []string 119 for _, tag := range image.RepoTags { 120 if tag != "<none>:<none>" { 121 result = append(result, tag) 122 } 123 } 124 for _, digest := range image.RepoDigests { 125 if digest != "<none>@<none>" { 126 result = append(result, digest) 127 } 128 } 129 return result 130 } 131 132 // ProtectNetwork adds the specified network(s) to be protected in case of 133 // clean 134 func (e *Execution) ProtectNetwork(t testing.TB, networks ...string) { 135 t.Helper() 136 for _, network := range networks { 137 e.protectedElements.networks[network] = struct{}{} 138 } 139 } 140 141 // ProtectNetworks protects existing networks from being cleaned up at the end 142 // of test runs 143 func ProtectNetworks(t testing.TB, testEnv *Execution) { 144 t.Helper() 145 networks := getExistingNetworks(t, testEnv) 146 testEnv.ProtectNetwork(t, networks...) 147 } 148 149 func getExistingNetworks(t testing.TB, testEnv *Execution) []string { 150 t.Helper() 151 client := testEnv.APIClient() 152 networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{}) 153 assert.NilError(t, err, "failed to list networks") 154 155 var networks []string 156 for _, network := range networkList { 157 networks = append(networks, network.ID) 158 } 159 return networks 160 } 161 162 // ProtectPlugin adds the specified plugin(s) to be protected in case of clean 163 func (e *Execution) ProtectPlugin(t testing.TB, plugins ...string) { 164 t.Helper() 165 for _, plugin := range plugins { 166 e.protectedElements.plugins[plugin] = struct{}{} 167 } 168 } 169 170 // ProtectPlugins protects existing plugins from being cleaned up at the end of 171 // test runs 172 func ProtectPlugins(t testing.TB, testEnv *Execution) { 173 t.Helper() 174 plugins := getExistingPlugins(t, testEnv) 175 testEnv.ProtectPlugin(t, plugins...) 176 } 177 178 func getExistingPlugins(t testing.TB, testEnv *Execution) []string { 179 t.Helper() 180 client := testEnv.APIClient() 181 pluginList, err := client.PluginList(context.Background(), filters.Args{}) 182 // Docker EE does not allow cluster-wide plugin management. 183 if dclient.IsErrNotImplemented(err) { 184 return []string{} 185 } 186 assert.NilError(t, err, "failed to list plugins") 187 188 var plugins []string 189 for _, plugin := range pluginList { 190 plugins = append(plugins, plugin.Name) 191 } 192 return plugins 193 } 194 195 // ProtectVolume adds the specified volume(s) to be protected in case of clean 196 func (e *Execution) ProtectVolume(t testing.TB, volumes ...string) { 197 t.Helper() 198 for _, volume := range volumes { 199 e.protectedElements.volumes[volume] = struct{}{} 200 } 201 } 202 203 // ProtectVolumes protects existing volumes from being cleaned up at the end of 204 // test runs 205 func ProtectVolumes(t testing.TB, testEnv *Execution) { 206 t.Helper() 207 volumes := getExistingVolumes(t, testEnv) 208 testEnv.ProtectVolume(t, volumes...) 209 } 210 211 func getExistingVolumes(t testing.TB, testEnv *Execution) []string { 212 t.Helper() 213 client := testEnv.APIClient() 214 volumeList, err := client.VolumeList(context.Background(), filters.Args{}) 215 assert.NilError(t, err, "failed to list volumes") 216 217 var volumes []string 218 for _, volume := range volumeList.Volumes { 219 volumes = append(volumes, volume.Name) 220 } 221 return volumes 222 }