diff --git a/surveil/api/controllers/v2/config/__init__.py b/surveil/api/controllers/v2/config/__init__.py index 5eaef58..3c415cf 100644 --- a/surveil/api/controllers/v2/config/__init__.py +++ b/surveil/api/controllers/v2/config/__init__.py @@ -17,6 +17,7 @@ from surveil.api.controllers.v2.config import contacts from surveil.api.controllers.v2.config import hosts from surveil.api.controllers.v2.config import reload_config from surveil.api.controllers.v2.config import services +from surveil.api.controllers.v2.config import timeperiods from pecan import rest @@ -28,11 +29,10 @@ class ConfigController(rest.RestController): services = services.ServicesController() reload_config = reload_config.ReloadConfigController() contacts = contacts.ContactsController() + timeperiods = timeperiods.TimePeriodsController() # hostgroups = HostGroupsController() # contactgroups = ContactGroupsController() # servicegroups = ServiceGroupsController() - # timeperiods = TimeperiodsController() # realms = RealmsController() # notificationways = NotificationWayController() # engine = EngineController() - pass diff --git a/surveil/api/controllers/v2/config/timeperiods.py b/surveil/api/controllers/v2/config/timeperiods.py new file mode 100644 index 0000000..9ff45d6 --- /dev/null +++ b/surveil/api/controllers/v2/config/timeperiods.py @@ -0,0 +1,62 @@ +# 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 pecan +from pecan import rest +import wsmeext.pecan as wsme_pecan + +from surveil.api.datamodel.config import timeperiod +from surveil.api.handlers.config import timeperiod_handler + + +class TimePeriodsController(rest.RestController): + + @wsme_pecan.wsexpose([timeperiod.TimePeriod]) + def get_all(self): + """Returns all time periods.""" + handler = timeperiod_handler.TimePeriodHandler(pecan.request) + time_periods = handler.get_all() + return time_periods + + @wsme_pecan.wsexpose(timeperiod.TimePeriod, unicode) + def get_one(self, timeperiod_name): + """Returns a specific time period.""" + handler = timeperiod_handler.TimePeriodHandler(pecan.request) + timeperiod = handler.get(timeperiod_name) + return timeperiod + + @wsme_pecan.wsexpose(body=timeperiod.TimePeriod, status_code=201) + def post(self, data): + """Create a new time period. + + :param data: a time period within the request body. + """ + handler = timeperiod_handler.TimePeriodHandler(pecan.request) + handler.create(data) + + @wsme_pecan.wsexpose(timeperiod.TimePeriod, unicode, status_code=204) + def delete(self, timeperiod_name): + """Returns a specific time period.""" + handler = timeperiod_handler.TimePeriodHandler(pecan.request) + handler.delete(timeperiod_name) + + @wsme_pecan.wsexpose(timeperiod.TimePeriod, + unicode, + body=timeperiod.TimePeriod, + status_code=204) + def put(self, timeperiod_name, timeperiod): + """Update a specific time period.""" + handler = timeperiod_handler.TimePeriodHandler(pecan.request) + handler.update(timeperiod_name, timeperiod) diff --git a/surveil/api/datamodel/checkresult.py b/surveil/api/datamodel/checkresult.py index 4e27761..5f5d654 100644 --- a/surveil/api/datamodel/checkresult.py +++ b/surveil/api/datamodel/checkresult.py @@ -17,7 +17,7 @@ import time import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class CheckResult(types.Base): diff --git a/surveil/api/datamodel/config/command.py b/surveil/api/datamodel/config/command.py index d48f36f..20a4811 100644 --- a/surveil/api/datamodel/config/command.py +++ b/surveil/api/datamodel/config/command.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types # import shinken.objects diff --git a/surveil/api/datamodel/config/contact.py b/surveil/api/datamodel/config/contact.py index 0f5f26a..a53c441 100644 --- a/surveil/api/datamodel/config/contact.py +++ b/surveil/api/datamodel/config/contact.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class Contact(types.Base): diff --git a/surveil/api/datamodel/config/host.py b/surveil/api/datamodel/config/host.py index 404db65..bf79555 100644 --- a/surveil/api/datamodel/config/host.py +++ b/surveil/api/datamodel/config/host.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class Host(types.Base): diff --git a/surveil/api/datamodel/config/service.py b/surveil/api/datamodel/config/service.py index 4e678ba..bbaa37b 100644 --- a/surveil/api/datamodel/config/service.py +++ b/surveil/api/datamodel/config/service.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class Service(types.Base): diff --git a/surveil/api/datamodel/config/timeperiod.py b/surveil/api/datamodel/config/timeperiod.py new file mode 100644 index 0000000..e266dfd --- /dev/null +++ b/surveil/api/datamodel/config/timeperiod.py @@ -0,0 +1,56 @@ +# 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 wsme +import wsme.types as wtypes + +from surveil.api.datamodel import types + + +class TimePeriod(types.Base): + timeperiod_name = wsme.wsattr(wtypes.text, mandatory=True) + exclude = wsme.wsattr(wtypes.text, mandatory=False) + + periods = wsme.wsattr( + wtypes.DictType(wtypes.text, wtypes.text), + mandatory=False + ) + + def __init__(self, **kwargs): + super(TimePeriod, self).__init__(**kwargs) + + periods = [i for i in kwargs.items() if isinstance(i[0], str) + and i[0] not in ['timeperiod_name', 'exclude', 'periods']] + if len(periods) > 0: + self.periods = {} + for item in periods: + self.periods[item[0]] = item[1] + + def as_dict(self): + timeperiod_dict = super(TimePeriod, self).as_dict() + periods = timeperiod_dict.pop("periods", None) + if periods: + for item in periods.items(): + timeperiod_dict[item[0]] = item[1] + return timeperiod_dict + + @classmethod + def sample(cls): + return cls( + timeperiod_name='nonworkhours', + periods={ + "sunday": "0:00-24:00", + "february 10": "00:00-24:00" + } + ) diff --git a/surveil/api/datamodel/status/live_host.py b/surveil/api/datamodel/status/live_host.py index b2f19ee..5464979 100644 --- a/surveil/api/datamodel/status/live_host.py +++ b/surveil/api/datamodel/status/live_host.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class LiveHost(types.Base): diff --git a/surveil/api/datamodel/status/live_query.py b/surveil/api/datamodel/status/live_query.py index befdc8d..2f342fe 100644 --- a/surveil/api/datamodel/status/live_query.py +++ b/surveil/api/datamodel/status/live_query.py @@ -17,7 +17,7 @@ import json import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class LiveQuery(types.Base): diff --git a/surveil/api/datamodel/status/live_service.py b/surveil/api/datamodel/status/live_service.py index 7d9c0fc..4a6487e 100644 --- a/surveil/api/datamodel/status/live_service.py +++ b/surveil/api/datamodel/status/live_service.py @@ -15,7 +15,7 @@ import wsme import wsme.types as wtypes -from surveil.api.controllers.v1.datamodel import types +from surveil.api.datamodel import types class LiveService(types.Base): diff --git a/surveil/api/handlers/config/timeperiod_handler.py b/surveil/api/handlers/config/timeperiod_handler.py new file mode 100644 index 0000000..c8bfbdf --- /dev/null +++ b/surveil/api/handlers/config/timeperiod_handler.py @@ -0,0 +1,62 @@ +# Copyright 2014 - 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. + +from surveil.api.datamodel.config import timeperiod +from surveil.api.handlers import handler + + +class TimePeriodHandler(handler.Handler): + """Fulfills a request on the contact resource.""" + + def get(self, timeperiod_name): + """Return a time period.""" + + t = self.request.mongo_connection.shinken.timeperiods.find_one( + {"timeperiod_name": timeperiod_name}, {'_id': 0} + ) + return timeperiod.TimePeriod(**t) + + def update(self, timeperiod_name, timeperiod): + """Modify an existing time period.""" + timeperiod_dict = timeperiod.as_dict() + if "timeperiod_name" not in timeperiod_dict.keys(): + timeperiod_dict['timeperiod_name'] = timeperiod_name + + self.request.mongo_connection.shinken.timeperiods.update( + {"timeperiod_name": timeperiod_name}, + timeperiod_dict + ) + + def delete(self, timeperiod_name): + """Delete existing time period.""" + self.request.mongo_connection.shinken.timeperiods.remove( + {"timeperiod_name": timeperiod_name} + ) + + def create(self, timeperiod): + """Create a new time period.""" + self.request.mongo_connection.shinken.timeperiods.insert( + timeperiod.as_dict() + ) + + def get_all(self): + """Return all time periods.""" + timeperiods = [t for t + in self.request.mongo_connection. + shinken.timeperiods.find( + {"register": {"$ne": "0"}}, + {'_id': 0} + )] + timeperiods = [timeperiod.TimePeriod(**t) for t in timeperiods] + return timeperiods diff --git a/surveil/tests/api/controllers/v2/config/test_timeperiods.py b/surveil/tests/api/controllers/v2/config/test_timeperiods.py new file mode 100644 index 0000000..8b953f7 --- /dev/null +++ b/surveil/tests/api/controllers/v2/config/test_timeperiods.py @@ -0,0 +1,118 @@ +# Copyright 2014 - 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 copy +import json + + +from surveil.tests.api import functionalTest + + +class TestTimePeriodsController(functionalTest.FunctionalTest): + + def setUp(self): + super(TestTimePeriodsController, self).setUp() + self.timeperiods = [ + { + 'timeperiod_name': 'nonworkhours', + 'sunday': '00:00-24:00', + 'monday': '00:00-09:00,17:00-24:00' + }, + { + 'timeperiod_name': 'misc-single-days', + '1999-01-28': '00:00-24:00', + 'day 2': '00:00-24:00', + }, + ] + self.mongoconnection.shinken.timeperiods.insert( + copy.deepcopy(self.timeperiods) + ) + + def test_get_all_timeperiods(self): + response = self.app.get('/v2/config/timeperiods') + + self.assertItemsEqual( + json.loads(response.body.decode()), + [ + {'timeperiod_name': 'misc-single-days', + 'periods': {'day 2': '00:00-24:00', + '1999-01-28': '00:00-24:00'}}, + {'timeperiod_name': 'nonworkhours', + 'periods': {'sunday': '00:00-24:00', + 'monday': '00:00-09:00,17:00-24:00'}} + ] + ) + self.assertEqual(response.status_int, 200) + + def test_get_one_timeperiod(self): + response = self.app.get('/v2/config/timeperiods/nonworkhours') + + self.assertEqual( + json.loads(response.body.decode()), + {'timeperiod_name': 'nonworkhours', + 'periods': {'sunday': '00:00-24:00', + 'monday': '00:00-09:00,17:00-24:00'}} + ) + + def test_create_timeperiod(self): + t = {"timeperiod_name": 'someperiod', + "periods": { + "monday": "fun day", + "tuesday": "pizza day" + }} + + self.app.post_json('/v2/config/timeperiods', t) + + self.assertIsNotNone( + self.mongoconnection.shinken.timeperiods.find_one( + {"timeperiod_name": 'someperiod', + "monday": "fun day", + "tuesday": "pizza day"}) + ) + + def test_delete_timeperiod(self): + self.assertIsNotNone( + self.mongoconnection.shinken.timeperiods.find_one( + {"timeperiod_name": 'nonworkhours'} + ) + ) + + self.app.delete('/v2/config/timeperiods/nonworkhours') + + self.assertIsNone( + self.mongoconnection.shinken.timeperiods.find_one( + {"timeperiod_name": 'nonworkhours'} + ) + ) + + def test_put_timeperiod(self): + self.assertEqual( + self.mongoconnection.shinken.timeperiods.find_one( + {'timeperiod_name': 'nonworkhours'} + )['sunday'], + '00:00-24:00' + ) + + self.app.put_json( + '/v2/config/timeperiods/nonworkhours', + {"timeperiod_name": "nonworkhours", + "periods": {"sunday": "updated"}} + ) + + self.assertEqual( + self.mongoconnection.shinken.timeperiods.find_one( + {'timeperiod_name': 'nonworkhours'} + )['sunday'], + 'updated' + )