[
https://issues.apache.org/jira/browse/LIBCLOUD-986?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16408315#comment-16408315
]
Joshua Hawkinson edited comment on LIBCLOUD-986 at 3/21/18 5:51 PM:
--------------------------------------------------------------------
Okay, done... Here are the diffs for your review:
{code:java}
diff --git a/libcloud/storage/drivers/azure_blobs.py
b/libcloud/storage/drivers/azure_blobs.py
index 82ee03a..2475793 100644
--- a/libcloud/storage/drivers/azure_blobs.py
+++ b/libcloud/storage/drivers/azure_blobs.py
@@ -381,11 +381,12 @@ class AzureBlobsStorageDriver(StorageDriver):
if not params['marker']:
break
- def iterate_container_objects(self, container):
+ def iterate_container_objects(self, container, ex_prefix=None):
"""
@inherits: :class:`StorageDriver.iterate_container_objects`
"""
- params = {'restype': 'container',
+ params = {'prefix': ex_prefix,
+ 'restype': 'container',
'comp': 'list',
'maxresults': RESPONSES_PER_REQUEST,
'include': 'metadata'}
@@ -416,6 +417,22 @@ class AzureBlobsStorageDriver(StorageDriver):
if not params['marker']:
break
+ def list_container_objects(self, container, ex_prefix=None):
+ """
+ Return a list of objects for the given container.
+
+ :param container: Container instance.
+ :type container: :class:`Container`
+
+ :param ex_prefix: Only return objects starting with ex_prefix
+ :type ex_prefix: ``str``
+
+ :return: A list of Object instances.
+ :rtype: ``list`` of :class:`Object`
+ """
+ return list(self.iterate_container_objects(container,
+ ex_prefix=ex_prefix))
+
def get_container(self, container_name):
"""
@inherits: :class:`StorageDriver.get_container`
diff --git a/libcloud/test/storage/test_azure_blobs.py
b/libcloud/test/storage/test_azure_blobs.py
index 95ab3f1..69bdebb 100644
--- a/libcloud/test/storage/test_azure_blobs.py
+++ b/libcloud/test/storage/test_azure_blobs.py
@@ -447,6 +447,28 @@ class AzureBlobsTests(unittest.TestCase):
self.assertTrue('content_encoding' in obj.extra)
self.assertTrue('content_language' in obj.extra)
+ def test_list_container_objects_with_prefix(self):
+ self.mock_response_klass.type = None
+ AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2
+
+ container = Container(name='test_container', extra={},
+ driver=self.driver)
+ objects = self.driver.list_container_objects(container=container,
+ ex_prefix='test_prefix')
+ self.assertEqual(len(objects), 4)
+
+ obj = objects[1]
+ self.assertEqual(obj.name, 'object2.txt')
+ self.assertEqual(obj.hash, '0x8CFB90F1BA8CD8F')
+ self.assertEqual(obj.size, 1048576)
+ self.assertEqual(obj.container.name, 'test_container')
+ self.assertTrue('meta1' in obj.meta_data)
+ self.assertTrue('meta2' in obj.meta_data)
+ self.assertTrue('last_modified' in obj.extra)
+ self.assertTrue('content_type' in obj.extra)
+ self.assertTrue('content_encoding' in obj.extra)
+ self.assertTrue('content_language' in obj.extra)
+
{code}
And the before and after test results:
{code:java}
[root@localhost libcloud]# python3 -m pytest -k azure_blobs
=================================================================== test
session starts
====================================================================
platform linux -- Python 3.4.3, pytest-3.4.2, py-1.5.2, pluggy-0.6.0
rootdir: /usr/libcloud, inifile: pytest.ini
collected 9116 items
libcloud/test/storage/test_azure_blobs.py ....................F................
[100%]
=========================================================================
FAILURES
=========================================================================
_________________________________________________
AzureBlobsTests.test_list_container_objects_with_prefix
__________________________________________________
self = <libcloud.test.storage.test_azure_blobs.AzureBlobsTests
testMethod=test_list_container_objects_with_prefix>
def test_list_container_objects_with_prefix(self):
self.mock_response_klass.type = None
AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2
container = Container(name='test_container', extra={},
driver=self.driver)
objects = self.driver.list_container_objects(container=container,
> ex_prefix='test_prefix')
E TypeError: list_container_objects() got an unexpected keyword argument
'ex_prefix'
libcloud/test/storage/test_azure_blobs.py:457: TypeError
================================================================== 9079 tests
deselected ===================================================================
=================================================== 1 failed, 36 passed, 9079
deselected in 3.39 seconds ===================================================
[root@localhost libcloud]# python3 -m pytest -k azure_blobs
=================================================================== test
session starts
====================================================================
platform linux -- Python 3.4.3, pytest-3.4.2, py-1.5.2, pluggy-0.6.0
rootdir: /usr/libcloud, inifile: pytest.ini
collected 9116 items
libcloud/test/storage/test_azure_blobs.py .....................................
[100%]
================================================================== 9079 tests
deselected ===================================================================
======================================================== 37 passed, 9079
deselected in 3.08 seconds
========================================================{code}
Some notes about the unit test for this feature... Ideally you'd have one
container that the Mock HTTP server would be able to return different results
for based on the prefix, I didn't see a way to simply accomplish this without
modifying some of the base mock server code. This test method was largely
pulled from the other driver's tests, but it seems to meet your base
requirements. Another note, I'm not sure why this Jira instance always strips
spaces, even in noformat, or code blocks (Sorry about the formatting).
As a bonus, Here are my personal unit test results using my Azure account
{code:java}
LOG.info("Testing basic object store operations...")
LOG.info("Creating unit test bucket %s" % UNITTEST_BUCKET)
obj_stores.create_container(UNITTEST_BUCKET)
LOG.info("Getting bucket....")
bucket = obj_stores.get_container(UNITTEST_BUCKET)
LOG.info("Creating a couple of files")
_ = obj_stores.upload_object(__file__, container=bucket,
object_name=UNITTEST_NAME1)
_ = obj_stores.upload_object(__file__, container=bucket,
object_name=UNITTEST_NAME2)
LOG.info("Validating list directory like behavior")
obj_list = list(obj_stores.iterate_container_objects(bucket,
ex_prefix=UNITTEST_DIR1))
obj_list2 = obj_stores.list_container_objects(bucket, ex_prefix=UNITTEST_DIR2)
{code}
output
{code:java}
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 Starting unit test
for object store abstraction...
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 ###### TEST VALIDATES
CONFIG FILE AND AWS CONNECTION
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 Forcing config file
read...
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 Connecting to BUILDER
AWS account
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 Testing basic object
store operations...
2018-03-15 16:42:29 CAELUM_UNIT_TEST INFO 139630231111488 Creating unit test
bucket peaxy-caelum-unit-test
2018-03-15 16:42:30 CAELUM_UNIT_TEST INFO 139630231111488 Getting bucket....
2018-03-15 16:42:30 CAELUM_UNIT_TEST INFO 139630231111488 Creating a couple of
files
2018-03-15 16:42:31 CAELUM_UNIT_TEST INFO 139630231111488 Validating list
directory like behavior
2018-03-15 18:00:31 CAELUM_UNIT_TEST INFO 139630231111488 Attempting to delete
bucket
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 ###### TEST PASSED
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 ###### TEST VALIDATES
CONFIG VARIABLES AND AZURE CONNECTION
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Instantiating object
and then manually setting the config variables
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Connecting to MSDN
Azure account
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Testing basic object
store operations...
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Creating unit test
bucket peaxy-caelum-unit-test
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Getting bucket....
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Creating a couple of
files
2018-03-15 18:00:35 CAELUM_UNIT_TEST INFO 139630231111488 Validating list
directory like behavior
>>> obj_list
[<Object: name=testing1/caelum_test1, size=5709, hash=0x8D58AD95464B16D,
provider=Microsoft Azure (blobs) ...>]
>>> obj_list2
[<Object: name=testing2/caelum_test2, size=5709, hash=0x8D58AD954709A90,
provider=Microsoft Azure (blobs) ...>]{code}
was (Author: sehafoc):
Okay, done... Here are the diffs for your review:
{code:java}
diff --git a/libcloud/storage/drivers/azure_blobs.py
b/libcloud/storage/drivers/azure_blobs.py
index 82ee03a..2475793 100644
--- a/libcloud/storage/drivers/azure_blobs.py
+++ b/libcloud/storage/drivers/azure_blobs.py
@@ -381,11 +381,12 @@ class AzureBlobsStorageDriver(StorageDriver):
if not params['marker']:
break
- def iterate_container_objects(self, container):
+ def iterate_container_objects(self, container, ex_prefix=None):
"""
@inherits: :class:`StorageDriver.iterate_container_objects`
"""
- params = {'restype': 'container',
+ params = {'prefix': ex_prefix,
+ 'restype': 'container',
'comp': 'list',
'maxresults': RESPONSES_PER_REQUEST,
'include': 'metadata'}
@@ -416,6 +417,22 @@ class AzureBlobsStorageDriver(StorageDriver):
if not params['marker']:
break
+ def list_container_objects(self, container, ex_prefix=None):
+ """
+ Return a list of objects for the given container.
+
+ :param container: Container instance.
+ :type container: :class:`Container`
+
+ :param ex_prefix: Only return objects starting with ex_prefix
+ :type ex_prefix: ``str``
+
+ :return: A list of Object instances.
+ :rtype: ``list`` of :class:`Object`
+ """
+ return list(self.iterate_container_objects(container,
+ ex_prefix=ex_prefix))
+
def get_container(self, container_name):
"""
@inherits: :class:`StorageDriver.get_container`
diff --git a/libcloud/test/storage/test_azure_blobs.py
b/libcloud/test/storage/test_azure_blobs.py
index 95ab3f1..69bdebb 100644
--- a/libcloud/test/storage/test_azure_blobs.py
+++ b/libcloud/test/storage/test_azure_blobs.py
@@ -447,6 +447,28 @@ class AzureBlobsTests(unittest.TestCase):
self.assertTrue('content_encoding' in obj.extra)
self.assertTrue('content_language' in obj.extra)
+ def test_list_container_objects_with_prefix(self):
+ self.mock_response_klass.type = None
+ AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2
+
+ container = Container(name='test_container', extra={},
+ driver=self.driver)
+ objects = self.driver.list_container_objects(container=container,
+ ex_prefix='test_prefix')
+ self.assertEqual(len(objects), 4)
+
+ obj = objects[1]
+ self.assertEqual(obj.name, 'object2.txt')
+ self.assertEqual(obj.hash, '0x8CFB90F1BA8CD8F')
+ self.assertEqual(obj.size, 1048576)
+ self.assertEqual(obj.container.name, 'test_container')
+ self.assertTrue('meta1' in obj.meta_data)
+ self.assertTrue('meta2' in obj.meta_data)
+ self.assertTrue('last_modified' in obj.extra)
+ self.assertTrue('content_type' in obj.extra)
+ self.assertTrue('content_encoding' in obj.extra)
+ self.assertTrue('content_language' in obj.extra)
+
{code}
And the before and after test results:
{code:java}
[root@localhost libcloud]# python3 -m pytest -k azure_blobs
=================================================================== test
session starts
====================================================================
platform linux -- Python 3.4.3, pytest-3.4.2, py-1.5.2, pluggy-0.6.0
rootdir: /usr/libcloud, inifile: pytest.ini
collected 9116 items
libcloud/test/storage/test_azure_blobs.py ....................F................
[100%]
=========================================================================
FAILURES
=========================================================================
_________________________________________________
AzureBlobsTests.test_list_container_objects_with_prefix
__________________________________________________
self = <libcloud.test.storage.test_azure_blobs.AzureBlobsTests
testMethod=test_list_container_objects_with_prefix>
def test_list_container_objects_with_prefix(self):
self.mock_response_klass.type = None
AzureBlobsStorageDriver.RESPONSES_PER_REQUEST = 2
container = Container(name='test_container', extra={},
driver=self.driver)
objects = self.driver.list_container_objects(container=container,
> ex_prefix='test_prefix')
E TypeError: list_container_objects() got an unexpected keyword argument
'ex_prefix'
libcloud/test/storage/test_azure_blobs.py:457: TypeError
================================================================== 9079 tests
deselected ===================================================================
=================================================== 1 failed, 36 passed, 9079
deselected in 3.39 seconds ===================================================
[root@localhost libcloud]# python3 -m pytest -k azure_blobs
=================================================================== test
session starts
====================================================================
platform linux -- Python 3.4.3, pytest-3.4.2, py-1.5.2, pluggy-0.6.0
rootdir: /usr/libcloud, inifile: pytest.ini
collected 9116 items
libcloud/test/storage/test_azure_blobs.py .....................................
[100%]
================================================================== 9079 tests
deselected ===================================================================
======================================================== 37 passed, 9079
deselected in 3.08 seconds
========================================================{code}
Some notes about the unit test for this feature... Ideally you'd have one
container that the Mock HTTP server would be able to return different results
for based on the prefix, I didn't see a way to simply accomplish this without
modifying some of the base mock server code. This test method was largely
pulled from the other driver's tests, but it seems to meet your base
requirements. Another note, I'm not sure why this Jira instance always strips
spaces, even in noformat, or code blocks (Sorry about the formatting).
> List / Iterate container with prefix for Azure Blob service (This support
> exists in the other drivers already)
> --------------------------------------------------------------------------------------------------------------
>
> Key: LIBCLOUD-986
> URL: https://issues.apache.org/jira/browse/LIBCLOUD-986
> Project: Libcloud
> Issue Type: Improvement
> Components: Storage
> Reporter: Joshua Hawkinson
> Priority: Major
>
> While testing out the libcloud storage abstraction I've come across a curious
> omission in driver support. It seems that for many drivers there is
> additional support for the {{list_container_objects()}} and
> {{iterate_container_objects()}} to support a prefix (or {{ex_prefix)}}.
> This functionality is not present in the Azure driver for some reason. I've
> gone and checked the list_blobs API and it also supports this functionality
> as seen here:
> [https://docs.microsoft.com/en-us/rest/api/storageservices/list-blobs]
>
> I've attempted a quick and dirty patch that seems to work as well.
> {code}
> azure_blobs.py Line 384
> - def iterate_container_objects(self, container):
> + def iterate_container_objects(self, container, ex_prefix=None):
> """
> @inherits: :class:`StorageDriver.iterate_container_objects`
> """
> params = {'restype': 'container',
> 'comp': 'list',
> + 'prefix': ex_prefix,
> 'maxresults': RESPONSES_PER_REQUEST,
> 'include': 'metadata'}
> Line 419 (Add new function)
> def list_container_objects(self, container, ex_prefix=None):
> """
> Return a list of objects for the given container.
>
> :param container: Container instance.
> :type container: :class:`Container`
>
> :param ex_prefix: Only return objects starting with ex_prefix
> :type ex_prefix: ``str``
>
> :return: A list of Object instances.
> :rtype: ``list`` of :class:`Object`
> """
> return list(self.iterate_container_objects(container,
> ex_prefix=ex_prefix))
>
> {code}
>
> I've just worked around this at a higher level for now. There isn't any
> urgency on my end, but it would be nice if the abstraction was more
> consistent so I could remove the workaround code.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)