237 lines
8.5 KiB
Python
237 lines
8.5 KiB
Python
# 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 types
|
|
from unittest import mock
|
|
|
|
from openstack import connection
|
|
from oslo_serialization import jsonutils
|
|
from requests import exceptions as req_exc
|
|
|
|
from senlin.common import exception as senlin_exc
|
|
from senlin.drivers import sdk
|
|
from senlin.tests.unit.common import base
|
|
from senlin import version
|
|
|
|
|
|
class OpenStackSDKTest(base.SenlinTestCase):
|
|
|
|
def setUp(self):
|
|
super(OpenStackSDKTest, self).setUp()
|
|
self.app_version = version.version_info.version_string()
|
|
|
|
def test_parse_exception_http_exception_with_details(self):
|
|
details = jsonutils.dumps({
|
|
'error': {
|
|
'code': 404,
|
|
'message': 'Resource BAR is not found.'
|
|
}
|
|
})
|
|
raw = sdk.exc.ResourceNotFound(message='A message', details=details,
|
|
response=None, http_status=404)
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(404, ex.code)
|
|
self.assertEqual('Resource BAR is not found.', str(ex))
|
|
# key name is not 'error' case
|
|
details = jsonutils.dumps({
|
|
'forbidden': {
|
|
'code': 403,
|
|
'message': 'Quota exceeded for instances.'
|
|
}
|
|
})
|
|
raw = sdk.exc.ResourceNotFound(message='A message', details=details,
|
|
http_status=403)
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(403, ex.code)
|
|
self.assertEqual('Quota exceeded for instances.', str(ex))
|
|
|
|
def test_parse_exception_http_exception_no_details(self):
|
|
resp = mock.Mock(headers={'x-openstack-request-id': 'FAKE_ID'})
|
|
resp.json.return_value = {}
|
|
resp.status_code = 404
|
|
|
|
raw = sdk.exc.ResourceNotFound(message='Error', details=None,
|
|
response=resp, http_status=404)
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(404, ex.code)
|
|
self.assertEqual('Error', str(ex))
|
|
|
|
def test_parse_exception_http_exception_no_details_no_response(self):
|
|
details = "An error message"
|
|
|
|
raw = sdk.exc.ResourceNotFound(message='A message.', details=details,
|
|
http_status=404)
|
|
raw.details = None
|
|
raw.response = None
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
self.assertEqual(404, ex.code)
|
|
self.assertEqual('A message.', str(ex))
|
|
|
|
def test_parse_exception_http_exception_code_displaced(self):
|
|
details = jsonutils.dumps({
|
|
'code': 400,
|
|
'error': {
|
|
'message': 'Resource BAR is in error state.'
|
|
}
|
|
})
|
|
|
|
raw = sdk.exc.HttpException(
|
|
message='A message.', details=details, http_status=400)
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(400, ex.code)
|
|
self.assertEqual('Resource BAR is in error state.', str(ex))
|
|
|
|
def test_parse_exception_sdk_exception(self):
|
|
raw = sdk.exc.InvalidResponse('INVALID')
|
|
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(500, ex.code)
|
|
self.assertEqual('InvalidResponse', str(ex))
|
|
|
|
def test_parse_exception_request_exception(self):
|
|
raw = req_exc.HTTPError(401, 'ERROR')
|
|
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(401, ex.code)
|
|
self.assertEqual('[Errno 401] ERROR', ex.message)
|
|
|
|
def test_parse_exception_other_exceptions(self):
|
|
raw = Exception('Unknown Error')
|
|
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.parse_exception, raw)
|
|
|
|
self.assertEqual(500, ex.code)
|
|
self.assertEqual('Unknown Error', str(ex))
|
|
|
|
def test_translate_exception_wrapper(self):
|
|
|
|
@sdk.translate_exception
|
|
def test_func(driver):
|
|
return driver.__name__
|
|
|
|
res = sdk.translate_exception(test_func)
|
|
self.assertEqual(types.FunctionType, type(res))
|
|
|
|
def test_translate_exception_with_exception(self):
|
|
|
|
@sdk.translate_exception
|
|
def test_func(driver):
|
|
raise(Exception('test exception'))
|
|
|
|
error = senlin_exc.InternalError(code=500, message='BOOM')
|
|
self.patchobject(sdk, 'parse_exception', side_effect=error)
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
test_func, mock.Mock())
|
|
|
|
self.assertEqual(500, ex.code)
|
|
self.assertEqual('BOOM', ex.message)
|
|
|
|
@mock.patch.object(connection, 'Connection')
|
|
def test_create_connection_token(self, mock_conn):
|
|
x_conn = mock.Mock()
|
|
mock_conn.return_value = x_conn
|
|
|
|
res = sdk.create_connection({'token': 'TOKEN', 'foo': 'bar'})
|
|
|
|
self.assertEqual(x_conn, res)
|
|
mock_conn.assert_called_once_with(
|
|
app_name=sdk.USER_AGENT, app_version=self.app_version,
|
|
identity_api_version='3',
|
|
messaging_api_version='2',
|
|
region_name=None,
|
|
auth_type='token',
|
|
token='TOKEN',
|
|
foo='bar')
|
|
|
|
@mock.patch.object(connection, 'Connection')
|
|
def test_create_connection_password(self, mock_conn):
|
|
x_conn = mock.Mock()
|
|
mock_conn.return_value = x_conn
|
|
|
|
res = sdk.create_connection({'user_id': '123', 'password': 'abc',
|
|
'foo': 'bar'})
|
|
|
|
self.assertEqual(x_conn, res)
|
|
mock_conn.assert_called_once_with(
|
|
app_name=sdk.USER_AGENT, app_version=self.app_version,
|
|
identity_api_version='3',
|
|
messaging_api_version='2',
|
|
region_name=None,
|
|
user_id='123',
|
|
password='abc',
|
|
foo='bar')
|
|
|
|
@mock.patch.object(connection, 'Connection')
|
|
def test_create_connection_with_region(self, mock_conn):
|
|
x_conn = mock.Mock()
|
|
mock_conn.return_value = x_conn
|
|
|
|
res = sdk.create_connection({'region_name': 'REGION_ONE'})
|
|
|
|
self.assertEqual(x_conn, res)
|
|
mock_conn.assert_called_once_with(
|
|
app_name=sdk.USER_AGENT, app_version=self.app_version,
|
|
identity_api_version='3',
|
|
messaging_api_version='2',
|
|
region_name='REGION_ONE')
|
|
|
|
@mock.patch.object(connection, 'Connection')
|
|
@mock.patch.object(sdk, 'parse_exception')
|
|
def test_create_connection_with_exception(self, mock_parse, mock_conn):
|
|
ex_raw = Exception('Whatever')
|
|
mock_conn.side_effect = ex_raw
|
|
mock_parse.side_effect = senlin_exc.InternalError(code=123,
|
|
message='BOOM')
|
|
|
|
ex = self.assertRaises(senlin_exc.InternalError,
|
|
sdk.create_connection)
|
|
|
|
mock_conn.assert_called_once_with(
|
|
app_name=sdk.USER_AGENT, app_version=self.app_version,
|
|
identity_api_version='3',
|
|
messaging_api_version='2',
|
|
region_name=None)
|
|
mock_parse.assert_called_once_with(ex_raw)
|
|
self.assertEqual(123, ex.code)
|
|
self.assertEqual('BOOM', ex.message)
|
|
|
|
@mock.patch.object(sdk, 'create_connection')
|
|
def test_authenticate(self, mock_conn):
|
|
x_conn = mock_conn.return_value
|
|
x_conn.session.get_token.return_value = 'TOKEN'
|
|
x_conn.session.get_user_id.return_value = 'test-user-id'
|
|
x_conn.session.get_project_id.return_value = 'test-project-id'
|
|
access_info = {
|
|
'token': 'TOKEN',
|
|
'user_id': 'test-user-id',
|
|
'project_id': 'test-project-id'
|
|
}
|
|
|
|
res = sdk.authenticate(foo='bar')
|
|
|
|
self.assertEqual(access_info, res)
|
|
mock_conn.assert_called_once_with({'foo': 'bar'})
|