HOT str_replace to use string.replace, not string.Template
str_replace uses python templates, whereas Fn::Replace uses python string.replace. During the original review for Fn::Replace, python templates were decided against because $ would often need double-escaping in shell scripts. https://review.openstack.org/#/c/31736/ Having different behaviours between Fn::Replace and str_replace will add complication for users migrating existing templates to HOT. Another advantage of using straight string replacement is seen when the template generates a executable script. In this case it is generally possible to write a template that can also be executed directly in a dev/test environment. This would often not be possible if the template format required placeholders to be prefixed with a $. Whatever behaviour exists when Havana is release will have to be supported indefinitely so now is the time to decide if this is going to be fixed. Closes-Bug: #1228640 Change-Id: I72879b374a3c61dfe0e4004251ab709d914f2e25
This commit is contained in:
parent
b21ce20427
commit
f424d6f6c3
|
@ -464,8 +464,8 @@ str_replace
|
|||
-----------
|
||||
The *str_replace* function allows for dynamically constructing strings by
|
||||
providing a template string with placeholders and a list of mappings to assign
|
||||
values to those placeholders at runtime. The functionality of this function is
|
||||
similar to that of Python Template strings.
|
||||
values to those placeholders at runtime. The placeholders are replaced with
|
||||
mapping values wherever a mapping key exactly matches a placeholder.
|
||||
The syntax of the str_replace function is as follows:
|
||||
|
||||
::
|
||||
|
@ -499,7 +499,7 @@ section of a template to build a URL for logging into a deployed application.
|
|||
description: The URL to log into the deployed application
|
||||
value:
|
||||
str_replace:
|
||||
template: http://$host/MyApplication
|
||||
template: http://host/MyApplication
|
||||
params:
|
||||
host: { get_attr: [ my_instance, PublicIp ] }
|
||||
|
||||
|
@ -528,7 +528,7 @@ like scripts for initializing compute instances as shown in the example below:
|
|||
mysqladmin -u root password $db_rootpassword
|
||||
# do more things ...
|
||||
params:
|
||||
db_rootpassword: { get_param: DBRootPassword }
|
||||
$db_rootpassword: { get_param: DBRootPassword }
|
||||
|
||||
In the example above, one can imagine that MySQL is being configured on a
|
||||
compute instance and the root password is going to be set based on a user
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import string
|
||||
|
||||
from heat.common import exception
|
||||
from heat.engine import template
|
||||
from heat.engine.parameters import ParamSchema
|
||||
|
@ -260,7 +258,7 @@ class HOTemplate(template.Template):
|
|||
raise KeyError()
|
||||
except KeyError:
|
||||
example = ('''str_replace:
|
||||
template: This is $var1 template $var2
|
||||
template: This is var1 template var2
|
||||
params:
|
||||
var1: a
|
||||
var2: string''')
|
||||
|
@ -271,13 +269,10 @@ class HOTemplate(template.Template):
|
|||
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 string.Template(text).safe_substitute(params)
|
||||
for key in params.iterkeys():
|
||||
value = params.get(key, '')
|
||||
text = text.replace(key, value)
|
||||
return text
|
||||
|
||||
match_str_replace = lambda k, v: k in ['str_replace', 'Fn::Replace']
|
||||
return template._resolve(match_str_replace,
|
||||
|
|
|
@ -269,7 +269,7 @@ class HOTemplateTest(HeatTestCase):
|
|||
def test_str_replace(self):
|
||||
"""Test str_replace function."""
|
||||
|
||||
snippet = {'str_replace': {'template': 'Template $var1 string $var2',
|
||||
snippet = {'str_replace': {'template': 'Template var1 string var2',
|
||||
'params': {'var1': 'foo', 'var2': 'bar'}}}
|
||||
snippet_resolved = 'Template foo string bar'
|
||||
|
||||
|
@ -297,7 +297,7 @@ class HOTemplateTest(HeatTestCase):
|
|||
validate that we get a TypeError.
|
||||
"""
|
||||
|
||||
snippet = {'str_replace': [{'template': 'Template $var1 string $var2'},
|
||||
snippet = {'str_replace': [{'template': 'Template var1 string var2'},
|
||||
{'params': {'var1': 'foo', 'var2': 'bar'}}]}
|
||||
|
||||
tmpl = parser.Template(hot_tpl_empty)
|
||||
|
@ -312,14 +312,14 @@ class HOTemplateTest(HeatTestCase):
|
|||
a KeyError.
|
||||
"""
|
||||
|
||||
snippet = {'str_replace': {'tmpl': 'Template $var1 string $var2',
|
||||
snippet = {'str_replace': {'tmpl': 'Template var1 string var2',
|
||||
'params': {'var1': 'foo', 'var2': 'bar'}}}
|
||||
|
||||
tmpl = parser.Template(hot_tpl_empty)
|
||||
|
||||
self.assertRaises(KeyError, tmpl.resolve_replace, snippet)
|
||||
|
||||
snippet = {'str_replace': {'tmpl': 'Template $var1 string $var2',
|
||||
snippet = {'str_replace': {'tmpl': 'Template var1 string var2',
|
||||
'parms': {'var1': 'foo', 'var2': 'bar'}}}
|
||||
|
||||
self.assertRaises(KeyError, tmpl.resolve_replace, snippet)
|
||||
|
@ -339,7 +339,7 @@ class HOTemplateTest(HeatTestCase):
|
|||
|
||||
self.assertRaises(TypeError, tmpl.resolve_replace, snippet)
|
||||
|
||||
snippet = {'str_replace': {'template': 'Template $var1 string $var2',
|
||||
snippet = {'str_replace': {'template': 'Template var1 string var2',
|
||||
'params': ['var1', 'foo', 'var2', 'bar']}}
|
||||
|
||||
self.assertRaises(TypeError, tmpl.resolve_replace, snippet)
|
||||
|
|
Loading…
Reference in New Issue