From 87e8b11d0b2bb0faee6e7948ecc434810f9de7bd Mon Sep 17 00:00:00 2001 From: Tetiana Lashchova Date: Fri, 4 Sep 2015 15:53:18 +0300 Subject: [PATCH] Add sahara.plugin custom constraint Change-Id: I042cfd88b07e393c1d6d2e8622a9135cdd485ee5 --- heat/engine/clients/os/sahara.py | 22 ++++++++++ .../openstack/sahara/sahara_cluster.py | 3 ++ .../openstack/sahara/sahara_templates.py | 6 +++ heat/tests/clients/test_sahara_client.py | 41 +++++++++++++++++++ heat/tests/common.py | 5 +++ heat/tests/test_sahara_templates.py | 7 ++-- setup.cfg | 1 + 7 files changed, 82 insertions(+), 3 deletions(-) diff --git a/heat/engine/clients/os/sahara.py b/heat/engine/clients/os/sahara.py index 39c76072d..b1ba173a0 100644 --- a/heat/engine/clients/os/sahara.py +++ b/heat/engine/clients/os/sahara.py @@ -118,6 +118,20 @@ class SaharaClientPlugin(client_plugin.ClientPlugin): else: return image_list[0].id + def get_plugin_id(self, plugin_name): + """Get the id for the specified plugin name. + + :param plugin_name: the name of the plugin to find + :returns: the id of :plugin: + :raises: exception.EntityNotFound + """ + try: + self.client().plugins.get(plugin_name) + except sahara_base.APIException: + LOG.info(_LI("Plugin %s was not found in sahara"), plugin_name) + raise exception.EntityNotFound(entity='Plugin', + name=plugin_name) + class ImageConstraint(constraints.BaseCustomConstraint): @@ -126,3 +140,11 @@ class ImageConstraint(constraints.BaseCustomConstraint): def validate_with_client(self, client, value): client.client_plugin('sahara').get_image_id(value) + + +class PluginConstraint(constraints.BaseCustomConstraint): + + expected_exceptions = (exception.EntityNotFound,) + + def validate_with_client(self, client, value): + client.client_plugin('sahara').get_plugin_id(value) diff --git a/heat/engine/resources/openstack/sahara/sahara_cluster.py b/heat/engine/resources/openstack/sahara/sahara_cluster.py index 20b6c77b2..bbb7fa2e9 100644 --- a/heat/engine/resources/openstack/sahara/sahara_cluster.py +++ b/heat/engine/resources/openstack/sahara/sahara_cluster.py @@ -57,6 +57,9 @@ class SaharaCluster(resource.Resource): properties.Schema.STRING, _('Plugin name.'), required=True, + constraints=[ + constraints.CustomConstraint('sahara.plugin') + ] ), HADOOP_VERSION: properties.Schema( properties.Schema.STRING, diff --git a/heat/engine/resources/openstack/sahara/sahara_templates.py b/heat/engine/resources/openstack/sahara/sahara_templates.py index 2c3390bc2..0cdc1781f 100644 --- a/heat/engine/resources/openstack/sahara/sahara_templates.py +++ b/heat/engine/resources/openstack/sahara/sahara_templates.py @@ -72,6 +72,9 @@ class SaharaNodeGroupTemplate(resource.Resource): properties.Schema.STRING, _('Plugin name.'), required=True, + constraints=[ + constraints.CustomConstraint('sahara.plugin') + ] ), HADOOP_VERSION: properties.Schema( properties.Schema.STRING, @@ -301,6 +304,9 @@ class SaharaClusterTemplate(resource.Resource): properties.Schema.STRING, _('Plugin name.'), required=True, + constraints=[ + constraints.CustomConstraint('sahara.plugin') + ] ), HADOOP_VERSION: properties.Schema( properties.Schema.STRING, diff --git a/heat/tests/clients/test_sahara_client.py b/heat/tests/clients/test_sahara_client.py index c66bddccb..52c13a5d5 100644 --- a/heat/tests/clients/test_sahara_client.py +++ b/heat/tests/clients/test_sahara_client.py @@ -37,6 +37,7 @@ class SaharaUtilsTests(common.HeatTestCase): self.sahara_plugin = c.client_plugin('sahara') self.sahara_plugin._client = self.sahara_client self.my_image = mock.MagicMock() + self.my_plugin = mock.MagicMock() def test_get_image_id(self): """Tests the get_image_id function.""" @@ -114,6 +115,26 @@ class SaharaUtilsTests(common.HeatTestCase): self.sahara_plugin.get_image_id, img_name) self.sahara_client.images.find.assert_called_once_with(name=img_name) + def test_get_plugin_id(self): + """Tests the get_plugin_id function.""" + plugin_name = 'myfakeplugin' + self.my_plugin.name = plugin_name + + def side_effect(name): + if name == plugin_name: + return self.my_plugin + else: + raise sahara_base.APIException(error_code=404, + error_name='NOT_FOUND') + + self.sahara_client.plugins.get.side_effect = side_effect + self.assertEqual(None, self.sahara_plugin.get_plugin_id(plugin_name)) + self.assertRaises(exception.EntityNotFound, + self.sahara_plugin.get_plugin_id, 'noplugin') + + calls = [mock.call(plugin_name), mock.call('noplugin')] + self.sahara_client.plugins.get.assert_has_calls(calls) + class ImageConstraintTest(common.HeatTestCase): @@ -133,3 +154,23 @@ class ImageConstraintTest(common.HeatTestCase): self.mock_get_image.side_effect = exception.EntityNotFound( entity='Image', name='bar') self.assertFalse(self.constraint.validate("bar", self.ctx)) + + +class PluginConstraintTest(common.HeatTestCase): + + def setUp(self): + super(PluginConstraintTest, self).setUp() + self.ctx = utils.dummy_context() + self.mock_get_plugin = mock.Mock() + self.ctx.clients.client_plugin( + 'sahara').get_plugin_id = self.mock_get_plugin + self.constraint = sahara.PluginConstraint() + + def test_validation(self): + self.mock_get_plugin.return_value = "id1" + self.assertTrue(self.constraint.validate("foo", self.ctx)) + + def test_validation_error(self): + self.mock_get_plugin.side_effect = exception.EntityNotFound( + entity='Plugin', name='bar') + self.assertFalse(self.constraint.validate("bar", self.ctx)) diff --git a/heat/tests/common.py b/heat/tests/common.py index b25883358..4d3026e0d 100644 --- a/heat/tests/common.py +++ b/heat/tests/common.py @@ -31,6 +31,7 @@ from heat.engine.clients.os import glance from heat.engine.clients.os import keystone from heat.engine.clients.os import neutron from heat.engine.clients.os import nova +from heat.engine.clients.os import sahara from heat.engine.clients.os import trove from heat.engine import environment from heat.engine import resource @@ -266,3 +267,7 @@ class HeatTestCase(testscenarios.WithScenarios, validate = self.patchobject(keystone.KeystoneProjectConstraint, 'validate') validate.return_value = True + + def stub_SaharaPluginConstraint(self): + validate = self.patchobject(sahara.PluginConstraint, 'validate') + validate.return_value = True diff --git a/heat/tests/test_sahara_templates.py b/heat/tests/test_sahara_templates.py index 59fe7d5ff..31337f3b7 100644 --- a/heat/tests/test_sahara_templates.py +++ b/heat/tests/test_sahara_templates.py @@ -102,8 +102,9 @@ class FakeClusterTemplate(object): class SaharaNodeGroupTemplateTest(common.HeatTestCase): def setUp(self): super(SaharaNodeGroupTemplateTest, self).setUp() - self.patchobject(st.constraints.CustomConstraint, - '_is_valid').return_value = True + self.stub_FlavorConstraint_validate() + self.stub_SaharaPluginConstraint() + self.stub_VolumeTypeConstraint_validate() self.patchobject(nova.NovaClientPlugin, 'get_flavor_id' ).return_value = 'someflavorid' self.patchobject(neutron.NeutronClientPlugin, '_create') @@ -215,7 +216,7 @@ class SaharaNodeGroupTemplateTest(common.HeatTestCase): self.t['resources']['node-group']['properties'].pop('floating_ip_pool') self.t['resources']['node-group']['properties'].pop('volume_type') ngt = self._init_ngt(self.t) - self.patchobject(st.constraints.CustomConstraint, '_is_valid' + self.patchobject(nova.FlavorConstraint, 'validate' ).return_value = False self.patchobject(ngt, 'is_using_neutron').return_value = False diff --git a/setup.cfg b/setup.cfg index ef9f4fd23..ccc71c28e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -98,6 +98,7 @@ heat.constraints = timezone = heat.engine.constraint.common_constraints:TimezoneConstraint cron_expression = heat.engine.constraint.common_constraints:CRONExpressionConstraint monasca.notification = heat.engine.clients.os.monasca:MonascaNotificationConstraint + sahara.plugin = heat.engine.clients.os.sahara:PluginConstraint heat.stack_lifecycle_plugins =