def test_version_matches(self): vers1 = vr.APIVersionRequest("1.0") vers2 = vr.APIVersionRequest("1.1") vers3 = vr.APIVersionRequest("1.2") v_null = vr.APIVersionRequest() self.assertTrue(vers2.matches(vers1, vers3)) self.assertTrue(vers2.matches(vers1, v_null)) self.assertFalse(vers1.matches(vers2, vers3)) self.assertFalse(vers2.matches(vers3, vers1)) self.assertRaises(ValueError, v_null.matches, vers1, vers3)
def test_versioned_request_inner_functions(self): data = mock.Mock() request = wsgi.Request.blank('/tests/123') request.version_request = vr.APIVersionRequest('3.0') c = FakeController(data) res = c.dance(request) self.assertEqual({'score': 100}, res) request.version_request = vr.APIVersionRequest('4.0') res = c.dance(request) self.assertEqual({'score': 60}, res)
def is_supported(cls, req, min_ver=None, max_ver=None): """Check if API request version satisfies version restrictions. :param req: request object :param min_ver: minimal version of API needed. :param max_ver: maximum version of API needed. :returns: True if request satisfies minimal and maximum API version requirements. False in other case. """ min_version = min_ver or cls._MIN_API_VERSION max_version = max_ver or cls._MAX_API_VERSION return (vr.APIVersionRequest(max_version) >= req.version_request >= vr.APIVersionRequest(min_version))
def test__check_version_request(self, mock_vc): controller = mock.Mock() minv = vr.APIVersionRequest('1.0') maxv = vr.APIVersionRequest('1.3') controller.min_api_version = mock.Mock(return_value=minv) controller.max_api_version = mock.Mock(return_value=maxv) request = webob.Request({'PATH_INFO': 'resource'}) request.headers[wsgi.API_VERSION_KEY] = 'clustering 1.0,compute 2.0' vnf = vn.VersionNegotiationFilter(None, None) vnf._check_version_request(request, controller) self.assertIsNotNone(request.version_request) expected = vr.APIVersionRequest('1.0') self.assertEqual(expected, request.version_request)
def _check_version_request(self, req, controller): """Set API version request based on the request header and controller. :param req: The webob.Request object. :param controller: The API version controller. :returns: ``None`` :raises: ``HTTPBadRequest`` if API version string is bad. """ api_version = mp.get_version(req.headers, service_type='clustering') if api_version is None: api_version = controller.DEFAULT_API_VERSION elif api_version.lower() == 'latest': req.version_request = controller.max_api_version() return try: ver = vr.APIVersionRequest(api_version) except exception.InvalidAPIVersionString as e: raise webob.exc.HTTPBadRequest(six.text_type(e)) if not ver.matches(controller.min_api_version(), controller.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=api_version, min_ver=six.text_type(controller.min_api_version()), max_ver=six.text_type(controller.max_api_version())) req.version_request = ver
def check_version_request(self, req): """Set API version request based on the request header.""" api_version = wsgi.DEFAULT_API_VERSION key = wsgi.API_VERSION_KEY if key in req.headers: versions = req.headers[key].split(',') for version in versions: svc_ver = version.strip().split(' ') if svc_ver[0].lower() in wsgi.SERVICE_ALIAS: api_version = svc_ver[1] break if api_version.lower() == 'latest': req.version_request = os_ver.max_api_version() return try: ver = vr.APIVersionRequest(api_version) except exception.InvalidAPIVersionString as e: raise webob.exc.HTTPBadRequest(six.text_type(e)) if not ver.matches(os_ver.min_api_version(), os_ver.max_api_version()): raise exception.InvalidGlobalAPIVersion( req_ver=api_version, min_ver=six.text_type(os_ver.min_api_version()), max_ver=six.text_type(os_ver.max_api_version())) req.version_request = ver
def _remove_cluster_id(self, req, obj): if req.version_request > vr.APIVersionRequest("1.13"): return obj if 'cluster_id' in obj: obj.pop('cluster_id') return obj
def _remove_tainted(self, req, obj): if req.version_request > vr.APIVersionRequest("1.12"): return obj if 'tainted' in obj: obj.pop('tainted') return obj
def test_process_request(self, mock_client, mock_ctx, mock_parse): cfg.CONF.set_override('auth_url', 'AUTH_URL', group='authentication', enforce_type=True) cfg.CONF.set_override('service_username', 'USERNAME', group='authentication', enforce_type=True) cfg.CONF.set_override('service_user_domain', 'DOMAIN', group='authentication', enforce_type=True) cfg.CONF.set_override('service_password', 'PASSWORD', group='authentication', enforce_type=True) req = mock.Mock() req.method = 'POST' req.url = 'http://url1' req.params = {'key': 'FAKE_KEY'} req.headers = {} req.version_request = vr.APIVersionRequest('1.0') rpcc = mock.Mock() fake_receiver = {'id': 'FAKE_ID', 'actor': {'foo': 'bar'}} rpcc.call.return_value = fake_receiver mock_client.return_value = rpcc dbctx = mock.Mock() mock_ctx.return_value = dbctx obj = mock.Mock() mock_parse.return_value = obj fake_return = ('WEBHOOK', {}) mock_extract = self.patchobject(self.middleware, '_parse_url', return_value=fake_return) mock_token = self.patchobject(self.middleware, '_get_token', return_value='FAKE_TOKEN') res = self.middleware.process_request(req) self.assertIsNone(res) self.assertEqual('FAKE_TOKEN', req.headers['X-Auth-Token']) mock_extract.assert_called_once_with('http://url1') mock_token.assert_called_once_with(auth_url='AUTH_URL', password='******', username='******', user_domain_name='DOMAIN', foo='bar') mock_parse.assert_called_once_with('ReceiverGetRequest', req, {'identity': 'WEBHOOK'}) rpcc.call.assert_called_with(dbctx, 'receiver_get', obj)
def test__check_version_request_invalid_version(self, mock_vc): controller = mock.Mock() minv = vr.APIVersionRequest('1.0') maxv = vr.APIVersionRequest('1.100') controller.min_api_version = mock.Mock(return_value=minv) controller.max_api_version = mock.Mock(return_value=maxv) request = webob.Request({'PATH_INFO': 'resource'}) request.headers[wsgi.API_VERSION_KEY] = 'clustering 2.3' vnf = vn.VersionNegotiationFilter(None, None) ex = self.assertRaises(exception.InvalidGlobalAPIVersion, vnf._check_version_request, request, controller) expected = ("Version '2.3' is not supported by the API. Minimum is " "'%(min_ver)s' and maximum is '%(max_ver)s'." % { 'min_ver': str(minv), 'max_ver': str(maxv) }) self.assertEqual(expected, six.text_type(ex))
def test_check_version_request_default(self): 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) version_negotiation.check_version_request(request) self.assertIsNotNone(request.version_request) expected = vr.APIVersionRequest(wsgi.DEFAULT_API_VERSION) self.assertEqual(expected, request.version_request)
def test_version_comparisons(self): vers1 = vr.APIVersionRequest("2.0") vers2 = vr.APIVersionRequest("2.5") vers3 = vr.APIVersionRequest("5.23") vers4 = vr.APIVersionRequest("2.0") v_null = vr.APIVersionRequest() self.assertTrue(v_null < vers2) self.assertTrue(vers1 < vers2) self.assertTrue(vers1 <= vers2) self.assertTrue(vers1 <= vers4) self.assertTrue(vers2 > v_null) self.assertTrue(vers3 > vers2) self.assertTrue(vers1 >= vers4) self.assertTrue(vers3 >= vers2) self.assertTrue(vers1 != vers2) self.assertTrue(vers1 == vers4) self.assertTrue(vers1 != v_null) self.assertTrue(v_null == v_null) self.assertRaises(TypeError, vers1.__lt__, "2.1")
def index(self, req): obj = util.parse_request('ProfileTypeListRequest', req, {}) types = self.rpc_client.call(req.context, 'profile_type_list', obj) result = types if req.version_request <= vr.APIVersionRequest("1.4"): # We return only profile type name before 1.5 result = [{ 'name': '-'.join((t['name'], t['version'])) } for t in types] return {'profile_types': result}
def test_version_comparisons(self): vers1 = vr.APIVersionRequest("2.0") vers2 = vr.APIVersionRequest("2.5") vers3 = vr.APIVersionRequest("5.23") vers4 = vr.APIVersionRequest("2.0") v_null = vr.APIVersionRequest() self.assertLess(v_null, vers2) self.assertLess(vers1, vers2) self.assertLessEqual(vers1, vers2) self.assertLessEqual(vers1, vers4) self.assertGreater(vers2, v_null) self.assertGreater(vers3, vers2) self.assertGreaterEqual(vers1, vers4) self.assertGreaterEqual(vers3, vers2) self.assertNotEqual(vers1, vers2) self.assertEqual(vers1, vers4) self.assertNotEqual(vers1, v_null) self.assertEqual(v_null, v_null) self.assertRaises(TypeError, vers1.__lt__, "2.1")
def index(self, req): """Gets the supported policy types""" obj = util.parse_request('PolicyTypeListRequest', req, {}) types = self.rpc_client.call(req.context, 'policy_type_list', obj) result = types if req.version_request <= vr.APIVersionRequest("1.4"): # we return only policy name before microversion 1.5 result = [{'name': '-'.join((t['name'], t['version']))} for t in types] return {'policy_types': result}
def get(self, req, type_name): """Gets the details about a specified profile type.""" obj = util.parse_request('ProfileTypeGetRequest', req, {'type_name': type_name}) content = self.rpc_client.call(req.context, 'profile_type_get', obj) key = 'support_status' if req.version_request <= vr.APIVersionRequest("1.4"): # We return support_status from 1.5 if key in content: content.pop(key) return {'profile_type': content}
def get(self, req, type_name): """Gets detailed information for a policy-type""" obj = util.parse_request( 'PolicyTypeGetRequest', req, {'type_name': type_name}) content = self.rpc_client.call(req.context, 'policy_type_get', obj) key = 'support_status' if req.version_request <= vr.APIVersionRequest("1.4"): # We return support_status from 1.5 if key in content: content.pop(key) return {'policy_type': content}
def test__check_version_request_default(self, mock_vc): controller = mock.Mock() controller.DEFAULT_API_VERSION = "1.0" request = webob.Request({'PATH_INFO': 'resource'}) request.headers[wsgi.API_VERSION_KEY] = 'compute 2.0' vnf = vn.VersionNegotiationFilter(None, None) vnf._check_version_request(request, controller) self.assertIsNotNone(request.version_request) expected = vr.APIVersionRequest(controller.DEFAULT_API_VERSION) self.assertEqual(expected, request.version_request)
def _data_request(self, path, data, content_type='application/json', method='POST', version=None): environ = self._environ(path) environ['REQUEST_METHOD'] = method req = wsgi.Request(environ) req.context = utils.dummy_context('api_test_user', self.project) self.context = req.context ver = version if version else wsgi.DEFAULT_API_VERSION req.version_request = vr.APIVersionRequest(ver) req.body = encodeutils.safe_encode(data) if data else None return req
def test_versioned_request_upper(self): data = mock.Mock() request = wsgi.Request.blank('/tests/123') request.version_request = vr.APIVersionRequest('3.0') c = FakeController(data) res = c.index(request) self.assertEqual({'foo': 'bar'}, res) res = c.foo(request) self.assertEqual({'bar': 'zoo'}, res) res = c.dance(request) self.assertEqual({'score': 100}, res)
def _simple_request(self, path, params=None, method='GET', version=None): environ = self._environ(path) environ['REQUEST_METHOD'] = method if params: qs = "&".join(["=".join([k, str(params[k])]) for k in params]) environ['QUERY_STRING'] = qs req = wsgi.Request(environ) req.context = utils.dummy_context('api_test_user', self.project) self.context = req.context ver = version if version else wsgi.DEFAULT_API_VERSION req.version_request = vr.APIVersionRequest(ver) return req
def decorator(f): obj_min_ver = version_request.APIVersionRequest(min_ver) obj_max_ver = version_request.APIVersionRequest(max_ver) func_name = f.__name__ new_func = versioned_method.VersionedMethod( func_name, obj_min_ver, obj_max_ver, f) func_dict = getattr(cls, VER_METHOD_ATTR, {}) if not func_dict: setattr(cls, VER_METHOD_ATTR, func_dict) func_list = func_dict.get(func_name, []) if not func_list: func_dict[func_name] = func_list func_list.append(new_func) # Ensure the list is sorted by minimum version (reversed) so when # we walk through the list later in order we find the method with # the latest version which supports the version requested func_list.sort(key=lambda f: f.min_version, reverse=True) return f
def _data_request(self, path, data, content_type='application/json', method='POST', version=None, params=None): environ = self._environ(path) environ['REQUEST_METHOD'] = method if params: qs = "&".join(["=".join([k, str(params[k])]) for k in params]) environ['QUERY_STRING'] = qs req = wsgi.Request(environ) req.context = utils.dummy_context('api_test_user', self.project) self.context = req.context ver = version if version else wsgi.DEFAULT_API_VERSION req.version_request = vr.APIVersionRequest(ver) req.body = encodeutils.safe_encode(data) if data else None return req
def test_versioned_request_too_high(self): data = mock.Mock() request = wsgi.Request.blank('/tests/123') request.version_request = vr.APIVersionRequest('3.5') c = FakeController(data) res = c.index(request) self.assertEqual({'foo': 'bar'}, res) res = c.foo(request) self.assertEqual({'bar': 'zoo'}, res) ex = self.assertRaises(exception.MethodVersionNotFound, c.dance, request) self.assertEqual('API version 3.5 is not supported on this method.', six.text_type(ex))
def test_context_middleware(self): avr = vr.APIVersionRequest('1.0') middleware = context.ContextMiddleware(None) request = webob.Request.blank('/clusters', headers=self.headers, environ=self.environ) request.version_request = avr if self.expected_exception: self.assertRaises(self.expected_exception, middleware.process_request, request) else: self.assertIsNone(middleware.process_request(request)) ctx = request.context.to_dict() for k, v in self.context_dict.items(): self.assertEqual(v, ctx[k], 'Key %s values do not match' % k) self.assertIsNotNone(ctx.get('request_id'))
def test_resource_call_with_version_header(self): class Controller(object): def dance(self, req): return {'foo': 'bar'} actions = {'action': 'dance'} env = {'wsgiorg.routing_args': [None, actions]} request = wsgi.Request.blank('/tests/123', environ=env) request.version_request = vr.APIVersionRequest('1.0') resource = wsgi.Resource(Controller()) resp = resource(request) self.assertEqual('{"foo": "bar"}', encodeutils.safe_decode(resp.body)) self.assertTrue(hasattr(resp, 'headers')) expected = 'clustering 1.0' self.assertEqual(expected, resp.headers['OpenStack-API-Version']) self.assertEqual('OpenStack-API-Version', resp.headers['Vary'])
def test_versioned_request_empty(self): data = mock.Mock() request = wsgi.Request.blank('/tests/123') request.version_request = vr.APIVersionRequest('1.0') c = FakeController(data) ex = self.assertRaises(exception.MethodVersionNotFound, c.index, request) self.assertEqual("API version '1.0' is not supported on " "this method.", six.text_type(ex)) res = c.foo(request) self.assertEqual({'bar': 'zoo'}, res) ex = self.assertRaises(exception.MethodVersionNotFound, c.dance, request) self.assertEqual("API version '1.0' is not supported on " "this method.", six.text_type(ex))
def test_context_middleware_with_requestid(self): avr = vr.APIVersionRequest('1.0') middleware = context.ContextMiddleware(None) request = webob.Request.blank('/clusters', headers=self.headers, environ=self.environ) req_id = 'req-5a63f0d7-1b69-447b-b621-4ea87cc7186d' request.environ[request_id.ENV_REQUEST_ID] = req_id request.version_request = avr if self.expected_exception: self.assertRaises(self.expected_exception, middleware.process_request, request) else: self.assertIsNone(middleware.process_request(request)) ctx = request.context.to_dict() for k, v in self.context_dict.items(): self.assertEqual(v, ctx[k], 'Key %s values do not match' % k) self.assertEqual(ctx.get('request_id'), req_id, 'Key request_id values do not match')
def max_api_version(cls): return vr.APIVersionRequest(cls._MAX_API_VERSION)
def min_api_version(cls): return vr.APIVersionRequest(cls._MIN_API_VERSION)