Merge "Enable client plugin to support dynamic api version"
This commit is contained in:
commit
0105e8f153
|
@ -500,3 +500,7 @@ class SIGHUPInterrupt(HeatException):
|
||||||
|
|
||||||
class NoActionRequired(Exception):
|
class NoActionRequired(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidServiceVersion(HeatException):
|
||||||
|
msg_fmt = _("Invalid service %(service)s version %(version)s")
|
||||||
|
|
|
@ -64,10 +64,13 @@ class OpenStackClients(object):
|
||||||
self._client_plugins[name] = client_plugin
|
self._client_plugins[name] = client_plugin
|
||||||
return client_plugin
|
return client_plugin
|
||||||
|
|
||||||
def client(self, name):
|
def client(self, name, version=None):
|
||||||
client_plugin = self.client_plugin(name)
|
client_plugin = self.client_plugin(name)
|
||||||
if client_plugin:
|
if client_plugin:
|
||||||
return client_plugin.client()
|
if version:
|
||||||
|
return client_plugin.client(version=version)
|
||||||
|
else:
|
||||||
|
return client_plugin.client()
|
||||||
|
|
||||||
if name in self._clients:
|
if name in self._clients:
|
||||||
return self._clients[name]
|
return self._clients[name]
|
||||||
|
|
|
@ -26,6 +26,7 @@ import requests
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from heat.common import config
|
from heat.common import config
|
||||||
|
from heat.common import exception as heat_exception
|
||||||
from heat.common.i18n import _
|
from heat.common.i18n import _
|
||||||
|
|
||||||
cfg.CONF.import_opt('client_retry_limit', 'heat.common.config')
|
cfg.CONF.import_opt('client_retry_limit', 'heat.common.config')
|
||||||
|
@ -99,10 +100,15 @@ class ClientPlugin(object):
|
||||||
# types, so its used in list format
|
# types, so its used in list format
|
||||||
service_types = []
|
service_types = []
|
||||||
|
|
||||||
|
# To make the backward compatibility with existing resource plugins
|
||||||
|
default_version = None
|
||||||
|
|
||||||
|
supported_versions = []
|
||||||
|
|
||||||
def __init__(self, context):
|
def __init__(self, context):
|
||||||
self._context = weakref.ref(context)
|
self._context = weakref.ref(context)
|
||||||
self._clients = weakref.ref(context.clients)
|
self._clients = weakref.ref(context.clients)
|
||||||
self._client = None
|
self.invalidate()
|
||||||
self._keystone_session_obj = None
|
self._keystone_session_obj = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -135,23 +141,38 @@ class ClientPlugin(object):
|
||||||
|
|
||||||
def invalidate(self):
|
def invalidate(self):
|
||||||
"""Invalidate/clear any cached client."""
|
"""Invalidate/clear any cached client."""
|
||||||
self._client = None
|
self._client_instances = {}
|
||||||
|
|
||||||
def client(self):
|
def client(self, version=None):
|
||||||
if not self._client:
|
if not version:
|
||||||
self._client = self._create()
|
version = self.default_version
|
||||||
elif (cfg.CONF.reauthentication_auth_method == 'trusts'
|
|
||||||
|
if version in self._client_instances:
|
||||||
|
if (cfg.CONF.reauthentication_auth_method == 'trusts'
|
||||||
and self.context.auth_plugin.auth_ref.will_expire_soon(
|
and self.context.auth_plugin.auth_ref.will_expire_soon(
|
||||||
cfg.CONF.stale_token_duration)):
|
cfg.CONF.stale_token_duration)):
|
||||||
# If the token is near expiry, force creating a new client,
|
# If the token is near expiry, force creating a new client,
|
||||||
# which will get a new token via another call to auth_token
|
# which will get a new token via another call to auth_token
|
||||||
# We also have to invalidate all other cached clients
|
# We also have to invalidate all other cached clients
|
||||||
self.clients.invalidate_plugins()
|
self.clients.invalidate_plugins()
|
||||||
self._client = self._create()
|
else:
|
||||||
return self._client
|
return self._client_instances[version]
|
||||||
|
|
||||||
|
# Back-ward compatibility
|
||||||
|
if version is None:
|
||||||
|
self._client_instances[version] = self._create()
|
||||||
|
else:
|
||||||
|
if version not in self.supported_versions:
|
||||||
|
raise heat_exception.InvalidServiceVersion(
|
||||||
|
version=version,
|
||||||
|
service=self._get_service_name())
|
||||||
|
|
||||||
|
self._client_instances[version] = self._create(version=version)
|
||||||
|
|
||||||
|
return self._client_instances[version]
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def _create(self):
|
def _create(self, version=None):
|
||||||
"""Return a newly created client."""
|
"""Return a newly created client."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -609,10 +609,10 @@ class Resource(object):
|
||||||
"""
|
"""
|
||||||
return [r.name for r in self.stack.dependencies.required_by(self)]
|
return [r.name for r in self.stack.dependencies.required_by(self)]
|
||||||
|
|
||||||
def client(self, name=None):
|
def client(self, name=None, version=None):
|
||||||
client_name = name or self.default_client_name
|
client_name = name or self.default_client_name
|
||||||
assert client_name, "Must specify client name"
|
assert client_name, "Must specify client name"
|
||||||
return self.stack.clients.client(client_name)
|
return self.stack.clients.client(client_name, version)
|
||||||
|
|
||||||
def client_plugin(self, name=None):
|
def client_plugin(self, name=None):
|
||||||
client_name = name or self.default_client_name
|
client_name = name or self.default_client_name
|
||||||
|
|
|
@ -30,7 +30,7 @@ class BarbicanClientPluginTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.barbican_plugin = c.client_plugin('barbican')
|
self.barbican_plugin = c.client_plugin('barbican')
|
||||||
self.barbican_plugin._client = self.barbican_client
|
self.barbican_plugin.client = lambda: self.barbican_client
|
||||||
|
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
context = utils.dummy_context()
|
context = utils.dummy_context()
|
||||||
|
|
|
@ -31,7 +31,7 @@ class CinderClientPluginTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.cinder_plugin = c.client_plugin('cinder')
|
self.cinder_plugin = c.client_plugin('cinder')
|
||||||
self.cinder_plugin._client = self.cinder_client
|
self.cinder_plugin.client = lambda: self.cinder_client
|
||||||
|
|
||||||
def test_get_volume(self):
|
def test_get_volume(self):
|
||||||
"""Tests the get_volume function."""
|
"""Tests the get_volume function."""
|
||||||
|
|
|
@ -155,7 +155,6 @@ class ClientsTest(common.HeatTestCase):
|
||||||
obj.get_heat_url.return_value = None
|
obj.get_heat_url.return_value = None
|
||||||
obj.url_for = mock.Mock(name="url_for")
|
obj.url_for = mock.Mock(name="url_for")
|
||||||
obj.url_for.return_value = "url_from_keystone"
|
obj.url_for.return_value = "url_from_keystone"
|
||||||
obj._client = None
|
|
||||||
heat = obj.client()
|
heat = obj.client()
|
||||||
heat_cached = obj.client()
|
heat_cached = obj.client()
|
||||||
self.assertEqual(heat, heat_cached)
|
self.assertEqual(heat, heat_cached)
|
||||||
|
@ -414,7 +413,7 @@ class TestClientPluginsInitialise(common.HeatTestCase):
|
||||||
self.assertIsNotNone(plugin)
|
self.assertIsNotNone(plugin)
|
||||||
self.assertEqual(c, plugin.clients)
|
self.assertEqual(c, plugin.clients)
|
||||||
self.assertEqual(con, plugin.context)
|
self.assertEqual(con, plugin.context)
|
||||||
self.assertIsNone(plugin._client)
|
self.assertEqual({}, plugin._client_instances)
|
||||||
self.assertTrue(clients.has_client(plugin_name))
|
self.assertTrue(clients.has_client(plugin_name))
|
||||||
self.assertIsInstance(plugin.service_types, list)
|
self.assertIsInstance(plugin.service_types, list)
|
||||||
self.assertTrue(len(plugin.service_types) >= 1,
|
self.assertTrue(len(plugin.service_types) >= 1,
|
||||||
|
@ -430,7 +429,9 @@ class TestClientPluginsInitialise(common.HeatTestCase):
|
||||||
plugin = c.client_plugin(plugin_name)
|
plugin = c.client_plugin(plugin_name)
|
||||||
self.assertIsNotNone(plugin)
|
self.assertIsNotNone(plugin)
|
||||||
c.invalidate_plugins()
|
c.invalidate_plugins()
|
||||||
self.assertEqual(len(plugin_types), mock_invalidate.call_count)
|
# while client plugin is initialized and while client is invoked
|
||||||
|
# its being invalidated, so the count will be doubled
|
||||||
|
self.assertEqual(len(plugin_types) * 2, mock_invalidate.call_count)
|
||||||
|
|
||||||
|
|
||||||
class TestIsNotFound(common.HeatTestCase):
|
class TestIsNotFound(common.HeatTestCase):
|
||||||
|
|
|
@ -31,7 +31,7 @@ class GlanceUtilsTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.glance_plugin = c.client_plugin('glance')
|
self.glance_plugin = c.client_plugin('glance')
|
||||||
self.glance_plugin._client = self.glance_client
|
self.glance_plugin.client = lambda: self.glance_client
|
||||||
self.my_image = mock.MagicMock()
|
self.my_image = mock.MagicMock()
|
||||||
|
|
||||||
def test_find_image_by_name_or_id(self):
|
def test_find_image_by_name_or_id(self):
|
||||||
|
|
|
@ -43,7 +43,7 @@ class ManilaClientPluginTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.manila_plugin = c.client_plugin('manila')
|
self.manila_plugin = c.client_plugin('manila')
|
||||||
self.manila_plugin._client = self.manila_client
|
self.manila_plugin.client = lambda: self.manila_client
|
||||||
# prepare list of items to test search
|
# prepare list of items to test search
|
||||||
Item = collections.namedtuple('Item', ['id', 'name'])
|
Item = collections.namedtuple('Item', ['id', 'name'])
|
||||||
self.item_list = [
|
self.item_list = [
|
||||||
|
|
|
@ -32,7 +32,7 @@ class NeutronClientPluginTestCase(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.neutron_plugin = c.client_plugin('neutron')
|
self.neutron_plugin = c.client_plugin('neutron')
|
||||||
self.neutron_plugin._client = self.neutron_client
|
self.neutron_plugin.client = lambda: self.neutron_client
|
||||||
|
|
||||||
|
|
||||||
class NeutronClientPluginTest(NeutronClientPluginTestCase):
|
class NeutronClientPluginTest(NeutronClientPluginTestCase):
|
||||||
|
|
|
@ -38,7 +38,7 @@ class NovaClientPluginTestCase(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.nova_plugin = c.client_plugin('nova')
|
self.nova_plugin = c.client_plugin('nova')
|
||||||
self.nova_plugin._client = self.nova_client
|
self.nova_plugin.client = lambda: self.nova_client
|
||||||
|
|
||||||
|
|
||||||
class NovaClientPluginTest(NovaClientPluginTestCase):
|
class NovaClientPluginTest(NovaClientPluginTestCase):
|
||||||
|
@ -628,7 +628,7 @@ class ConsoleUrlsTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.nova_plugin = c.client_plugin('nova')
|
self.nova_plugin = c.client_plugin('nova')
|
||||||
self.nova_plugin._client = self.nova_client
|
self.nova_plugin.client = lambda: self.nova_client
|
||||||
self.server = mock.Mock()
|
self.server = mock.Mock()
|
||||||
self.console_method = getattr(self.server,
|
self.console_method = getattr(self.server,
|
||||||
'get_%s_console' % self.srv_method)
|
'get_%s_console' % self.srv_method)
|
||||||
|
|
|
@ -32,7 +32,7 @@ class SaharaUtilsTest(common.HeatTestCase):
|
||||||
con = utils.dummy_context()
|
con = utils.dummy_context()
|
||||||
c = con.clients
|
c = con.clients
|
||||||
self.sahara_plugin = c.client_plugin('sahara')
|
self.sahara_plugin = c.client_plugin('sahara')
|
||||||
self.sahara_plugin._client = self.sahara_client
|
self.sahara_plugin.client = lambda: self.sahara_client
|
||||||
self.my_image = mock.MagicMock()
|
self.my_image = mock.MagicMock()
|
||||||
self.my_plugin = mock.MagicMock()
|
self.my_plugin = mock.MagicMock()
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class SwiftClientPluginTestCase(common.HeatTestCase):
|
||||||
self.context.tenant_id = "demo"
|
self.context.tenant_id = "demo"
|
||||||
c = self.context.clients
|
c = self.context.clients
|
||||||
self.swift_plugin = c.client_plugin('swift')
|
self.swift_plugin = c.client_plugin('swift')
|
||||||
self.swift_plugin._client = self.swift_client
|
self.swift_plugin.client = lambda: self.swift_client
|
||||||
|
|
||||||
|
|
||||||
class SwiftUtilsTest(SwiftClientPluginTestCase):
|
class SwiftUtilsTest(SwiftClientPluginTestCase):
|
||||||
|
|
Loading…
Reference in New Issue