Add field translation to complex query from OldSample to Sample
Complex query returns the samples according to the new Sample model, but it accepts the field names in the query expression only from the OldSample model during the validation. This patch adds translation between the old and new field names and translates the field names to the format of the DB model. Closes-bug: #1291415 Change-Id: I8ef71b6d43b82cd75f0d7a6ea08cdc8881ca62d3
This commit is contained in:
@@ -1134,14 +1134,14 @@ class ValidatedComplexQuery(object):
|
||||
order_directions = _list_to_regexp(order_directions, regexp_prefix)
|
||||
|
||||
timestamp_fields = ["timestamp", "state_timestamp"]
|
||||
name_mapping = {"user": "user_id",
|
||||
"project": "project_id",
|
||||
"resource": "resource_id"}
|
||||
|
||||
def __init__(self, query, db_model, additional_valid_keys,
|
||||
def __init__(self, query, db_model, additional_name_mapping={},
|
||||
metadata_allowed=False):
|
||||
self.name_mapping = {"user": "user_id",
|
||||
"project": "project_id"}
|
||||
self.name_mapping.update(additional_name_mapping)
|
||||
valid_keys = db_model.get_field_names()
|
||||
valid_keys = list(valid_keys) + additional_valid_keys
|
||||
valid_keys = list(valid_keys) + self.name_mapping.keys()
|
||||
valid_fields = _list_to_regexp(valid_keys)
|
||||
|
||||
if metadata_allowed:
|
||||
@@ -2300,9 +2300,15 @@ class QuerySamplesController(rest.RestController):
|
||||
|
||||
:param body: Query rules for the samples to be returned.
|
||||
"""
|
||||
sample_name_mapping = {"resource": "resource_id",
|
||||
"meter": "counter_name",
|
||||
"type": "counter_type",
|
||||
"unit": "counter_unit",
|
||||
"volume": "counter_volume"}
|
||||
|
||||
query = ValidatedComplexQuery(body,
|
||||
storage.models.Sample,
|
||||
["user", "project", "resource"],
|
||||
sample_name_mapping,
|
||||
metadata_allowed=True)
|
||||
query.validate(visibility_field="project_id")
|
||||
conn = pecan.request.storage_conn
|
||||
@@ -2322,8 +2328,7 @@ class QueryAlarmHistoryController(rest.RestController):
|
||||
:param body: Query rules for the alarm history to be returned.
|
||||
"""
|
||||
query = ValidatedComplexQuery(body,
|
||||
storage.models.AlarmChange,
|
||||
["user", "project"])
|
||||
storage.models.AlarmChange)
|
||||
query.validate(visibility_field="on_behalf_of")
|
||||
conn = pecan.request.storage_conn
|
||||
return [AlarmChange.from_db_model(s)
|
||||
@@ -2344,8 +2349,7 @@ class QueryAlarmsController(rest.RestController):
|
||||
:param body: Query rules for the alarms to be returned.
|
||||
"""
|
||||
query = ValidatedComplexQuery(body,
|
||||
storage.models.Alarm,
|
||||
["user", "project"])
|
||||
storage.models.Alarm)
|
||||
query.validate(visibility_field="project_id")
|
||||
conn = pecan.request.storage_conn
|
||||
return [Alarm.from_db_model(s)
|
||||
|
||||
@@ -29,27 +29,32 @@ from ceilometer import storage as storage
|
||||
|
||||
|
||||
class FakeComplexQuery(api.ValidatedComplexQuery):
|
||||
def __init__(self, db_model, additional_valid_keys, metadata=False):
|
||||
def __init__(self, db_model, additional_name_mapping={}, metadata=False):
|
||||
super(FakeComplexQuery, self).__init__(query=None,
|
||||
db_model=db_model,
|
||||
additional_valid_keys=
|
||||
additional_valid_keys,
|
||||
additional_name_mapping=
|
||||
additional_name_mapping,
|
||||
metadata_allowed=metadata)
|
||||
|
||||
|
||||
sample_name_mapping = {"resource": "resource_id",
|
||||
"meter": "counter_name",
|
||||
"type": "counter_type",
|
||||
"unit": "counter_unit",
|
||||
"volume": "counter_volume"}
|
||||
|
||||
|
||||
class TestComplexQuery(test.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestComplexQuery, self).setUp()
|
||||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'pecan.response', mock.MagicMock()))
|
||||
self.query = FakeComplexQuery(storage.models.Sample,
|
||||
["user", "project", "resource"],
|
||||
sample_name_mapping,
|
||||
True)
|
||||
self.query_alarm = FakeComplexQuery(storage.models.Alarm,
|
||||
["user", "project"])
|
||||
self.query_alarm = FakeComplexQuery(storage.models.Alarm)
|
||||
self.query_alarmchange = FakeComplexQuery(
|
||||
storage.models.AlarmChange,
|
||||
["user", "project"])
|
||||
storage.models.AlarmChange)
|
||||
|
||||
def test_replace_isotime_utc(self):
|
||||
filter_expr = {"=": {"timestamp": "2013-12-05T19:38:29Z"}}
|
||||
@@ -231,7 +236,7 @@ class TestFilterSyntaxValidation(test.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(TestFilterSyntaxValidation, self).setUp()
|
||||
self.query = FakeComplexQuery(storage.models.Sample,
|
||||
["user", "project", "resource"],
|
||||
sample_name_mapping,
|
||||
True)
|
||||
|
||||
def test_simple_operator(self):
|
||||
|
||||
@@ -67,7 +67,7 @@ class TestQueryMetersController(tests_api.FunctionalTest,
|
||||
sample.Sample('meter.test',
|
||||
'cumulative',
|
||||
'',
|
||||
1,
|
||||
2,
|
||||
'user-id2',
|
||||
'project-id2',
|
||||
'resource-id2',
|
||||
@@ -81,7 +81,7 @@ class TestQueryMetersController(tests_api.FunctionalTest,
|
||||
sample.Sample('meter.test',
|
||||
'cumulative',
|
||||
'',
|
||||
1,
|
||||
3,
|
||||
'user-id3',
|
||||
'project-id3',
|
||||
'resource-id3',
|
||||
@@ -224,6 +224,15 @@ class TestQueryMetersController(tests_api.FunctionalTest,
|
||||
for sample in data.json:
|
||||
self.assertIn(sample['user_id'], set(["user-id2"]))
|
||||
|
||||
def test_query_with_field_name_meter(self):
|
||||
data = self.post_json(self.url,
|
||||
params={"filter":
|
||||
'{"=": {"meter": "meter.test"}}'})
|
||||
|
||||
self.assertEqual(3, len(data.json))
|
||||
for sample in data.json:
|
||||
self.assertIn(sample['meter'], set(["meter.test"]))
|
||||
|
||||
def test_query_with_lower_and_upper_case_orderby(self):
|
||||
data = self.post_json(self.url,
|
||||
params={"orderby": '[{"project_id": "DeSc"}]'})
|
||||
@@ -240,6 +249,14 @@ class TestQueryMetersController(tests_api.FunctionalTest,
|
||||
self.assertEqual(["user-id1", "user-id2", "user-id3"],
|
||||
[s["user_id"] for s in data.json])
|
||||
|
||||
def test_query_with_volume_field_name_orderby(self):
|
||||
data = self.post_json(self.url,
|
||||
params={"orderby": '[{"volume": "deSc"}]'})
|
||||
|
||||
self.assertEqual(3, len(data.json))
|
||||
self.assertEqual([3, 2, 1],
|
||||
[s["volume"] for s in data.json])
|
||||
|
||||
def test_query_with_missing_order_in_orderby(self):
|
||||
data = self.post_json(self.url,
|
||||
params={"orderby": '[{"project_id": ""}]'},
|
||||
|
||||
Reference in New Issue
Block a user