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 just a subset of those that can be used to successfully authenticate. These
are the most common and recommended combinations. 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 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 use of this network path causes no bandwidth charges but requires the
client to be running on Rackspace's ServiceNet network. client to be running on Rackspace's ServiceNet network.
""" """
session = kwargs.get('session', None)
auth_version = kwargs.get('auth_version', '1') auth_version = kwargs.get('auth_version', '1')
os_options = kwargs.get('os_options', {}) os_options = kwargs.get('os_options', {})
@ -624,7 +625,14 @@ def get_auth(auth_url, user, key, **kwargs):
cert = kwargs.get('cert') cert = kwargs.get('cert')
cert_key = kwargs.get('cert_key') cert_key = kwargs.get('cert_key')
timeout = kwargs.get('timeout', None) 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, storage_url, token = get_auth_1_0(auth_url,
user, user,
key, key,
@ -661,8 +669,8 @@ def get_auth(auth_url, user, key, **kwargs):
timeout=timeout, timeout=timeout,
auth_version=auth_version) auth_version=auth_version)
else: else:
raise ClientException('Unknown auth_version %s specified.' raise ClientException('Unknown auth_version %s specified and no '
% auth_version) 'session found.' % auth_version)
# Override storage url, if necessary # Override storage url, if necessary
if os_options.get('object_storage_url'): if os_options.get('object_storage_url'):
@ -1498,7 +1506,7 @@ class Connection(object):
os_options=None, auth_version="1", cacert=None, os_options=None, auth_version="1", cacert=None,
insecure=False, cert=None, cert_key=None, insecure=False, cert=None, cert_key=None,
ssl_compression=True, retry_on_ratelimit=False, ssl_compression=True, retry_on_ratelimit=False,
timeout=None): timeout=None, session=None):
""" """
:param authurl: authentication URL :param authurl: authentication URL
:param user: user name to authenticate as :param user: user name to authenticate as
@ -1533,7 +1541,9 @@ class Connection(object):
this parameter to True will cause a retry this parameter to True will cause a retry
after a backoff. after a backoff.
:param timeout: The connect timeout for the HTTP connection. :param timeout: The connect timeout for the HTTP connection.
:param session: A keystoneauth session object.
""" """
self.session = session
self.authurl = authurl self.authurl = authurl
self.user = user self.user = user
self.key = key self.key = key
@ -1577,7 +1587,7 @@ class Connection(object):
def get_auth(self): def get_auth(self):
self.url, self.token = get_auth(self.authurl, self.user, self.key, 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, auth_version=self.auth_version,
os_options=self.os_options, os_options=self.os_options,
cacert=self.cacert, cacert=self.cacert,
@ -1596,8 +1606,8 @@ class Connection(object):
None) None)
service_user = opts.get('service_username', None) service_user = opts.get('service_username', None)
service_key = opts.get('service_key', None) service_key = opts.get('service_key', None)
return get_auth(self.authurl, service_user, return get_auth(self.authurl, service_user, service_key,
service_key, session=self.session,
snet=self.snet, snet=self.snet,
auth_version=self.auth_version, auth_version=self.auth_version,
os_options=service_options, os_options=service_options,
@ -1658,10 +1668,15 @@ class Connection(object):
except ClientException as err: except ClientException as err:
self._add_response_dict(caller_response_dict, kwargs) self._add_response_dict(caller_response_dict, kwargs)
if err.http_status == 401: 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 self.url = self.token = self.service_token = None
if retried_auth or not all((self.authurl,
self.user, if retried_auth or not should_retry:
self.key)):
logger.exception(err) logger.exception(err)
raise raise
retried_auth = True retried_auth = True

@ -573,6 +573,15 @@ class TestGetAuth(MockHttpTest):
self.assertTrue(url.startswith("http")) self.assertTrue(url.startswith("http"))
self.assertTrue(token) 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): class TestGetAccount(MockHttpTest):
@ -2028,6 +2037,39 @@ class TestConnection(MockHttpTest):
('HEAD', '/v1/AUTH_test', '', {'x-auth-token': 'token'}), ('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): def test_preauth_token_with_no_storage_url_requires_auth(self):
conn = c.Connection( conn = c.Connection(
'http://auth.example.com', 'user', 'password', 'http://auth.example.com', 'user', 'password',