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:
parent
0380c88c4a
commit
55968a9ce4
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)'
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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')
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user