diff --git a/surveilclient/common/utils.py b/surveilclient/common/utils.py index 66752a3..fb39f81 100644 --- a/surveilclient/common/utils.py +++ b/surveilclient/common/utils.py @@ -110,3 +110,20 @@ def print_list(objs, fields, field_labels=None, formatters={}, sortby=None): print(pt.get_string()) else: print(pt.get_string(sortby=field_labels[sortby])) + + +def get_columns(lines, ordered_columns): + columns_dict = {} + + for line in lines: + for key, value in line.iteritems(): + if value is not None: + columns_dict[key] = True + + valid_columns = [] + for col in ordered_columns: + if col in columns_dict: + valid_columns.append(col) + del columns_dict[col] + + return valid_columns + sorted(columns_dict.keys()) diff --git a/surveilclient/tests/v2_0/status/test_events.py b/surveilclient/tests/v2_0/status/test_events.py new file mode 100644 index 0000000..6b42621 --- /dev/null +++ b/surveilclient/tests/v2_0/status/test_events.py @@ -0,0 +1,94 @@ +# Copyright 2015 - Savoir-Faire Linux inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +import json + +import httpretty + +from surveilclient.tests.v2_0 import clienttest + + +class TestEvents(clienttest.ClientTest): + + @httpretty.activate + def test_list(self): + httpretty.register_uri( + httpretty.POST, "http://localhost:8080/v2/status/events", + body='[{"host_name": "sfl.com", "service_description": "cpu", ' + '"event_type": "ALERT", "output": "Ok"},' + '{"host_name": "sfl.com", "service_description": "cpu", ' + '"event_type": "ALERT", "output": "Not Ok"}]' + ) + + events = self.client.status.events.list(host_name='sfl.com', + service_description='cpu', + event_type='ALERT') + + filters = json.loads( + httpretty.last_request().body.decode())['filters'] + self.assertEqual( + json.loads(filters)['is'], + {"service_description": ["cpu"], + "host_name": ["sfl.com"], "event_type": ["ALERT"]} + ) + + self.assertEqual( + events, + [{"host_name": "sfl.com", "service_description": "cpu", + "event_type": "ALERT", "output": "Ok"}, + {"host_name": "sfl.com", "service_description": "cpu", + "event_type": "ALERT", "output": "Not Ok"}] + ) + + @httpretty.activate + def test_list_with_live_query(self): + httpretty.register_uri( + httpretty.POST, "http://localhost:8080/v2/status/events", + body='[{"host_name": "sfl.com", "service_description": "cpu", ' + '"event_type": "ALERT", "output": "Ok"},' + '{"host_name": "sfl.com", "service_description": "cpu", ' + '"event_type": "ALERT", "output": "Not Ok"}]' + ) + + events = self.client.status.events.list( + live_query='{"filters": {"is": {"host_name": ["sfl.com"], ' + '"event_type": ["ALERT"]},' + '"isnot": {"service_description": ["load"]}}}', + start_time='2015-05-22T13:38:08Z', + end_time='2015-05-22T13:42:08Z' + ) + + filters = json.loads(httpretty.last_request().body.decode())['filters'] + self.assertEqual( + json.loads(filters)['is'], + {"host_name": ["sfl.com"], "event_type": ["ALERT"]} + ) + self.assertEqual( + json.loads(filters)['isnot'], + {"service_description": ["load"]} + ) + + self.assertEqual( + json.loads( + httpretty.last_request().body.decode())['time_interval'], + {u"start_time": u"2015-05-22T13:38:08Z", + u"end_time": u"2015-05-22T13:42:08Z"} + ) + + self.assertEqual( + events, + [{"host_name": u"sfl.com", "service_description": u"cpu", + "event_type": u"ALERT", "output": u"Ok"}, + {"host_name": u"sfl.com", "service_description": u"cpu", + "event_type": u"ALERT", "output": u"Not Ok"}] + ) diff --git a/surveilclient/v2_0/shell.py b/surveilclient/v2_0/shell.py index f9bc472..7521d77 100644 --- a/surveilclient/v2_0/shell.py +++ b/surveilclient/v2_0/shell.py @@ -11,7 +11,6 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. - import json from surveilclient.common import utils @@ -462,3 +461,37 @@ def do_action_recheck(sc, args): recheck = _dict_from_args(args, arg_names) sc.actions.recheck.create(**recheck) + + +@cliutils.arg("--host_name", help="Name of the host") +@cliutils.arg("--service_description", help="Service description") +@cliutils.arg("--event_type", help="Event type") +@cliutils.arg("--start_time", help="Start of the event to query") +@cliutils.arg("--end_time", help="End of the event to query") +@cliutils.arg("--live_query", help="A live query") +def do_status_events_list(sc, args): + """List all events.""" + + arg_names = ['host_name', + 'service_description', + 'event_type', + 'start_time', + 'end_time', + 'live_query'] + arg = _dict_from_args(args, arg_names) + events = sc.status.events.list(**arg) + + if args.json: + print(utils.json_formatter(events)) + else: + cols = utils.get_columns(events, + ['host_name', + 'service_description', + 'event_type']) + + def create_format(init, col): + init[col] = lambda x: x.get(col, '') + return init + formatters = reduce(create_format, cols, {}) + + utils.print_list(events, cols, formatters=formatters) diff --git a/surveilclient/v2_0/status/__init__.py b/surveilclient/v2_0/status/__init__.py index b9c28df..c4975c2 100644 --- a/surveilclient/v2_0/status/__init__.py +++ b/surveilclient/v2_0/status/__init__.py @@ -13,6 +13,7 @@ # under the License. from surveilclient.common import surveil_manager +from surveilclient.v2_0.status import events from surveilclient.v2_0.status import hosts from surveilclient.v2_0.status import services @@ -22,5 +23,6 @@ class StatusManager(surveil_manager.SurveilManager): def __init__(self, http_client): super(StatusManager, self).__init__(http_client) + self.events = events.EventsManager(self.http_client) self.hosts = hosts.HostsManager(self.http_client) - self.services = services.ServicesManager(self.http_client) \ No newline at end of file + self.services = services.ServicesManager(self.http_client) diff --git a/surveilclient/v2_0/status/events.py b/surveilclient/v2_0/status/events.py new file mode 100644 index 0000000..23d1fd1 --- /dev/null +++ b/surveilclient/v2_0/status/events.py @@ -0,0 +1,59 @@ +# Copyright 2014-2015 - Savoir-Faire Linux inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json + +from surveilclient.common import surveil_manager + + +class EventsManager(surveil_manager.SurveilManager): + base_url = '/status/events' + + def list(self, host_name=None, service_description=None, event_type=None, + start_time=None, end_time=None, live_query=None): + """List events.""" + + if live_query is None: + live_query = {} + else: + live_query = json.loads(live_query) + + if start_time and end_time: + live_query['time_interval'] = { + "start_time": start_time, + "end_time": end_time + } + + if 'filters' not in live_query: + live_query['filters'] = {} + + if 'is' not in live_query['filters']: + live_query['filters']['is'] = {} + + if host_name: + live_query['filters']['is']['host_name'] = [host_name] + + if service_description: + (live_query['filters']['is'] + ['service_description']) = [service_description] + + if event_type: + live_query['filters']['is']['event_type'] = [event_type] + + live_query['filters'] = json.dumps(live_query['filters']) + + resp, body = self.http_client.json_request( + EventsManager.base_url, 'POST', body=live_query + ) + return body