Merge "Adding keystoneauth sessions support"
This commit is contained in:
		@@ -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',
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user