Skip to content

Commit

Permalink
Merge pull request Yelp#1 from glance-/exclude-volume
Browse files Browse the repository at this point in the history
Implement volume exclusion
  • Loading branch information
johanlundberg authored Oct 28, 2019
2 parents cc0fdbb + 4a39410 commit 90b89d1
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
31 changes: 28 additions & 3 deletions docker_custodian/docker_gc.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,23 @@ def remove_volume(client, volume, dry_run):
api_call(client.remove_volume, name=volume['Name'])


def cleanup_volumes(client, dry_run):
def filter_excluded_volumes(volumes, exclude_set):
def include_volume(volume):
image_name = volume['Name']
for exclude_pattern in exclude_set:
if fnmatch.fnmatch(image_name, exclude_pattern):
return False
return True

return filter(include_volume, volumes)


def cleanup_volumes(client, dry_run, exclude_set):
dangling_volumes = get_dangling_volumes(client)

for volume in reversed(dangling_volumes):
dangling_volumes = filter_excluded_volumes(dangling_volumes, exclude_set)

for volume in dangling_volumes:
log.info("Removing dangling volume %s", volume['Name'])
remove_volume(client, volume, dry_run)

Expand Down Expand Up @@ -317,7 +330,10 @@ def main():
cleanup_images(client, args.max_image_age, args.dry_run, exclude_set)

if args.dangling_volumes:
cleanup_volumes(client, args.dry_run)
exclude_set = build_exclude_set(
args.exclude_volume,
args.exclude_volume_file)
cleanup_volumes(client, args.dry_run, exclude_set)


def get_args(args=None):
Expand Down Expand Up @@ -353,6 +369,15 @@ def get_args(args=None):
type=argparse.FileType('r'),
help="Path to a file which contains a list of images to exclude, one "
"image tag per line.")
parser.add_argument(
'--exclude-volume',
action='append',
help="Never remove volume with this name.")
parser.add_argument(
'--exclude-volume-file',
type=argparse.FileType('r'),
help="Path to a file which contains a list of volumes to exclude, one "
"image tag per line.")
parser.add_argument(
'--exclude-container-label',
action='append', type=str, default=[],
Expand Down
60 changes: 58 additions & 2 deletions tests/docker_gc_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,67 @@ def test_cleanup_volumes(mock_client):
'Warnings': None,
}

docker_gc.cleanup_volumes(mock_client, False)
docker_gc.cleanup_volumes(mock_client, False, set())
assert mock_client.remove_volume.mock_calls == [
mock.call(name=volume['Name'])
for volume in reversed(volumes['Volumes'])
for volume in volumes['Volumes']
]


def test_filter_cleanup_volumes(mock_client):
mock_client.volumes.return_value = {
'Volumes': [
{
'Mountpoint': 'unused',
'Labels': None,
'Driver': 'unused',
'Name': u'unused'
},
{
'Mountpoint': 'filtered',
'Labels': None,
'Driver': 'unused',
'Name': u'filtered'
},
],
'Warnings': None,
}

docker_gc.cleanup_volumes(mock_client, False, set(['filtered']))
assert mock_client.remove_volume.mock_calls == [
mock.call(name='unused')
]


def test_filter_excluded_volumes(mock_client):
exclude_set = set(['filtered'])
volumes = [
{
'Mountpoint': 'unused',
'Labels': None,
'Driver': 'unused',
'Name': u'unused'
},
{
'Mountpoint': 'filtered',
'Labels': None,
'Driver': 'unused',
'Name': u'filtered'
},
]
expected = [
{
'Mountpoint': 'unused',
'Labels': None,
'Driver': 'unused',
'Name': u'unused'
},
]

actual = docker_gc.filter_excluded_volumes(volumes, exclude_set)
assert list(actual) == expected


def test_filter_images_in_use():
image_tags_in_use = set([
'user/one:latest',
Expand Down Expand Up @@ -527,6 +581,8 @@ def test_main(mock_client):
max_container_age=200,
exclude_image=[],
exclude_image_file=None,
exclude_volume=[],
exclude_volume_file=None,
exclude_container_label=[],
)
docker_gc.main()

0 comments on commit 90b89d1

Please sign in to comment.