]> review.fuel-infra Code Review - openstack-build/heat-build.git/commitdiff
Make some heat resolve functions workable in hot
authorJUN JIE NAN <nanjj@cn.ibm.com>
Thu, 5 Sep 2013 05:26:01 +0000 (13:26 +0800)
committerJUN JIE NAN <nanjj@cn.ibm.com>
Tue, 10 Sep 2013 01:14:55 +0000 (09:14 +0800)
Make resolve functions Ref, Fn::GetAtt, Fn::Replace workable in hot.

Fixes bug #1221017

Change-Id: I9b7ca58720b3c7d157c79c3756510ebc62d81ee5

heat/engine/hot.py
heat/tests/test_hot.py

index 0dccb232eebf545bf03a34ac059e49715c2d9c06..d48ef22ab420ca9d53d19163b43b08da7352c713 100644 (file)
@@ -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):
               <param dictionary>
         """
         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):
index 21f970b1f2d86a6a99aca5810cc135c6ffffa98b..8beaaf3ec1c71c2cb0ea098840fd2d799dd9e4d2 100644 (file)
@@ -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."""