Skip to content

Commit

Permalink
Add field translation to complex query from OldSample to Sample
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Ildiko Vancsa committed Mar 12, 2014
1 parent a4f693b commit edd2013
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 21 deletions.
24 changes: 14 additions & 10 deletions ceilometer/api/controllers/v2.py
Expand Up @@ -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:
Expand Down Expand Up @@ -2300,9 +2300,15 @@ def post(self, body):
: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
Expand All @@ -2322,8 +2328,7 @@ def post(self, body):
: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)
Expand All @@ -2344,8 +2349,7 @@ def post(self, body):
: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)
Expand Down
23 changes: 14 additions & 9 deletions ceilometer/tests/api/v2/test_complex_query.py
Expand Up @@ -29,27 +29,32 @@


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"}}
Expand Down Expand Up @@ -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):
Expand Down
21 changes: 19 additions & 2 deletions ceilometer/tests/api/v2/test_complex_query_scenarios.py
Expand Up @@ -67,7 +67,7 @@ def setUp(self):
sample.Sample('meter.test',
'cumulative',
'',
1,
2,
'user-id2',
'project-id2',
'resource-id2',
Expand All @@ -81,7 +81,7 @@ def setUp(self):
sample.Sample('meter.test',
'cumulative',
'',
1,
3,
'user-id3',
'project-id3',
'resource-id3',
Expand Down Expand Up @@ -224,6 +224,15 @@ def test_query_with_field_name_user(self):
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"}]'})
Expand All @@ -240,6 +249,14 @@ def test_query_with_user_field_name_orderby(self):
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": ""}]'},
Expand Down

0 comments on commit edd2013

Please sign in to comment.