github.com/sams1990/dockerrepo@v17.12.1-ce-rc2+incompatible/internal/test/environment/protect.go (about)

     1  package 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/stretchr/testify/require"
    10  )
    11  
    12  var frozenImages = []string{"busybox:latest", "hello-world:frozen", "debian:jessie"}
    13  
    14  type protectedElements struct {
    15  	containers map[string]struct{}
    16  	images     map[string]struct{}
    17  	networks   map[string]struct{}
    18  	plugins    map[string]struct{}
    19  	volumes    map[string]struct{}
    20  }
    21  
    22  func newProtectedElements() protectedElements {
    23  	return protectedElements{
    24  		containers: map[string]struct{}{},
    25  		images:     map[string]struct{}{},
    26  		networks:   map[string]struct{}{},
    27  		plugins:    map[string]struct{}{},
    28  		volumes:    map[string]struct{}{},
    29  	}
    30  }
    31  
    32  // ProtectAll protects the existing environment (containers, images, networks,
    33  // volumes, and, on Linux, plugins) from being cleaned up at the end of test
    34  // runs
    35  func ProtectAll(t testingT, testEnv *Execution) {
    36  	ProtectContainers(t, testEnv)
    37  	ProtectImages(t, testEnv)
    38  	ProtectNetworks(t, testEnv)
    39  	ProtectVolumes(t, testEnv)
    40  	if testEnv.OSType == "linux" {
    41  		ProtectPlugins(t, testEnv)
    42  	}
    43  }
    44  
    45  // ProtectContainer adds the specified container(s) to be protected in case of
    46  // clean
    47  func (e *Execution) ProtectContainer(t testingT, containers ...string) {
    48  	for _, container := range containers {
    49  		e.protectedElements.containers[container] = struct{}{}
    50  	}
    51  }
    52  
    53  // ProtectContainers protects existing containers from being cleaned up at the
    54  // end of test runs
    55  func ProtectContainers(t testingT, testEnv *Execution) {
    56  	containers := getExistingContainers(t, testEnv)
    57  	testEnv.ProtectContainer(t, containers...)
    58  }
    59  
    60  func getExistingContainers(t require.TestingT, testEnv *Execution) []string {
    61  	client := testEnv.APIClient()
    62  	containerList, err := client.ContainerList(context.Background(), types.ContainerListOptions{
    63  		All: true,
    64  	})
    65  	require.NoError(t, err, "failed to list containers")
    66  
    67  	containers := []string{}
    68  	for _, container := range containerList {
    69  		containers = append(containers, container.ID)
    70  	}
    71  	return containers
    72  }
    73  
    74  // ProtectImage adds the specified image(s) to be protected in case of clean
    75  func (e *Execution) ProtectImage(t testingT, images ...string) {
    76  	for _, image := range images {
    77  		e.protectedElements.images[image] = struct{}{}
    78  	}
    79  }
    80  
    81  // ProtectImages protects existing images and on linux frozen images from being
    82  // cleaned up at the end of test runs
    83  func ProtectImages(t testingT, testEnv *Execution) {
    84  	images := getExistingImages(t, testEnv)
    85  
    86  	if testEnv.OSType == "linux" {
    87  		images = append(images, frozenImages...)
    88  	}
    89  	testEnv.ProtectImage(t, images...)
    90  }
    91  
    92  func getExistingImages(t require.TestingT, testEnv *Execution) []string {
    93  	client := testEnv.APIClient()
    94  	filter := filters.NewArgs()
    95  	filter.Add("dangling", "false")
    96  	imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
    97  		All:     true,
    98  		Filters: filter,
    99  	})
   100  	require.NoError(t, err, "failed to list images")
   101  
   102  	images := []string{}
   103  	for _, image := range imageList {
   104  		images = append(images, tagsFromImageSummary(image)...)
   105  	}
   106  	return images
   107  }
   108  
   109  func tagsFromImageSummary(image types.ImageSummary) []string {
   110  	result := []string{}
   111  	for _, tag := range image.RepoTags {
   112  		if tag != "<none>:<none>" {
   113  			result = append(result, tag)
   114  		}
   115  	}
   116  	for _, digest := range image.RepoDigests {
   117  		if digest != "<none>@<none>" {
   118  			result = append(result, digest)
   119  		}
   120  	}
   121  	return result
   122  }
   123  
   124  // ProtectNetwork adds the specified network(s) to be protected in case of
   125  // clean
   126  func (e *Execution) ProtectNetwork(t testingT, networks ...string) {
   127  	for _, network := range networks {
   128  		e.protectedElements.networks[network] = struct{}{}
   129  	}
   130  }
   131  
   132  // ProtectNetworks protects existing networks from being cleaned up at the end
   133  // of test runs
   134  func ProtectNetworks(t testingT, testEnv *Execution) {
   135  	networks := getExistingNetworks(t, testEnv)
   136  	testEnv.ProtectNetwork(t, networks...)
   137  }
   138  
   139  func getExistingNetworks(t require.TestingT, testEnv *Execution) []string {
   140  	client := testEnv.APIClient()
   141  	networkList, err := client.NetworkList(context.Background(), types.NetworkListOptions{})
   142  	require.NoError(t, err, "failed to list networks")
   143  
   144  	networks := []string{}
   145  	for _, network := range networkList {
   146  		networks = append(networks, network.ID)
   147  	}
   148  	return networks
   149  }
   150  
   151  // ProtectPlugin adds the specified plugin(s) to be protected in case of clean
   152  func (e *Execution) ProtectPlugin(t testingT, plugins ...string) {
   153  	for _, plugin := range plugins {
   154  		e.protectedElements.plugins[plugin] = struct{}{}
   155  	}
   156  }
   157  
   158  // ProtectPlugins protects existing plugins from being cleaned up at the end of
   159  // test runs
   160  func ProtectPlugins(t testingT, testEnv *Execution) {
   161  	plugins := getExistingPlugins(t, testEnv)
   162  	testEnv.ProtectPlugin(t, plugins...)
   163  }
   164  
   165  func getExistingPlugins(t require.TestingT, testEnv *Execution) []string {
   166  	client := testEnv.APIClient()
   167  	pluginList, err := client.PluginList(context.Background(), filters.Args{})
   168  	// Docker EE does not allow cluster-wide plugin management.
   169  	if dclient.IsErrNotImplemented(err) {
   170  		return []string{}
   171  	}
   172  	require.NoError(t, err, "failed to list plugins")
   173  
   174  	plugins := []string{}
   175  	for _, plugin := range pluginList {
   176  		plugins = append(plugins, plugin.Name)
   177  	}
   178  	return plugins
   179  }
   180  
   181  // ProtectVolume adds the specified volume(s) to be protected in case of clean
   182  func (e *Execution) ProtectVolume(t testingT, volumes ...string) {
   183  	for _, volume := range volumes {
   184  		e.protectedElements.volumes[volume] = struct{}{}
   185  	}
   186  }
   187  
   188  // ProtectVolumes protects existing volumes from being cleaned up at the end of
   189  // test runs
   190  func ProtectVolumes(t testingT, testEnv *Execution) {
   191  	volumes := getExistingVolumes(t, testEnv)
   192  	testEnv.ProtectVolume(t, volumes...)
   193  }
   194  
   195  func getExistingVolumes(t require.TestingT, testEnv *Execution) []string {
   196  	client := testEnv.APIClient()
   197  	volumeList, err := client.VolumeList(context.Background(), filters.Args{})
   198  	require.NoError(t, err, "failed to list volumes")
   199  
   200  	volumes := []string{}
   201  	for _, volume := range volumeList.Volumes {
   202  		volumes = append(volumes, volume.Name)
   203  	}
   204  	return volumes
   205  }