Use keystoneauth plugins and session instead of keystoneclient

This removes the usage of keystoneclient in favor of using keystoneauth's
sessions. For this it uses keystone sessions by default for both the
caller and the target.

The default settings for the user and project's domain was removed as well,
since passing these to the generic auth plugins caused a failure. They
should only be set if the user had specified so.

Change-Id: Ia8e461d9e27cf1256c988d49eeef050872d5af12
Co-Authored-By: Sharat Sharma <sharat.sharma@nectechnologies.in>
Co-Authored-By: Thomas Hervé <therve@redhat.com>
Implements-blueprint: mistral-use-keystoneauth
This commit is contained in:
Sharat Sharma 2017-07-31 17:08:55 +05:30
parent 0380c88c4a
commit 55968a9ce4
12 changed files with 253 additions and 166 deletions

View File

@ -31,6 +31,8 @@ source openrc alt_demo alt_demo
export OS_ALT_USERNAME=${OS_USERNAME}
export OS_ALT_TENANT_NAME=${OS_TENANT_NAME}
export OS_ALT_USER_DOMAIN_NAME=${OS_USER_DOMAIN_NAME}
export OS_ALT_PROJECT_DOMAIN__NAME=${OS_PROJECT_DOMAIN_NAME}
export OS_ALT_PASSWORD=${OS_PASSWORD}
# Get admin credentials.
@ -46,10 +48,14 @@ uri = $OS_AUTH_URL
user = $OS_USERNAME
tenant = $OS_TENANT_NAME
pass = $OS_PASSWORD
user_domain = $OS_USER_DOMAIN_NAME
project_domain = $OS_PROJECT_DOMAIN_NAME
[demo]
user = $OS_ALT_USERNAME
tenant = $OS_ALT_TENANT_NAME
pass = $OS_ALT_PASSWORD
user_domain = $OS_ALT_USER_DOMAIN_NAME
project_domain = $OS_ALT_PROJECT_DOMAIN_NAME
EOF
cd $MISTRALCLIENT_DIR

View File

@ -15,6 +15,8 @@
import copy
import json
from keystoneauth1 import exceptions
class Resource(object):
resource_name = 'Something'
@ -89,7 +91,10 @@ class ResourceManager(object):
if dump_json:
data = json.dumps(data)
resp = self.http_client.post(url, data)
try:
resp = self.http_client.post(url, data)
except exceptions.HttpError as ex:
self._raise_api_exception(ex.response)
if resp.status_code != 201:
self._raise_api_exception(resp)
@ -100,7 +105,10 @@ class ResourceManager(object):
if dump_json:
data = json.dumps(data)
resp = self.http_client.put(url, data)
try:
resp = self.http_client.put(url, data)
except exceptions.HttpError as ex:
self._raise_api_exception(ex.response)
if resp.status_code != 200:
self._raise_api_exception(resp)
@ -108,7 +116,10 @@ class ResourceManager(object):
return self.resource_class(self, extract_json(resp, response_key))
def _list(self, url, response_key=None):
resp = self.http_client.get(url)
try:
resp = self.http_client.get(url)
except exceptions.HttpError as ex:
self._raise_api_exception(ex.response)
if resp.status_code != 200:
self._raise_api_exception(resp)
@ -117,7 +128,10 @@ class ResourceManager(object):
for resource_data in extract_json(resp, response_key)]
def _get(self, url, response_key=None):
resp = self.http_client.get(url)
try:
resp = self.http_client.get(url)
except exceptions.HttpError as ex:
self._raise_api_exception(ex.response)
if resp.status_code == 200:
return self.resource_class(self, extract_json(resp, response_key))
@ -125,7 +139,10 @@ class ResourceManager(object):
self._raise_api_exception(resp)
def _delete(self, url):
resp = self.http_client.delete(url)
try:
resp = self.http_client.delete(url)
except exceptions.HttpError as ex:
self._raise_api_exception(ex.response)
if resp.status_code != 204:
self._raise_api_exception(resp)

View File

