summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-08-06 17:14:52 +0000
committerGerrit Code Review <review@openstack.org>2018-08-06 17:14:52 +0000
commitec32eb4c733e96e0e1bc219c6819058b947a0d70 (patch)
tree7329313b470fbd04070e5a547a98c6e1995b8bc6
parent2356dac20ff50f5aab5693996463461ceb2ab823 (diff)
parent0187203940ab77a5382d77061c0f4a9022b1e9f7 (diff)
downloadheat-ec32eb4c733e96e0e1bc219c6819058b947a0d70.tar.gz
Merge "Ignore RESOLVE translation errors when translating before_props" into stable/ocata
-rw-r--r--heat/engine/resource.py6
-rw-r--r--heat/engine/translation.py74
-rw-r--r--heat/tests/openstack/nova/test_server.py2
-rw-r--r--heat/tests/test_translation_rule.py19
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'}