Skip to content

Commit

Permalink
Add --property-filter option to v2 image-list
Browse files Browse the repository at this point in the history
The option is present in the v1 shell, but missing from the v2 shell. This
allows the user to filter based on any image property.

Example:

    $ glance --os-image-api-version 2 image-list --property-filter os_distro=NixOS

DocImpact
Closes-Bug: #1383326

Change-Id: Ia65a08520e3eaf3ecd9b9018be9f6a8e2d3d4f0b
  • Loading branch information
kragniz committed Nov 14, 2014
1 parent 711f28a commit 4194a55
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
9 changes: 9 additions & 0 deletions glanceclient/v2/shell.py
Expand Up @@ -93,6 +93,9 @@ def do_image_update(gc, args):
help='The status of images to display.')
@utils.arg('--owner', metavar='<OWNER>',
help='Display images owned by <OWNER>.')
@utils.arg('--property-filter', metavar='<KEY=VALUE>',
help="Filter images by a user-defined image property.",
action='append', dest='properties', default=[])
@utils.arg('--checksum', metavar='<CHECKSUM>',
help='Displays images that match the checksum.')
@utils.arg('--tag', metavar='<TAG>', action='append',
Expand All @@ -101,6 +104,12 @@ def do_image_list(gc, args):
"""List images you can access."""
filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag']
filter_items = [(key, getattr(args, key)) for key in filter_keys]
if args.properties:
filter_properties = [prop.split('=', 1) for prop in args.properties]
if False in (len(pair) == 2 for pair in filter_properties):
utils.exit('Argument --property-filter expected properties in the'
' format KEY=VALUE')
filter_items += filter_properties
filters = dict([item for item in filter_items if item[1] is not None])

kwargs = {'filters': filters}
Expand Down
30 changes: 30 additions & 0 deletions tests/v2/test_images.py
Expand Up @@ -346,6 +346,25 @@
'',
)
},
'/v2/images?limit=%d&os_distro=NixOS' % images.DEFAULT_PAGE_SIZE: {
'GET': (
{},
{'images': [
{
'id': '8b052954-c76c-4e02-8e90-be89a70183a8',
'name': 'image-5',
'os_distro': 'NixOS',
},
]},
),
},
'/v2/images?limit=%d&my_little_property=cant_be_this_cute' %
images.DEFAULT_PAGE_SIZE: {
'GET': (
{},
{'images': []},
),
},
}


Expand Down Expand Up @@ -503,6 +522,17 @@ def test_list_images_for_non_existent_tag(self):
images = list(self.controller.list(**filters))
self.assertEqual(0, len(images))

def test_list_images_for_property(self):
filters = {'filters': dict([('os_distro', 'NixOS')])}
images = list(self.controller.list(**filters))
self.assertEqual(1, len(images))

def test_list_images_for_non_existent_property(self):
filters = {'filters': dict([('my_little_property',
'cant_be_this_cute')])}
images = list(self.controller.list(**filters))
self.assertEqual(0, len(images))

def test_get_image(self):
image = self.controller.get('3a4560a1-e585-443e-9b39-553b46ec92d1')
self.assertEqual('3a4560a1-e585-443e-9b39-553b46ec92d1', image.id)
Expand Down
33 changes: 32 additions & 1 deletion tests/v2/test_shell_v2.py
Expand Up @@ -64,7 +64,8 @@ def test_do_image_list(self):
'member_status': 'Fake',
'owner': 'test',
'checksum': 'fake_checksum',
'tag': 'fake tag'
'tag': 'fake tag',
'properties': []
}
args = self._make_args(input)
with mock.patch.object(self.gc.images, 'list') as mocked_list:
Expand All @@ -83,6 +84,36 @@ def test_do_image_list(self):
filters=exp_img_filters)
utils.print_list.assert_called_once_with({}, ['ID', 'Name'])

def test_do_image_list_with_property_filter(self):
input = {
'page_size': 1,
'visibility': True,
'member_status': 'Fake',
'owner': 'test',
'checksum': 'fake_checksum',
'tag': 'fake tag',
'properties': ['os_distro=NixOS', 'architecture=x86_64']
}
args = self._make_args(input)
with mock.patch.object(self.gc.images, 'list') as mocked_list:
mocked_list.return_value = {}

test_shell.do_image_list(self.gc, args)

exp_img_filters = {
'owner': 'test',
'member_status': 'Fake',
'visibility': True,
'checksum': 'fake_checksum',
'tag': 'fake tag',
'os_distro': 'NixOS',
'architecture': 'x86_64'
}

mocked_list.assert_called_once_with(page_size=1,
filters=exp_img_filters)
utils.print_list.assert_called_once_with({}, ['ID', 'Name'])

def test_do_image_show(self):
args = self._make_args({'id': 'pass', 'page_size': 18,
'max_column_width': 120})
Expand Down

0 comments on commit 4194a55

Please sign in to comment.