From: JUN JIE NAN Date: Thu, 5 Sep 2013 05:26:01 +0000 (+0800) Subject: Make some heat resolve functions workable in hot X-Git-Tag: 2014.1~53^2 X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=ca0ec0878a82bfb0f64beb73e669e3978d3a0e4c;p=openstack-build%2Fheat-build.git Make some heat resolve functions workable in hot Make resolve functions Ref, Fn::GetAtt, Fn::Replace workable in hot. Fixes bug #1221017 Change-Id: I9b7ca58720b3c7d157c79c3756510ebc62d81ee5 --- diff --git a/heat/engine/hot.py b/heat/engine/hot.py index 0dccb232..d48ef22a 100644 --- a/heat/engine/hot.py +++ b/heat/engine/hot.py @@ -12,7 +12,7 @@ # License for the specific language governing permissions and limitations # under the License. -from string import Template +import string from heat.common import exception from heat.engine import template @@ -180,8 +180,8 @@ class HOTemplate(template.Template): Resolve constructs of the form { get_param: my_param } """ def match_param_ref(key, value): - return (key == 'get_param' and - isinstance(value, basestring) and + return (key in ['get_param', 'Ref'] and + value is not None and value in parameters) def handle_param_ref(ref): @@ -198,7 +198,7 @@ class HOTemplate(template.Template): Resolve constructs of the form { "get_resource" : "resource" } ''' def match_resource_ref(key, value): - return key == 'get_resource' and value in resources + return key in ['get_resource', 'Ref'] and value in resources def handle_resource_ref(arg): return resources[arg].FnGetRefId() @@ -211,10 +211,10 @@ class HOTemplate(template.Template): Resolve constructs of the form { get_attr: [my_resource, my_attr] } """ def match_get_attr(key, value): - return (key == 'get_attr' and + return (key in ['get_attr', 'Fn::GetAtt'] and isinstance(value, list) and len(value) == 2 and - isinstance(value[0], basestring) and + None not in value and value[0] in resources) def handle_get_attr(args): @@ -246,31 +246,41 @@ class HOTemplate(template.Template): """ def handle_str_replace(args): - if not isinstance(args, dict): + if not (isinstance(args, dict) or isinstance(args, list)): raise TypeError('Arguments to "str_replace" must be a' - 'dictionary') + 'dictionary or a list') try: - template = args['template'] - params = args['params'] + if isinstance(args, dict): + text = args.get('template') + params = args.get('params', {}) + elif isinstance(args, list): + params, text = args + if text is None: + raise KeyError() except KeyError: example = ('''str_replace: template: This is $var1 template $var2 params: - - var1: a - - var2: string''') + var1: a + var2: string''') raise KeyError('"str_replace" syntax should be %s' % example) - - if not isinstance(template, basestring): + if not hasattr(text, 'replace'): raise TypeError('"template" parameter must be a string') if not isinstance(params, dict): raise TypeError( '"params" parameter must be a dictionary') + if isinstance(args, list): + for key in params.iterkeys(): + value = params.get(key, '') + text = text.replace(key, value) + return text - return Template(template).substitute(params) + return string.Template(text).safe_substitute(params) - return template._resolve(lambda k, v: k == 'str_replace', + match_str_replace = lambda k, v: k in ['str_replace', 'Fn::Replace'] + return template._resolve(match_str_replace, handle_str_replace, s) def param_schemata(self): diff --git a/heat/tests/test_hot.py b/heat/tests/test_hot.py index 21f970b1..8beaaf3e 100644 --- a/heat/tests/test_hot.py +++ b/heat/tests/test_hot.py @@ -258,6 +258,13 @@ class HOTemplateTest(HeatTestCase): tmpl = parser.Template(hot_tpl_empty) self.assertEqual(tmpl.resolve_param_refs(snippet, params), snippet_resolved) + snippet = {'properties': {'key1': {'Ref': 'foo'}, + 'key2': {'Ref': 'blarg'}}} + snippet_resolved = {'properties': {'key1': 'bar', + 'key2': 'wibble'}} + tmpl = parser.Template(hot_tpl_empty) + self.assertEqual(snippet_resolved, + tmpl.resolve_param_refs(snippet, params)) def test_str_replace(self): """Test str_replace function.""" @@ -268,6 +275,18 @@ class HOTemplateTest(HeatTestCase): tmpl = parser.Template(hot_tpl_empty) + self.assertEqual(snippet_resolved, + tmpl.resolve_replace(snippet)) + + def test_str_fn_replace(self): + """Test Fn:Replace function.""" + + snippet = {'Fn::Replace': [{'$var1': 'foo', '$var2': 'bar'}, + 'Template $var1 string $var2']} + snippet_resolved = 'Template foo string bar' + + tmpl = parser.Template(hot_tpl_empty) + self.assertEqual(tmpl.resolve_replace(snippet), snippet_resolved) def test_str_replace_syntax(self): @@ -358,6 +377,10 @@ class StackTest(test_parser.StackTest): {'Value': {'get_attr': ['resource1', 'NotThere']}}, self.stack) + snippet = {'Value': {'Fn::GetAtt': ['resource1', 'foo']}} + resolved = hot.HOTemplate.resolve_attributes(snippet, self.stack) + self.assertEqual({'Value': 'resource1'}, resolved) + @utils.stack_delete_after def test_get_resource(self): """Test resolution of get_resource occurrences in HOT template."""