From 91167d8520b8659d722c580df142cb061c45495f Mon Sep 17 00:00:00 2001 From: zhuxiaolong37 <85101990+zhuxiaolong37@users.noreply.github.com> Date: Thu, 11 May 2023 11:17:07 +0800 Subject: [PATCH] Add headers parameters to the list bucket interface (#341) --- oss2/api.py | 12 +-- oss2/models.py | 18 +++- oss2/xml_utils.py | 10 +- tests/test_bucket.py | 13 +++ unittests/test_bucket.py | 195 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 236 insertions(+), 12 deletions(-) diff --git a/oss2/api.py b/oss2/api.py index baf090ce..096d1884 100644 --- a/oss2/api.py +++ b/oss2/api.py @@ -311,13 +311,14 @@ def __init__(self, auth, endpoint, app_name=app_name, proxies=proxies, region=region, cloudbox_id=cloudbox_id) - def list_buckets(self, prefix='', marker='', max_keys=100, params=None): + def list_buckets(self, prefix='', marker='', max_keys=100, params=None, headers=None): """根据前缀罗列用户的Bucket。 :param str prefix: 只罗列Bucket名为该前缀的Bucket,空串表示罗列所有的Bucket :param str marker: 分页标志。首次调用传空串,后续使用返回值中的next_marker :param int max_keys: 每次调用最多返回的Bucket数目 :param dict params: list操作参数,传入'tag-key','tag-value'对结果进行过滤 + :param headers: 用户指定的HTTP头部。可以指定Content-Type、Content-MD5、x-oss-meta-开头的头部等。可以是dict,建议是oss2.CaseInsensitiveDict :return: 罗列的结果 :rtype: oss2.models.ListBucketsResult @@ -329,13 +330,12 @@ def list_buckets(self, prefix='', marker='', max_keys=100, params=None): listParam['marker'] = marker listParam['max-keys'] = str(max_keys) + headers = http.CaseInsensitiveDict(headers) + if params is not None: - if 'tag-key' in params: - listParam['tag-key'] = params['tag-key'] - if 'tag-value' in params: - listParam['tag-value'] = params['tag-value'] + listParam.update(params) - resp = self._do('GET', '', '', params=listParam) + resp = self._do('GET', '', '', params=listParam, headers=headers) logger.debug("List buckets done, req_id: {0}, status_code: {1}".format(resp.request_id, resp.status)) return self._parse_result(resp, xml_utils.parse_list_buckets, ListBucketsResult) diff --git a/oss2/models.py b/oss2/models.py index 9a8bd681..2d9a1cbc 100644 --- a/oss2/models.py +++ b/oss2/models.py @@ -505,7 +505,7 @@ def __init__(self, resp): class SimplifiedBucketInfo(object): """:func:`list_buckets ` 结果中的单个元素类型。""" - def __init__(self, name, location, creation_date, extranet_endpoint, intranet_endpoint, storage_class): + def __init__(self, name, location, creation_date, extranet_endpoint, intranet_endpoint, storage_class, region=None, resource_group_id=None): #: Bucket名 self.name = name @@ -524,6 +524,12 @@ def __init__(self, name, location, creation_date, extranet_endpoint, intranet_en #: Bucket存储类型,支持“Standard”、“IA”、“Archive”、“ColdArchive” self.storage_class = storage_class + #: Bucket所在地域 + self.region = region + + #: Bucket所属资源组ID + self.resource_group_id = resource_group_id + class ListBucketsResult(RequestResult): def __init__(self, resp): @@ -538,6 +544,9 @@ def __init__(self, resp): #: 得到的Bucket列表,类型为 :class:`SimplifiedBucketInfo` 。 self.buckets = [] + #: owner信息, 类型为: class:`Owner ` + self.owner = Owner('', '') + class MultipartUploadInfo(object): def __init__(self, key, upload_id, initiation_date): @@ -698,7 +707,8 @@ def __init__(self, display_name, owner_id): class BucketInfo(object): def __init__(self, name=None, owner=None, location=None, storage_class=None, intranet_endpoint=None, extranet_endpoint=None, creation_date=None, acl=None, data_redundancy_type=None, comment=None, - bucket_encryption_rule=None, versioning_status=None, access_monitor=None): + bucket_encryption_rule=None, versioning_status=None, access_monitor=None, + transfer_acceleration=None, cross_region_replication=None, resource_group_id=None): self.name = name self.owner = owner self.location = location @@ -713,6 +723,9 @@ def __init__(self, name=None, owner=None, location=None, storage_class=None, int self.bucket_encryption_rule = bucket_encryption_rule self.versioning_status = versioning_status self.access_monitor = access_monitor + self.transfer_acceleration = transfer_acceleration + self.cross_region_replication = cross_region_replication + self.resource_group_id = resource_group_id class GetBucketStatResult(RequestResult, BucketStat): @@ -2732,3 +2745,4 @@ class CallbackPolicyResult(RequestResult): def __init__(self, resp): super(CallbackPolicyResult, self).__init__(resp) self.callback_policies = [] + diff --git a/oss2/xml_utils.py b/oss2/xml_utils.py index 4d6ff487..1cc7b9f3 100644 --- a/oss2/xml_utils.py +++ b/oss2/xml_utils.py @@ -223,6 +223,9 @@ def parse_list_buckets(result, body): if result.is_truncated: result.next_marker = _find_tag(root, 'NextMarker') + if root.find('Owner'): + result.owner = Owner(_find_tag_with_default(root, 'Owner/DisplayName', None), _find_tag_with_default(root, 'Owner/ID', None)) + for bucket_node in root.findall('Buckets/Bucket'): result.buckets.append(SimplifiedBucketInfo( _find_tag(bucket_node, 'Name'), @@ -230,7 +233,9 @@ def parse_list_buckets(result, body): iso8601_to_unixtime(_find_tag(bucket_node, 'CreationDate')), _find_tag(bucket_node, 'ExtranetEndpoint'), _find_tag(bucket_node, 'IntranetEndpoint'), - _find_tag(bucket_node, 'StorageClass') + _find_tag(bucket_node, 'StorageClass'), + _find_tag_with_default(bucket_node, 'Region', None), + _find_tag_with_default(bucket_node, 'ResourceGroupId', None), )) return result @@ -380,6 +385,9 @@ def parse_get_bucket_info(result, body): result.versioning_status = _find_tag_with_default(root, 'Bucket/Versioning', None) result.data_redundancy_type = _find_tag_with_default(root, 'Bucket/DataRedundancyType', None) result.access_monitor = _find_tag_with_default(root, 'Bucket/AccessMonitor', None) + result.transfer_acceleration = _find_tag_with_default(root, 'Bucket/TransferAcceleration', None) + result.cross_region_replication = _find_tag_with_default(root, 'Bucket/CrossRegionReplication', None) + result.resource_group_id = _find_tag_with_default(root, 'Bucket/ResourceGroupId', None) server_side_encryption = root.find("Bucket/ServerSideEncryptionRule") if server_side_encryption is None: diff --git a/tests/test_bucket.py b/tests/test_bucket.py index 46f7beb2..99be0253 100644 --- a/tests/test_bucket.py +++ b/tests/test_bucket.py @@ -1201,5 +1201,18 @@ def test_bucket_header_SM4(self): self.assertEqual(oss2.BUCKET_STORAGE_CLASS_IA, bucket_info3.storage_class) self.assertEqual("SM4", bucket_info3.bucket_encryption_rule.sse_algorithm) + + def test_bucket_with_group_id(self): + auth = oss2.Auth(OSS_ID, OSS_SECRET) + service = oss2.Service(auth, OSS_ENDPOINT) + + # By getting_ bucket_ Information to obtain resource_ group_ id + bucket_info = self.bucket.get_bucket_info() + + headers = dict() + headers['x-oss-resource-group-id'] = bucket_info.resource_group_id + result = service.list_buckets(prefix='oss-python-sdk-', max_keys=10, headers=headers) + self.assertEqual(bucket_info.resource_group_id, result.buckets[0].resource_group_id) + if __name__ == '__main__': unittest.main() diff --git a/unittests/test_bucket.py b/unittests/test_bucket.py index 480d9c8e..a2fdb8a5 100644 --- a/unittests/test_bucket.py +++ b/unittests/test_bucket.py @@ -5,7 +5,7 @@ from mock import patch from functools import partial -from oss2 import to_string +from oss2 import to_string, iso8601_to_unixtime from oss2.models import AggregationsRequest, MetaQuery, CallbackPolicyInfo from unittests.common import * @@ -2443,7 +2443,7 @@ def test_describe_regions(self, do_request): self.assertEqual(result.regions[1].internet_endpoint, 'oss-cn-shanghai.aliyuncs.com') self.assertEqual(result.regions[1].internal_endpoint, 'oss-cn-shanghai-internal.aliyuncs.com') self.assertEqual(result.regions[1].accelerate_endpoint, 'oss-accelerate.aliyuncs.com') - + @patch('oss2.Session.do_request') def test_async_process_object(self, do_request): request_text = '''POST /test-video.mp4?x-oss-async-process HTTP/1.1 @@ -2474,7 +2474,7 @@ def test_async_process_object(self, do_request): self.assertEqual(result.event_id, '3D7-1XxFtV2t3VtcOn2CXqI2ldsMN3i') self.assertEqual(result.task_id, 'MediaConvert-d2280366-cd33-48f7-90c6-a0dab65bed63') - + @patch('oss2.Session.do_request') def test_put_bucket_callback_policy(self, do_request): request_text = '''PUT /?policy&comp=callback HTTP/1.1 @@ -2582,5 +2582,194 @@ def test_delete_callback_policy(self, do_request): self.assertRequest(req_info, request_text) + + @patch('oss2.Session.do_request') + def test_list_buckets(self, do_request): + request_text = '''GET /?prefix=my&max-keys=10 HTTP/1.1 +Host: oss-cn-hangzhou.aliyuncs.com +Accept-Encoding: identity +Connection: keep-alive +date: Sat, 12 Dec 2015 00:35:38 GMT +User-Agent: aliyun-sdk-python/2.0.2(Windows/7/;3.3.3) +Accept: */* +x-oss-resource-group-id: rg-acfmxmt3*** +authorization: OSS ZCDmm7TPZKHtx77j:Pt0DtPQ/FODOGs5y0yTIVctRcok=''' + + response_text = '''HTTP/1.1 200 OK +Server: AliyunOSS +Date: Sat, 12 Dec 2015 00:35:38 GMT +Content-Type: application/xml +Content-Length: 277 +Connection: keep-alive +x-oss-resource-group-id: rg-acfmxmt3*** +x-oss-request-id: 566B6BDA010B7A4314D1614A + + + + + 512** + 51264 + + + + 2014-02-07T18:12:43.000Z + oss-cn-shanghai.aliyuncs.com + oss-cn-shanghai-internal.aliyuncs.com + oss-cn-shanghai + test-bucket-1 + cn-shanghai + IA + rg-acfmxmt3*** + + + 2014-02-05T11:21:04.000Z + oss-cn-hangzhou.aliyuncs.com + oss-cn-hangzhou-internal.aliyuncs.com + oss-cn-hangzhou + test-bucket-2 + cn-hangzhou + Standard + rg-*** + + +''' + + req_info = mock_response(do_request, response_text) + + headers = dict() + headers['x-oss-resource-group-id'] = 'rg-acfmxmt3***' + result = service().list_buckets(prefix='my', max_keys=10, headers=headers) + + self.assertRequest(req_info, request_text) + self.assertEqual("512**", result.owner.id) + self.assertEqual("51264", result.owner.display_name) + self.assertEqual("test-bucket-1", result.buckets[0].name) + self.assertEqual("cn-shanghai", result.buckets[0].region) + self.assertEqual("IA", result.buckets[0].storage_class) + self.assertEqual("rg-acfmxmt3***", result.buckets[0].resource_group_id) + self.assertEqual("oss-cn-shanghai", result.buckets[0].location) + self.assertEqual(iso8601_to_unixtime("2014-02-07T18:12:43.000Z"), result.buckets[0].creation_date) + self.assertEqual("oss-cn-shanghai.aliyuncs.com", result.buckets[0].extranet_endpoint) + self.assertEqual("oss-cn-shanghai-internal.aliyuncs.com", result.buckets[0].intranet_endpoint) + self.assertEqual("test-bucket-2", result.buckets[1].name) + self.assertEqual("cn-hangzhou", result.buckets[1].region) + self.assertEqual("Standard", result.buckets[1].storage_class) + self.assertEqual("rg-***", result.buckets[1].resource_group_id) + self.assertEqual("oss-cn-hangzhou", result.buckets[1].location) + self.assertEqual(iso8601_to_unixtime("2014-02-05T11:21:04.000Z"), result.buckets[1].creation_date) + self.assertEqual("oss-cn-hangzhou.aliyuncs.com", result.buckets[1].extranet_endpoint) + self.assertEqual("oss-cn-hangzhou-internal.aliyuncs.com", result.buckets[1].intranet_endpoint) + + + @patch('oss2.Session.do_request') + def test_list_buckets_2(self, do_request): + request_text = '''GET /?prefix=my&max-keys=10 HTTP/1.1 +Host: oss-cn-hangzhou.aliyuncs.com +Accept-Encoding: identity +Connection: keep-alive +date: Sat, 12 Dec 2015 00:35:38 GMT +User-Agent: aliyun-sdk-python/2.0.2(Windows/7/;3.3.3) +Accept: */* +x-oss-resource-group-id: rg-acfmxmt3*** +authorization: OSS ZCDmm7TPZKHtx77j:Pt0DtPQ/FODOGs5y0yTIVctRcok=''' + + response_text = '''HTTP/1.1 200 OK +Server: AliyunOSS +Date: Sat, 12 Dec 2015 00:35:38 GMT +Content-Type: application/xml +Content-Length: 277 +Connection: keep-alive +x-oss-resource-group-id: rg-acfmxmt3*** +x-oss-request-id: 566B6BDA010B7A4314D1614A + + + + + + 2014-02-07T18:12:43.000Z + oss-cn-shanghai.aliyuncs.com + oss-cn-shanghai-internal.aliyuncs.com + oss-cn-shanghai + test-bucket-1 + Standard + + +''' + + req_info = mock_response(do_request, response_text) + + headers = dict() + headers['x-oss-resource-group-id'] = 'rg-acfmxmt3***' + result = service().list_buckets(prefix='my', max_keys=10, headers=headers) + + self.assertRequest(req_info, request_text) + + self.assertEqual("test-bucket-1", result.buckets[0].name) + self.assertEqual("Standard", result.buckets[0].storage_class) + self.assertEqual("oss-cn-shanghai", result.buckets[0].location) + self.assertEqual(iso8601_to_unixtime("2014-02-07T18:12:43.000Z"), result.buckets[0].creation_date) + self.assertEqual("oss-cn-shanghai.aliyuncs.com", result.buckets[0].extranet_endpoint) + self.assertEqual("oss-cn-shanghai-internal.aliyuncs.com", result.buckets[0].intranet_endpoint) + + + @patch('oss2.Session.do_request') + def test_get_bucket_info(self, do_request): + request_text = '''GET /?bucketInfo HTTP/1.1 +Date: Fri , 30 Apr 2021 13:08:38 GMT +Content-Length:443 +Host: ming-oss-share.oss-cn-hangzhou.aliyuncs.com +Authorization: OSS qn6qrrqxo2oawuk53otf****:PYbzsdWAIWAlMW8luk****''' + + response_text = '''HTTP/1.1 200 OK +x-oss-request-id: 566B6BD927A4046E9C725578 +Date: Fri , 30 Apr 2021 13:08:38 GMT + + + + + Enabled + 2013-07-31T10:56:21.000Z + oss-cn-hangzhou.aliyuncs.com + oss-cn-hangzhou-internal.aliyuncs.com + oss-cn-hangzhou + IA + Disabled + Disabled + oss-example + rg-aek27tc******** + + username + 27183473914**** + + + private + + test + +''' + + req_info = mock_response(do_request, response_text) + + result = bucket().get_bucket_info() + + self.assertRequest(req_info, request_text) + self.assertEqual(result.request_id, '566B6BD927A4046E9C725578') + self.assertEqual(result.status, 200) + self.assertEqual(result.name, 'oss-example') + self.assertEqual(result.owner.display_name, 'username') + self.assertEqual(result.owner.id, '27183473914****') + self.assertEqual(result.location, 'oss-cn-hangzhou') + self.assertEqual(result.storage_class, 'IA') + self.assertEqual(result.access_monitor, 'Enabled') + self.assertEqual(result.creation_date, '2013-07-31T10:56:21.000Z') + self.assertEqual(result.intranet_endpoint, 'oss-cn-hangzhou-internal.aliyuncs.com') + self.assertEqual(result.extranet_endpoint, 'oss-cn-hangzhou.aliyuncs.com') + self.assertEqual(result.transfer_acceleration, 'Disabled') + self.assertEqual(result.cross_region_replication, 'Disabled') + self.assertEqual(result.resource_group_id, 'rg-aek27tc********') + self.assertEqual(result.acl.grant, 'private') + self.assertEqual(result.comment, 'test') + + if __name__ == '__main__': unittest.main()