Add --query to alarm list

As discussed in the MailList and aggred, we should now
add --query to alarm list" to perform the functionality
what "alarm search" does.

Change-Id: Icf8888b91f7040d6158919cb667e8fa7d46a54ee
Closes-Bug: #1555910
This commit is contained in:
Kevin_Zheng 2016-03-11 11:42:56 +08:00
parent e7df19eb61
commit 9feb0e0d50
6 changed files with 86 additions and 32 deletions

View File

@ -84,6 +84,13 @@ class AodhClientTest(base.ClientTestBase):
if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('ev_alarm1', alarm_list['name'])
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
self.assertEqual('ev_alarm1', alarm_list['name'])
# DELETE
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
self.assertEqual("", result)
@ -180,6 +187,13 @@ class AodhClientTest(base.ClientTestBase):
if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('alarm1', alarm_list['name'])
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
self.assertEqual('alarm1', alarm_list['name'])
# DELETE
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
self.assertEqual("", result)
@ -269,6 +283,13 @@ class AodhClientTest(base.ClientTestBase):
if alarm_list["alarm_id"] == alarm_id:
self.assertEqual('calarm1', alarm_list['name'])
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % project_id))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(alarm_id, alarm_list["alarm_id"])
self.assertEqual('calarm1', alarm_list['name'])
# DELETE
result = self.aodh('alarm', params="delete %s" % alarm_id)
self.assertEqual("", result)
@ -376,6 +397,13 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('alarm1', alarm_list['name'])
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
self.assertEqual('alarm1', alarm_list['name'])
# DELETE
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
self.assertEqual("", result)
@ -589,6 +617,13 @@ class AodhClientGnocchiRulesTest(base.ClientTestBase):
if alarm_list["alarm_id"] == ALARM_ID:
self.assertEqual('alarm1', alarm_list['name'])
# LIST WITH QUERY
result = self.aodh('alarm',
params=("list --query project_id=%s" % PROJECT_ID))
alarm_list = self.parser.listing(result)[0]
self.assertEqual(ALARM_ID, alarm_list["alarm_id"])
self.assertEqual('alarm1', alarm_list['name'])
# DELETE
result = self.aodh('alarm', params="delete %s" % ALARM_ID)
self.assertEqual("", result)

View File

@ -46,6 +46,20 @@ class AlarmManagerTest(testtools.TestCase):
am.list()
mock_am.assert_called_with('v2/alarms')
@mock.patch.object(alarm.AlarmManager, '_post')
def test_list_with_query(self, mock_am):
am = alarm.AlarmManager(self.client)
query = '{"=": {"type": "event"}}'
am.list(query)
url = 'v2/query/alarms'
expected_value = ('{"filter": "{\\"=\\": {\\"type\\":'
' \\"event\\"}}"}')
headers_value = {'Content-Type': "application/json"}
mock_am.assert_called_with(
url,
data=expected_value,
headers=headers_value)
@mock.patch.object(alarm.AlarmManager, '_get')
def test_get(self, mock_am):
am = alarm.AlarmManager(self.client)

View File

