From 5a1dfd23f8926d0ff986477a50dfed5a59298e7c Mon Sep 17 00:00:00 2001 From: Goutham Pratapa Date: Tue, 22 Aug 2017 19:21:17 +0530 Subject: [PATCH] Usage of Keystone plugins in Kingbirdclient. Currently we are using certain Keystone api's which are deprecated in pike release and the communication to keystone has to be occur via session plugins. Closes-Bug: #1712354 Change-Id: I17995b912011795e6d4445788951126552870098 --- kingbirdclient/api/v1/client.py | 81 +++++++------- kingbirdclient/tests/test_client.py | 158 +++++++++++++++------------- 2 files changed, 120 insertions(+), 119 deletions(-) diff --git a/kingbirdclient/api/v1/client.py b/kingbirdclient/api/v1/client.py index 5d76336..9faf374 100644 --- a/kingbirdclient/api/v1/client.py +++ b/kingbirdclient/api/v1/client.py @@ -14,26 +14,32 @@ # See the License for the specific language governing permissions and # limitations under the License. -import six - -import osprofiler.profiler +import keystoneauth1.identity.generic as auth_plugin +from keystoneauth1 import session as ks_session from kingbirdclient.api import httpclient from kingbirdclient.api.v1 import quota_class_manager as qcm from kingbirdclient.api.v1 import quota_manager as qm from kingbirdclient.api.v1 import sync_manager as sm +import osprofiler.profiler + +import six + + _DEFAULT_KINGBIRD_URL = "http://localhost:8118/v1.0" class Client(object): + """Class where the communication from KB to Keystone happens.""" + def __init__(self, kingbird_url=None, username=None, api_key=None, project_name=None, auth_url=None, project_id=None, endpoint_type='publicURL', service_type='synchronization', auth_token=None, user_id=None, cacert=None, insecure=False, profile=None, auth_type='keystone', client_id=None, client_secret=None): - + """Kingbird communicates with Keystone to fetch necessary values.""" if kingbird_url and not isinstance(kingbird_url, six.string_types): raise RuntimeError('Kingbird url should be a string.') @@ -87,6 +93,7 @@ def authenticate(kingbird_url=None, username=None, project_id=None, endpoint_type='publicURL', service_type='synchronization', auth_token=None, user_id=None, cacert=None, insecure=False): + """Get token, project_id, user_id and Endpoint.""" if project_name and project_id: raise RuntimeError( 'Only project name or project id should be set' @@ -97,47 +104,35 @@ def authenticate(kingbird_url=None, username=None, 'Only user name or user id should be set' ) - keystone_client = _get_keystone_client(auth_url) + if auth_token: + auth = auth_plugin.Token( + auth_url=auth_url, + token=auth_token, + project_id=project_id, + project_name=project_name) - keystone = keystone_client.Client( - username=username, - user_id=user_id, - password=api_key, - token=auth_token, - tenant_id=project_id, - tenant_name=project_name, - auth_url=auth_url, - endpoint=auth_url, - cacert=cacert, - insecure=insecure - ) + elif api_key and (username or user_id): + auth = auth_plugin.Password( + auth_url=auth_url, + username=username, + user_id=user_id, + password=api_key, + project_id=project_id, + project_name=project_name) - keystone.authenticate() + else: + raise RuntimeError('You must either provide a valid token or' + 'a password (api_key) and a user.') + if auth: + session = ks_session.Session(auth=auth) - token = keystone.auth_token - user_id = keystone.user_id - project_id = keystone.project_id - - if not kingbird_url: - catalog = keystone.service_catalog.get_endpoints( - service_type=service_type, - endpoint_type=endpoint_type - ) - - # For Keystone version 'V2.0' and other. - serv_endpoint = endpoint_type if keystone.version == 'v2.0' else 'url' - if service_type in catalog: - service = catalog.get(service_type) - kingbird_url = service[0].get( - serv_endpoint) if service else None + if session: + token = session.get_token() + project_id = session.get_project_id() + user_id = session.get_user_id() + if not kingbird_url: + kingbird_url = session.get_endpoint( + service_type=service_type, + endpoint_type=endpoint_type) return kingbird_url, token, project_id, user_id - - -def _get_keystone_client(auth_url): - if "v2.0" in auth_url: - from keystoneclient.v2_0 import client - else: - from keystoneclient.v3 import client - - return client diff --git a/kingbirdclient/tests/test_client.py b/kingbirdclient/tests/test_client.py index 71814d4..5950a4f 100644 --- a/kingbirdclient/tests/test_client.py +++ b/kingbirdclient/tests/test_client.py @@ -33,85 +33,77 @@ PROFILER_HMAC_KEY = 'SECRET_HMAC_KEY' class BaseClientTests(testtools.TestCase): - @mock.patch('keystoneclient.v3.client.Client') + @mock.patch('keystoneauth1.session.Session') @mock.patch('kingbirdclient.api.httpclient.HTTPClient') - def test_kingbird_url_default(self, mock, keystone_client_mock): - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) + def test_kingbird_url_default(self, mock, mock_keystone_auth_session): + keystone_session_instance = mock_keystone_auth_session.return_value + token = keystone_session_instance.get_token.return_value = \ + str(uuid.uuid4()) + project_id = keystone_session_instance.get_project_id.return_value = \ + str(uuid.uuid4()) + user_id = keystone_session_instance.get_user_id.return_value = \ + str(uuid.uuid4()) + keystone_session_instance.get_endpoint.return_value = \ + KINGBIRD_HTTP_URL expected_args = ( - KINGBIRD_HTTP_URL, - keystone_client_instance.auth_token, - keystone_client_instance.project_id, - keystone_client_instance.user_id - ) + KINGBIRD_HTTP_URL, token, project_id, user_id) expected_kwargs = { 'cacert': None, 'insecure': False } - client.client( - username='kingbird', - project_name='kingbird', - auth_url=AUTH_HTTP_URL - ) - + client.client(username='kingbird', project_name='kingbird', + auth_url=AUTH_HTTP_URL, api_key='password') self.assertTrue(mock.called) self.assertEqual(mock.call_args[0], expected_args) self.assertDictEqual(mock.call_args[1], expected_kwargs) - @mock.patch('keystoneclient.v3.client.Client') + @mock.patch('keystoneauth1.session.Session') @mock.patch('kingbirdclient.api.httpclient.HTTPClient') - def test_kingbird_url_https_insecure(self, mock, keystone_client_mock): - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) + def test_kingbird_url_https_insecure(self, mock, + mock_keystone_auth_session): + keystone_session_instance = mock_keystone_auth_session.return_value + token = keystone_session_instance.get_token.return_value = \ + str(uuid.uuid4()) + project_id = keystone_session_instance.get_project_id.return_value = \ + str(uuid.uuid4()) + user_id = keystone_session_instance.get_user_id.return_value = \ + str(uuid.uuid4()) + keystone_session_instance.get_endpoint.return_value = \ + KINGBIRD_HTTP_URL - expected_args = ( - KINGBIRD_HTTPS_URL, - keystone_client_instance.auth_token, - keystone_client_instance.project_id, - keystone_client_instance.user_id - ) + expected_args = (KINGBIRD_HTTPS_URL, token, project_id, user_id) expected_kwargs = { 'cacert': None, 'insecure': True } - client.client( - kingbird_url=KINGBIRD_HTTPS_URL, - username='kingbird', - project_name='kingbird', - auth_url=AUTH_HTTP_URL, - cacert=None, - insecure=True - ) + client.client(kingbird_url=KINGBIRD_HTTPS_URL, username='kingbird', + project_name='kingbird', auth_url=AUTH_HTTP_URL, + api_key='password', cacert=None, insecure=True) self.assertTrue(mock.called) self.assertEqual(mock.call_args[0], expected_args) self.assertDictEqual(mock.call_args[1], expected_kwargs) - @mock.patch('keystoneclient.v3.client.Client') + @mock.patch('keystoneauth1.session.Session') @mock.patch('kingbirdclient.api.httpclient.HTTPClient') - def test_kingbird_url_https_secure(self, mock, keystone_client_mock): + def test_kingbird_url_https_secure(self, mock, mock_keystone_auth_session): fd, path = tempfile.mkstemp(suffix='.pem') + keystone_session_instance = mock_keystone_auth_session.return_value + token = keystone_session_instance.get_token.return_value = \ + str(uuid.uuid4()) + project_id = keystone_session_instance.get_project_id.return_value = \ + str(uuid.uuid4()) + user_id = keystone_session_instance.get_user_id.return_value = \ + str(uuid.uuid4()) + keystone_session_instance.get_endpoint.return_value = \ + KINGBIRD_HTTPS_URL - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) - - expected_args = ( - KINGBIRD_HTTPS_URL, - keystone_client_instance.auth_token, - keystone_client_instance.project_id, - keystone_client_instance.user_id - ) + expected_args = (KINGBIRD_HTTPS_URL, token, project_id, user_id) expected_kwargs = { 'cacert': path, @@ -124,6 +116,7 @@ class BaseClientTests(testtools.TestCase): username='kingbird', project_name='kingbird', auth_url=AUTH_HTTP_URL, + api_key='password', cacert=path, insecure=False ) @@ -135,40 +128,32 @@ class BaseClientTests(testtools.TestCase): self.assertEqual(mock.call_args[0], expected_args) self.assertDictEqual(mock.call_args[1], expected_kwargs) - @mock.patch('keystoneclient.v3.client.Client') - def test_kingbird_url_https_bad_cacert(self, keystone_client_mock): - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) - + @mock.patch('keystoneauth1.session.Session') + def test_kingbird_url_https_bad_cacert(self, mock_keystone_auth_session): self.assertRaises( ValueError, client.client, kingbird_url=KINGBIRD_HTTPS_URL, username='kingbird', project_name='kingbird', + api_key='password', auth_url=AUTH_HTTP_URL, cacert='/path/to/foobar', insecure=False ) @mock.patch('logging.Logger.warning') - @mock.patch('keystoneclient.v3.client.Client') - def test_kingbird_url_https_bad_insecure(self, keystone_client_mock, + @mock.patch('keystoneauth1.session.Session') + def test_kingbird_url_https_bad_insecure(self, mock_keystone_auth_session, log_warning_mock): fd, path = tempfile.mkstemp(suffix='.pem') - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) - try: client.client( kingbird_url=KINGBIRD_HTTPS_URL, username='kingbird', project_name='kingbird', + api_key='password', auth_url=AUTH_HTTP_URL, cacert=path, insecure=True @@ -179,20 +164,20 @@ class BaseClientTests(testtools.TestCase): self.assertTrue(log_warning_mock.called) - @mock.patch('keystoneclient.v3.client.Client') + @mock.patch('keystoneauth1.session.Session') @mock.patch('kingbirdclient.api.httpclient.HTTPClient') - def test_kingbird_profile_enabled(self, mock, keystone_client_mock): - keystone_client_instance = keystone_client_mock.return_value - keystone_client_instance.auth_token = str(uuid.uuid4()) - keystone_client_instance.project_id = str(uuid.uuid4()) - keystone_client_instance.user_id = str(uuid.uuid4()) + def test_kingbird_profile_enabled(self, mock, mock_keystone_auth_session): + keystone_session_instance = mock_keystone_auth_session.return_value + token = keystone_session_instance.get_token.return_value = \ + str(uuid.uuid4()) + project_id = keystone_session_instance.get_project_id.return_value = \ + str(uuid.uuid4()) + user_id = keystone_session_instance.get_user_id.return_value = \ + str(uuid.uuid4()) + keystone_session_instance.get_endpoint.return_value = \ + KINGBIRD_HTTP_URL - expected_args = ( - KINGBIRD_HTTP_URL, - keystone_client_instance.auth_token, - keystone_client_instance.project_id, - keystone_client_instance.user_id - ) + expected_args = (KINGBIRD_HTTP_URL, token, project_id, user_id) expected_kwargs = { 'cacert': None, @@ -203,6 +188,7 @@ class BaseClientTests(testtools.TestCase): username='kingbird', project_name='kingbird', auth_url=AUTH_HTTP_URL, + api_key='password', profile=PROFILER_HMAC_KEY ) @@ -213,3 +199,23 @@ class BaseClientTests(testtools.TestCase): profiler = osprofiler.profiler.get() self.assertEqual(profiler.hmac_key, PROFILER_HMAC_KEY) + + def test_no_api_key(self): + self.assertRaises(RuntimeError, client.client, + kingbird_url=KINGBIRD_HTTP_URL, + username='kingbird', project_name='kingbird', + auth_url=AUTH_HTTP_URL) + + def test_project_name_and_project_id(self): + self.assertRaises(RuntimeError, client.client, + kingbird_url=KINGBIRD_HTTP_URL, + username='kingbird', project_name='kingbird', + project_id=str(uuid.uuid4()), + auth_url=AUTH_HTTP_URL) + + def test_user_name_and_user_id(self): + self.assertRaises(RuntimeError, client.client, + kingbird_url=KINGBIRD_HTTP_URL, + username='kingbird', project_name='kingbird', + user_id=str(uuid.uuid4()), + auth_url=AUTH_HTTP_URL)