diff --git a/openstack/object_store/v1/_base.py b/openstack/object_store/v1/_base.py index 779f1e92d..cb8bbb464 100644 --- a/openstack/object_store/v1/_base.py +++ b/openstack/object_store/v1/_base.py @@ -26,6 +26,23 @@ class BaseResource(resource.Resource): _custom_metadata_prefix = None _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): headers = {} for key in metadata: diff --git a/openstack/object_store/v1/_proxy.py b/openstack/object_store/v1/_proxy.py index 6722440ff..9e9130330 100644 --- a/openstack/object_store/v1/_proxy.py +++ b/openstack/object_store/v1/_proxy.py @@ -359,11 +359,6 @@ class Proxy(proxy.Proxy): headers[self._connection._OBJECT_MD5_KEY] = md5 or '' if sha256: 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) endpoint = '{container}/{name}'.format(container=container_name, @@ -376,7 +371,8 @@ class Proxy(proxy.Proxy): # TODO(gtema): custom headers need to be somehow injected return self._create( _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 # to be an int diff --git a/openstack/object_store/v1/obj.py b/openstack/object_store/v1/obj.py index 116b8ccaf..8c7a11aa7 100644 --- a/openstack/object_store/v1/obj.py +++ b/openstack/object_store/v1/obj.py @@ -175,7 +175,7 @@ class Object(_base.BaseResource): has_body = False def __init__(self, data=None, **attrs): - super(_base.BaseResource, self).__init__(**attrs) + super().__init__(**attrs) self.data = data # The Object Store treats the metadata for its resources inconsistently so @@ -290,7 +290,8 @@ class Object(_base.BaseResource): response = session.put( request.url, data=self.data, - headers=request.headers) + headers=request.headers + ) self._translate_response(response, has_body=False) return self diff --git a/openstack/tests/unit/object_store/v1/test_container.py b/openstack/tests/unit/object_store/v1/test_container.py index 7f522aa65..36698e752 100644 --- a/openstack/tests/unit/object_store/v1/test_container.py +++ b/openstack/tests/unit/object_store/v1/test_container.py @@ -137,6 +137,7 @@ class TestContainer(base.TestCase): "x-container-read": "some ACL", "x-container-write": "another ACL", "x-detect-content-type": 'True', + "X-Container-Meta-foo": "bar" } self.register_uris([ dict(method=sess_method, uri=self.container_endpoint, @@ -148,11 +149,13 @@ class TestContainer(base.TestCase): self.assert_calls() 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') 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') def test_to_dict_recursion(self): diff --git a/openstack/tests/unit/object_store/v1/test_obj.py b/openstack/tests/unit/object_store/v1/test_obj.py index 85642251e..448652796 100644 --- a/openstack/tests/unit/object_store/v1/test_obj.py +++ b/openstack/tests/unit/object_store/v1/test_obj.py @@ -128,10 +128,14 @@ class TestObject(base_test_object.BaseTestObject): self.assert_calls() def _test_create(self, method, data): - sot = obj.Object.new(container=self.container, name=self.object, - data=data) + sot = obj.Object.new( + container=self.container, name=self.object, + data=data, metadata={'foo': 'bar'}) sot.is_newest = True - sent_headers = {"x-newest": 'True'} + sent_headers = { + "x-newest": 'True', + "X-Object-Meta-foo": "bar" + } self.register_uris([ dict(method=method, uri=self.object_endpoint, headers=self.headers, diff --git a/openstack/tests/unit/object_store/v1/test_proxy.py b/openstack/tests/unit/object_store/v1/test_proxy.py index 81cf1f19c..a88bb5838 100644 --- a/openstack/tests/unit/object_store/v1/test_proxy.py +++ b/openstack/tests/unit/object_store/v1/test_proxy.py @@ -93,7 +93,12 @@ class TestObjectStoreProxy(test_proxy_base.TestProxyBase): self._test_object_delete(True) def test_object_create_attrs(self): - kwargs = {"name": "test", "data": "data", "container": "name"} + kwargs = { + "name": "test", + "data": "data", + "container": "name", + "metadata": {} + } self._verify( "openstack.proxy.Proxy._create", diff --git a/releasenotes/notes/swift-set-metadata-c18c60e440f9e4a7.yaml b/releasenotes/notes/swift-set-metadata-c18c60e440f9e4a7.yaml new file mode 100644 index 000000000..6fe599ef4 --- /dev/null +++ b/releasenotes/notes/swift-set-metadata-c18c60e440f9e4a7.yaml @@ -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.