mirror of
https://github.com/thegeeklab/docker-tidy.git
synced 2024-11-25 05:30:39 +00:00
Merge pull request #40 from ymilki/dangling_volumes
Remove dangling volumes
This commit is contained in:
commit
4925cb0d9a
@ -74,6 +74,13 @@ def get_all_images(client):
|
|||||||
return images
|
return images
|
||||||
|
|
||||||
|
|
||||||
|
def get_dangling_volumes(client):
|
||||||
|
log.info("Getting dangling volumes")
|
||||||
|
volumes = client.volumes({'dangling': True})['Volumes']
|
||||||
|
log.info("Found %s dangling volumes", len(volumes))
|
||||||
|
return volumes
|
||||||
|
|
||||||
|
|
||||||
def cleanup_images(client, max_image_age, dry_run, exclude_set):
|
def cleanup_images(client, max_image_age, dry_run, exclude_set):
|
||||||
# re-fetch container list so that we don't include removed containers
|
# re-fetch container list so that we don't include removed containers
|
||||||
image_tags_in_use = set(
|
image_tags_in_use = set(
|
||||||
@ -141,6 +148,25 @@ def remove_image(client, image_summary, min_date, dry_run):
|
|||||||
api_call(client.remove_image, image=image_tag)
|
api_call(client.remove_image, image=image_tag)
|
||||||
|
|
||||||
|
|
||||||
|
def remove_volume(client, volume, dry_run):
|
||||||
|
if not volume:
|
||||||
|
return
|
||||||
|
|
||||||
|
log.info("Removing volume %s" % volume['Name'])
|
||||||
|
if dry_run:
|
||||||
|
return
|
||||||
|
|
||||||
|
api_call(client.remove_volume, name=volume['Name'])
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup_volumes(client, dry_run):
|
||||||
|
dangling_volumes = get_dangling_volumes(client)
|
||||||
|
|
||||||
|
for volume in reversed(dangling_volumes):
|
||||||
|
log.info("Removing dangling volume %s", volume['Name'])
|
||||||
|
remove_volume(client, volume, dry_run)
|
||||||
|
|
||||||
|
|
||||||
def api_call(func, **kwargs):
|
def api_call(func, **kwargs):
|
||||||
try:
|
try:
|
||||||
return func(**kwargs)
|
return func(**kwargs)
|
||||||
@ -192,6 +218,9 @@ def main():
|
|||||||
args.exclude_image_file)
|
args.exclude_image_file)
|
||||||
cleanup_images(client, args.max_image_age, args.dry_run, exclude_set)
|
cleanup_images(client, args.max_image_age, args.dry_run, exclude_set)
|
||||||
|
|
||||||
|
if args.dangling_volumes:
|
||||||
|
cleanup_volumes(client, args.dry_run)
|
||||||
|
|
||||||
|
|
||||||
def get_args(args=None):
|
def get_args(args=None):
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
@ -207,6 +236,10 @@ def get_args(args=None):
|
|||||||
help="Maxium age for an image. Images older than this age will be "
|
help="Maxium age for an image. Images older than this age will be "
|
||||||
"removed. Age can be specified in any pytimeparse supported "
|
"removed. Age can be specified in any pytimeparse supported "
|
||||||
"format.")
|
"format.")
|
||||||
|
parser.add_argument(
|
||||||
|
'--dangling-volumes',
|
||||||
|
action="store_true",
|
||||||
|
help="Dangling volumes will be removed.")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--dry-run', action="store_true",
|
'--dry-run', action="store_true",
|
||||||
help="Only log actions, don't remove anything.")
|
help="Only log actions, don't remove anything.")
|
||||||
|
@ -93,6 +93,32 @@ def test_cleanup_images(mock_client, now):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_cleanup_volumes(mock_client):
|
||||||
|
mock_client.volumes.return_value = volumes = {
|
||||||
|
'Volumes': [
|
||||||
|
{
|
||||||
|
'Mountpoint': 'unused',
|
||||||
|
'Labels': None,
|
||||||
|
'Driver': 'unused',
|
||||||
|
'Name': u'one'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'Mountpoint': 'unused',
|
||||||
|
'Labels': None,
|
||||||
|
'Driver': 'unused',
|
||||||
|
'Name': u'two'
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'Warnings': None,
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_gc.cleanup_volumes(mock_client, False)
|
||||||
|
assert mock_client.remove_volume.mock_calls == [
|
||||||
|
mock.call(name=volume['Name'])
|
||||||
|
for volume in reversed(volumes['Volumes'])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_filter_images_in_use():
|
def test_filter_images_in_use():
|
||||||
image_tags_in_use = set([
|
image_tags_in_use = set([
|
||||||
'user/one:latest',
|
'user/one:latest',
|
||||||
@ -355,6 +381,18 @@ def test_get_all_images(mock_client):
|
|||||||
mock_log.info.assert_called_with("Found %s images", count)
|
mock_log.info.assert_called_with("Found %s images", count)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_dangling_volumes(mock_client):
|
||||||
|
count = 4
|
||||||
|
mock_client.volumes.return_value = {
|
||||||
|
'Volumes': [mock.Mock() for _ in range(count)]
|
||||||
|
}
|
||||||
|
with mock.patch('docker_custodian.docker_gc.log',
|
||||||
|
autospec=True) as mock_log:
|
||||||
|
volumes = docker_gc.get_dangling_volumes(mock_client)
|
||||||
|
assert volumes == mock_client.volumes.return_value['Volumes']
|
||||||
|
mock_log.info.assert_called_with("Found %s dangling volumes", count)
|
||||||
|
|
||||||
|
|
||||||
def test_build_exclude_set():
|
def test_build_exclude_set():
|
||||||
image_tags = [
|
image_tags = [
|
||||||
'some_image:latest',
|
'some_image:latest',
|
||||||
|
Loading…
Reference in New Issue
Block a user