Merge "Remove unnecessary old translation mechanism"
This commit is contained in:
commit
46d209ef2b
|
@ -12,15 +12,10 @@
|
|||
# under the License.
|
||||
|
||||
import functools
|
||||
import six
|
||||
|
||||
from oslo_utils import encodeutils
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.engine.cfn import functions as cfn_funcs
|
||||
from heat.engine import function
|
||||
from heat.engine.hot import functions as hot_funcs
|
||||
|
||||
|
||||
@functools.total_ordering
|
||||
|
@ -135,220 +130,6 @@ class TranslationRule(object):
|
|||
path.extend(self.custom_value_path)
|
||||
return path
|
||||
|
||||
def execute_rule(self, client_resolve=True):
|
||||
try:
|
||||
self._prepare_data(self.properties.data, self.translation_path,
|
||||
self.properties.props)
|
||||
if self.value_path:
|
||||
if self.custom_value_path:
|
||||
self.value_path.extend(self.custom_value_path)
|
||||
self._prepare_data(self.properties.data, self.value_path,
|
||||
self.properties.props)
|
||||
(value_key,
|
||||
value_data) = self.translate_property(self.value_path,
|
||||
self.properties.data,
|
||||
return_value=True)
|
||||
value = (value_data[value_key]
|
||||
if value_data and value_data.get(value_key)
|
||||
else self.value)
|
||||
else:
|
||||
(value_key, value_data) = None, None
|
||||
value = self.value
|
||||
except AttributeError:
|
||||
return
|
||||
|
||||
self.translate_property(self.translation_path, self.properties.data,
|
||||
value=value, value_data=value_data,
|
||||
value_key=value_key,
|
||||
client_resolve=client_resolve)
|
||||
|
||||
def _prepare_data(self, data, path, props):
|
||||
pass
|
||||
|
||||
def _exec_action(self, key, data, value=None, value_key=None,
|
||||
value_data=None, client_resolve=True):
|
||||
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)
|
||||
elif self.rule == TranslationRule.DELETE:
|
||||
self._exec_delete(key, data)
|
||||
|
||||
def _resolve_param(self, param):
|
||||
"""Check whether given item is param and resolve, if it is."""
|
||||
if isinstance(param, (hot_funcs.GetParam, cfn_funcs.ParamRef)):
|
||||
try:
|
||||
return function.resolve(param)
|
||||
except exception.UserParameterMissing as ex:
|
||||
# We can't resolve parameter now. Abort translation.
|
||||
err_msg = encodeutils.exception_to_unicode(ex)
|
||||
raise AttributeError(
|
||||
_('Can not resolve parameter '
|
||||
'due to: %s') % err_msg)
|
||||
elif isinstance(param, list):
|
||||
return [self._resolve_param(param_item) for param_item in param]
|
||||
else:
|
||||
return param
|
||||
|
||||
def resolve_custom_value_path(self, translation_data, translation_key):
|
||||
new_value = translation_data[self.value_name]
|
||||
for key in self.custom_value_path[:-1]:
|
||||
if isinstance(new_value, (list, six.string_types)):
|
||||
raise ValueError(
|
||||
_('Incorrectly specified custom_value_path - '
|
||||
'cannot pull out required value from '
|
||||
'data of %s type.') % type(new_value))
|
||||
if new_value.get(key) is None:
|
||||
return
|
||||
new_value = self._resolve_param(new_value[key])
|
||||
resolved_value = self._resolve_param(
|
||||
new_value.get(self.custom_value_path[-1]))
|
||||
if resolved_value is None:
|
||||
return
|
||||
if self.rule == self.REPLACE:
|
||||
translation_data[translation_key] = resolved_value
|
||||
del new_value[self.custom_value_path[-1]]
|
||||
elif self.rule == self.ADD:
|
||||
if isinstance(resolved_value, list):
|
||||
translation_data[translation_key].extend(resolved_value)
|
||||
else:
|
||||
translation_data[translation_key].append(resolved_value)
|
||||
|
||||
def translate_property(self, path, data, return_value=False, value=None,
|
||||
value_data=None, value_key=None,
|
||||
client_resolve=True):
|
||||
if isinstance(data, function.Function):
|
||||
if return_value:
|
||||
raise AttributeError('No chance to translate value due to '
|
||||
'value is function. Skip translation.')
|
||||
return
|
||||
current_key = path[0]
|
||||
if len(path) <= 1:
|
||||
if return_value:
|
||||
return current_key, data
|
||||
else:
|
||||
self._exec_action(current_key, data,
|
||||
value=value, value_data=value_data,
|
||||
value_key=value_key,
|
||||
client_resolve=client_resolve)
|
||||
return
|
||||
if data.get(current_key) is None:
|
||||
return
|
||||
elif isinstance(data[current_key], list):
|
||||
for item in data[current_key]:
|
||||
if return_value:
|
||||
# Until there's no reasonable solution for cases of using
|
||||
# one list for value and another list for destination,
|
||||
# error would be raised.
|
||||
msg = _('Cannot use value_path for properties inside '
|
||||
'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)
|
||||
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)
|
||||
|
||||
def _exec_add(self, translation_key, translation_data, value):
|
||||
if not isinstance(translation_data[translation_key], list):
|
||||
raise ValueError(_('Add rule must be used only for '
|
||||
'lists.'))
|
||||
if value is not None:
|
||||
translation_data[translation_key].extend(value)
|
||||
elif (self.value_name is not None and
|
||||
translation_data.get(self.value_name) is not None):
|
||||
if self.custom_value_path:
|
||||
self.resolve_custom_value_path(translation_data,
|
||||
translation_key)
|
||||
elif isinstance(translation_data[self.value_name], list):
|
||||
translation_data[translation_key].extend(
|
||||
translation_data[self.value_name])
|
||||
else:
|
||||
translation_data[translation_key].append(
|
||||
translation_data[self.value_name])
|
||||
|
||||
def _exec_replace(self, translation_key, translation_data,
|
||||
value_key, value_data, value):
|
||||
value_ind = None
|
||||
if translation_data and translation_data.get(translation_key):
|
||||
if value_data and value_data.get(value_key):
|
||||
value_ind = value_key
|
||||
elif translation_data.get(self.value_name) is not None:
|
||||
value_ind = self.value_name
|
||||
if self.custom_value_path is not None:
|
||||
data = translation_data.get(self.value_name)
|
||||
for key in self.custom_value_path:
|
||||
data = data.get(key)
|
||||
if data is None:
|
||||
value_ind = None
|
||||
break
|
||||
|
||||
if value_ind is not None:
|
||||
raise exception.ResourcePropertyConflict(props=[translation_key,
|
||||
value_ind])
|
||||
if value is not None:
|
||||
translation_data[translation_key] = value
|
||||
elif (self.value_name is not None and
|
||||
translation_data.get(self.value_name) is not None):
|
||||
if self.custom_value_path:
|
||||
self.resolve_custom_value_path(translation_data,
|
||||
translation_key)
|
||||
else:
|
||||
translation_data[
|
||||
translation_key] = translation_data[self.value_name]
|
||||
del translation_data[self.value_name]
|
||||
|
||||
# If value defined with value_path, need to delete value_path
|
||||
# property data after it's replacing.
|
||||
if value_data and value_data.get(value_key):
|
||||
del value_data[value_key]
|
||||
|
||||
def _exec_resolve(self, translation_key, translation_data):
|
||||
|
||||
def resolve_and_find(translation_value):
|
||||
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))
|
||||
return resolved_value
|
||||
finder = getattr(self.client_plugin, self.finder)
|
||||
if self.entity:
|
||||
return finder(self.entity, translation_value)
|
||||
else:
|
||||
return finder(translation_value)
|
||||
|
||||
if isinstance(translation_data, list):
|
||||
for item in translation_data:
|
||||
translation_value = item.get(translation_key)
|
||||
resolved_value = resolve_and_find(translation_value)
|
||||
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)
|
||||
if resolved_value is not None:
|
||||
translation_data[translation_key] = resolved_value
|
||||
|
||||
def _exec_delete(self, translation_key, translation_data):
|
||||
if isinstance(translation_data, list):
|
||||
for item in translation_data:
|
||||
if item.get(translation_key) is not None:
|
||||
del item[translation_key]
|
||||
elif translation_data.get(translation_key) is not None:
|
||||
del translation_data[translation_key]
|
||||
|
||||
|
||||
class Translation(object):
|
||||
"""Mechanism for translating one properties to other.
|
||||
|
|
|
@ -172,7 +172,7 @@ class ResourceTest(common.HeatTestCase):
|
|||
self.assertEqual('Resource name may not contain "/"',
|
||||
six.text_type(ex))
|
||||
|
||||
@mock.patch.object(translation.TranslationRule, '_exec_resolve')
|
||||
@mock.patch.object(translation, 'resolve_and_find')
|
||||
@mock.patch.object(parser.Stack, 'db_resource_get')
|
||||
@mock.patch.object(resource.Resource, '_load_data')
|
||||
@mock.patch.object(resource.Resource, 'translate_properties')
|
||||
|
|
Loading…
Reference in New Issue