Merge "Fix case-sensitivity for metadata keys" into stable/2025.1

This commit is contained in:
Zuul
2025-08-27 05:27:06 +00:00
committed by Gerrit Code Review
5 changed files with 54 additions and 3 deletions

View File

@@ -258,7 +258,8 @@ class AggregateController(wsgi.Controller):
id, metadata)
except exception.AggregateNotFound as e:
raise exc.HTTPNotFound(explanation=e.format_message())
except exception.InvalidAggregateAction as e:
except (exception.InvalidAggregateAction,
exception.AggregateMetadataKeyExists) as e:
raise exc.HTTPBadRequest(explanation=e.format_message())
return self._marshall_aggregate(req, aggregate)

View File

@@ -482,6 +482,12 @@ class InvalidAggregateActionUpdateMeta(InvalidAggregateAction):
"%(aggregate_id)s. Reason: %(reason)s.")
class AggregateMetadataKeyExists(NovaException):
msg_fmt = _("Aggregate %(aggregate_id)s already contain metadata "
"key %(key)s.")
code = 400
class InvalidSortKey(Invalid):
msg_fmt = _("Sort key supplied was not valid.")

View File

@@ -113,8 +113,15 @@ def _metadata_add_to_db(context, aggregate_id, metadata, max_retries=10,
api_models.AggregateMetadata.key.in_(all_keys))
for meta_ref in query.all():
key = meta_ref.key
meta_ref.update({"value": metadata[key]})
already_existing_keys.add(key)
try:
meta_ref.update({"value": metadata[key]})
already_existing_keys.add(key)
except KeyError:
# NOTE(ratailor): When user tries updating
# metadata using case-sensitive key, we get
# KeyError.
raise exception.AggregateMetadataKeyExists(
aggregate_id=aggregate_id, key=key)
new_entries = []
for key, value in metadata.items():

View File

@@ -675,6 +675,19 @@ class AggregateTestCaseV21(test.NoDBTestCase):
self.assertRaises(self.bad_request, eval(self.set_metadata),
self.req, "1", body=body)
def test_set_metadata_case_sensitive(self):
body = {"set_metadata": {"metadata": {"foo": "bar"}}}
side_effect = exception.AggregateMetadataKeyExists(
aggregate_id="2", key="foo")
with mock.patch.object(self.controller.api,
'update_aggregate_metadata',
side_effect=side_effect) as mock_update:
self.assertRaises(exc.HTTPBadRequest, eval(self.set_metadata),
self.req, "2", body=body)
mock_update.assert_called_once_with(
self.context, "2", body["set_metadata"]["metadata"])
def test_delete_aggregate(self):
with mock.patch.object(self.controller.api,
'delete_aggregate') as mock_del:

View File

@@ -175,6 +175,30 @@ class _TestAggregateObject(object):
123,
{'toadd': 'myval'})
@mock.patch('nova.compute.utils.notify_about_aggregate_action')
def test_update_metadata_api_case_sensitive(self, mock_notify):
# Mock context.session.query().filter_by().filter().all()
fake_context = mock.Mock()
mock_query = mock.Mock()
fake_context.session.query.return_value = mock_query
mock_query = mock_query.filter_by.return_value.filter.return_value
# Return a fake meta_ref that raises a KeyError
fake_meta_ref = mock.Mock()
fake_meta_ref.update.side_effect = KeyError
mock_query.all.return_value = [fake_meta_ref]
# Create an aggregate in the database
agg = aggregate.Aggregate(
context=self.context, name='agg', metadata={'Abc': 'bar'})
agg.create()
# Then replace its context with mock context
agg._context = fake_context
self.assertRaises(exception.AggregateMetadataKeyExists,
agg.update_metadata,
{'abC': 'barbar'})
@mock.patch('nova.objects.aggregate._host_add_to_db')
def test_add_host_api(self, mock_host_add_api):
mock_host_add_api.return_value = {'host': 'bar'}