From 95f569fc701c0891e981754b3ec1bfef7a4343bc Mon Sep 17 00:00:00 2001 From: Idan Narotzki Date: Wed, 2 Aug 2017 09:21:40 +0000 Subject: [PATCH] Add content_length to header in upload_blob Complementary update to glare server commit: "Allocate blob size before starting the upload" Co-Authored-By: Mike Fedosin Change-Id: If3ad1bc69fd0a68b5c03abe163b76ba166245b81 --- glareclient/tests/unit/v1/test_artifacts.py | 33 +++++++++++++++++++-- glareclient/v1/artifacts.py | 18 ++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/glareclient/tests/unit/v1/test_artifacts.py b/glareclient/tests/unit/v1/test_artifacts.py index ef235c7..cf488d4 100644 --- a/glareclient/tests/unit/v1/test_artifacts.py +++ b/glareclient/tests/unit/v1/test_artifacts.py @@ -13,6 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +import io +import os +import tempfile + import mock from oslo_serialization import jsonutils import testtools @@ -110,13 +114,38 @@ class TestController(testtools.TestCase): self.mock_http_client.delete.assert_called_once_with( '/artifacts/checked_name/test-id') - def test_upload_blob(self): + def test_upload_blob_str(self): self.c.upload_blob('test-id', 'blob-prop', 'data', type_name='test-type', content_type='application/test') self.mock_http_client.put.assert_called_once_with( '/artifacts/checked_name/test-id/blob-prop', - data='data', headers={'Content-Type': 'application/test'}) + data='data', headers={'Content-Length': '4', + 'Content-Type': 'application/test'}) + + def test_upload_blob_file(self): + tfd, path = tempfile.mkstemp() + try: + os.write(tfd, b'data') + tfile = open(path, "rb") + self.c.upload_blob('test-id', 'blob-prop', tfile, + type_name='test-type', + content_type='application/test') + self.mock_http_client.put.assert_called_once_with( + '/artifacts/checked_name/test-id/blob-prop', + data=tfile, headers={'Content-Length': '4', + 'Content-Type': 'application/test'}) + finally: + os.remove(path) + + def test_upload_blob_stream(self): + data = io.BytesIO(b'data') + self.c.upload_blob('test-id', 'blob-prop', data, + type_name='test-type', + content_type='application/test') + self.mock_http_client.put.assert_called_once_with( + '/artifacts/checked_name/test-id/blob-prop', + data=data, headers={'Content-Type': 'application/test'}) def test_get_type_list(self): schemas = {'schemas': {'a': {'version': 1}, 'b': {'version': 2}}} diff --git a/glareclient/v1/artifacts.py b/glareclient/v1/artifacts.py index 55d7776..e2f010c 100644 --- a/glareclient/v1/artifacts.py +++ b/glareclient/v1/artifacts.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import os + from oslo_serialization import jsonutils from oslo_utils import encodeutils import six @@ -244,8 +246,22 @@ class Controller(object): :param blob_property: blob property name """ content_type = content_type or 'application/octet-stream' - type_name = self._check_type_name(type_name) hdrs = {'Content-Type': content_type} + type_name = self._check_type_name(type_name) + + content_length = None + if isinstance(data, six.string_types): + content_length = len(data) + else: + try: + content_length = os.path.getsize(data.name) + except Exception: + # if for some reason we can't get the file size, then we just + # ignore it. + pass + if content_length is not None: + hdrs['Content-Length'] = str(content_length) + url = '/artifacts/%s/%s/%s' % (type_name, artifact_id, blob_property) self.http_client.put(url, headers=hdrs, data=data)