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  }