Merge "Add validation for podmanager API"

This commit is contained in:
Jenkins 2017-04-06 21:26:52 +00:00 committed by Gerrit Code Review
commit dea13b1036
6 changed files with 114 additions and 41 deletions

View File

@ -21,6 +21,7 @@ from six.moves import http_client
from valence.common import exception
from valence.common import utils
from valence.controller import podmanagers
from valence.validation import validator
LOG = logging.getLogger(__name__)
@ -31,6 +32,7 @@ class PodManagersList(flask_restful.Resource):
def get(self):
return utils.make_response(http_client.OK, podmanagers.get_podm_list())
@validator.check_input('podmanager_schema')
def post(self):
values = flask.request.get_json()
return utils.make_response(http_client.OK,

View File

@ -33,22 +33,6 @@ def _check_creation(values):
:returns: improved values that could be inserted to db
"""
if not ('name' in values and
'url' in values and
'authentication' in values):
raise exception.BadRequest(detail="Incomplete parameters")
# check authentication's format and content
try:
if not (values['authentication'][0]['type'] and
values['authentication'][0]['auth_items']):
LOG.error("invalid authentication when creating podmanager")
raise exception.BadRequest(detail="invalid "
"authentication properties")
except KeyError:
LOG.error("Incomplete parameters when creating podmanager")
raise exception.BadRequest(detail="invalid "
"authentication properties")
pod_manager_list = get_podm_list()
names = [podm['name'] for podm in pod_manager_list]
urls = [podm['url'] for podm in pod_manager_list]

View File

@ -53,28 +53,6 @@ class TestPodManagers(unittest.TestCase):
values['authentication'])
mock_get_podm_list.assert_called_once_with()
def test_check_creation_incomplete_parameters(self):
incomplete_values = {
'name': 'name',
'url': 'url'
}
self.assertRaises(BadRequest,
podmanagers._check_creation,
incomplete_values)
def test_check_creation_invalid_authentication(self):
invalid_authentication_values = {
"name": "podm_name",
"url": "https://10.0.0.2",
'authentication': {
"username": "username",
"password": "password"
}
}
self.assertRaises(BadRequest,
podmanagers._check_creation,
invalid_authentication_values)
@mock.patch('valence.controller.podmanagers.get_podm_list')
def test_check_creation_duplicate_Exception(self, mock_get_podm_list):
mock_get_podm_list.return_value = [

View File

@ -1,9 +1,11 @@
import copy
import json
import mock
from oslotest import base
from valence.api import app as flask_app
from valence.common import constants
from valence.tests.unit.fakes import flavor_fakes
@ -15,6 +17,11 @@ class TestApiValidation(base.BaseTestCase):
app = flask_app.get_app()
app.config['TESTING'] = True
self.app = app.test_client()
class TestFlavorApi(TestApiValidation):
def setUp(self):
super(TestFlavorApi, self).setUp()
self.flavor = flavor_fakes.fake_flavor()
@mock.patch('valence.controller.flavors.create_flavor')
@ -48,3 +55,61 @@ class TestApiValidation(base.BaseTestCase):
response = json.loads(response.data.decode())
self.assertEqual(400, response['status'])
self.assertEqual('ValidationError', response['code'])
class TestPodmanagerApi(TestApiValidation):
@mock.patch('valence.controller.podmanagers.create_podm')
@mock.patch('valence.controller.podmanagers.get_podm_list')
@mock.patch('valence.controller.podmanagers.get_podm_status')
def test_podmanager_create(self, pstatus_mock, plist_mock, pcreate_mock):
pstatus_mock.return_value = constants.PODM_STATUS_ONLINE
plist_mock.return_value = []
values = {
"name": "podm_name",
"url": "https://10.240.212.123",
"authentication": [
{
"type": "basic",
"auth_items":
{
"username": "xxxxxxx",
"password": "xxxxxxx"
}
}]
}
result = copy.deepcopy(values)
result['status'] = constants.PODM_STATUS_ONLINE
pcreate_mock.return_value = result
response = self.app.post('/v1/pod_managers',
content_type='application/json',
data=json.dumps(values))
self.assertEqual(200, response.status_code)
def test_check_creation_incomplete_parameters(self):
incomplete_values = {
'name': 'name',
'url': 'url'
}
response = self.app.post('/v1/pod_managers',
content_type='application/json',
data=json.dumps(incomplete_values))
response = json.loads(response.data.decode())
self.assertEqual(400, response['status'])
self.assertEqual('ValidationError', response['code'])
def test_check_creation_invalid_authentication(self):
invalid_auth_values = {
"name": "podm_name",
"url": "https://10.0.0.2",
'authentication': {
"username": "username",
"password": "password"
}
}
response = self.app.post('/v1/pod_managers',
content_type='application/json',
data=json.dumps(invalid_auth_values))
response = json.loads(response.data.decode())
self.assertEqual(400, response['status'])
self.assertEqual('ValidationError', response['code'])

View File

@ -32,6 +32,43 @@ flavor_schema = {
'additionalProperties': False,
}
jsonschema.Draft4Validator.check_schema(flavor_schema)
SCHEMAS = {'flavor_schema': flavor_schema}
podmanager_schema = {
'type': 'object',
'properties': {
'name': {'type': 'string'},
'url': {
'type': 'string',
'format': 'uri',
},
'authentication': {
'type': 'array',
'minItems': 1,
'items': {
'type': 'object',
'properties': {
'type': {'type': 'string'},
'auth_items': {
'type': 'object',
'properties': {
'username': {'type': 'string'},
'password': {'type': 'string'},
},
'required': ['username', 'password'],
'additionalProperties': False,
},
},
'required': ['type', 'auth_items'],
'additionalProperties': False,
},
},
},
'required': ['name', 'url', 'authentication'],
'additionalProperties': False,
}
jsonschema.Draft4Validator.check_schema(podmanager_schema)
SCHEMAS = {'flavor_schema': flavor_schema,
'podmanager_schema': podmanager_schema, }

View File

@ -49,5 +49,12 @@ class Validator(object):
try:
self.validator.validate(data)
except jsonschema.ValidationError as e:
if len(e.path) > 0:
detail = (("Invalid input for field/attribute '%(path)s' "
"Value: '%(value)s'. %(message)s") %
{'path': e.path.pop(), 'value': e.instance,
'message': e.message})
else:
detail = e.message
LOG.exception("Failed to validate the input")
raise exception.ValidationError(detail=e.message)
raise exception.ValidationError(detail=detail)