Handle missing plugin in is_service_available

When a client is not installed, Heat should behave as if the service was
unavailable. We recently started exposing exceptions when checking for
service availability, which displayed that it fails if the client plugin
returs None. Let's test and handle that case.

Change-Id: I71d5fd5be2efd7734d8569e4d26ab1b512453343
Closes-Bug: #1543759
This commit is contained in:
Thomas Herve 2016-02-09 21:35:19 +01:00
parent 278e7a67be
commit 76f99a9036
5 changed files with 40 additions and 1 deletions

View File

@ -240,6 +240,10 @@ class ResourceNotAvailable(HeatException):
msg_fmt = _("The Resource (%(resource_name)s) is not available.")
class ClientNotAvailable(HeatException):
msg_fmt = _("The client (%(client_name)s) is not available.")
class WatchRuleNotFound(EntityNotFound):
"""Keep this for AWS compatiblility."""
msg_fmt = _("The Watch Rule (%(watch_name)s) could not be found.")

View File

@ -526,7 +526,10 @@ class ResourceRegistry(object):
if cnxt is None:
return True
return cls.get_class().is_service_available(cnxt)
try:
return cls.get_class().is_service_available(cnxt)
except Exception:
return False
def not_hidden_matches(cls):
return cls.get_class().support_status.status != support.HIDDEN

View File

@ -571,6 +571,10 @@ class Resource(object):
client_plugin = clients.Clients(context).client_plugin(
cls.default_client_name)
if not client_plugin:
raise exception.ClientNotAvailable(
client_name=cls.default_client_name)
service_types = client_plugin.service_types
if not service_types:
return True

View File

@ -28,6 +28,7 @@ from heat.engine.resources.openstack.nova import server
from heat.engine import support
from heat.tests import common
from heat.tests import generic_resource
from heat.tests import utils
cfg.CONF.import_opt('environment_dir', 'heat.common.config')
@ -826,6 +827,15 @@ class ResourceRegistryTest(common.HeatTestCase):
self.assertIn('ResourceTypeUnSupportedLiberty', types)
self.assertIn('GenericResourceType', types)
def test_list_type_with_is_available_exception(self):
registry = resources.global_env().registry
self.patchobject(
generic_resource.GenericResource,
'is_service_available',
side_effect=exception.ClientNotAvailable(client_name='generic'))
types = registry.get_types(utils.dummy_context())
self.assertNotIn('GenericResourceType', types)
def test_list_type_with_invalid_type_name(self):
registry = resources.global_env().registry
types = registry.get_types(type_name="r'[^\+]'")

View File

@ -3115,6 +3115,24 @@ class ResourceAvailabilityTest(common.HeatTestCase):
service_name=(generic_rsrc.ResourceWithDefaultClientName
.default_client_name))
@mock.patch.object(clients.OpenStackClients, 'client_plugin')
def test_service_not_installed_required_extension(
self,
mock_client_plugin_method):
"""Test availability of resource when the client is not installed.
When the client is not installed, we can't create the resource properly
so raise a proper exception for information.
"""
mock_client_plugin_method.return_value = None
self.assertRaises(
exception.ClientNotAvailable,
generic_rsrc.ResourceWithDefaultClientNameExt.is_service_available,
context=mock.Mock())
mock_client_plugin_method.assert_called_once_with(
generic_rsrc.ResourceWithDefaultClientName.default_client_name)
def test_service_not_available_returns_false(self):
"""Test when the service is not in service catalog.