import os from aioresponses import aioresponses from aiounittest import AsyncTestCase, futurized from asyncopenstackclient import AuthPassword from unittest.mock import MagicMock, patch class TestAuth(AsyncTestCase): def setUp(self): self.auth_args = ('http://url', 'm_user', 'm_pass', 'm_project', 'm_user_domain', 'm_project_domain') self.auth = AuthPassword(*self.auth_args) def tearDown(self): patch.stopall() for name in list(os.environ.keys()): if name.startswith('OS_'): del os.environ[name] async def test_create_object(self): expected_payload_password = {'auth': { 'identity': {'methods': ['password'], 'password': {'user': { 'domain': {'name': 'm_user_domain'}, 'name': 'm_user', 'password': 'm_pass' }}}, 'scope': {'project': {'domain': {'name': 'm_project_domain'}, 'name': 'm_project'}} }} expected_payload_application_credential = {'auth': { 'identity': {'methods': ['application_credential'], 'application_credential': {'id': 'm_app_id', 'secret': 'm_app_secret'}} }} auth_args_application_credentials = ('http://url', None, None, None, None, None, 'm_app_id', 'm_app_secret') auth_application_credentials = AuthPassword(*auth_args_application_credentials) for auth, expected_payload in ((self.auth, expected_payload_password), (auth_application_credentials, expected_payload_application_credential)): self.assertEqual(auth._auth_payload, expected_payload) self.assertEqual(auth._auth_endpoint, 'http://url/auth/tokens') self.assertTrue('Content-Type' in auth.headers) async def test_create_object_use_environ(self): expected_payload_password = {'auth': { 'identity': {'methods': ['password'], 'password': {'user': {'domain': {'name': 'udm'}, 'name': 'uuu', 'password': 'ppp'}}}, 'scope': {'project': {'domain': {'name': 'udm'}, 'name': 'prj'}} }} env_password = { 'OS_AUTH_URL': 'https://keystone/v3', 'OS_PASSWORD': 'ppp', 'OS_USERNAME': 'uuu', 'OS_USER_DOMAIN_NAME': 'udm', 'OS_PROJECT_NAME': 'prj' } expected_payload_application_credentials = {'auth': { 'identity': {'methods': ['application_credential'], 'application_credential': {'id': 'iid', 'secret': 'ssecret' } } }} env_application_credentials = { 'OS_AUTH_URL': 'https://keystone/v3', 'OS_APPLICATION_CREDENTIAL_ID': 'iid', 'OS_APPLICATION_CREDENTIAL_SECRET': 'ssecret', 'OS_USER_DOMAIN_NAME': 'udm', 'OS_PROJECT_NAME': 'prj' } for env, expected_payload in ((env_password, expected_payload_password), (env_application_credentials, expected_payload_application_credentials)): with patch.dict('os.environ', env, clear=True): auth = AuthPassword() self.assertEqual(auth._auth_payload, expected_payload) self.assertEqual(auth._auth_endpoint, 'https://keystone/v3/auth/tokens') self.assertTrue('Content-Type' in auth.headers) async def test_get_token(self): body = { "token": { "catalog": { "endpoints": [ {"name": "mock_endpoint", "endpoints": [{"url": "mock_url", "interface": "public"}]} ] }, "expires_at": "1970-01-01T01:00:00.000000Z" } } headers = { "Vary": "X-Auth-Token", "x-openstack-request-id": "1234", "Content-Type": "application/json", "X-Subject-Token": "gAAAAABao" } with aioresponses() as req: req.post('http://url/auth/tokens', payload=body, headers=headers) res = await self.auth.get_token() self.assertEqual(res, (headers["X-Subject-Token"], 3600, body["token"]["catalog"])) def test_get_endpoint_url_existing_endpoint(self): self.auth.endpoints = [ {"name": "mock_endpoint", "endpoints": [{"url": "mock_url", "interface": "public"}]} ] endpoint_url = self.auth.get_endpoint_url("mock_endpoint") self.assertEqual(endpoint_url, "mock_url") def test_get_endpoint_url_bad_endpoint_name(self): self.auth.endpoints = [ {"name": "mock_endpoint", "endpoints": [{"url": "mock_url", "interface": "public"}]} ] with self.assertRaises(ValueError): self.auth.get_endpoint_url("none_existing_endpoint") def test_get_endpoint_url_bad_interface(self): self.auth.endpoints = [ {"name": "mock_endpoint", "endpoints": [{"url": "mock_url", "interface": "public"}]} ] with self.assertRaises(ValueError): self.auth.get_endpoint_url("mock_endpoint", prefered_interface="not_existing_interface") async def test_authenticate_first_time(self): mock_get_token_results = [ futurized(('mock-token1', 1000, 'whatever')), futurized(('mock-token2', 1000, 'whatever')), ] # time is gonna be called 2 times becouse of Pythons lazy evaluation mock_time_results = [ 900, 1100 ] get_token_mock = patch('asyncopenstackclient.auth.AuthPassword.get_token', new=MagicMock()).start() get_token_mock.side_effect = mock_get_token_results patch('asyncopenstackclient.auth.time', side_effect=mock_time_results).start() # first time token should be None and get_token shall be called await self.auth.authenticate() self.assertEqual(self.auth.token, 'mock-token1') # second time, token is not None and current time is before token expiration, no change await self.auth.authenticate() self.assertEqual(self.auth.token, 'mock-token1') # third time, token expires and should be renewed await self.auth.authenticate() self.assertEqual(self.auth.token, 'mock-token2')