Merge "Refactor version negotiation middleware"

This commit is contained in:
Jenkins 2016-08-13 02:31:43 +00:00 committed by Gerrit Code Review
commit e51e7e88fc
4 changed files with 63 additions and 84 deletions

View File

@ -15,12 +15,10 @@ from senlin.api.middleware import fault
from senlin.api.middleware import trust
from senlin.api.middleware import version_negotiation as vn
from senlin.api.middleware import webhook
from senlin.api.openstack import versions
def version_filter(app, conf, **local_conf):
return vn.VersionNegotiationFilter(versions.Controller, app,
conf, **local_conf)
return vn.VersionNegotiationFilter(app, conf)
def fault_filter(app, conf, **local_conf):

View File

@ -34,8 +34,8 @@ LOG = logging.getLogger(__name__)
class VersionNegotiationFilter(wsgi.Middleware):
def __init__(self, version_controller, app, conf, **local_conf):
self.versions_app = version_controller(conf)
def __init__(self, app, conf):
self.versions_app = os_ver.Controller(conf)
self.version_uri_regex = re.compile(r"^v([1-9]\d*)\.?([1-9]\d*|0)?$")
self.conf = conf
super(VersionNegotiationFilter, self).__init__(app)
@ -55,7 +55,7 @@ class VersionNegotiationFilter(wsgi.Middleware):
return self.versions_app
# Check if there is a requested (micro-)version for API
self.check_version_request(req)
self._check_version_request(req)
match = self._match_version_string(req.path_info_peek(), req)
if match:
major = req.environ['api.major']
@ -120,7 +120,7 @@ class VersionNegotiationFilter(wsgi.Middleware):
return match is not None
def check_version_request(self, req):
def _check_version_request(self, req):
"""Set API version request based on the request header."""
api_version = microversion_parse.get_version(req.headers,
service_type='clustering')

View File