@ -15,15 +15,16 @@
import base64
import copy
import logging
import os
from oslo_utils import importutils
import requests
import logging
import requests
AUTH_TOKEN = 'auth_token'
SESSION = 'session'
CACERT = 'cacert'
CERT_FILE = 'cert'
CERT_KEY = 'key'
@ -33,6 +34,7 @@ USER_ID = 'user_id'
REGION_NAME = 'region_name'
TARGET_AUTH_TOKEN = 'target_auth_token'
TARGET_SESSION = 'target_session'
TARGET_AUTH_URI = 'target_auth_url'
TARGET_PROJECT_ID = 'target_project_id'
TARGET_USER_ID = 'target_user_id'
@ -59,7 +61,9 @@ def log_request(func):
class HTTPClient(object):
def __init__(self, base_url, **kwargs):
self.base_url = base_url
self.session = kwargs.pop('session', None)
self.session = kwargs.get('session')
if not self.session:
self.session = requests.Session()
self.auth_token = kwargs.get(AUTH_TOKEN)
self.project_id = kwargs.get(PROJECT_ID)
self.user_id = kwargs.get(USER_ID)
@ -68,6 +72,7 @@ class HTTPClient(object):
self.region_name = kwargs.get(REGION_NAME)
self.ssl_options = {}
self.target_session = kwargs.get(TARGET_SESSION)
self.target_auth_token = kwargs.get(TARGET_AUTH_TOKEN)
self.target_auth_uri = kwargs.get(TARGET_AUTH_URI)
self.target_user_id = kwargs.get(TARGET_USER_ID)
@ -80,11 +85,6 @@ class HTTPClient(object):
TARGET_PROJECT_DOMAIN_NAME
)
if self.session:
self.crud_provider = self.session
else:
self.crud_provider = requests
if self.base_url.startswith('https'):
if self.cacert and not os.path.exists(self.cacert):
raise ValueError('Unable to locate cacert file '
@ -94,47 +94,42 @@ class HTTPClient(object):
LOG.warning('Client is set to not verify even though '
'cacert is provided.')
# These are already set by the session, so it's not needed
if not self.session:
if self.insecure:
self.ssl_options['verify'] = False
if self.insecure:
self.ssl_options['verify'] = False
else:
if self.cacert:
self.ssl_options['verify'] = self.cacert
else:
if self.cacert:
self.ssl_options['verify'] = self.cacert
else:
self.ssl_options['verify'] = True
self.ssl_options['verify'] = True
self.ssl_options['cert'] = (
kwargs.get(CERT_FILE),
kwargs.get(CERT_KEY)
)
self.ssl_options['cert'] = (
kwargs.get(CERT_FILE),
kwargs.get(CERT_KEY)
)
@log_request
def get(self, url, headers=None):
options = self._get_request_options('get', headers)
return self.crud_provider.get(self.base_url + url, **options)
return self.session.get(self.base_url + url, **options)
@log_request
def post(self, url, body, headers=None):
options = self._get_request_options('post', headers)
return self.crud_provider.post(self.base_url + url,
data=body, **options)
return self.session.post(self.base_url + url, data=body, **options)
@log_request
def put(self, url, body, headers=None):
options = self._get_request_options('put', headers)
return self.crud_provider.put(self.base_url + url,
data=body, **options)
return self.session.put(self.base_url + url, data=body, **options)
@log_request
def delete(self, url, headers=None):
options = self._get_request_options('delete', headers)
return self.crud_provider.delete(self.base_url + url,
**options)
return self.session.delete(self.base_url + url, **options)
def _get_request_options(self, method, headers):
headers = self._update_headers(headers)
@ -152,9 +147,9 @@ class HTTPClient(object):
if not headers:
headers = {}
if not self.session:
if isinstance(self.session, requests.Session):
if self.auth_token:
headers['x-auth-token'] = self.auth_token
headers['X-Auth-Token'] = self.auth_token
if self.project_id:
headers['X-Project-Id'] = self.project_id

View File

@ -54,6 +54,10 @@ class Client(object):
auth_handler = auth.get_auth_handler(auth_type)
auth_response = auth_handler.authenticate(req, session=session) or {}
# If the session was None and we're using keystone auth, it will be
# created by the auth_handler.
session = auth_response.pop('session', None)
req.update(auth_response)
mistral_url = auth_response.get('mistral_url') or mistral_url

View File

@ -12,14 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from keystoneclient import client
from mistralclient import auth
import logging
import keystoneauth1.identity.generic as auth_plugin
from keystoneauth1 import session as ks_session
import mistralclient.api.httpclient as api
from mistralclient import auth as mistral_auth
from oslo_serialization import jsonutils
import mistralclient.api.httpclient as api
LOG = logging.getLogger(__name__)
class KeystoneAuthHandler(auth.AuthHandler):
class KeystoneAuthHandler(mistral_auth.AuthHandler):
def authenticate(self, req, session=None):
"""Performs authentication via Keystone.
@ -44,8 +49,8 @@ class KeystoneAuthHandler(auth.AuthHandler):
project_name = req.get('project_name')
project_id = req.get('project_id')
region_name = req.get('region_name')
user_domain_name = req.get('user_domain_name', 'Default')
project_domain_name = req.get('project_domain_name', 'Default')
user_domain_name = req.get('user_domain_name')
project_domain_name = req.get('project_domain_name')
cacert = req.get('cacert')
insecure = req.get('insecure', False)
@ -56,12 +61,8 @@ class KeystoneAuthHandler(auth.AuthHandler):
target_auth_token = req.get('target_auth_token')
target_project_name = req.get('target_project_name')
target_project_id = req.get('target_project_id')
target_region_name = req.get('target_region_name')
target_user_domain_name = req.get('target_user_domain_name', 'Default')
target_project_domain_name = req.get(
'target_project_domain_name',
'Default'
)
target_user_domain_name = req.get('target_user_domain_name')
target_project_domain_name = req.get('target_project_domain_name')
target_cacert = req.get('target_cacert')
target_insecure = req.get('target_insecure')
@ -77,33 +78,42 @@ class KeystoneAuthHandler(auth.AuthHandler):
auth_response = {}
if session:
keystone = client.Client(session=session)
elif auth_url:
keystone = client.Client(
username=username,
user_id=user_id,
password=api_key,
token=auth_token,
tenant_id=project_id,
tenant_name=project_name,
auth_url=auth_url,
cacert=cacert,
insecure=insecure,
user_domain_name=user_domain_name,
project_domain_name=project_domain_name
)
keystone.authenticate()
auth_response.update({
api.AUTH_TOKEN: keystone.auth_token,
api.PROJECT_ID: keystone.project_id,
api.USER_ID: keystone.user_id,
})
if not session:
auth = None
if auth_token:
auth = auth_plugin.Token(
auth_url=auth_url,
token=auth_token,
project_id=project_id,
project_name=project_name,
project_domain_name=project_domain_name,
cacert=cacert,
insecure=insecure)
elif api_key and (username or user_id):
auth = auth_plugin.Password(
auth_url=auth_url,
username=username,
user_id=user_id,
password=api_key,
user_domain_name=user_domain_name,
project_id=project_id,
project_name=project_name,
project_domain_name=project_domain_name)
if session or auth_url:
else:
# NOTE(jaosorior): We don't crash here cause it's needed for
# bash-completion to work. However, we do issue a warning to
# the user so if the request doesn't work. It's because of
# this.
LOG.warning("You must either provide a valid token or "
"a password (api_key) and a user.")
if auth:
session = ks_session.Session(auth=auth)
if session:
if not mistral_url:
try:
mistral_url = keystone.service_catalog.url_for(
mistral_url = session.get_endpoint(
service_type=service_type,
endpoint_type=endpoint_type,
region_name=region_name
@ -112,35 +122,48 @@ class KeystoneAuthHandler(auth.AuthHandler):
mistral_url = None
auth_response['mistral_url'] = mistral_url
auth_response['session'] = session
if target_auth_url:
target_keystone = client.Client(
username=target_username,
user_id=target_user_id,
password=target_api_key,
token=target_auth_token,
tenant_id=target_project_id,
tenant_name=target_project_name,
project_id=target_project_id,
project_name=target_project_name,
auth_url=target_auth_url,
cacert=target_cacert,
insecure=target_insecure,
region_name=target_region_name,
user_domain_name=target_user_domain_name,
project_domain_name=target_project_domain_name
)
if target_auth_token:
target_auth = auth_plugin.Token(
auth_url=target_auth_url,
token=target_auth_token,
project_id=target_project_id,
project_name=target_project_name,
project_domain_name=target_project_domain_name,
cacert=target_cacert,
insecure=target_insecure)
elif target_api_key and (target_username or target_user_id):
target_auth = auth_plugin.Password(
auth_url=target_auth_url,
username=target_username,
user_id=target_user_id,
password=target_api_key,
user_domain_name=target_user_domain_name,
project_id=target_project_id,
project_name=target_project_name,
project_domain_name=target_project_domain_name,
)
else:
raise RuntimeError("You must either provide a valid token or "
"a password (target_api_key) and a user.")
target_keystone.authenticate()
target_session = ks_session.Session(auth=target_auth)
target_auth_headers = target_session.get_auth_headers() or {}
# NOTE: (sharatss) The target_auth_token is required here so that
# it can be passed as a separate header later.
target_auth_token = target_auth_headers.get('X-Auth-Token')
auth_response.update({
api.TARGET_AUTH_TOKEN: target_keystone.auth_token,
api.TARGET_PROJECT_ID: target_keystone.project_id,
api.TARGET_USER_ID: target_keystone.user_id,
api.TARGET_AUTH_TOKEN: target_auth_token,
api.TARGET_PROJECT_ID: target_session.get_project_id(),
api.TARGET_USER_ID: target_session.get_user_id(),
api.TARGET_AUTH_URI: target_auth_url,
api.TARGET_SERVICE_CATALOG: jsonutils.dumps(
target_keystone.auth_ref
)
target_auth.get_access(
target_session)._data['access'])
})
return auth_response

View File

@ -285,8 +285,7 @@ class MistralShell(app.App):
'--os-tenant-name',
action='store',
dest='tenant_name',
default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME',
default='Default'),
default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME'),
help='Authentication tenant name (Env: OS_TENANT_NAME'
' or OS_PROJECT_NAME)'
)
@ -295,8 +294,7 @@ class MistralShell(app.App):
'--os-project-name',
action='store',
dest='project_name',
default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME',
default='Default'),
default=env('OS_TENANT_NAME', 'OS_PROJECT_NAME'),
help='Authentication project name (Env: OS_TENANT_NAME'
' or OS_PROJECT_NAME), will use tenant_name if both'
' tenant_name and project_name are set'
@ -314,7 +312,7 @@ class MistralShell(app.App):
'--os-project-domain-name',
action='store',
dest='project_domain_name',
default=env('OS_PROJECT_DOMAIN_NAME', default='Default'),
default=env('OS_PROJECT_DOMAIN_NAME'),
help='Authentication project domain name'
' (Env: OS_PROJECT_DOMAIN_NAME)'
)
@ -323,7 +321,7 @@ class MistralShell(app.App):
'--os-user-domain-name',
action='store',
dest='user_domain_name',
default=env('OS_USER_DOMAIN_NAME', default='Default'),
default=env('OS_USER_DOMAIN_NAME'),
help='Authentication user domain name'
' (Env: OS_USER_DOMAIN_NAME)'
)
@ -435,7 +433,7 @@ class MistralShell(app.App):
'--os-target-tenant-name',
action='store',
dest='target_tenant_name',
default=env('OS_TARGET_TENANT_NAME', 'Default'),
default=env('OS_TARGET_TENANT_NAME'),
help='Authentication tenant name for target cloud'
' (Env: OS_TARGET_TENANT_NAME)'
)

View File

@ -39,10 +39,14 @@ def credentials(group='admin'):
username = os.environ.get('OS_USERNAME')
password = os.environ.get('OS_PASSWORD')
tenant_name = os.environ.get('OS_TENANT_NAME')
user_domain = os.environ.get('OS_USER_DOMAIN_NAME')
project_domain = os.environ.get('OS_PROJECT_DOMAIN_NAME')
else:
username = os.environ.get('OS_ALT_USERNAME')
password = os.environ.get('OS_ALT_PASSWORD')
tenant_name = os.environ.get('OS_ALT_TENANT_NAME')
user_domain = os.environ.get('OS_ALT_USER_DOMAIN_NAME')
project_domain = os.environ.get('OS_ALT_PROJECT_DOMAIN_NAME')
auth_url = os.environ.get('OS_AUTH_URL')
@ -52,6 +56,8 @@ def credentials(group='admin'):
password = password or config.get(group, 'pass')
tenant_name = tenant_name or config.get(group, 'tenant')
auth_url = auth_url or config.get('auth', 'uri')
user_domain = user_domain or config.get(group, 'user_domain')
project_domain = project_domain or config.get(group, 'project_domain')
# TODO(ddeja): Default value of OS_AUTH_URL is to provide url to v3 API.
# Since tempest openstack client doesn't properly handle it, we switch
@ -77,6 +83,7 @@ class MistralCLIAuth(base.ClientTestBase):
username=creds['username'],
password=creds['password'],
tenant_name=creds['tenant_name'],
project_name=creds['tenant_name'],
uri=creds['auth_url'],
cli_dir=CLI_DIR
)
@ -130,6 +137,7 @@ class MistralCLIAltAuth(base.ClientTestBase):
clients = base.CLIClient(
username=creds['username'],
password=creds['password'],
project_name=creds['tenant_name'],
tenant_name=creds['tenant_name'],
uri=creds['auth_url'],
cli_dir=CLI_DIR

View File

@ -192,7 +192,8 @@ class WorkflowSharingCLITests(base_v2.MistralClientTestBase):
self.assertEqual('pending', status)
cmd_param = '%s workflow --status %s' % (self.wf[0]["ID"], new_status)
cmd_param = '%s workflow --status %s --member-id %s' % (
self.wf[0]["ID"], new_status, self.get_project_id("demo"))
member = self.mistral_alt_user("member-update", params=cmd_param)
status = self.get_field_value(member, 'Status')

View File

@ -35,26 +35,26 @@ PROFILER_HMAC_KEY = 'SECRET_HMAC_KEY'
class BaseClientTests(base.BaseTestCase):
@staticmethod
def setup_keystone_mock(keystone_client_mock):
keystone_client_instance = keystone_client_mock.return_value
def setup_keystone_mock(session_mock):
keystone_client_instance = session_mock.return_value
keystone_client_instance.auth_token = uuidutils.generate_uuid()
keystone_client_instance.project_id = uuidutils.generate_uuid()
keystone_client_instance.user_id = uuidutils.generate_uuid()
keystone_client_instance.auth_ref = str(json.dumps({}))
return keystone_client_instance
@mock.patch('keystoneclient.client.Client')
def test_mistral_url_from_catalog_v2(self, keystone_client_mock):
keystone_client_instance = self.setup_keystone_mock(
keystone_client_mock
)
@mock.patch('keystoneauth1.session.Session')
def test_mistral_url_from_catalog_v2(self, session_mock):
session = mock.Mock()
session_mock.side_effect = [session]
url_for = mock.Mock(return_value='http://mistral_host:8989/v2')
keystone_client_instance.service_catalog.url_for = url_for
get_endpoint = mock.Mock(return_value='http://mistral_host:8989/v2')
session.get_endpoint = get_endpoint
mistralclient = client.client(
username='mistral',
project_name='mistral',
api_key='password',
auth_url=AUTH_HTTP_URL_v2_0,
service_type='workflowv2'
)
@ -64,19 +64,20 @@ class BaseClientTests(base.BaseTestCase):
mistralclient.actions.http_client.base_url
)
@mock.patch('keystoneclient.client.Client')
def test_mistral_url_from_catalog(self, keystone_client_mock):
keystone_client_instance = self.setup_keystone_mock(
keystone_client_mock
)
@mock.patch('keystoneauth1.session.Session')
def test_mistral_url_from_catalog(self, session_mock):
session = mock.Mock()
session_mock.side_effect = [session]
url_for = mock.Mock(return_value='http://mistral_host:8989/v2')
keystone_client_instance.service_catalog.url_for = url_for
get_endpoint = mock.Mock(return_value='http://mistral_host:8989/v2')
session.get_endpoint = get_endpoint
mistralclient = client.client(
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
service_type='workflowv2'
)
@ -86,82 +87,97 @@ class BaseClientTests(base.BaseTestCase):
mistralclient.actions.http_client.base_url
)
@mock.patch('keystoneclient.client.Client')
@mock.patch('keystoneauth1.session.Session')
@mock.patch('mistralclient.api.httpclient.HTTPClient')
def test_mistral_url_default(self, http_client_mock, keystone_client_mock):
keystone_client_instance = self.setup_keystone_mock(
keystone_client_mock
)
def test_mistral_url_default(self, http_client_mock, session_mock):
session = mock.Mock()
session_mock.side_effect = [session]
url_for = mock.Mock(side_effect=Exception)
keystone_client_instance.service_catalog.url_for = url_for
get_endpoint = mock.Mock(side_effect=Exception)
session.get_endpoint = get_endpoint
client.client(
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3
)
self.assertTrue(http_client_mock.called)
mistral_url_for_http = http_client_mock.call_args[0][0]
kwargs = http_client_mock.call_args[1]
self.assertEqual(MISTRAL_HTTP_URL, mistral_url_for_http)
self.assertEqual(
keystone_client_instance.auth_token, kwargs['auth_token']
)
self.assertEqual(
keystone_client_instance.project_id, kwargs['project_id']
)
self.assertEqual(
keystone_client_instance.user_id, kwargs['user_id']
)
@mock.patch('keystoneclient.client.Client')
@mock.patch('keystoneauth1.identity.generic.Password')
@mock.patch('keystoneauth1.session.Session')
@mock.patch('mistralclient.api.httpclient.HTTPClient')
def test_target_parameters_processed(
self,
http_client_mock,
keystone_client_mock
session_mock,
password_mock
):
keystone_client_instance = self.setup_keystone_mock(
keystone_client_mock
)
url_for = mock.Mock(return_value='http://mistral_host:8989/v2')
keystone_client_instance.service_catalog.url_for = url_for
session = mock.MagicMock()
target_session = mock.MagicMock()
session_mock.side_effect = [session, target_session]
auth = mock.MagicMock()
password_mock.side_effect = [auth, auth]
get_endpoint = mock.Mock(return_value='http://mistral_host:8989/v2')
session.get_endpoint = get_endpoint
target_session.get_project_id = mock.Mock(return_value='projectid')
target_session.get_user_id = mock.Mock(return_value='userid')
target_session.get_auth_headers = mock.Mock(return_value={
'X-Auth-Token': 'authtoken'
})
mock_access = mock.MagicMock()
mock_catalog = mock.MagicMock()
mock_catalog.catalog = {}
mock_access.service_catalog = mock_catalog
auth.get_access = mock.Mock(return_value=mock_access)
client.client(
username='user',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
target_username='tmistral',
target_project_name='tmistralp',
target_auth_url=AUTH_HTTP_URL_v3,
target_api_key='tpassword',
target_user_domain_name='Default',
target_project_domain_name='Default',
target_region_name='tregion'
)
self.assertTrue(http_client_mock.called)
mistral_url_for_http = http_client_mock.call_args[0][0]
kwargs = http_client_mock.call_args[1]
self.assertEqual(MISTRAL_HTTP_URL, mistral_url_for_http)
self.assertEqual('http://mistral_host:8989/v2', mistral_url_for_http)
expected_values = {
'target_project_id': keystone_client_instance.project_id,
'target_auth_token': keystone_client_instance.auth_token,
'target_user_id': keystone_client_instance.user_id,
'target_project_id': 'projectid',
'target_auth_token': 'authtoken',
'target_user_id': 'userid',
'target_auth_url': AUTH_HTTP_URL_v3,
'target_project_name': 'tmistralp',
'target_username': 'tmistral',
'target_region_name': 'tregion',
'target_service_catalog': '"{}"'
'target_service_catalog': "{}"
}
for key in expected_values:
self.assertEqual(expected_values[key], kwargs[key])
@mock.patch('keystoneclient.client.Client')
@mock.patch('keystoneauth1.session.Session')
@mock.patch('mistralclient.api.httpclient.HTTPClient')
def test_mistral_url_https_insecure(self, http_client_mock,
keystone_client_mock):
def test_mistral_url_https_insecure(self, http_client_mock, session_mock):
keystone_client_instance = self.setup_keystone_mock( # noqa
keystone_client_mock
session_mock
)
expected_args = (
@ -172,6 +188,9 @@ class BaseClientTests(base.BaseTestCase):
mistral_url=MISTRAL_HTTPS_URL,
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
cacert=None,
insecure=True
@ -181,14 +200,13 @@ class BaseClientTests(base.BaseTestCase):
self.assertEqual(http_client_mock.call_args[0], expected_args)
self.assertEqual(http_client_mock.call_args[1]['insecure'], True)
@mock.patch('keystoneclient.client.Client')
@mock.patch('keystoneauth1.session.Session')
@mock.patch('mistralclient.api.httpclient.HTTPClient')
def test_mistral_url_https_secure(self, http_client_mock,
keystone_client_mock):
def test_mistral_url_https_secure(self, http_client_mock, session_mock):
fd, cert_path = tempfile.mkstemp(suffix='.pem')
keystone_client_instance = self.setup_keystone_mock( # noqa
keystone_client_mock
session_mock
)
expected_args = (
@ -200,6 +218,9 @@ class BaseClientTests(base.BaseTestCase):
mistral_url=MISTRAL_HTTPS_URL,
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
cacert=cert_path,
insecure=False
@ -212,10 +233,10 @@ class BaseClientTests(base.BaseTestCase):
self.assertEqual(http_client_mock.call_args[0], expected_args)
self.assertEqual(http_client_mock.call_args[1]['cacert'], cert_path)
@mock.patch('keystoneclient.client.Client')
def test_mistral_url_https_bad_cacert(self, keystone_client_mock):
@mock.patch('keystoneauth1.session.Session')
def test_mistral_url_https_bad_cacert(self, session_mock):
keystone_client_instance = self.setup_keystone_mock( # noqa
keystone_client_mock
session_mock
)
self.assertRaises(
@ -224,19 +245,22 @@ class BaseClientTests(base.BaseTestCase):
mistral_url=MISTRAL_HTTPS_URL,
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
cacert='/path/to/foobar',
insecure=False
)
@mock.patch('logging.Logger.warning')
@mock.patch('keystoneclient.client.Client')
def test_mistral_url_https_bad_insecure(self, keystone_client_mock,
@mock.patch('keystoneauth1.session.Session')
def test_mistral_url_https_bad_insecure(self, session_mock,
log_warning_mock):
fd, path = tempfile.mkstemp(suffix='.pem')
keystone_client_instance = self.setup_keystone_mock(
keystone_client_mock
session_mock
)
try:
@ -244,6 +268,9 @@ class BaseClientTests(base.BaseTestCase):
mistral_url=MISTRAL_HTTPS_URL,
user_id=keystone_client_instance.user_id,
project_id=keystone_client_instance.project_id,
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
cacert=path,
insecure=True
@ -254,17 +281,19 @@ class BaseClientTests(base.BaseTestCase):
self.assertTrue(log_warning_mock.called)
@mock.patch('keystoneclient.client.Client')
@mock.patch('keystoneauth1.session.Session')
@mock.patch('mistralclient.api.httpclient.HTTPClient')
def test_mistral_profile_enabled(self, http_client_mock,
keystone_client_mock):
def test_mistral_profile_enabled(self, http_client_mock, session_mock):
keystone_client_instance = self.setup_keystone_mock( # noqa
keystone_client_mock
session_mock
)
client.client(
username='mistral',
project_name='mistral',
api_key='password',
user_domain_name='Default',
project_domain_name='Default',
auth_url=AUTH_HTTP_URL_v3,
profile=PROFILER_HMAC_KEY
)

View File

@ -38,7 +38,7 @@ PROFILER_HMAC_KEY = 'SECRET_HMAC_KEY'
PROFILER_TRACE_ID = uuidutils.generate_uuid()
EXPECTED_AUTH_HEADERS = {
'x-auth-token': AUTH_TOKEN,
'X-Auth-Token': AUTH_TOKEN,
'X-Project-Id': PROJECT_ID,
'X-User-Id': USER_ID,
'X-Region-Name': REGION_NAME

View File

@ -0,0 +1,6 @@
---
other:
- The dependency to python-keystoneclient was removed. Relying solely on
keystoneauth1.
- The user has to set the "OS_USER_DOMAIN_NAME" and "OS_PROJECT_DOMAIN_NAME"
explicitly if keystone v3 version is being used.

View File

@ -6,7 +6,7 @@ osc-lib>=1.7.0 # Apache-2.0
oslo.utils>=3.20.0 # Apache-2.0
oslo.i18n!=3.15.2,>=2.1.0 # Apache-2.0
pbr!=2.1.0,>=2.0.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
keystoneauth1>=3.1.0 # Apache-2.0
PyYAML>=3.10.0 # MIT
requests>=2.14.2 # Apache-2.0
six>=1.9.0 # MIT