Add ability to pass data to create_object
create_object currently only accepts data in files. That's not awesome for some usecases, such as creating 0-byte 'directory' nodes. Add a data parameter so that data can be passed in. Change-Id: I35e08d7b1a4fd6ded822edeba9e62a1390a6c4e8
This commit is contained in:
parent
5f46fe8842
commit
6ef2b1fffb
@ -7421,7 +7421,7 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
self, container, name, filename=None,
|
||||
md5=None, sha256=None, segment_size=None,
|
||||
use_slo=True, metadata=None,
|
||||
generate_checksums=True,
|
||||
generate_checksums=None, data=None,
|
||||
**headers):
|
||||
"""Create a file object.
|
||||
|
||||
@ -7431,7 +7431,9 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
This container will be created if it does not exist already.
|
||||
:param name: Name for the object within the container.
|
||||
:param filename: The path to the local file whose contents will be
|
||||
uploaded.
|
||||
uploaded. Mutually exclusive with data.
|
||||
:param data: The content to upload to the object. Mutually exclusive
|
||||
with filename.
|
||||
:param md5: A hexadecimal md5 of the file. (Optional), if it is known
|
||||
and can be passed here, it will save repeating the expensive md5
|
||||
process. It is assumed to be accurate.
|
||||
@ -7454,10 +7456,25 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
|
||||
:raises: ``OpenStackCloudException`` on operation error.
|
||||
"""
|
||||
if data is not None and filename:
|
||||
raise ValueError(
|
||||
"Both filename and data given. Please choose one.")
|
||||
if data is not None and not name:
|
||||
raise ValueError(
|
||||
"name is a required parameter when data is given")
|
||||
if data is not None and generate_checksums:
|
||||
raise ValueError(
|
||||
"checksums cannot be generated with data parameter")
|
||||
if generate_checksums is None:
|
||||
if data is not None:
|
||||
generate_checksums = False
|
||||
else:
|
||||
generate_checksums = True
|
||||
|
||||
if not metadata:
|
||||
metadata = {}
|
||||
|
||||
if not filename:
|
||||
if not filename and data is None:
|
||||
filename = name
|
||||
|
||||
# segment_size gets used as a step value in a range call, so needs
|
||||
@ -7465,7 +7482,10 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
if segment_size:
|
||||
segment_size = int(segment_size)
|
||||
segment_size = self.get_object_segment_size(segment_size)
|
||||
file_size = os.path.getsize(filename)
|
||||
if filename:
|
||||
file_size = os.path.getsize(filename)
|
||||
else:
|
||||
file_size = len(data)
|
||||
|
||||
if generate_checksums and (md5 is None or sha256 is None):
|
||||
(md5, sha256) = self._get_file_hashes(filename)
|
||||
@ -7479,10 +7499,17 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
# On some clouds this is not necessary. On others it is. I'm confused.
|
||||
self.create_container(container)
|
||||
|
||||
endpoint = '{container}/{name}'.format(container=container, name=name)
|
||||
|
||||
if data is not None:
|
||||
self.log.debug(
|
||||
"swift uploading data to %(endpoint)s",
|
||||
{'endpoint': endpoint})
|
||||
|
||||
return self._upload_object_data(endpoint, data, headers)
|
||||
|
||||
if self.is_object_stale(container, name, filename, md5, sha256):
|
||||
|
||||
endpoint = '{container}/{name}'.format(
|
||||
container=container, name=name)
|
||||
self.log.debug(
|
||||
"swift uploading %(filename)s to %(endpoint)s",
|
||||
{'filename': filename, 'endpoint': endpoint})
|
||||
@ -7494,6 +7521,10 @@ class OpenStackCloud(_normalize.Normalizer):
|
||||
endpoint, filename, headers,
|
||||
file_size, segment_size, use_slo)
|
||||
|
||||
def _upload_object_data(self, endpoint, data, headers):
|
||||
return self._object_store_client.put(
|
||||
endpoint, headers=headers, data=data)
|
||||
|
||||
def _upload_object(self, endpoint, filename, headers):
|
||||
return self._object_store_client.put(
|
||||
endpoint, headers=headers, data=open(filename, 'r'))
|
||||
|
@ -594,7 +594,7 @@ class TestCase(base.TestCase):
|
||||
key = '{method}|{uri}|{params}'.format(
|
||||
method=method, uri=uri, params=kw_params)
|
||||
validate = to_mock.pop('validate', {})
|
||||
valid_keys = set(['json', 'headers', 'params'])
|
||||
valid_keys = set(['json', 'headers', 'params', 'data'])
|
||||
invalid_keys = set(validate.keys()) - valid_keys
|
||||
if invalid_keys:
|
||||
raise TypeError(
|
||||
|
@ -950,3 +950,55 @@ class TestObjectUploads(BaseTestObject):
|
||||
generate_checksums=False)
|
||||
|
||||
self.assert_calls()
|
||||
|
||||
def test_create_object_data(self):
|
||||
|
||||
self.register_uris([
|
||||
dict(method='GET',
|
||||
uri='https://object-store.example.com/info',
|
||||
json=dict(
|
||||
swift={'max_file_size': 1000},
|
||||
slo={'min_segment_size': 500})),
|
||||
dict(method='HEAD',
|
||||
uri='{endpoint}/{container}'.format(
|
||||
endpoint=self.endpoint,
|
||||
container=self.container),
|
||||
status_code=404),
|
||||
dict(method='PUT',
|
||||
uri='{endpoint}/{container}'.format(
|
||||
endpoint=self.endpoint, container=self.container),
|
||||
status_code=201,
|
||||
headers={
|
||||
'Date': 'Fri, 16 Dec 2016 18:21:20 GMT',
|
||||
'Content-Length': '0',
|
||||
'Content-Type': 'text/html; charset=UTF-8',
|
||||
}),
|
||||
dict(method='HEAD',
|
||||
uri='{endpoint}/{container}'.format(
|
||||
endpoint=self.endpoint, container=self.container),
|
||||
headers={
|
||||
'Content-Length': '0',
|
||||
'X-Container-Object-Count': '0',
|
||||
'Accept-Ranges': 'bytes',
|
||||
'X-Storage-Policy': 'Policy-0',
|
||||
'Date': 'Fri, 16 Dec 2016 18:29:05 GMT',
|
||||
'X-Timestamp': '1481912480.41664',
|
||||
'X-Trans-Id': 'tx60ec128d9dbf44b9add68-0058543271dfw1',
|
||||
'X-Container-Bytes-Used': '0',
|
||||
'Content-Type': 'text/plain; charset=utf-8'}),
|
||||
dict(method='PUT',
|
||||
uri='{endpoint}/{container}/{object}'.format(
|
||||
endpoint=self.endpoint,
|
||||
container=self.container, object=self.object),
|
||||
status_code=201,
|
||||
validate=dict(
|
||||
headers={},
|
||||
data=self.content,
|
||||
)),
|
||||
])
|
||||
|
||||
self.cloud.create_object(
|
||||
container=self.container, name=self.object,
|
||||
data=self.content)
|
||||
|
||||
self.assert_calls()
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Add a data parameter to ``openstack.connection.Connection.create_object``
|
||||
so that data can be passed in directly instead of through a file.
|
Loading…
x
Reference in New Issue
Block a user