diff --git a/heat/engine/attributes.py b/heat/engine/attributes.py index 7fee4b3493..a6628476a9 100644 --- a/heat/engine/attributes.py +++ b/heat/engine/attributes.py @@ -174,3 +174,27 @@ class Attributes(collections.Mapping): def __repr__(self): return ("Attributes for %s:\n\t" % self._resource_name + '\n\t'.join(self._attributes.values())) + + +def select_from_attribute(attribute_value, path): + ''' + Select an element from an attribute value. + + :param attribute_value: the attribute value. + :param path: a list of path components to select from the attribute. + :returns: the selected attribute component value. + ''' + def get_path_component(collection, key): + if not isinstance(collection, (collections.Mapping, + collections.Sequence)): + raise TypeError(_("Can't traverse attribute path")) + + if not isinstance(key, (basestring, int)): + raise TypeError(_('Path components in attributes must be strings')) + + return collection[key] + + try: + return reduce(get_path_component, path, attribute_value) + except (KeyError, IndexError, TypeError): + return None diff --git a/heat/engine/hot/functions.py b/heat/engine/hot/functions.py index 3c7e5d8f71..84bd05aab8 100644 --- a/heat/engine/hot/functions.py +++ b/heat/engine/hot/functions.py @@ -14,6 +14,7 @@ import collections from heat.common import exception +from heat.engine import attributes from heat.engine.cfn import functions as cfn_funcs from heat.engine import function @@ -116,22 +117,7 @@ class GetAtt(cfn_funcs.GetAtt): return None path_components = function.resolve(self._path_components) - - def get_path_component(collection, key): - if not isinstance(collection, (collections.Mapping, - collections.Sequence)): - raise TypeError(_('"%s" can\'t traverse path') % self.fn_name) - - if not isinstance(key, (basestring, int)): - raise TypeError(_('Path components in "%s" ' - 'must be strings') % self.fn_name) - - return collection[key] - - try: - return reduce(get_path_component, path_components, attribute) - except (KeyError, IndexError, TypeError): - return None + return attributes.select_from_attribute(attribute, path_components) class Replace(cfn_funcs.Replace):