Made keystone authentication optional

You need to supply auth_url to authenticate using Keystone. Otherwise,
auth_token, user_id, project_id and mistral_url provided will be
directly transmitted to HTTPClient.

Also:
 * renamed input_auth_token as auth_token
 * optimized few checks
 * added checks to prevent header update when not needed
 * simplified API test setUp

Change-Id: I1b34282956d21a1809ec37b0368fbb68aa113bea
Implements: blueprint mistral-optional-keystone-authentication
This commit is contained in:
Kirill Izotov 2014-02-28 15:45:40 +07:00
parent aca36f75b2
commit df55840009
4 changed files with 59 additions and 48 deletions

View File

@ -29,19 +29,23 @@ class Client(object):
def __init__(self, mistral_url=None, username=None, api_key=None,
project_name=None, auth_url=None, project_id=None,
endpoint_type='publicURL', service_type='workflow',
input_auth_token=None):
auth_token=None, user_id=None):
(mistral_url,
token,
project_id,
user_id) = self.authenticate(mistral_url, username,
api_key, project_name,
auth_url, project_id,
endpoint_type, service_type,
input_auth_token)
if mistral_url and not isinstance(mistral_url, six.string_types):
raise RuntimeError('Mistral url should be string')
if auth_url:
(mistral_url, auth_token, project_id, user_id) = \
self.authenticate(mistral_url, username, api_key,
project_name, auth_url, project_id,
endpoint_type, service_type, auth_token,
user_id)
if not mistral_url:
mistral_url = "http://localhost:8989/v1"
self.http_client = httpclient.HTTPClient(mistral_url,
token,
auth_token,
project_id,
user_id)
# Create all resource managers.
@ -53,34 +57,42 @@ class Client(object):
def authenticate(self, mistral_url=None, username=None, api_key=None,
project_name=None, auth_url=None, project_id=None,
endpoint_type='publicURL', service_type='workflow',
input_auth_token=None):
if mistral_url and not isinstance(mistral_url, six.string_types):
raise RuntimeError('Mistral url should be string')
if ((isinstance(project_name, six.string_types) and project_name) or
(isinstance(project_id, six.string_types) and project_id)):
if project_name and project_id:
raise RuntimeError('Only project name or '
'project id should be set')
auth_token=None, user_id=None):
if "v2.0" in auth_url:
raise RuntimeError('Mistral supports only v3 '
'keystone API.')
if (not (project_name or project_id) or
not (isinstance(project_name, six.string_types) or
isinstance(project_id, six.string_types))):
raise RuntimeError('Either project name or project id should'
' be non-empty string')
if project_name and project_id:
raise RuntimeError('Only project name or '
'project id should be set')
keystone = keystone_client.Client(username=username,
password=api_key,
token=input_auth_token,
tenant_id=project_id,
tenant_name=project_name,
auth_url=auth_url)
if (not (username or user_id) or
not (isinstance(username, six.string_types) or
isinstance(user_id, six.string_types))):
raise RuntimeError('Either user name or user id should'
' be non-empty string')
if username and user_id:
raise RuntimeError('Only user name or user id'
' should be set')
keystone.authenticate()
token = keystone.auth_token
user_id = keystone.user_id
if project_name and not project_id:
project_id = keystone.project_id
else:
raise RuntimeError('Project name or project id should'
' not be empty and should be non-empty string')
if "v2.0" in auth_url:
raise RuntimeError('Mistral supports only v3 '
'keystone API.')
keystone = keystone_client.Client(username=username,
user_id=user_id,
password=api_key,
token=auth_token,
project_id=project_id,
project_name=project_name,
auth_url=auth_url)
keystone.authenticate()
token = keystone.auth_token
user_id = keystone.user_id
project_id = keystone.project_id
if not mistral_url:
catalog = keystone.service_catalog.get_endpoints(service_type)
@ -90,7 +102,4 @@ class Client(object):
mistral_url = endpoint
break
if not mistral_url:
mistral_url = "http://localhost:8989/v1"
return mistral_url, token, project_id, user_id

View File

@ -18,7 +18,7 @@ import requests
class HTTPClient(object):
def __init__(self, base_url, token, project_id, user_id):
def __init__(self, base_url, token=None, project_id=None, user_id=None):
self.base_url = base_url
self.token = token
self.project_id = project_id
@ -51,12 +51,17 @@ class HTTPClient(object):
def _update_headers(self, headers):
if not headers:
headers = {}
token = headers.get('x-auth-token', self.token)
headers['x-auth-token'] = token
if token:
headers['x-auth-token'] = token
project_id = headers.get('X-Project-Id', self.project_id)
headers['X-Project-Id'] = project_id
if project_id:
headers['X-Project-Id'] = project_id
user_id = headers.get('X-User-Id', self.user_id)
headers['X-User-Id'] = user_id
if user_id:
headers['X-User-Id'] = user_id
return headers

View File

@ -176,7 +176,7 @@ class MistralShell(App):
'--os-auth-url',
action='store',
dest='auth_url',
default=env('OS_AUTH_URL', default='http://localhost:5000/v3'),
default=env('OS_AUTH_URL'),
help='Authentication URL (Env: OS_AUTH_URL)'
)
return parser
@ -190,7 +190,7 @@ class MistralShell(App):
project_id=self.options.tenant_id,
endpoint_type='publicURL',
service_type='workflow',
input_auth_token=self.options.token)
auth_token=self.options.token)
def main(argv=sys.argv[1:]):

View File

@ -33,11 +33,8 @@ class FakeResponse(object):
class BaseClientTest(unittest2.TestCase):
@mock.patch('keystoneclient.v3.client.Client')
def setUp(self, keystone):
keystone.return_value = mock.Mock()
def setUp(self):
self._client = client.Client(project_name="test",
auth_url="v3.0",
mistral_url="test")
self.workbooks = self._client.workbooks
self.executions = self._client.executions