@ -28,37 +28,27 @@ class SearchQueryBuilderTest(base.BaseTestCase):
self._do_test('foo=True', {"=": {"foo": True}})
self._do_test('foo=null', {"=": {"foo": None}})
self._do_test('foo="null"', {"=": {"foo": "null"}})
self._do_test('foo in ["null", "foo"]',
{"in": {"foo": ["null", "foo"]}})
self._do_test(u'foo="quote" and bar≠1',
{"and": [{u"": {"bar": 1}},
{"=": {"foo": "quote"}}]})
self._do_test('foo="quote" or bar like "%%foo"',
{"or": [{"like": {"bar": "%%foo"}},
{"=": {"foo": "quote"}}]})
self._do_test('not (foo="quote" or bar like "%%foo" or foo="what!" '
self._do_test('not (foo="quote" or foo="what!" '
'or bar="who?")',
{"not": {"or": [
{"=": {"bar": "who?"}},
{"=": {"foo": "what!"}},
{"like": {"bar": "%%foo"}},
{"=": {"foo": "quote"}},
]}})
self._do_test('(foo="quote" or bar like "%%foo" or not foo="what!" '
self._do_test('(foo="quote" or not foo="what!" '
'or bar="who?") and cat="meme"',
{"and": [
{"=": {"cat": "meme"}},
{"or": [
{"=": {"bar": "who?"}},
{"not": {"=": {"foo": "what!"}}},
{"like": {"bar": "%%foo"}},
{"=": {"foo": "quote"}},
]}
]})
self._do_test('foo="quote" or bar like "%%foo" or foo="what!" '
self._do_test('foo="quote" or foo="what!" '
'or bar="who?" and cat="meme"',
{"or": [
{"and": [
@ -66,20 +56,18 @@ class SearchQueryBuilderTest(base.BaseTestCase):
{"=": {"bar": "who?"}},
]},
{"=": {"foo": "what!"}},
{"like": {"bar": "%%foo"}},
{"=": {"foo": "quote"}},
]})
self._do_test('foo="quote" or bar like "%%foo" and foo="what!" '
self._do_test('foo="quote" and foo="what!" '
'or bar="who?" or cat="meme"',
{"or": [
{"=": {"cat": "meme"}},
{"=": {"bar": "who?"}},
{"and": [
{"=": {"foo": "what!"}},
{"like": {"bar": "%%foo"}},
]},
{"=": {"foo": "quote"}},
{'or': [
{'=': {'cat': 'meme'}},
{'=': {'bar': 'who?'}},
{'and': [
{'=': {'foo': 'what!'}},
{'=': {'foo': 'quote'}}
]}
]})

View File

@ -17,9 +17,8 @@ import pyparsing as pp
uninary_operators = ("not", )
binary_operator = (u">=", u"<=", u"!=", u">", u"<", u"=", u"==", u"eq", u"ne",
u"lt", u"gt", u"ge", u"le", u"in", u"like", u"", u"",
u"", u"like" "in")
multiple_operators = (u"and", u"or", u"", u"")
u"lt", u"gt", u"ge", u"le")
multiple_operators = (u"and", u"or")
operator = pp.Regex(u"|".join(binary_operator))
null = pp.Regex("None|none|null").setParseAction(pp.replaceWith(None))
@ -37,15 +36,13 @@ in_list = pp.Group(pp.Suppress('[') +
pp.Optional(pp.delimitedList(comparison_term)) +
pp.Suppress(']'))("list")
comparison_term << (null | boolean | uuid | identifier | number |
quoted_string | in_list)
quoted_string)
condition = pp.Group(comparison_term + operator + comparison_term)
expr = pp.operatorPrecedence(condition, [
("not", 1, pp.opAssoc.RIGHT, ),
("and", 2, pp.opAssoc.LEFT, ),
("", 2, pp.opAssoc.LEFT, ),
("or", 2, pp.opAssoc.LEFT, ),
("", 2, pp.opAssoc.LEFT, ),
])
OP_LOOKUP = {'!=': 'ne',

View File

@ -21,9 +21,16 @@ class AlarmManager(base.Manager):
url = "v2/alarms"
def list(self):
def list(self, query=None):
"""List alarms"""
return self._get(self.url).json()
if query:
query = {'filter': query}
url = "v2/query/alarms"
return self._post(url,
headers={'Content-Type': "application/json"},
data=jsonutils.dumps(query)).json()
else:
return self._get(self.url).json()
def get(self, alarm_id):
"""Get an alarm

View File

@ -36,8 +36,21 @@ ALARM_LIST_COLS = ['alarm_id', 'type', 'name', 'state', 'severity', 'enabled']
class CliAlarmList(lister.Lister):
"""List alarms"""
def get_parser(self, prog_name):
parser = super(CliAlarmList, self).get_parser(prog_name)
parser.add_argument("--query",
help="Rich query supported by aodh, "
"e.g. project_id!=my-id "
"user_id=foo or user_id=bar"),
return parser
def take_action(self, parsed_args):
alarms = self.app.client.alarm.list()
if parsed_args.query:
query = jsonutils.dumps(
utils.search_query_builder(parsed_args.query))
else:
query = None
alarms = self.app.client.alarm.list(query)
return utils.list2cols(ALARM_LIST_COLS, alarms)