Fix setting initial object/container metadata.

As of now we can not easily set object_store resources metadata on the
creation when using proxy layer directly. While create_object claimed
that it was never really working. As a prerequisite for switching cloud
layer to rely on proxy we need to address this.

Change-Id: Icacef2044efd6e1096bb88aa830dc64cac43bde5
This commit is contained in:
Artem Goncharov 2021-09-09 15:11:39 +02:00
parent 5f9cc4fe00
commit bba9c5c508
7 changed files with 45 additions and 14 deletions

View File

@ -26,6 +26,23 @@ class BaseResource(resource.Resource):
_custom_metadata_prefix = None _custom_metadata_prefix = None
_system_metadata = dict() _system_metadata = dict()
def __init__(self, metadata=None, **attrs):
"""Process and save metadata known at creation stage
"""
super().__init__(**attrs)
if metadata is not None:
for k, v in metadata.items():
if not k.lower().startswith(
self._custom_metadata_prefix.lower()):
self.metadata[self._custom_metadata_prefix + k] = v
else:
self.metadata[k] = v
def _prepare_request(self, **kwargs):
request = super()._prepare_request(**kwargs)
request.headers.update(self._calculate_headers(self.metadata))
return request
def _calculate_headers(self, metadata): def _calculate_headers(self, metadata):
headers = {} headers = {}
for key in metadata: for key in metadata:

View File

@ -359,11 +359,6 @@ class Proxy(proxy.Proxy):
headers[self._connection._OBJECT_MD5_KEY] = md5 or '' headers[self._connection._OBJECT_MD5_KEY] = md5 or ''
if sha256: if sha256:
headers[self._connection._OBJECT_SHA256_KEY] = sha256 or '' headers[self._connection._OBJECT_SHA256_KEY] = sha256 or ''
for (k, v) in metadata.items():
if not k.lower().startswith('x-object-meta-'):
headers['x-object-meta-' + k] = v
else:
headers[k] = v
container_name = self._get_container_name(container=container) container_name = self._get_container_name(container=container)
endpoint = '{container}/{name}'.format(container=container_name, endpoint = '{container}/{name}'.format(container=container_name,
@ -376,7 +371,8 @@ class Proxy(proxy.Proxy):
# TODO(gtema): custom headers need to be somehow injected # TODO(gtema): custom headers need to be somehow injected
return self._create( return self._create(
_obj.Object, container=container_name, _obj.Object, container=container_name,
name=name, data=data, **headers) name=name, data=data, metadata=metadata,
**headers)
# segment_size gets used as a step value in a range call, so needs # segment_size gets used as a step value in a range call, so needs
# to be an int # to be an int

View File

@ -175,7 +175,7 @@ class Object(_base.BaseResource):
has_body = False has_body = False
def __init__(self, data=None, **attrs): def __init__(self, data=None, **attrs):
super(_base.BaseResource, self).__init__(**attrs) super().__init__(**attrs)
self.data = data self.data = data
# The Object Store treats the metadata for its resources inconsistently so # The Object Store treats the metadata for its resources inconsistently so
@ -290,7 +290,8 @@ class Object(_base.BaseResource):
response = session.put( response = session.put(
request.url, request.url,
data=self.data, data=self.data,
headers=request.headers) headers=request.headers
)
self._translate_response(response, has_body=False) self._translate_response(response, has_body=False)
return self return self

View File

@ -137,6 +137,7 @@ class TestContainer(base.TestCase):
"x-container-read": "some ACL", "x-container-read": "some ACL",
"x-container-write": "another ACL", "x-container-write": "another ACL",
"x-detect-content-type": 'True', "x-detect-content-type": 'True',
"X-Container-Meta-foo": "bar"
} }
self.register_uris([ self.register_uris([
dict(method=sess_method, uri=self.container_endpoint, dict(method=sess_method, uri=self.container_endpoint,
@ -148,11 +149,13 @@ class TestContainer(base.TestCase):
self.assert_calls() self.assert_calls()
def test_create(self): def test_create(self):
sot = container.Container.new(name=self.container) sot = container.Container.new(
name=self.container, metadata={'foo': 'bar'})
self._test_create_update(sot, sot.create, 'PUT') self._test_create_update(sot, sot.create, 'PUT')
def test_commit(self): def test_commit(self):
sot = container.Container.new(name=self.container) sot = container.Container.new(
name=self.container, metadata={'foo': 'bar'})
self._test_create_update(sot, sot.commit, 'POST') self._test_create_update(sot, sot.commit, 'POST')
def test_to_dict_recursion(self): def test_to_dict_recursion(self):

View File

@ -128,10 +128,14 @@ class TestObject(base_test_object.BaseTestObject):
self.assert_calls() self.assert_calls()
def _test_create(self, method, data): def _test_create(self, method, data):
sot = obj.Object.new(container=self.container, name=self.object, sot = obj.Object.new(
data=data) container=self.container, name=self.object,
data=data, metadata={'foo': 'bar'})
sot.is_newest = True sot.is_newest = True
sent_headers = {"x-newest": 'True'} sent_headers = {
"x-newest": 'True',
"X-Object-Meta-foo": "bar"
}
self.register_uris([ self.register_uris([
dict(method=method, uri=self.object_endpoint, dict(method=method, uri=self.object_endpoint,
headers=self.headers, headers=self.headers,

View File

@ -93,7 +93,12 @@ class TestObjectStoreProxy(test_proxy_base.TestProxyBase):
self._test_object_delete(True) self._test_object_delete(True)
def test_object_create_attrs(self): def test_object_create_attrs(self):
kwargs = {"name": "test", "data": "data", "container": "name"} kwargs = {
"name": "test",
"data": "data",
"container": "name",
"metadata": {}
}
self._verify( self._verify(
"openstack.proxy.Proxy._create", "openstack.proxy.Proxy._create",

View File

@ -0,0 +1,5 @@
---
fixes:
- |
It is now possible to pass `metadata` parameter directly into the create_container,
create_object object_store methods and will not be ignored.