From 123976539ccb687c53998f2d68e54d4a25fd0c8d Mon Sep 17 00:00:00 2001 From: rabi Date: Fri, 27 Jul 2018 10:10:59 +0530 Subject: [PATCH] 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) --- heat/engine/properties.py | 6 +++-- heat/engine/resource.py | 8 ++++--- heat/engine/translation.py | 34 ++++++++++++++++++++++------- heat/tests/test_translation_rule.py | 23 ++++++++++++++++++- 4 files changed, 57 insertions(+), 14 deletions(-) diff --git a/heat/engine/properties.py b/heat/engine/properties.py index 92b9fe983a..059ce5f7b8 100644 --- a/heat/engine/properties.py +++ b/heat/engine/properties.py @@ -390,8 +390,10 @@ class Properties(collections.Mapping): self.translation = (trans.Translation(properties=self) if translation is None else translation) - def update_translation(self, rules, client_resolve=True): - self.translation.set_rules(rules, client_resolve=client_resolve) + def update_translation(self, rules, client_resolve=True, + ignore_resolve_error=False): + self.translation.set_rules(rules, client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) @staticmethod def schema_from_params(params_snippet): diff --git a/heat/engine/resource.py b/heat/engine/resource.py index 3b297285d7..4d9004921d 100644 --- a/heat/engine/resource.py +++ b/heat/engine/resource.py @@ -1265,7 +1265,7 @@ class Resource(status.ResourceStatus): return [] def translate_properties(self, properties, - client_resolve=True): + client_resolve=True, ignore_resolve_error=False): """Set resource specific rules for properties translation. The properties parameter is a properties object and the @@ -1273,7 +1273,9 @@ class Resource(status.ResourceStatus): do 'RESOLVE' translation with client lookup. """ rules = self.translation_rules(properties) or [] - properties.update_translation(rules, client_resolve=client_resolve) + properties.update_translation( + rules, client_resolve=client_resolve, + ignore_resolve_error=ignore_resolve_error) def cancel_grace_period(self): canceller = getattr(self, @@ -1447,7 +1449,7 @@ class Resource(status.ResourceStatus): 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 or self.converge) and before_props: if not self.resource_id: diff --git a/heat/engine/translation.py b/heat/engine/translation.py index 90d8083eac..bc684901f7 100644 --- a/heat/engine/translation.py +++ b/heat/engine/translation.py @@ -13,10 +13,15 @@ import functools +from oslo_log import log as logging +import six + from heat.common import exception from heat.common.i18n import _ from heat.engine import function +LOG = logging.getLogger(__name__) + @functools.total_ordering class TranslationRule(object): @@ -159,15 +164,18 @@ class Translation(object): self.resolved_translations = {} self.is_active = True self.store_translated_values = True + self._ignore_resolve_error = False self._deleted_props = [] self._replaced_props = [] - def set_rules(self, rules, client_resolve=True): + def set_rules(self, rules, client_resolve=True, + ignore_resolve_error=False): if not rules: return self._rules = {} self.store_translated_values = client_resolve + self._ignore_resolve_error = ignore_resolve_error for rule in rules: if not client_resolve and rule.rule == TranslationRule.RESOLVE: continue @@ -223,7 +231,8 @@ class Translation(object): resolved_value = resolve_and_find(result, rule.client_plugin, rule.finder, - rule.entity) + rule.entity, + self._ignore_resolve_error) if self.store_translated_values: self.resolved_translations[key] = resolved_value result = resolved_value @@ -326,7 +335,8 @@ def get_value(path, props, validate=False, template=None): return get_value(path[1:], prop) -def resolve_and_find(value, cplugin, finder, entity=None): +def resolve_and_find(value, cplugin, finder, entity=None, + ignore_resolve_error=False): if isinstance(value, function.Function): value = function.resolve(value) if value: @@ -336,10 +346,18 @@ def resolve_and_find(value, cplugin, finder, entity=None): resolved_value.append(resolve_and_find(item, cplugin, finder, - entity)) + entity, + ignore_resolve_error)) return resolved_value finder = getattr(cplugin, finder) - if entity: - return finder(entity, value) - else: - return finder(value) + try: + if entity: + return finder(entity, value) + else: + return finder(value) + except Exception as ex: + if ignore_resolve_error: + LOG.info("Ignoring error in RESOLVE translation: %s", + six.text_type(ex)) + return value + raise diff --git a/heat/tests/test_translation_rule.py b/heat/tests/test_translation_rule.py index be336e2186..59c054e03a 100644 --- a/heat/tests/test_translation_rule.py +++ b/heat/tests/test_translation_rule.py @@ -547,10 +547,13 @@ class TestTranslationRule(common.HeatTestCase): self.assertIsNone(tran.translate('far')) self.assertIsNone(tran.resolved_translations['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' @@ -681,6 +684,24 @@ class TestTranslationRule(common.HeatTestCase): self.assertEqual(['yellow', 'pink'], result) self.assertEqual(['yellow', 'pink'], tran.resolved_translations['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') + + tran = translation.Translation(props) + tran.set_rules([rule], ignore_resolve_error=True) + self.assertTrue(tran.has_translation('far')) + result = tran.translate('far', data['far']) + self.assertEqual('one', result) + self.assertEqual('one', tran.resolved_translations['far']) + def test_resolve_rule_other(self): client_plugin, schema = self._test_resolve_rule() data = {'far': 'one'}