Merge "Retrieve service catalog when it is missing"

This commit is contained in:
Jenkins 2015-03-15 22:12:58 +00:00 committed by Gerrit Code Review
commit 1cbd7db09e
2 changed files with 68 additions and 2 deletions

View File

@ -13,11 +13,17 @@
import abc
from keystoneclient import auth
from keystoneclient.auth.identity import v2
from keystoneclient.auth.identity import v3
from keystoneclient import exceptions
from keystoneclient import session
from oslo_config import cfg
import six
from heat.common import context
from heat.common.i18n import _
@six.add_metaclass(abc.ABCMeta)
class ClientPlugin(object):
@ -66,6 +72,10 @@ class ClientPlugin(object):
return self.context.auth_plugin.get_token(self._keystone_session)
def url_for(self, **kwargs):
def get_endpoint():
auth_plugin = self.context.auth_plugin
return auth_plugin.get_endpoint(self._keystone_session, **kwargs)
# NOTE(jamielennox): use the session defined by the keystoneclient
# options as traditionally the token was always retrieved from
# keystoneclient.
@ -77,8 +87,37 @@ class ClientPlugin(object):
reg = self.context.region_name or cfg.CONF.region_name_for_services
kwargs.setdefault('region_name', reg)
url = self.context.auth_plugin.get_endpoint(self._keystone_session,
**kwargs)
try:
url = get_endpoint()
except exceptions.EmptyCatalog:
kc = self.clients.client('keystone').client
auth_plugin = self.context.auth_plugin
endpoint = auth_plugin.get_endpoint(None,
interface=auth.AUTH_INTERFACE)
token = auth_plugin.get_token(None)
project_id = auth_plugin.get_project_id(None)
if kc.version == 'v3':
token_obj = v3.Token(endpoint, token, project_id=project_id)
catalog_key = 'catalog'
access_key = 'token'
elif kc.version == 'v2.0':
endpoint = endpoint.replace('v3', 'v2.0')
token_obj = v2.Token(endpoint, token, tenant_id=project_id)
catalog_key = 'serviceCatalog'
access_key = 'access'
else:
raise exceptions.Error(_("Unknown Keystone version"))
auth_ref = token_obj.get_auth_ref(self._keystone_session)
if catalog_key in auth_ref:
cxt = self.context.to_dict()
access_info = cxt['auth_token_info'][access_key]
access_info[catalog_key] = auth_ref[catalog_key]
self.context = context.RequestContext.from_dict(cxt)
url = get_endpoint()
# NOTE(jamielennox): raising exception maintains compatibility with
# older keystoneclient service catalog searching.

View File

@ -17,6 +17,7 @@ from cinderclient import exceptions as cinder_exc
from glanceclient import exc as glance_exc
from heatclient import client as heatclient
from heatclient import exc as heat_exc
from keystoneclient.auth.identity import v3
from keystoneclient import exceptions as keystone_exc
import mock
from neutronclient.common import exceptions as neutron_exc
@ -27,6 +28,7 @@ from swiftclient import exceptions as swift_exc
from testtools import testcase
from troveclient import client as troveclient
from heat.common import context
from heat.common import exception
from heat.engine import clients
from heat.engine.clients import client_plugin
@ -195,6 +197,31 @@ class ClientPluginTest(common.HeatTestCase):
plugin.url_for(service_type='foo'))
con.auth_plugin.get_endpoint.assert_called()
@mock.patch.object(context, "RequestContext")
@mock.patch.object(v3, "Token", name="v3_token")
def test_get_missing_service_catalog(self, mock_v3, mkreqctx):
con = mock.Mock(auth_token="1234", trust_id=None)
c = clients.Clients(con)
con.clients = c
con.auth_plugin = mock.Mock(name="auth_plugin")
get_endpoint_side_effects = [
keystone_exc.EmptyCatalog(), None, 'http://192.0.2.1/bar']
con.auth_plugin.get_endpoint = mock.Mock(
name="get_endpoint", side_effect=get_endpoint_side_effects)
mock_token_obj = mock.Mock()
mock_token_obj.get_auth_ref.return_value = {'catalog': 'foo'}
mock_v3.return_value = mock_token_obj
plugin = FooClientsPlugin(con)
mock_cxt_dict = {'auth_token_info': {'token': {'catalog': 'baz'}}}
plugin.context.to_dict.return_value = mock_cxt_dict
mkreqctx.from_dict.return_value.auth_plugin = con.auth_plugin
self.assertEqual('http://192.0.2.1/bar',
plugin.url_for(service_type='bar'))
def test_abstract_create(self):
con = mock.Mock()
c = clients.Clients(con)