diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py index 7b22d59aa9..e9306c1856 100644 --- a/ceilometer/api/controllers/v2.py +++ b/ceilometer/api/controllers/v2.py @@ -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 @@ 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 @@ -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) @@ -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) diff --git a/ceilometer/tests/api/v2/test_complex_query.py b/ceilometer/tests/api/v2/test_complex_query.py index 19f4232f13..e1fe4d9693 100644 --- a/ceilometer/tests/api/v2/test_complex_query.py +++ b/ceilometer/tests/api/v2/test_complex_query.py @@ -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"}} @@ -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): diff --git a/ceilometer/tests/api/v2/test_complex_query_scenarios.py b/ceilometer/tests/api/v2/test_complex_query_scenarios.py index e38364b49e..a7c250e881 100644 --- a/ceilometer/tests/api/v2/test_complex_query_scenarios.py +++ b/ceilometer/tests/api/v2/test_complex_query_scenarios.py @@ -67,7 +67,7 @@ def setUp(self): sample.Sample('meter.test', 'cumulative', '', - 1, + 2, 'user-id2', 'project-id2', 'resource-id2', @@ -81,7 +81,7 @@ def setUp(self): sample.Sample('meter.test', 'cumulative', '', - 1, + 3, 'user-id3', 'project-id3', 'resource-id3', @@ -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"}]'}) @@ -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": ""}]'},