diff options
author | rabi <ramishra@redhat.com> | 2018-07-27 10:10:59 +0530 |
---|---|---|
committer | rabi <ramishra@redhat.com> | 2018-08-01 08:32:42 +0530 |
commit | 0187203940ab77a5382d77061c0f4a9022b1e9f7 (patch) | |
tree | 3c2abdccb9dafcc7438bdac65f12fec02c6909c1 | |
parent | 4a9fd8fa9aed62efaa7a3f327a99c177df606321 (diff) | |
download | heat-0187203940ab77a5382d77061c0f4a9022b1e9f7.tar.gz |
Ignore RESOLVE translation errors when translating before_props
When translating name to id, if we don't find the resource it's
better to ignore the error and return the non-translated value
for before properties.
Change-Id: Ic25c35098cff8b68e184a336b21f2e8df70bb1ee
Story: #2003015
Task: 23103
(cherry picked from commit 8c39f3bb8b08ad37cb5411b448ef2acde6345d55)
-rw-r--r-- | heat/engine/resource.py | 6 | ||||
-rw-r--r-- | heat/engine/translation.py | 74 | ||||
-rw-r--r-- | heat/tests/openstack/nova/test_server.py | 2 | ||||
-rw-r--r-- | heat/tests/test_translation_rule.py | 19 |
4 files changed, 68 insertions, 33 deletions
diff --git a/heat/engine/resource.py b/heat/engine/resource.py index cd4909bdd..6e46bbbc3 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -1075,7 +1075,7 @@ class Resource(object): """Return specified rules for resource.""" def translate_properties(self, properties, - client_resolve=True): + client_resolve=True, ignore_resolve_error=False): """Translates properties with resource specific rules. The properties parameter is a properties object and the @@ -1085,7 +1085,7 @@ class Resource(object): rules = self.translation_rules(properties) or [] for rule in rules: try: - rule.execute_rule(client_resolve) + rule.execute_rule(client_resolve, ignore_resolve_error) except exception.ResourcePropertyConflict as ex: path = [self.stack.t.RESOURCES, self.name, self.stack.t.get_section_name( @@ -1265,7 +1265,7 @@ class Resource(object): after_props = after.properties(self.properties_schema, self.context) self.translate_properties(after_props) - self.translate_properties(before_props) + self.translate_properties(before_props, ignore_resolve_error=True) if cfg.CONF.observe_on_update and before_props: if not self.resource_id: diff --git a/heat/engine/translation.py b/heat/engine/translation.py index b8afbe0ec..374f3ef7b 100644 --- a/heat/engine/translation.py +++ b/heat/engine/translation.py @@ -11,9 +11,9 @@ # License for the specific language governing permissions and limitations # under the License. -import six - +from oslo_log import log as logging from oslo_utils import encodeutils +import six from heat.common import exception from heat.common.i18n import _ @@ -22,6 +22,8 @@ from heat.engine import function from heat.engine.hot import functions as hot_funcs from heat.engine import properties +LOG = logging.getLogger(__name__) + class TranslationRule(object): """Translating mechanism one properties to another. @@ -112,7 +114,7 @@ class TranslationRule(object): raise ValueError(_('client_plugin and finder should be specified ' 'for Resolve rule')) - def execute_rule(self, client_resolve=True): + def execute_rule(self, client_resolve=True, ignore_resolve_error=False): try: self._prepare_data(self.properties.data, self.translation_path, self.properties.props) @@ -137,7 +139,8 @@ class TranslationRule(object): self.translate_property(self.translation_path, self.properties.data, value=value, value_data=value_data, value_key=value_key, - client_resolve=client_resolve) + client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) def _prepare_data(self, data, path, props): def get_props(props, key): @@ -177,13 +180,14 @@ class TranslationRule(object): get_props(props, current_key)) def _exec_action(self, key, data, value=None, value_key=None, - value_data=None, client_resolve=True): + value_data=None, client_resolve=True, + ignore_resolve_error=False): if self.rule == TranslationRule.ADD: self._exec_add(key, data, value) elif self.rule == TranslationRule.REPLACE: self._exec_replace(key, data, value_key, value_data, value) elif self.rule == TranslationRule.RESOLVE and client_resolve: - self._exec_resolve(key, data) + self._exec_resolve(key, data, ignore_resolve_error) elif self.rule == TranslationRule.DELETE: self._exec_delete(key, data) @@ -229,7 +233,7 @@ class TranslationRule(object): def translate_property(self, path, data, return_value=False, value=None, value_data=None, value_key=None, - client_resolve=True): + client_resolve=True, ignore_resolve_error=False): if isinstance(data, function.Function): if return_value: raise AttributeError('No chance to translate value due to ' @@ -243,7 +247,8 @@ class TranslationRule(object): self._exec_action(current_key, data, value=value, value_data=value_data, value_key=value_key, - client_resolve=client_resolve) + client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) return if data.get(current_key) is None: return @@ -257,17 +262,19 @@ class TranslationRule(object): 'list-type properties') raise ValueError(msg) else: - self.translate_property(path[1:], item, - return_value=return_value, - value=value, value_data=value_data, - value_key=value_key, - client_resolve=client_resolve) + self.translate_property( + path[1:], item, return_value=return_value, + value=value, value_data=value_data, + value_key=value_key, + client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) else: - return self.translate_property(path[1:], data[current_key], - return_value=return_value, - value=value, value_data=value_data, - value_key=value_key, - client_resolve=client_resolve) + return self.translate_property( + path[1:], data[current_key], return_value=return_value, + value=value, value_data=value_data, + value_key=value_key, + client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) def _exec_add(self, translation_key, translation_data, value): if not isinstance(translation_data[translation_key], list): @@ -323,32 +330,43 @@ class TranslationRule(object): if value_data and value_data.get(value_key): del value_data[value_key] - def _exec_resolve(self, translation_key, translation_data): + def _exec_resolve(self, translation_key, translation_data, + ignore_resolve_error=False): - def resolve_and_find(translation_value): + def resolve_and_find(translation_value, ignore_resolve_error): if isinstance(translation_value, function.Function): translation_value = function.resolve(translation_value) if translation_value: if isinstance(translation_value, list): resolved_value = [] for item in translation_value: - resolved_value.append(resolve_and_find(item)) + resolved_value.append( + resolve_and_find(item, + ignore_resolve_error)) return resolved_value finder = getattr(self.client_plugin, self.finder) - if self.entity: - return finder(self.entity, translation_value) - else: - return finder(translation_value) - + try: + if self.entity: + return finder(self.entity, translation_value) + else: + return finder(translation_value) + except Exception as ex: + if ignore_resolve_error: + LOG.info("Ignoring error in RESOLVE translation: %s", + six.text_type(ex)) + return translation_value + raise if isinstance(translation_data, list): for item in translation_data: translation_value = item.get(translation_key) - resolved_value = resolve_and_find(translation_value) + resolved_value = resolve_and_find(translation_value, + ignore_resolve_error) if resolved_value is not None: item[translation_key] = resolved_value else: translation_value = translation_data.get(translation_key) - resolved_value = resolve_and_find(translation_value) + resolved_value = resolve_and_find(translation_value, + ignore_resolve_error) if resolved_value is not None: translation_data[translation_key] = resolved_value diff --git a/heat/tests/openstack/nova/test_server.py b/heat/tests/openstack/nova/test_server.py index b6c08daee..af730d60b 100644 --- a/heat/tests/openstack/nova/test_server.py +++ b/heat/tests/openstack/nova/test_server.py @@ -3672,7 +3672,7 @@ class ServersTest(common.HeatTestCase): args='Update Image') self.patchobject(glance.GlanceClientPlugin, 'find_image_by_name_or_id', - side_effect=[1, ex]) + side_effect=ex) update_props = self.server_props.copy() update_props['image'] = 'Update Image' update_template = server.t.freeze(properties=update_props) diff --git a/heat/tests/test_translation_rule.py b/heat/tests/test_translation_rule.py index 93b5ae598..c1c999911 100644 --- a/heat/tests/test_translation_rule.py +++ b/heat/tests/test_translation_rule.py @@ -465,10 +465,13 @@ class TestTranslationRule(common.HeatTestCase): self.assertIsNone(props.get('far')) - def _test_resolve_rule(self, is_list=False): + def _test_resolve_rule(self, is_list=False, + check_error=False): class FakeClientPlugin(object): def find_name_id(self, entity=None, src_value='far'): + if check_error: + raise exception.NotFound() if entity == 'rose': return 'pink' return 'yellow' @@ -599,6 +602,20 @@ class TestTranslationRule(common.HeatTestCase): rule.execute_rule() self.assertEqual([], props.get('far')) + def test_resolve_rule_ignore_error(self): + client_plugin, schema = self._test_resolve_rule(check_error=True) + data = {'far': 'one'} + props = properties.Properties(schema, data) + rule = translation.TranslationRule( + props, + translation.TranslationRule.RESOLVE, + ['far'], + client_plugin=client_plugin, + finder='find_name_id') + + rule.execute_rule(ignore_resolve_error=True) + self.assertEqual('one', props.get('far')) + def test_resolve_rule_other(self): client_plugin, schema = self._test_resolve_rule() data = {'far': 'one'} |