Merge pull request #23 from analogue/min_container_age

Don't remove recently created containers that were never used
This commit is contained in:
Kyle Anderson 2015-12-15 09:30:44 -08:00
commit a6a66db9e9
3 changed files with 26 additions and 16 deletions

View File

@ -5,7 +5,7 @@ from pytimeparse import timeparse
def timedelta_type(value): def timedelta_type(value):
"""Retrun the :class:`datetime.datetime.DateTime` for a time in the past. """Return the :class:`datetime.datetime.DateTime` for a time in the past.
:param value: a string containing a time format supported by :mod:`pytimeparse` :param value: a string containing a time format supported by :mod:`pytimeparse`
""" """

View File

@ -26,7 +26,8 @@ def cleanup_containers(client, max_container_age, dry_run):
for container_summary in reversed(all_containers): for container_summary in reversed(all_containers):
container = api_call(client.inspect_container, container_summary['Id']) container = api_call(client.inspect_container, container_summary['Id'])
if not container or not is_container_old(container, max_container_age): if not container or not should_remove_container(container,
max_container_age):
continue continue
log.info("Removing container %s %s %s" % ( log.info("Removing container %s %s %s" % (
@ -38,24 +39,26 @@ def cleanup_containers(client, max_container_age, dry_run):
api_call(client.remove_container, container['Id']) api_call(client.remove_container, container['Id'])
def is_container_old(container, min_date): def should_remove_container(container, min_date):
state = container.get('State', {}) state = container.get('State', {})
if state.get('Running'): if state.get('Running'):
return False return False
if state.get('Ghost'): if state.get('Ghost'):
return True return True
# Container was created, but never used # Container was created, but never started
if (state.get('FinishedAt') == YEAR_ZERO and if state.get('FinishedAt') == YEAR_ZERO:
dateutil.parser.parse(container['Created']) < min_date): created_date = dateutil.parser.parse(container['Created'])
return True return created_date < min_date
return dateutil.parser.parse(state['FinishedAt']) < min_date finished_date = dateutil.parser.parse(state['FinishedAt'])
return finished_date < min_date
def get_all_containers(client): def get_all_containers(client):
log.info("Getting all continers") log.info("Getting all containers")
containers = client.containers(all=True) containers = client.containers(all=True)
log.info("Found %s containers", len(containers)) log.info("Found %s containers", len(containers))
return containers return containers
@ -174,6 +177,7 @@ def main():
if args.max_container_age: if args.max_container_age:
cleanup_containers(client, args.max_container_age, args.dry_run) cleanup_containers(client, args.max_container_age, args.dry_run)
if args.max_image_age: if args.max_image_age:
exclude_set = build_exclude_set( exclude_set = build_exclude_set(
args.exclude_image, args.exclude_image,

View File

@ -11,26 +11,32 @@ import requests.exceptions
from docker_custodian import docker_gc from docker_custodian import docker_gc
class TestIsOldContainer(object): class TestShouldRemoveContainer(object):
def test_is_running(self, container, now): def test_is_running(self, container, now):
container['State']['Running'] = True container['State']['Running'] = True
assert not docker_gc.is_container_old(container, now) assert not docker_gc.should_remove_container(container, now)
def test_is_ghost(self, container, now): def test_is_ghost(self, container, now):
container['State']['Ghost'] = True container['State']['Ghost'] = True
assert docker_gc.is_container_old(container, now) assert docker_gc.should_remove_container(container, now)
def test_old_never_run(self, container, now): def test_old_never_run(self, container, now, earlier_time):
container['Created'] = str(earlier_time)
container['State']['FinishedAt'] = docker_gc.YEAR_ZERO container['State']['FinishedAt'] = docker_gc.YEAR_ZERO
assert docker_gc.is_container_old(container, now) assert docker_gc.should_remove_container(container, now)
def test_not_old_never_run(self, container, now, earlier_time):
container['Created'] = str(now)
container['State']['FinishedAt'] = docker_gc.YEAR_ZERO
assert not docker_gc.should_remove_container(container, now)
def test_old_stopped(self, container, now): def test_old_stopped(self, container, now):
assert docker_gc.is_container_old(container, now) assert docker_gc.should_remove_container(container, now)
def test_not_old(self, container, now): def test_not_old(self, container, now):
container['State']['FinishedAt'] = '2014-01-21T00:00:00Z' container['State']['FinishedAt'] = '2014-01-21T00:00:00Z'
assert not docker_gc.is_container_old(container, now) assert not docker_gc.should_remove_container(container, now)
def test_cleanup_containers(mock_client, now): def test_cleanup_containers(mock_client, now):