Added Commands controller

Change-Id: I29fa3f74503f3d6be566e6de3cd8082e28848012
This commit is contained in:
aviau 2014-08-20 15:37:57 -04:00
parent 6b263f9cad
commit 87cf98e0e1
8 changed files with 251 additions and 2 deletions

View File

@ -12,7 +12,7 @@ run: kill build
run-interactive: kill build
sudo docker run -i -t --name surveil surveil_image bash
test:
test: clean
tox
clean:

View File

@ -17,4 +17,16 @@ Hosts
:webprefix: /v1/hosts
.. rest-controller:: surveil.api.controllers.v1.hosts:HostController
:webprefix: /v1/hosts
:webprefix: /v1/hosts
Commands
========
.. rest-controller:: surveil.api.controllers.v1.commands:CommandsController
:webprefix: /v1/hosts
.. rest-controller:: surveil.api.controllers.v1.commands:CommandController
:webprefix: /v1/hosts
.. autotype:: surveil.api.controllers.v1.commands.Command
:members:

View File

@ -0,0 +1,72 @@
# 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 pecan
from pecan import rest
import wsmeext.pecan as wsme_pecan
from surveil.api.controllers.v1.datamodel import command
class CommandController(rest.RestController):
def __init__(self, host_id):
pecan.request.context['host_id'] = host_id
self._id = host_id
@wsme_pecan.wsexpose(command.Command)
def get(self):
"""Returns a specific command."""
c = pecan.request.mongo_connection.shinken.commands.find_one(
{"command_name": self._id}
)
return command.Command(**c)
@wsme_pecan.wsexpose(None, body=command.Command, status_code=204)
def put(self, data):
"""Modify this command.
:param data: a command within the request body.
"""
command_dict = data.as_dict()
if "command_name" not in command_dict.keys():
command_dict['command_name'] = self._id
pecan.request.mongo_connection.shinken.commands.update(
{"command_name": self._id},
command_dict
)
@wsme_pecan.wsexpose(None, status_code=204)
def delete(self):
"""Delete this command."""
pecan.request.mongo_connection.shinken.commands.remove(
{"command_name": self._id}
)
class CommandsController(rest.RestController):
@pecan.expose()
def _lookup(self, host_id, *remainder):
return CommandController(host_id), remainder
@wsme_pecan.wsexpose([command.Command])
def get_all(self):
"""Returns all commands."""
commands = [host for host
in pecan.request.mongo_connection.shinken.commands.find()]
return [command.Command(**c) for c in commands]

View File

@ -0,0 +1,41 @@
# 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 wsme
import wsme.types as wtypes
from surveil.api.controllers.v1.datamodel import types
# import shinken.objects
# Command = type(
# 'Command',
# (wtypes.Base,),
# {key: wtypes.text for key in shinken.objects.Command.properties.keys()}
# )
class Command(types.Base):
command_name = wsme.wsattr(wtypes.text, mandatory=True)
"""The name of the command"""
command_line = wsme.wsattr(wtypes.text, mandatory=True)
"""This directive is used to define what is actually executed by Shinken"""
@classmethod
def sample(cls):
return cls(
command_name="check_http",
command_line="/bin/check_http"
)

View File

@ -0,0 +1,36 @@
# 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 inspect
import wsme
from wsme import types as wtypes
class Base(wtypes.Base):
"""Base class for all API types."""
def as_dict(self):
keys = [
member[0] for member
in inspect.getmembers(self.__class__)
if member[0][0] is not '_' and type(member[1]) is wtypes.wsattr
]
return self.as_dict_from_keys(keys)
def as_dict_from_keys(self, keys):
return dict((k, getattr(self, k))
for k in keys
if hasattr(self, k) and
getattr(self, k) != wsme.Unset)

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from surveil.api.controllers.v1 import commands
from surveil.api.controllers.v1 import hello
from surveil.api.controllers.v1 import hosts
@ -20,3 +21,4 @@ class V1Controller(object):
"""Version 1 API controller root."""
hello = hello.HelloController()
hosts = hosts.HostsController()
commands = commands.CommandsController()

View File

@ -0,0 +1,86 @@
# 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 TestRootController(functionalTest.FunctionalTest):
def setUp(self):
super(TestRootController, self).setUp()
self.commands = [
{u"command_name": u"check_test1",
u"command_line": u"/test/test1/test.py"},
{u"command_name": u"check_test2",
u"command_line": u"/test/test2/test.py"},
]
self.mongoconnection.shinken.commands.insert(
copy.deepcopy(self.commands)
)
def test_get_all_commands(self):
response = self.app.get('/v1/commands')
self.assert_count_equal_backport(
json.loads(response.body.decode()),
self.commands
)
self.assertEqual(response.status_int, 200)
def test_get_specific_command(self):
response = self.app.get('/v1/commands/check_test2')
self.assert_count_equal_backport(
json.loads(response.body.decode()),
self.commands[1]
)
self.assertEqual(response.status_int, 200)
def test_update_command(self):
put_body = {"command_line": "test_put",
"command_name": "check_test2"}
response = self.app.put_json(
"/v1/commands/check_test2", params=put_body
)
expected_command = {u"command_name": u"check_test2",
u"command_line": u"test_put"}
mongo_command = self.mongoconnection.shinken.commands.find_one(
{'command_name': 'check_test2'}
)
del mongo_command['_id']
self.assertEqual(expected_command, mongo_command)
self.assertEqual(response.status_int, 204)
def test_delete_command(self):
response = self.app.delete('/v1/commands/check_test2')
expected_commands = [
{u"command_name": u"check_test1",
u"command_line": u"/test/test1/test.py"}
]
mongo_commands = [command for command
in self.mongoconnection.shinken.commands.find()]
for command in mongo_commands:
del command['_id']
self.assertEqual(expected_commands, mongo_commands)
self.assertEqual(response.status_int, 204)