Merge pull request #27 from kentwills/remove_py26_support

Remove py26 support, code cleanup
This commit is contained in:
Kyle Anderson 2016-04-20 14:10:18 -07:00
commit 0749ece61a
9 changed files with 127 additions and 86 deletions

View File

@ -1,11 +1,9 @@
language: python
env:
- TOX_ENV=py26
- TOX_ENV=py27
- TOX_ENV=py33
- TOX_ENV=py34
- TOXENV=py27
- TOXENV=py33
- TOXENV=py34
install:
- "pip install --use-mirrors tox"
- pip install tox
script:
- tox -e $TOX_ENV
sudo: false
- tox

2
debian/rules vendored
View File

@ -7,7 +7,7 @@ export DH_OPTIONS
dh $@ --with python-virtualenv
override_dh_virtualenv:
dh_virtualenv
dh_virtualenv --python python2.7
# do not call `make clean` as part of packaging
override_dh_auto_clean:

View File

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

View File

@ -7,7 +7,8 @@ from pytimeparse import timeparse
def timedelta_type(value):
"""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`
"""
if value is None:
return None

View File

@ -77,18 +77,22 @@ def get_opts(args=None):
parser.add_argument(
'--max-run-time',
type=timedelta_type,
help="Maximum time a container is allows to run. Time may be specified "
"in any pytimeparse supported format.")
help="Maximum time a container is allows to run. Time may "
"be specified in any pytimeparse supported format."
)
parser.add_argument(
'--prefix', action="append", default=[],
help="Only stop containers which match one of the "
"prefix.")
"prefix."
)
parser.add_argument(
'--dry-run', action="store_true",
help="Only log actions, don't stop anything.")
help="Only log actions, don't stop anything."
)
parser.add_argument(
'-t', '--timeout', type=int, default=60,
help="HTTP timeout in seconds for making docker API calls.")
help="HTTP timeout in seconds for making docker API calls."
)
opts = parser.parse_args(args=args)
if not opts.prefix:

View File

