Add --property-filter option to v2 image-list

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
This commit is contained in:
Louis Taylor
2014-10-20 14:26:14 +00:00
parent 711f28a5a8
commit 4194a55a09
3 changed files with 71 additions and 1 deletions

View File

@@ -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',
@@ -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}

View File

@@ -346,6 +346,25 @@ data_fixtures = {
'',
)
},
'/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': []},
),
},
}
@@ -503,6 +522,17 @@ class TestController(testtools.TestCase):
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)

View File

@@ -64,7 +64,8 @@ class ShellV2Test(testtools.TestCase):
'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:
@@ -83,6 +84,36 @@ class ShellV2Test(testtools.TestCase):
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})