diff options
author | Fei Long Wang <flwang@cn.ibm.com> | 2013-08-11 11:02:32 +0800 |
---|---|---|
committer | Fei Long Wang <flwang@cn.ibm.com> | 2013-08-28 14:13:27 +0800 |
commit | 897ae3d795423a0f1d92f0738ad4dff99c28c6de (patch) | |
tree | f10072da8d30024e3794e76b0b04a3509ef3a659 | |
parent | b6e117f151e6d3ed8dc4849c4138d7fb28652e75 (diff) | |
download | python-glanceclient-897ae3d795423a0f1d92f0738ad4dff99c28c6de.tar.gz |
Enable query image by tag
This patch will enable Glance client to query images by user
defined tags.
Implement bp image-query-by-tag
Implement bp glance-client-v2
Change-Id: I6f54630c5b7c9c567d85485ad4289284e5486814
-rw-r--r-- | glanceclient/v2/images.py | 10 | ||||
-rw-r--r-- | glanceclient/v2/shell.py | 4 | ||||
-rw-r--r-- | tests/v2/test_images.py | 77 | ||||
-rw-r--r-- | tests/v2/test_shell_v2.py | 2 |
4 files changed, 92 insertions, 1 deletions
diff --git a/glanceclient/v2/images.py b/glanceclient/v2/images.py index 2f59db9..76c185d 100644 --- a/glanceclient/v2/images.py +++ b/glanceclient/v2/images.py @@ -52,12 +52,22 @@ class Controller(object): else: filters['limit'] = kwargs['page_size'] + tags = filters.pop('tag', []) + tags_url_params = [] + + for tag in tags: + if isinstance(tag, basestring): + tags_url_params.append({'tag': strutils.safe_encode(tag)}) + for param, value in filters.iteritems(): if isinstance(value, basestring): filters[param] = strutils.safe_encode(value) url = '/v2/images?%s' % urllib.urlencode(filters) + for param in tags_url_params: + url = '%s&%s' % (url, urllib.urlencode(param)) + for image in paginate(url): #NOTE(bcwaldon): remove 'self' for now until we have an elegant # way to pass it into the model constructor without conflict diff --git a/glanceclient/v2/shell.py b/glanceclient/v2/shell.py index 87705ba..f601f38 100644 --- a/glanceclient/v2/shell.py +++ b/glanceclient/v2/shell.py @@ -28,9 +28,11 @@ from glanceclient import exc help='Display images owned by <OWNER>.') @utils.arg('--checksum', metavar='<CHECKSUM>', help='Display images matching the checksum') +@utils.arg('--tag', metavar='<TAG>', action='append', + help="Filter images by an user-defined tag.") def do_image_list(gc, args): """List images you can access.""" - filter_keys = ['visibility', 'member_status', 'owner', 'checksum'] + filter_keys = ['visibility', 'member_status', 'owner', 'checksum', 'tag'] filter_items = [(key, getattr(args, key)) for key in filter_keys] filters = dict([item for item in filter_items if item[1] is not None]) diff --git a/tests/v2/test_images.py b/tests/v2/test_images.py index cd1eb6c..c19c95f 100644 --- a/tests/v2/test_images.py +++ b/tests/v2/test_images.py @@ -24,6 +24,9 @@ from tests import utils _CHKSUM = '93264c3edf5972c9f1cb309543d38a5c' _CHKSUM1 = '54264c3edf5972c9f1cb309453d38a46' +_TAG1 = 'power' +_TAG2 = '64bit' + _BOGUS_ID = '63e7f218-29de-4477-abdc-8db7c9533188' _EVERYTHING_ID = '802cbbb7-0379-4c38-853f-37302b5e3d29' _OWNED_IMAGE_ID = 'a4963502-acc7-42ba-ad60-5aa0962b7faf' @@ -254,6 +257,51 @@ fixtures = { {'images': []}, ), }, + '/v2/images?limit=%d&tag=%s' % (images.DEFAULT_PAGE_SIZE, _TAG1): { + 'GET': ( + {}, + {'images': [ + { + 'id': '3a4560a1-e585-443e-9b39-553b46ec92d1', + 'name': 'image-1', + } + ]}, + ), + }, + '/v2/images?limit=%d&tag=%s' % (images.DEFAULT_PAGE_SIZE, _TAG2): { + 'GET': ( + {}, + {'images': [ + { + 'id': '2a4560b2-e585-443e-9b39-553b46ec92d1', + 'name': 'image-1', + }, + { + 'id': '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810', + 'name': 'image-2', + }, + ]}, + ), + }, + '/v2/images?limit=%d&tag=%s&tag=%s' % (images.DEFAULT_PAGE_SIZE, + _TAG1, _TAG2): + { + 'GET': ( + {}, + {'images': [ + { + 'id': '2a4560b2-e585-443e-9b39-553b46ec92d1', + 'name': 'image-1', + } + ]}, + ), + }, + '/v2/images?limit=%d&tag=fake' % images.DEFAULT_PAGE_SIZE: { + 'GET': ( + {}, + {'images': []}, + ), + }, } @@ -358,6 +406,35 @@ class TestController(testtools.TestCase): self.assertEqual(filters["owner"], "ni\xc3\xb1o") + def test_list_images_for_tag_single_image(self): + img_id = '3a4560a1-e585-443e-9b39-553b46ec92d1' + filters = {'filters': dict([('tag', [_TAG1])])} + images = list(self.controller.list(**filters)) + self.assertEquals(1, len(images)) + self.assertEqual(images[0].id, '%s' % img_id) + pass + + def test_list_images_for_tag_multiple_images(self): + img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1' + img_id2 = '6f99bf80-2ee6-47cf-acfe-1f1fabb7e810' + filters = {'filters': dict([('tag', [_TAG2])])} + images = list(self.controller.list(**filters)) + self.assertEquals(2, len(images)) + self.assertEqual(images[0].id, '%s' % img_id1) + self.assertEqual(images[1].id, '%s' % img_id2) + + def test_list_images_for_multi_tags(self): + img_id1 = '2a4560b2-e585-443e-9b39-553b46ec92d1' + filters = {'filters': dict([('tag', [_TAG1, _TAG2])])} + images = list(self.controller.list(**filters)) + self.assertEquals(1, len(images)) + self.assertEqual(images[0].id, '%s' % img_id1) + + def test_list_images_for_non_existent_tag(self): + filters = {'filters': dict([('tag', ['fake'])])} + images = list(self.controller.list(**filters)) + self.assertEquals(0, len(images)) + def test_get_image(self): image = self.controller.get('3a4560a1-e585-443e-9b39-553b46ec92d1') self.assertEqual(image.id, '3a4560a1-e585-443e-9b39-553b46ec92d1') diff --git a/tests/v2/test_shell_v2.py b/tests/v2/test_shell_v2.py index d4ef1a2..2f8ae91 100644 --- a/tests/v2/test_shell_v2.py +++ b/tests/v2/test_shell_v2.py @@ -70,6 +70,7 @@ class ShellV2Test(testtools.TestCase): 'member_status': 'Fake', 'owner': 'test', 'checksum': 'fake_checksum', + 'tag': 'fake tag' } args = self._make_args(input) with mock.patch.object(self.gc.images, 'list') as mocked_list: @@ -82,6 +83,7 @@ class ShellV2Test(testtools.TestCase): 'member_status': 'Fake', 'visibility': True, 'checksum': 'fake_checksum', + 'tag': 'fake tag' } mocked_list.assert_called_once_with(page_size=18, filters=exp_img_filters) |