Merge "Retrieve service catalog when it is missing"
This commit is contained in:
commit
1cbd7db09e
@ -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.
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user