Merge pull request #36 from Yelp/remove_volumes

Remove volumes when removing containers
This commit is contained in:
Kyle Anderson 2016-10-05 09:36:06 -07:00 committed by GitHub
commit f645eafbad
5 changed files with 39 additions and 28 deletions

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
docker-custodian (0.7.0) lucid; urgency=low
* Delete volumes along with containers
-- Paul O'Connor <poc@yelp.com> Wed, 05 Oct 2016 00:58:10 -0700
docker-custodian (0.6.1) lucid; urgency=low
* New release for pypi

View File

@ -1,4 +1,4 @@
# -*- coding: utf8 -*-
__version_info__ = (0, 6, 1)
__version_info__ = (0, 7, 0)
__version__ = '%d.%d.%d' % __version_info__

View File

@ -25,7 +25,8 @@ def cleanup_containers(client, max_container_age, dry_run):
all_containers = get_all_containers(client)
for container_summary in reversed(all_containers):
container = api_call(client.inspect_container, container_summary['Id'])
container = api_call(client.inspect_container,
container=container_summary['Id'])
if not container or not should_remove_container(container,
max_container_age):
continue
@ -36,7 +37,8 @@ def cleanup_containers(client, max_container_age, dry_run):
container['State']['FinishedAt']))
if not dry_run:
api_call(client.remove_container, container['Id'])
api_call(client.remove_container, container=container['Id'],
v=True)
def should_remove_container(container, min_date):
@ -116,7 +118,7 @@ def no_image_tags(image_tags):
def remove_image(client, image_summary, min_date, dry_run):
image = api_call(client.inspect_image, image_summary['Id'])
image = api_call(client.inspect_image, image=image_summary['Id'])
if not image or not is_image_old(image, min_date):
return
@ -127,21 +129,23 @@ def remove_image(client, image_summary, min_date, dry_run):
image_tags = image_summary.get('RepoTags')
# If there are no tags, remove the id
if no_image_tags(image_tags):
api_call(client.remove_image, image_summary['Id'])
api_call(client.remove_image, image=image_summary['Id'])
return
# Remove any repository tags so we don't hit 409 Conflict
for image_tag in image_tags:
api_call(client.remove_image, image_tag)
api_call(client.remove_image, image=image_tag)
def api_call(func, id):
def api_call(func, **kwargs):
try:
return func(id)
return func(**kwargs)
except requests.exceptions.Timeout as e:
log.warn("Failed to call %s %s %s" % (func.__name__, id, e))
params = ','.join('%s=%s' % item for item in kwargs.items())
log.warn("Failed to call %s %s %s" % (func.__name__, params, e))
except docker.errors.APIError as ae:
log.warn("Error calling %s %s %s" % (func.__name__, id, ae))
params = ','.join('%s=%s' % item for item in kwargs.items())
log.warn("Error calling %s %s %s" % (func.__name__, params, ae))
def format_image(image, image_summary):

View File

@ -1,6 +1,6 @@
argparse==1.3.0
backports.ssl-match-hostname==3.4.0.2
docker-py==1.7.2
docker-py==1.8.1
future==0.14.3
python-dateutil==2.4.0
pytimeparse==1.1.2

View File

@ -65,7 +65,8 @@ def test_cleanup_containers(mock_client, now):
]
mock_client.inspect_container.side_effect = iter(mock_containers)
docker_gc.cleanup_containers(mock_client, max_container_age, False)
mock_client.remove_container.assert_called_once_with('abcd')
mock_client.remove_container.assert_called_once_with(container='abcd',
v=True)
def test_cleanup_images(mock_client, now):
@ -88,7 +89,7 @@ def test_cleanup_images(mock_client, now):
docker_gc.cleanup_images(mock_client, max_image_age, False, set())
assert mock_client.remove_image.mock_calls == [
mock.call(image['Id']) for image in reversed(images)
mock.call(image=image['Id']) for image in reversed(images)
]
@ -191,7 +192,7 @@ def test_remove_image_no_tags(mock_client, image, now):
mock_client.inspect_image.return_value = image
docker_gc.remove_image(mock_client, image_summary, now, False)
mock_client.remove_image.assert_called_once_with(image_id)
mock_client.remove_image.assert_called_once_with(image=image_id)
def test_remove_image_new_image_not_removed(mock_client, image, later_time):
@ -214,15 +215,15 @@ def test_remove_image_with_tags(mock_client, image, now):
docker_gc.remove_image(mock_client, image_summary, now, False)
assert mock_client.remove_image.mock_calls == [
mock.call(tag) for tag in repo_tags
mock.call(image=tag) for tag in repo_tags
]
def test_api_call_success():
func = mock.Mock()
id = "abcd"
result = docker_gc.api_call(func, id)
func.assert_called_once_with(id)
container = "abcd"
result = docker_gc.api_call(func, container=container)
func.assert_called_once_with(container="abcd")
assert result == func.return_value
@ -230,17 +231,17 @@ def test_api_call_with_timeout():
func = mock.Mock(
side_effect=requests.exceptions.ReadTimeout("msg"),
__name__="remove_image")
id = "abcd"
image = "abcd"
with mock.patch(
'docker_custodian.docker_gc.log',
autospec=True) as mock_log:
docker_gc.api_call(func, id)
docker_gc.api_call(func, image=image)
func.assert_called_once_with(id)
mock_log.warn.assert_called_once_with(
'Failed to call remove_image abcd msg'
)
func.assert_called_once_with(image="abcd")
mock_log.warn.assert_called_once_with('Failed to call remove_image '
+ 'image=abcd msg'
)
def test_api_call_with_api_error():
@ -250,16 +251,16 @@ def test_api_call_with_api_error():
mock.Mock(status_code=409, reason="Conflict"),
explanation="failed"),
__name__="remove_image")
id = "abcd"
image = "abcd"
with mock.patch(
'docker_custodian.docker_gc.log',
autospec=True) as mock_log:
docker_gc.api_call(func, id)
docker_gc.api_call(func, image=image)
func.assert_called_once_with(id)
func.assert_called_once_with(image="abcd")
mock_log.warn.assert_called_once_with(
'Error calling remove_image abcd '
'Error calling remove_image image=abcd '
'409 Client Error: Conflict ("failed")')