@ -19,7 +19,6 @@ from senlin.api.middleware import fault
from senlin.api.middleware import trust
from senlin.api.middleware import version_negotiation as vn
from senlin.api.middleware import webhook
from senlin.api.openstack import versions
from senlin.tests.unit.common import base
@ -40,9 +39,7 @@ class MiddlewareFilterTest(base.SenlinTestCase):
actual = mw.version_filter(self.app, self.conf, **self.local_conf)
self.assertEqual(exp, actual)
mock_vnf.assert_called_once_with(versions.Controller,
self.app, self.conf,
**self.local_conf)
mock_vnf.assert_called_once_with(self.app, self.conf)
@mock.patch.object(fault, 'FaultWrapper')
def test_faultwrap_filter(self, mock_fw):

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import six
import webob
@ -21,170 +22,154 @@ from senlin.common import exception
from senlin.tests.unit.common import base
class VersionController(object):
pass
@mock.patch("senlin.api.openstack.versions.Controller")
class VersionNegotiationTest(base.SenlinTestCase):
def setUp(self):
super(VersionNegotiationTest, self).setUp()
class VersionNegotiationMiddlewareTest(base.SenlinTestCase):
def _version_controller_factory(self, conf):
return VersionController()
def test_match_version_string(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_match_version_string(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({})
major = 1
minor = 0
match = version_negotiation._match_version_string(
'v{0}.{1}'.format(major, minor), request)
match = vnf._match_version_string('v{0}.{1}'.format(major, minor),
request)
self.assertTrue(match)
self.assertEqual(major, request.environ['api.major'])
self.assertEqual(minor, request.environ['api.minor'])
def test_not_match_version_string(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_not_match_version_string(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({})
match = version_negotiation._match_version_string("invalid", request)
match = vnf._match_version_string("invalid", request)
self.assertFalse(match)
def test_return_version_controller_when_request_path_is_version(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_request_path_is_version(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({'PATH_INFO': 'versions'})
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, VersionController)
self.assertIs(mock_vc.return_value, response)
def test_return_version_controller_when_request_path_is_empty(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_request_path_is_empty(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({'PATH_INFO': '/'})
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, VersionController)
self.assertIs(mock_vc.return_value, response)
def test_request_path_contains_valid_version(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_request_path_contains_valid_version(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
major = 1
minor = 0
request = webob.Request({'PATH_INFO':
'v{0}.{1}/resource'.format(major, minor)})
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsNone(response)
self.assertEqual(major, request.environ['api.major'])
self.assertEqual(minor, request.environ['api.minor'])
def test_removes_version_from_request_path(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_removes_version_from_request_path(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
expected_path = 'resource'
request = webob.Request({'PATH_INFO': 'v1.0/%s' % expected_path})
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsNone(response)
self.assertEqual(expected_path, request.path_info_peek())
def test_request_path_contains_unknown_version(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_request_path_contains_unknown_version(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({'PATH_INFO': 'v2.0/resource'})
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, VersionController)
self.assertIs(mock_vc.return_value, response)
def test_accept_header_contains_valid_version(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_accept_header_contains_valid_version(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
major = 1
minor = 0
request = webob.Request({'PATH_INFO': 'resource'})
request.headers['Accept'] = 'application/vnd.openstack.clustering-v1.0'
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsNone(response)
self.assertEqual(major, request.environ['api.major'])
self.assertEqual(minor, request.environ['api.minor'])
def test_accept_header_contains_unknown_version(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_accept_header_contains_unknown_version(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({'PATH_INFO': 'resource'})
request.headers['Accept'] = 'application/vnd.openstack.clustering-v2.0'
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, VersionController)
self.assertIs(mock_vc.return_value, response)
request.headers['Accept'] = 'application/vnd.openstack.clustering-vab'
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsNone(response)
def test_no_URI_version_accept_header_contains_invalid_MIME_type(self):
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
def test_no_URI_version_accept_with_invalid_MIME_type(self, mock_vc):
vnf = vn.VersionNegotiationFilter(None, None)
request = webob.Request({'PATH_INFO': 'resource'})
request.headers['Accept'] = 'application/invalidMIMEType'
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, webob.exc.HTTPNotFound)
request.headers['Accept'] = ''
response = version_negotiation.process_request(request)
response = vnf.process_request(request)
self.assertIsInstance(response, webob.exc.HTTPNotFound)
def test_check_version_request(self):
def test__check_version_request(self, mock_vc):
request = webob.Request({'PATH_INFO': 'resource'})
request.headers[wsgi.API_VERSION_KEY] = 'clustering 1.0,compute 2.0'
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
vnf = vn.VersionNegotiationFilter(None, None)
version_negotiation.check_version_request(request)
vnf._check_version_request(request)
self.assertIsNotNone(request.version_request)
expected = vr.APIVersionRequest('1.0')
self.assertEqual(expected, request.version_request)
def test_check_version_request_default(self):
def test__check_version_request_default(self, mock_vc):
request = webob.Request({'PATH_INFO': 'resource'})
request.headers[wsgi.API_VERSION_KEY] = 'compute 2.0'
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
vnf = vn.VersionNegotiationFilter(None, None)
version_negotiation.check_version_request(request)
vnf._check_version_request(request)
self.assertIsNotNone(request.version_request)
expected = vr.APIVersionRequest(wsgi.DEFAULT_API_VERSION)
self.assertEqual(expected, request.version_request)
def test_check_version_request_invalid_format(self):
def test__check_version_request_invalid_format(self, mock_vc):
request = webob.Request({'PATH_INFO': 'resource'})
request.headers[wsgi.API_VERSION_KEY] = 'clustering 2.03'
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
vnf = vn.VersionNegotiationFilter(None, None)
ex = self.assertRaises(webob.exc.HTTPBadRequest,
version_negotiation.check_version_request,
vnf._check_version_request,
request)
self.assertEqual("API Version String (2.03) is of invalid format. It "
"must be of format 'major.minor'.",
six.text_type(ex))
def test_check_version_request_invalid_version(self):
def test__check_version_request_invalid_version(self, mock_vc):
request = webob.Request({'PATH_INFO': 'resource'})
request.headers[wsgi.API_VERSION_KEY] = 'clustering 2.3'
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
vnf = vn.VersionNegotiationFilter(None, None)
ex = self.assertRaises(exception.InvalidGlobalAPIVersion,
version_negotiation.check_version_request,
vnf._check_version_request,
request)
expected = ("Version 2.3 is not supported by the API. Minimum is "
"%(min_ver)s and maximum is %(max_ver)s." %
@ -192,13 +177,12 @@ class VersionNegotiationMiddlewareTest(base.SenlinTestCase):
'max_ver': str(os_ver.max_api_version())})
self.assertEqual(expected, six.text_type(ex))
def test_check_version_request_latest(self):
def test__check_version_request_latest(self, mock_vc):
request = webob.Request({'PATH_INFO': 'resource'})
request.headers[wsgi.API_VERSION_KEY] = 'clustering Latest'
version_negotiation = vn.VersionNegotiationFilter(
self._version_controller_factory, None, None)
vnf = vn.VersionNegotiationFilter(None, None)
version_negotiation.check_version_request(request)
vnf._check_version_request(request)
self.assertIsNotNone(request.version_request)
expected = os_ver.max_api_version()
self.assertEqual(expected, request.version_request)