Fix some map_replace issues
While testing I discovered a couple of corner cases not previously handled: - If you provide values/keys via a get_attr reference it's possible for them to be None during validation - If the input map has an unhashable value, it breaks the values replacement so we need to tolerate a failure to lookup an unhashable key in the values data. Change-Id: I14d92056e0a07816a216aba752711887e8ac0aa5
This commit is contained in:
parent
849868d641
commit
f019fb002e
@ -1329,6 +1329,10 @@ The keys/values mappings are optional, either or both may be specified.
|
||||
Note that an error is raised if a replacement defined in "keys" results
|
||||
in a collision with an existing keys in the input or output map.
|
||||
|
||||
Also note that while unhashable values (e.g lists) in the input map are valid,
|
||||
they will be ignored by the values replacement, because no key can be defined
|
||||
in the values mapping to define their replacement.
|
||||
|
||||
yaql
|
||||
----
|
||||
The ``yaql`` evaluates yaql expression on a given data.
|
||||
|
@ -542,8 +542,8 @@ class MapReplace(function.Function):
|
||||
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
|
||||
'should be: %(example)s') % self.fmt_data)
|
||||
|
||||
repl_keys = repl_map.get('keys', {})
|
||||
repl_values = repl_map.get('values', {})
|
||||
repl_keys = ensure_map(repl_map.get('keys', {}))
|
||||
repl_values = ensure_map(repl_map.get('values', {}))
|
||||
ret_map = {}
|
||||
for k, v in six.iteritems(in_map):
|
||||
key = repl_keys.get(k)
|
||||
@ -559,7 +559,11 @@ class MapReplace(function.Function):
|
||||
msg = _('key replacement %s collides with '
|
||||
'a key in the output map')
|
||||
raise ValueError(msg % key)
|
||||
value = repl_values.get(v, v)
|
||||
try:
|
||||
value = repl_values.get(v, v)
|
||||
except TypeError:
|
||||
# If the value is unhashable, we get here
|
||||
value = v
|
||||
ret_map[key] = value
|
||||
return ret_map
|
||||
|
||||
|
@ -926,6 +926,30 @@ class HOTemplateTest(common.HeatTestCase):
|
||||
self.assertEqual({'f1': 'b1', 'F2': 'b2'},
|
||||
resolved)
|
||||
|
||||
def test_map_replace_none_values(self):
|
||||
snippet = {'map_replace': [{'f1': 'b1', 'f2': 'b2'},
|
||||
{'values': None}]}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
resolved = self.resolve(snippet, tmpl)
|
||||
self.assertEqual({'f1': 'b1', 'f2': 'b2'},
|
||||
resolved)
|
||||
|
||||
def test_map_replace_none_keys(self):
|
||||
snippet = {'map_replace': [{'f1': 'b1', 'f2': 'b2'},
|
||||
{'keys': None}]}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
resolved = self.resolve(snippet, tmpl)
|
||||
self.assertEqual({'f1': 'b1', 'f2': 'b2'},
|
||||
resolved)
|
||||
|
||||
def test_map_replace_unhashable_value(self):
|
||||
snippet = {'map_replace': [{'f1': 'b1', 'f2': []},
|
||||
{'values': {}}]}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
resolved = self.resolve(snippet, tmpl)
|
||||
self.assertEqual({'f1': 'b1', 'f2': []},
|
||||
resolved)
|
||||
|
||||
def test_map_replace_keys_collide(self):
|
||||
snippet = {'map_replace': [{'f1': 'b1', 'f2': 'b2'},
|
||||
{'keys': {'f2': 'f1'}}]}
|
||||
|
Loading…
Reference in New Issue
Block a user