@ -1,20 +1,8 @@
# -*- coding: utf-8 -*-
from setuptools import setup, find_packages
import sys
from docker_custodian.__about__ import __version__
install_requires = [
'python-dateutil',
'docker-py >= 0.5',
'pytimeparse',
]
if sys.version_info < (2, 7):
install_requires.append('argparse')
setup(
name='docker_custodian',
version=__version__,
@ -24,7 +12,11 @@ setup(
description='Keep docker hosts tidy.',
packages=find_packages(exclude=['tests*']),
include_package_data=True,
install_requires=install_requires,
install_requires=[
'python-dateutil',
'docker-py >= 0.5',
'pytimeparse',
],
license="Apache License 2.0",
entry_points={
'console_scripts': [

View File

@ -54,7 +54,12 @@ def test_has_been_running_since_false(container, earlier_time):
@mock.patch('docker_custodian.docker_autostop.get_opts',
autospec=True)
@mock.patch('docker_custodian.docker_autostop.docker', autospec=True)
def test_main(mock_docker, mock_get_opts, mock_stop_containers, mock_build_matcher):
def test_main(
mock_docker,
mock_get_opts,
mock_stop_containers,
mock_build_matcher
):
mock_get_opts.return_value.timeout = 30
main()
mock_get_opts.assert_called_once_with()

View File

@ -42,18 +42,26 @@ class TestShouldRemoveContainer(object):
def test_cleanup_containers(mock_client, now):
max_container_age = now
mock_client.containers.return_value = [
dict(Id='abcd'),
dict(Id='abbb'),
{'Id': 'abcd'},
{'Id': 'abbb'},
]
mock_containers = [
dict(
Id='abcd',
Name='one',
State=dict(Running=False, FinishedAt='2014-01-01T01:01:01Z')),
dict(
Id='abbb',
Name='two',
State=dict(Running=True, FinishedAt='2014-01-01T01:01:01Z'))
{
'Id': 'abcd',
'Name': 'one',
'State': {
'Running': False,
'FinishedAt': '2014-01-01T01:01:01Z'
}
},
{
'Id': 'abbb',
'Name': 'two',
'State': {
'Running': True,
'FinishedAt': '2014-01-01T01:01:01Z'
}
}
]
mock_client.inspect_container.side_effect = iter(mock_containers)
docker_gc.cleanup_containers(mock_client, max_container_age, False)
@ -63,12 +71,18 @@ def test_cleanup_containers(mock_client, now):
def test_cleanup_images(mock_client, now):
max_image_age = now
mock_client.images.return_value = images = [
dict(Id='abcd'),
dict(Id='abbb'),
{'Id': 'abcd'},
{'Id': 'abbb'},
]
mock_images = [
dict(Id='abcd', Created='2014-01-01T01:01:01Z'),
dict(Id='abbb', Created='2014-01-01T01:01:01Z'),
{
'Id': 'abcd',
'Created': '2014-01-01T01:01:01Z'
},
{
'Id': 'abbb',
'Created': '2014-01-01T01:01:01Z'
},
]
mock_client.inspect_image.side_effect = iter(mock_images)
@ -86,17 +100,38 @@ def test_filter_images_in_use():
'2471708c19be:latest',
])
images = [
dict(RepoTags=['<none>:<none>'], Id='2471708c19beabababab'),
dict(RepoTags=['<none>:<none>'], Id='babababababaabababab'),
dict(RepoTags=['user/one:latest', 'user/one:abcd']),
dict(RepoTags=['other:abcda']),
dict(RepoTags=['other:12345']),
dict(RepoTags=['new_image:latest', 'new_image:123']),
{
'RepoTags': ['<none>:<none>'],
'Id': '2471708c19beabababab'
},
{
'RepoTags': ['<none>:<none>'],
'Id': 'babababababaabababab'
},
{
'RepoTags': ['user/one:latest', 'user/one:abcd']
},
{
'RepoTags': ['other:abcda']
},
{
'RepoTags': ['other:12345']
},
{
'RepoTags': ['new_image:latest', 'new_image:123']
},
]
expected = [
dict(RepoTags=['<none>:<none>'], Id='babababababaabababab'),
dict(RepoTags=['other:abcda']),
dict(RepoTags=['new_image:latest', 'new_image:123']),
{
'RepoTags': ['<none>:<none>'],
'Id': 'babababababaabababab'
},
{
'RepoTags': ['other:abcda']
},
{
'RepoTags': ['new_image:latest', 'new_image:123']
},
]
actual = docker_gc.filter_images_in_use(images, image_tags_in_use)
assert list(actual) == expected
@ -109,16 +144,34 @@ def test_filter_excluded_images():
'other:12345',
])
images = [
dict(RepoTags=['<none>:<none>'], Id='babababababaabababab'),
dict(RepoTags=['user/one:latest', 'user/one:abcd']),
dict(RepoTags=['other:abcda']),
dict(RepoTags=['other:12345']),
dict(RepoTags=['new_image:latest', 'new_image:123']),
{
'RepoTags': ['<none>:<none>'],
'Id': 'babababababaabababab'
},
{
'RepoTags': ['user/one:latest', 'user/one:abcd']
},
{
'RepoTags': ['other:abcda']
},
{
'RepoTags': ['other:12345']
},
{
'RepoTags': ['new_image:latest', 'new_image:123']
},
]
expected = [
dict(RepoTags=['<none>:<none>'], Id='babababababaabababab'),
dict(RepoTags=['other:abcda']),
dict(RepoTags=['new_image:latest', 'new_image:123']),
{
'RepoTags': ['<none>:<none>'],
'Id': 'babababababaabababab'
},
{
'RepoTags': ['other:abcda']
},
{
'RepoTags': ['new_image:latest', 'new_image:123']
},
]
actual = docker_gc.filter_excluded_images(images, exclude_set)
assert list(actual) == expected
@ -134,7 +187,7 @@ def test_is_image_old_false(image, later_time):
def test_remove_image_no_tags(mock_client, image, now):
image_id = 'abcd'
image_summary = dict(Id=image_id)
image_summary = {'Id': image_id}
mock_client.inspect_image.return_value = image
docker_gc.remove_image(mock_client, image_summary, now, False)
@ -143,7 +196,7 @@ def test_remove_image_no_tags(mock_client, image, now):
def test_remove_image_new_image_not_removed(mock_client, image, later_time):
image_id = 'abcd'
image_summary = dict(Id=image_id)
image_summary = {'Id': image_id}
mock_client.inspect_image.return_value = image
docker_gc.remove_image(mock_client, image_summary, later_time, False)
@ -153,7 +206,10 @@ def test_remove_image_new_image_not_removed(mock_client, image, later_time):
def test_remove_image_with_tags(mock_client, image, now):
image_id = 'abcd'
repo_tags = ['user/one:latest', 'user/one:12345']
image_summary = dict(Id=image_id, RepoTags=repo_tags)
image_summary = {
'Id': image_id,
'RepoTags': repo_tags
}
mock_client.inspect_image.return_value = image
docker_gc.remove_image(mock_client, image_summary, now, False)
@ -182,7 +238,9 @@ def test_api_call_with_timeout():
docker_gc.api_call(func, id)
func.assert_called_once_with(id)
mock_log.warn.assert_called_once_with('Failed to call remove_image abcd msg')
mock_log.warn.assert_called_once_with(
'Failed to call remove_image abcd msg'
)
def test_api_call_with_api_error():

27
tox.ini
View File

@ -1,30 +1,13 @@
[tox]
envlist = py26,py27,py33,py34
envlist = py27,py33,py34
[testenv]
deps =
-rrequirements.txt
flake8
pytest
mock
pre-commit
pytest
commands =
py.test {posargs:tests}
flake8 .
[testenv:py26]
deps =
-rrequirements.txt
flake8
pytest
mock < 1.1.0
[testenv:install-hooks]
deps =
pre-commit
commands =
pre-commit install
[flake8]
ignore =
exclude = .git/*,.tox/*,debian/*
max_line_length = 85
pre-commit install -f --install-hooks
pre-commit run --all-files