-
-
Save BenjamenMeyer/1a0712c10fc6beb01a84 to your computer and use it in GitHub Desktop.
import base64 | |
import binascii | |
import simplejson as json | |
import redis | |
from keystoneclient.v2_0 import client as keystonev2_client | |
import keystone.exceptions | |
import keystoneclient.access as keystone_access | |
LOG = logging.getLogger(__name__) | |
def _send_data_to_cache(redis_client, url, access_info): | |
"""Stores the authentication data to memcache | |
:param redis_client: redis.Redis object connected to the redis cache | |
:param url: URL used for authentication | |
:param access_info: keystoneclient.access.AccessInfo containing | |
the auth data | |
:returns: True on success, otherwise False | |
""" | |
try: | |
# Convert the access_info dictionary into a string for storage | |
data = {} | |
data.update(access_info) | |
cache_data = json.dumps(data) | |
cache_data_utf8 = cache_data.encode(encoding='utf-8', errors='strict') | |
cache_data_b64 = base64.b64encode(cache_data_utf8) | |
tenant = access_info.tenant_id | |
token = access_info.auth_token | |
# Guild the cache key and store the value | |
# Use the token's expiration time for the cache expiration | |
cache_key = _tuple_to_cache_key((tenant, token, url)) | |
redis_client.set(cache_key, cache_data) | |
redis_client.pexpire(cache_key, access_info.expires) | |
return True | |
except Exception as ex: | |
msg = _('Failed to cache the data - Exception: %(s_except)s') % { | |
's_except': ex, | |
} | |
LOG.error(msg) | |
return False | |
def _retrieve_data_from_keystone(redis_client, url, tenant, token): | |
"""Retrieve the authentication data from OpenStack Keystone | |
:param redis_client: redis.Redis object connected to the redis cache | |
:param url: Keystone Identity URL to authenticate against | |
:param tenant: tenant id of user data to retrieve | |
:param token: auth_token for the tenant_id | |
:returns: a keystoneclient.access.AccessInfo on success or None on error | |
""" | |
try: | |
keystone = keystonev2_client.Client(tenant_id=tenant, token=token, auth_url=url) | |
except Exception as ex: | |
msg = _('Failed to retrieve Keystone client - %(s_except)s') % { | |
's_except': ex | |
} | |
LOG.debug(msg) | |
return None | |
# Now try to authenticate the user and get the user information using | |
# only the data provided, no special administrative tokens required | |
try: | |
access_info = keystone.get_raw_token_from_identity_service( | |
auth_url=url, tenant_id=tenant, token=token) | |
# cache the data so it is easier to access next time | |
_send_data_to_cache(redis_client, url, access_info) | |
return access_info | |
except keystoneclient.exceptions.AuthorizationFailure as ex: | |
# Provided data was invalid | |
msg = _('Failed to authenticate against %(s_url) - %(s_except)s') % { | |
's_url' : auth_url, | |
's_except' : ex | |
} | |
LOG.debug( msg ) | |
return None |
from __future__ import division | |
from wsgiref import simple_server | |
import fakeredis | |
import mock | |
import base64 | |
import binascii | |
import simplejson as json | |
import keystoneclient.exceptions | |
from keystoneclient.access import AccessInfoV2 | |
from eom import auth | |
import tests | |
from . import util | |
from .mocks import servicecatalog | |
def fakeredis_connection(): | |
return fakeredis.FakeRedis() | |
def run_server(app, host, port): | |
httpd = simple_server.make_server(host, port, app) | |
httpd.serve_forever() | |
class TestAuth(tests.util.TestCase): | |
def setUp(self): | |
super(TestAuth, self).setUp() | |
redis_client = fakeredis_connection() | |
self.auth = auth.wrap(tests.util.app, redis_client) | |
self.test_url = '/v2/vault' | |
#config = auth.CONF['eom:auth'] | |
#self.runtime_url = config['auth_url'] | |
#config['auth_url'] = 'localhost/v2' | |
def tearDown(self): | |
super(TestAuth, self).tearDown() | |
redis_client = fakeredis_connection() | |
redis_client.flushall() | |
#config = auth.CONF['eom:auth'] | |
#config['auth_url'] = self.runtime_url | |
def test_retrieve_keystone_stone(self): | |
url = 'myurl' | |
tenant_id = '789012345' | |
token = 'abcdefABCDEF' | |
redis_client = fakeredis_connection() | |
with mock.patch( | |
'keystoneclient.v2_0.client.Client', autospec=True) as MockKeystoneClient: | |
MockKeystoneClient.side_effect = Exception('Mock - invalid client object') | |
keystone_create_error = auth._retrieve_data_from_keystone(redis_client, url, tenant_id, token) | |
self.assertIsNone(keystone_create_error) | |
with mock.patch( | |
'keystoneclient.v2_0.client.Client', autospec=True) as MockKeystoneClient: | |
reload(keystoneclient) | |
# Fail to get a valid Client object | |
# Note: Client() uses the requests package to do an auth; | |
# on failure it is the requests module that fails. | |
MockKeystoneClient.get_raw_token_from_identity_service = mock.Mock(side_effect = \ | |
keystoneclient.exceptions.AuthorizationFailure('mock Keystone error')) | |
keystone_error = auth._retrieve_data_from_keystone(redis_client, url, tenant_id, token) | |
self.assertIsNone(keystone_error) | |
# Note: This fails because the side effect on get_raw_token_from_identity_service is not happening. Why??? |
(Note: I can provide more of the code if required)
Here's the run:
(py27)bmeyer@ben-linux-ubuntu:~/rackspace/envs/eom$ nosetests tests.test_auth
tests.test_auth.TestAuth.test_cache_key ... ok
tests.test_auth.TestAuth.test_retrieve_cache_data ... ok
tests.test_auth.TestAuth.test_retrieve_keystone_stone ... FAIL
tests.test_auth.TestAuth.test_store_data_to_cache ... ok
FAIL: tests.test_auth.TestAuth.test_retrieve_keystone_stone
_StringException: Traceback (most recent call last):
File "/home/bmeyer/rackspace/envs/eom/tests/test_auth.py", line 231, in test_retrieve_keystone_stone
self.assertIsNone(keystone_error)
File "/home/bmeyer/rackspace/envs/eom/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py", line 353, in assertIsNone
self.assertThat(observed, matcher, message)
File "/home/bmeyer/rackspace/envs/eom/.tox/py27/local/lib/python2.7/site-packages/testtools/testcase.py", line 423, in assertThat
raise mismatch_error
MismatchError: is not:
reference = None
actual =
-------------------- >> begin captured logging << --------------------
eom.auth: DEBUG: Failed to retrieve Keystone client - Mock - invalid client object
eom.auth: ERROR: Failed to cache the data - Exception: sequence item 0: expected string, MagicMock found
--------------------- >> end captured logging << ---------------------
Note: the eom.auth.ERROR is generated by line 43 in implementation.py because the parameter access_info in line 77 is a mock object due to the exception not happening
Lines 55-59 pass.
Lines 61-73 fail due to a mocking issue. I am trying to figure out why it is not raising the Exception like it should. I've tried a number of methods, including a new mock.patch on the function, or setting the function to a function that simply raises the exception without any luck.
What am I doing wrong?