Merge "Adding keystoneauth sessions support"

This commit is contained in:
Jenkins 2016-10-26 11:41:21 +00:00 committed by Gerrit Code Review
commit e9887703d0
3 changed files with 89 additions and 10 deletions
doc/source
swiftclient
tests/unit

@ -18,6 +18,28 @@ version are detailed below, but are
just a subset of those that can be used to successfully authenticate. These
are the most common and recommended combinations.
Keystone Session
~~~~~~~~~~~~~~~~
.. code-block:: python
from keystoneauth1 import session
from keystoneauth1 import v3
# Create a password auth plugin
auth = v3.Password(auth_url='http://127.0.0.1:5000/v3/',
username='tester',
password='testing',
user_domain_name='Default',
project_name='Default',
project_domain_name='Default')
# Create session
session = session.Session(auth=auth)
# Create swiftclient Connection
swift_conn = Connection(session=session)
Keystone v3
~~~~~~~~~~~

@ -616,6 +616,7 @@ def get_auth(auth_url, user, key, **kwargs):
use of this network path causes no bandwidth charges but requires the
client to be running on Rackspace's ServiceNet network.
"""
session = kwargs.get('session', None)
auth_version = kwargs.get('auth_version', '1')
os_options = kwargs.get('os_options', {})
@ -624,7 +625,14 @@ def get_auth(auth_url, user, key, **kwargs):
cert = kwargs.get('cert')
cert_key = kwargs.get('cert_key')
timeout = kwargs.get('timeout', None)
if auth_version in AUTH_VERSIONS_V1:
if session:
service_type = os_options.get('service_type', 'object-store')
interface = os_options.get('endpoint_type', 'public')
storage_url = session.get_endpoint(service_type=service_type,
interface=interface)
token = session.get_token()
elif auth_version in AUTH_VERSIONS_V1:
storage_url, token = get_auth_1_0(auth_url,
user,
key,
@ -661,8 +669,8 @@ def get_auth(auth_url, user, key, **kwargs):
timeout=timeout,
auth_version=auth_version)
else:
raise ClientException('Unknown auth_version %s specified.'
% auth_version)
raise ClientException('Unknown auth_version %s specified and no '
'session found.' % auth_version)
# Override storage url, if necessary
if os_options.get('object_storage_url'):
@ -1498,7 +1506,7 @@ class Connection(object):
os_options=None, auth_version="1", cacert=None,
insecure=False, cert=None, cert_key=None,
ssl_compression=True, retry_on_ratelimit=False,
timeout=None):
timeout=None, session=None):
"""
:param authurl: authentication URL
:param user: user name to authenticate as
@ -1533,7 +1541,9 @@ class Connection(object):
this parameter to True will cause a retry
after a backoff.
:param timeout: The connect timeout for the HTTP connection.
:param session: A keystoneauth session object.
"""
self.session = session
self.authurl = authurl
self.user = user
self.key = key
@ -1577,7 +1587,7 @@ class Connection(object):
def get_auth(self):
self.url, self.token = get_auth(self.authurl, self.user, self.key,
snet=self.snet,
session=self.session, snet=self.snet,
auth_version=self.auth_version,
os_options=self.os_options,
cacert=self.cacert,
@ -1596,8 +1606,8 @@ class Connection(object):
None)
service_user = opts.get('service_username', None)
service_key = opts.get('service_key', None)
return get_auth(self.authurl, service_user,
service_key,
return get_auth(self.authurl, service_user, service_key,
session=self.session,
snet=self.snet,
auth_version=self.auth_version,
os_options=service_options,
@ -1658,10 +1668,15 @@ class Connection(object):
except ClientException as err:
self._add_response_dict(caller_response_dict, kwargs)
if err.http_status == 401:
if self.session:
should_retry = self.session.invalidate()
else:
# Without a proper session, just check for auth creds
should_retry = all((self.authurl, self.user, self.key))
self.url = self.token = self.service_token = None
if retried_auth or not all((self.authurl,
self.user,
self.key)):
if retried_auth or not should_retry:
logger.exception(err)
raise
retried_auth = True

@ -573,6 +573,15 @@ class TestGetAuth(MockHttpTest):
self.assertTrue(url.startswith("http"))
self.assertTrue(token)
def test_auth_with_session(self):
mock_session = mock.MagicMock()
mock_session.get_endpoint.return_value = 'http://storagehost/v1/acct'
mock_session.get_token.return_value = 'token'
url, token = c.get_auth('http://www.test.com', 'asdf', 'asdf',
session=mock_session)
self.assertEqual(url, 'http://storagehost/v1/acct')
self.assertTrue(token)
class TestGetAccount(MockHttpTest):
@ -2028,6 +2037,39 @@ class TestConnection(MockHttpTest):
('HEAD', '/v1/AUTH_test', '', {'x-auth-token': 'token'}),
])
def test_session_no_invalidate(self):
mock_session = mock.MagicMock()
mock_session.get_endpoint.return_value = 'http://storagehost/v1/acct'
mock_session.get_token.return_value = 'expired'
mock_session.invalidate.return_value = False
conn = c.Connection(session=mock_session)
fake_conn = self.fake_http_connection(401)
with mock.patch.multiple('swiftclient.client',
http_connection=fake_conn,
sleep=mock.DEFAULT):
self.assertRaises(c.ClientException, conn.head_account)
self.assertEqual(mock_session.get_token.mock_calls, [mock.call()])
self.assertEqual(mock_session.invalidate.mock_calls, [mock.call()])
def test_session_can_invalidate(self):
mock_session = mock.MagicMock()
mock_session.get_endpoint.return_value = 'http://storagehost/v1/acct'
mock_session.get_token.side_effect = ['expired', 'token']
mock_session.invalidate.return_value = True
conn = c.Connection(session=mock_session)
fake_conn = self.fake_http_connection(401, 200)
with mock.patch.multiple('swiftclient.client',
http_connection=fake_conn,
sleep=mock.DEFAULT):
conn.head_account()
self.assertRequests([
('HEAD', '/v1/acct', '', {'x-auth-token': 'expired'}),
('HEAD', '/v1/acct', '', {'x-auth-token': 'token'}),
])
self.assertEqual(mock_session.get_token.mock_calls, [
mock.call(), mock.call()])
self.assertEqual(mock_session.invalidate.mock_calls, [mock.call()])
def test_preauth_token_with_no_storage_url_requires_auth(self):
conn = c.Connection(
'http://auth.example.com', 'user', 'password',