Kaydet (Commit) 42b93584 authored tarafından Joffrey F's avatar Joffrey F Kaydeden (comit) GitHub

Merge pull request #1425 from shin-/prunes

Prunes
...@@ -911,9 +911,6 @@ class ContainerApiMixin(object): ...@@ -911,9 +911,6 @@ class ContainerApiMixin(object):
Raises: Raises:
:py:class:`docker.errors.APIError` :py:class:`docker.errors.APIError`
If the server returns an error. If the server returns an error.
Raises:
:py:class:`~docker.errors.APIError` If an error occurs.
""" """
params = {'path': path} params = {'path': path}
url = self._url('/containers/{0}/archive', container) url = self._url('/containers/{0}/archive', container)
...@@ -921,6 +918,28 @@ class ContainerApiMixin(object): ...@@ -921,6 +918,28 @@ class ContainerApiMixin(object):
self._raise_for_status(res) self._raise_for_status(res)
return res.status_code == 200 return res.status_code == 200
@utils.minimum_version('1.25')
def prune_containers(self, filters=None):
"""
Delete stopped containers
Args:
filters (dict): Filters to process on the prune list.
Returns:
(dict): A dict containing a list of deleted container IDs and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
url = self._url('/containers/prune')
return self._result(self._post(url, params=params), True)
@utils.check_resource @utils.check_resource
def remove_container(self, container, v=False, link=False, force=False): def remove_container(self, container, v=False, link=False, force=False):
""" """
......
...@@ -274,6 +274,31 @@ class ImageApiMixin(object): ...@@ -274,6 +274,31 @@ class ImageApiMixin(object):
res = self._post(self._url("/images/load"), data=data) res = self._post(self._url("/images/load"), data=data)
self._raise_for_status(res) self._raise_for_status(res)
@utils.minimum_version('1.25')
def prune_images(self, filters=None):
"""
Delete unused images
Args:
filters (dict): Filters to process on the prune list.
Available filters:
- dangling (bool): When set to true (or 1), prune only
unused and untagged images.
Returns:
(dict): A dict containing a list of deleted image IDs and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
url = self._url("/images/prune")
params = {}
if filters is not None:
params['filters'] = utils.convert_filters(filters)
return self._result(self._post(url, params=params), True)
def pull(self, repository, tag=None, stream=False, def pull(self, repository, tag=None, stream=False,
insecure_registry=False, auth_config=None, decode=False): insecure_registry=False, auth_config=None, decode=False):
""" """
......
...@@ -133,6 +133,28 @@ class NetworkApiMixin(object): ...@@ -133,6 +133,28 @@ class NetworkApiMixin(object):
res = self._post_json(url, data=data) res = self._post_json(url, data=data)
return self._result(res, json=True) return self._result(res, json=True)
@minimum_version('1.25')
def prune_networks(self, filters=None):
"""
Delete unused networks
Args:
filters (dict): Filters to process on the prune list.
Returns:
(dict): A dict containing a list of deleted network names and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
url = self._url('/networks/prune')
return self._result(self._post(url, params=params), True)
@minimum_version('1.21') @minimum_version('1.21')
def remove_network(self, net_id): def remove_network(self, net_id):
""" """
......
...@@ -116,6 +116,28 @@ class VolumeApiMixin(object): ...@@ -116,6 +116,28 @@ class VolumeApiMixin(object):
url = self._url('/volumes/{0}', name) url = self._url('/volumes/{0}', name)
return self._result(self._get(url), True) return self._result(self._get(url), True)
@utils.minimum_version('1.25')
def prune_volumes(self, filters=None):
"""
Delete unused volumes
Args:
filters (dict): Filters to process on the prune list.
Returns:
(dict): A dict containing a list of deleted volume names and
the amount of disk space reclaimed in bytes.
Raises:
:py:class:`docker.errors.APIError`
If the server returns an error.
"""
params = {}
if filters:
params['filters'] = utils.convert_filters(filters)
url = self._url('/volumes/prune')
return self._result(self._post(url, params=params), True)
@utils.minimum_version('1.21') @utils.minimum_version('1.21')
def remove_volume(self, name, force=False): def remove_volume(self, name, force=False):
""" """
......
import copy import copy
from ..api import APIClient
from ..errors import (ContainerError, ImageNotFound, from ..errors import (ContainerError, ImageNotFound,
create_unexpected_kwargs_error) create_unexpected_kwargs_error)
from ..types import HostConfig from ..types import HostConfig
...@@ -763,6 +764,10 @@ class ContainerCollection(Collection): ...@@ -763,6 +764,10 @@ class ContainerCollection(Collection):
since=since) since=since)
return [self.get(r['Id']) for r in resp] return [self.get(r['Id']) for r in resp]
def prune(self, filters=None):
return self.client.api.prune_containers(filters=filters)
prune.__doc__ = APIClient.prune_containers.__doc__
# kwargs to copy straight from run to create # kwargs to copy straight from run to create
RUN_CREATE_KWARGS = [ RUN_CREATE_KWARGS = [
......
...@@ -269,3 +269,7 @@ class ImageCollection(Collection): ...@@ -269,3 +269,7 @@ class ImageCollection(Collection):
def search(self, *args, **kwargs): def search(self, *args, **kwargs):
return self.client.api.search(*args, **kwargs) return self.client.api.search(*args, **kwargs)
search.__doc__ = APIClient.search.__doc__ search.__doc__ = APIClient.search.__doc__
def prune(self, filters=None):
return self.client.api.prune_images(filters=filters)
prune.__doc__ = APIClient.prune_images.__doc__
from ..api import APIClient
from .containers import Container from .containers import Container
from .resource import Model, Collection from .resource import Model, Collection
...@@ -180,3 +181,7 @@ class NetworkCollection(Collection): ...@@ -180,3 +181,7 @@ class NetworkCollection(Collection):
""" """
resp = self.client.api.networks(*args, **kwargs) resp = self.client.api.networks(*args, **kwargs)
return [self.prepare_model(item) for item in resp] return [self.prepare_model(item) for item in resp]
def prune(self, filters=None):
self.client.api.prune_networks(filters=filters)
prune.__doc__ = APIClient.prune_networks.__doc__
from ..api import APIClient
from .resource import Model, Collection from .resource import Model, Collection
...@@ -92,3 +93,7 @@ class VolumeCollection(Collection): ...@@ -92,3 +93,7 @@ class VolumeCollection(Collection):
if not resp.get('Volumes'): if not resp.get('Volumes'):
return [] return []
return [self.prepare_model(obj) for obj in resp['Volumes']] return [self.prepare_model(obj) for obj in resp['Volumes']]
def prune(self, filters=None):
return self.client.api.prune_volumes(filters=filters)
prune.__doc__ = APIClient.prune_volumes.__doc__
...@@ -14,6 +14,7 @@ Methods available on ``client.containers``: ...@@ -14,6 +14,7 @@ Methods available on ``client.containers``:
.. automethod:: create(image, command=None, **kwargs) .. automethod:: create(image, command=None, **kwargs)
.. automethod:: get(id_or_name) .. automethod:: get(id_or_name)
.. automethod:: list(**kwargs) .. automethod:: list(**kwargs)
.. automethod:: prune
Container objects Container objects
----------------- -----------------
......
...@@ -18,6 +18,7 @@ Methods available on ``client.images``: ...@@ -18,6 +18,7 @@ Methods available on ``client.images``:
.. automethod:: push .. automethod:: push
.. automethod:: remove .. automethod:: remove
.. automethod:: search .. automethod:: search
.. automethod:: prune
Image objects Image objects
......
...@@ -13,6 +13,7 @@ Methods available on ``client.networks``: ...@@ -13,6 +13,7 @@ Methods available on ``client.networks``:
.. automethod:: create .. automethod:: create
.. automethod:: get .. automethod:: get
.. automethod:: list .. automethod:: list
.. automethod:: prune
Network objects Network objects
----------------- -----------------
......
...@@ -13,6 +13,7 @@ Methods available on ``client.volumes``: ...@@ -13,6 +13,7 @@ Methods available on ``client.volumes``:
.. automethod:: create .. automethod:: create
.. automethod:: get .. automethod:: get
.. automethod:: list .. automethod:: list
.. automethod:: prune
Volume objects Volume objects
-------------- --------------
......
...@@ -1094,6 +1094,20 @@ class PauseTest(BaseAPIIntegrationTest): ...@@ -1094,6 +1094,20 @@ class PauseTest(BaseAPIIntegrationTest):
self.assertEqual(state['Paused'], False) self.assertEqual(state['Paused'], False)
class PruneTest(BaseAPIIntegrationTest):
@requires_api_version('1.25')
def test_prune_containers(self):
container1 = self.client.create_container(BUSYBOX, ['echo', 'hello'])
container2 = self.client.create_container(BUSYBOX, ['sleep', '9999'])
self.client.start(container1)
self.client.start(container2)
self.client.wait(container1)
result = self.client.prune_containers()
assert container1['Id'] in result['ContainersDeleted']
assert result['SpaceReclaimed'] > 0
assert container2['Id'] not in result['ContainersDeleted']
class GetContainerStatsTest(BaseAPIIntegrationTest): class GetContainerStatsTest(BaseAPIIntegrationTest):
@requires_api_version('1.19') @requires_api_version('1.19')
def test_get_container_stats_no_stream(self): def test_get_container_stats_no_stream(self):
......
...@@ -14,6 +14,7 @@ from six.moves import socketserver ...@@ -14,6 +14,7 @@ from six.moves import socketserver
import docker import docker
from ..helpers import requires_api_version
from .base import BaseAPIIntegrationTest, BUSYBOX from .base import BaseAPIIntegrationTest, BUSYBOX
...@@ -285,3 +286,32 @@ class ImportImageTest(BaseAPIIntegrationTest): ...@@ -285,3 +286,32 @@ class ImportImageTest(BaseAPIIntegrationTest):
self.assertIn('status', result) self.assertIn('status', result)
img_id = result['status'] img_id = result['status']
self.tmp_imgs.append(img_id) self.tmp_imgs.append(img_id)
@requires_api_version('1.25')
class PruneImagesTest(BaseAPIIntegrationTest):
def test_prune_images(self):
try:
self.client.remove_image('hello-world')
except docker.errors.APIError:
pass
# Ensure busybox does not get pruned
ctnr = self.client.create_container(BUSYBOX, ['sleep', '9999'])
self.tmp_containers.append(ctnr)
self.client.pull('hello-world')
self.tmp_imgs.append('hello-world')
img_id = self.client.inspect_image('hello-world')['Id']
result = self.client.prune_images()
assert img_id not in [
img.get('Deleted') for img in result['ImagesDeleted']
]
result = self.client.prune_images({'dangling': False})
assert result['SpaceReclaimed'] > 0
assert 'hello-world:latest' in [
img.get('Untagged') for img in result['ImagesDeleted']
]
assert img_id in [
img.get('Deleted') for img in result['ImagesDeleted']
]
...@@ -3,7 +3,7 @@ from docker.types import IPAMConfig, IPAMPool ...@@ -3,7 +3,7 @@ from docker.types import IPAMConfig, IPAMPool
import pytest import pytest
from ..helpers import random_name, requires_api_version from ..helpers import random_name, requires_api_version
from .base import BaseAPIIntegrationTest from .base import BaseAPIIntegrationTest, BUSYBOX
class TestNetworks(BaseAPIIntegrationTest): class TestNetworks(BaseAPIIntegrationTest):
...@@ -98,7 +98,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -98,7 +98,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_and_disconnect_container(self): def test_connect_and_disconnect_container(self):
net_name, net_id = self.create_network() net_name, net_id = self.create_network()
container = self.client.create_container('busybox', 'top') container = self.client.create_container(BUSYBOX, 'top')
self.tmp_containers.append(container) self.tmp_containers.append(container)
self.client.start(container) self.client.start(container)
...@@ -126,7 +126,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -126,7 +126,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_and_force_disconnect_container(self): def test_connect_and_force_disconnect_container(self):
net_name, net_id = self.create_network() net_name, net_id = self.create_network()
container = self.client.create_container('busybox', 'top') container = self.client.create_container(BUSYBOX, 'top')
self.tmp_containers.append(container) self.tmp_containers.append(container)
self.client.start(container) self.client.start(container)
...@@ -153,7 +153,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -153,7 +153,7 @@ class TestNetworks(BaseAPIIntegrationTest):
def test_connect_with_aliases(self): def test_connect_with_aliases(self):
net_name, net_id = self.create_network() net_name, net_id = self.create_network()
container = self.client.create_container('busybox', 'top') container = self.client.create_container(BUSYBOX, 'top')
self.tmp_containers.append(container) self.tmp_containers.append(container)
self.client.start(container) self.client.start(container)
...@@ -171,7 +171,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -171,7 +171,7 @@ class TestNetworks(BaseAPIIntegrationTest):
net_name, net_id = self.create_network() net_name, net_id = self.create_network()
container = self.client.create_container( container = self.client.create_container(
image='busybox', image=BUSYBOX,
command='top', command='top',
host_config=self.client.create_host_config(network_mode=net_name), host_config=self.client.create_host_config(network_mode=net_name),
) )
...@@ -192,7 +192,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -192,7 +192,7 @@ class TestNetworks(BaseAPIIntegrationTest):
net_name, net_id = self.create_network() net_name, net_id = self.create_network()
container = self.client.create_container( container = self.client.create_container(
image='busybox', image=BUSYBOX,
command='top', command='top',
host_config=self.client.create_host_config( host_config=self.client.create_host_config(
network_mode=net_name, network_mode=net_name,
...@@ -222,7 +222,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -222,7 +222,7 @@ class TestNetworks(BaseAPIIntegrationTest):
), ),
) )
container = self.client.create_container( container = self.client.create_container(
image='busybox', command='top', image=BUSYBOX, command='top',
host_config=self.client.create_host_config(network_mode=net_name), host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({ networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config( net_name: self.client.create_endpoint_config(
...@@ -251,7 +251,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -251,7 +251,7 @@ class TestNetworks(BaseAPIIntegrationTest):
), ),
) )
container = self.client.create_container( container = self.client.create_container(
image='busybox', command='top', image=BUSYBOX, command='top',
host_config=self.client.create_host_config(network_mode=net_name), host_config=self.client.create_host_config(network_mode=net_name),
networking_config=self.client.create_networking_config({ networking_config=self.client.create_networking_config({
net_name: self.client.create_endpoint_config( net_name: self.client.create_endpoint_config(
...@@ -274,7 +274,7 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -274,7 +274,7 @@ class TestNetworks(BaseAPIIntegrationTest):
@requires_api_version('1.24') @requires_api_version('1.24')
def test_create_with_linklocal_ips(self): def test_create_with_linklocal_ips(self):
container = self.client.create_container( container = self.client.create_container(
'busybox', 'top', BUSYBOX, 'top',
networking_config=self.client.create_networking_config( networking_config=self.client.create_networking_config(
{ {
'bridge': self.client.create_endpoint_config( 'bridge': self.client.create_endpoint_config(
...@@ -451,3 +451,9 @@ class TestNetworks(BaseAPIIntegrationTest): ...@@ -451,3 +451,9 @@ class TestNetworks(BaseAPIIntegrationTest):
_, net_id = self.create_network(driver='overlay', attachable=True) _, net_id = self.create_network(driver='overlay', attachable=True)
net = self.client.inspect_network(net_id) net = self.client.inspect_network(net_id)
assert net['Attachable'] is True assert net['Attachable'] is True
@requires_api_version('1.25')
def test_prune_networks(self):
net_name, _ = self.create_network()
result = self.client.prune_networks()
assert net_name in result['NetworksDeleted']
...@@ -3,7 +3,7 @@ import random ...@@ -3,7 +3,7 @@ import random
import docker import docker
from ..helpers import force_leave_swarm, requires_api_version from ..helpers import force_leave_swarm, requires_api_version
from .base import BaseAPIIntegrationTest from .base import BaseAPIIntegrationTest, BUSYBOX
class ServiceTest(BaseAPIIntegrationTest): class ServiceTest(BaseAPIIntegrationTest):
...@@ -31,7 +31,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -31,7 +31,7 @@ class ServiceTest(BaseAPIIntegrationTest):
name = self.get_service_name() name = self.get_service_name()
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['echo', 'hello'] BUSYBOX, ['echo', 'hello']
) )
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
return name, self.client.create_service(task_tmpl, name=name) return name, self.client.create_service(task_tmpl, name=name)
...@@ -81,7 +81,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -81,7 +81,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_custom_log_driver(self): def test_create_service_custom_log_driver(self):
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['echo', 'hello'] BUSYBOX, ['echo', 'hello']
) )
log_cfg = docker.types.DriverConfig('none') log_cfg = docker.types.DriverConfig('none')
task_tmpl = docker.types.TaskTemplate( task_tmpl = docker.types.TaskTemplate(
...@@ -99,7 +99,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -99,7 +99,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_volume_mount(self): def test_create_service_with_volume_mount(self):
vol_name = self.get_service_name() vol_name = self.get_service_name()
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['ls'], BUSYBOX, ['ls'],
mounts=[ mounts=[
docker.types.Mount(target='/test', source=vol_name) docker.types.Mount(target='/test', source=vol_name)
] ]
...@@ -119,7 +119,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -119,7 +119,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert mount['Type'] == 'volume' assert mount['Type'] == 'volume'
def test_create_service_with_resources_constraints(self): def test_create_service_with_resources_constraints(self):
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
resources = docker.types.Resources( resources = docker.types.Resources(
cpu_limit=4000000, mem_limit=3 * 1024 * 1024 * 1024, cpu_limit=4000000, mem_limit=3 * 1024 * 1024 * 1024,
cpu_reservation=3500000, mem_reservation=2 * 1024 * 1024 * 1024 cpu_reservation=3500000, mem_reservation=2 * 1024 * 1024 * 1024
...@@ -139,7 +139,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -139,7 +139,7 @@ class ServiceTest(BaseAPIIntegrationTest):
] ]
def test_create_service_with_update_config(self): def test_create_service_with_update_config(self):
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
update_config = docker.types.UpdateConfig( update_config = docker.types.UpdateConfig(
parallelism=10, delay=5, failure_action='pause' parallelism=10, delay=5, failure_action='pause'
...@@ -173,7 +173,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -173,7 +173,7 @@ class ServiceTest(BaseAPIIntegrationTest):
assert update_config['MaxFailureRatio'] == uc['MaxFailureRatio'] assert update_config['MaxFailureRatio'] == uc['MaxFailureRatio']
def test_create_service_with_restart_policy(self): def test_create_service_with_restart_policy(self):
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
policy = docker.types.RestartPolicy( policy = docker.types.RestartPolicy(
docker.types.RestartPolicy.condition_types.ANY, docker.types.RestartPolicy.condition_types.ANY,
delay=5, max_attempts=5 delay=5, max_attempts=5
...@@ -196,7 +196,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -196,7 +196,7 @@ class ServiceTest(BaseAPIIntegrationTest):
'dockerpytest_2', driver='overlay', ipam={'Driver': 'default'} 'dockerpytest_2', driver='overlay', ipam={'Driver': 'default'}
) )
self.tmp_networks.append(net2['Id']) self.tmp_networks.append(net2['Id'])
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name() name = self.get_service_name()
svc_id = self.client.create_service( svc_id = self.client.create_service(
...@@ -212,7 +212,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -212,7 +212,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_placement(self): def test_create_service_with_placement(self):
node_id = self.client.nodes()[0]['ID'] node_id = self.client.nodes()[0]['ID']
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
task_tmpl = docker.types.TaskTemplate( task_tmpl = docker.types.TaskTemplate(
container_spec, placement=['node.id=={}'.format(node_id)] container_spec, placement=['node.id=={}'.format(node_id)]
) )
...@@ -224,7 +224,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -224,7 +224,7 @@ class ServiceTest(BaseAPIIntegrationTest):
{'Constraints': ['node.id=={}'.format(node_id)]}) {'Constraints': ['node.id=={}'.format(node_id)]})
def test_create_service_with_endpoint_spec(self): def test_create_service_with_endpoint_spec(self):
container_spec = docker.types.ContainerSpec('busybox', ['true']) container_spec = docker.types.ContainerSpec(BUSYBOX, ['true'])
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name() name = self.get_service_name()
endpoint_spec = docker.types.EndpointSpec(ports={ endpoint_spec = docker.types.EndpointSpec(ports={
...@@ -255,7 +255,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -255,7 +255,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_with_env(self): def test_create_service_with_env(self):
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['true'], env={'DOCKER_PY_TEST': 1} BUSYBOX, ['true'], env={'DOCKER_PY_TEST': 1}
) )
task_tmpl = docker.types.TaskTemplate( task_tmpl = docker.types.TaskTemplate(
container_spec, container_spec,
...@@ -271,7 +271,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -271,7 +271,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_global_mode(self): def test_create_service_global_mode(self):
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['echo', 'hello'] BUSYBOX, ['echo', 'hello']
) )
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name() name = self.get_service_name()
...@@ -284,7 +284,7 @@ class ServiceTest(BaseAPIIntegrationTest): ...@@ -284,7 +284,7 @@ class ServiceTest(BaseAPIIntegrationTest):
def test_create_service_replicated_mode(self): def test_create_service_replicated_mode(self):
container_spec = docker.types.ContainerSpec( container_spec = docker.types.ContainerSpec(
'busybox', ['echo', 'hello'] BUSYBOX, ['echo', 'hello']
) )
task_tmpl = docker.types.TaskTemplate(container_spec) task_tmpl = docker.types.TaskTemplate(container_spec)
name = self.get_service_name() name = self.get_service_name()
......
...@@ -56,6 +56,14 @@ class TestVolumes(BaseAPIIntegrationTest): ...@@ -56,6 +56,14 @@ class TestVolumes(BaseAPIIntegrationTest):
self.client.create_volume(name) self.client.create_volume(name)
self.client.remove_volume(name, force=True) self.client.remove_volume(name, force=True)
@requires_api_version('1.25')
def test_prune_volumes(self):
name = 'hopelessmasquerade'
self.client.create_volume(name)
self.tmp_volumes.append(name)
result = self.client.prune_volumes()
assert name in result['VolumesDeleted']
def test_remove_nonexistent_volume(self): def test_remove_nonexistent_volume(self):
name = 'shootthebullet' name = 'shootthebullet'
with pytest.raises(docker.errors.NotFound): with pytest.raises(docker.errors.NotFound):
......
...@@ -81,7 +81,7 @@ class BaseAPIIntegrationTest(BaseIntegrationTest): ...@@ -81,7 +81,7 @@ class BaseAPIIntegrationTest(BaseIntegrationTest):
return container return container
def create_and_start(self, image='busybox', command='top', **kwargs): def create_and_start(self, image=BUSYBOX, command='top', **kwargs):
container = self.client.create_container( container = self.client.create_container(
image=image, command=command, **kwargs) image=image, command=command, **kwargs)
self.tmp_containers.append(container) self.tmp_containers.append(container)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment