Merge "Add str_split function to HOT 2015-10-15"
This commit is contained in:
commit
4b4b27d0ff
|
@ -171,6 +171,7 @@ For example, Heat currently supports the following values for the
|
||||||
digest
|
digest
|
||||||
resource_facade
|
resource_facade
|
||||||
str_replace
|
str_replace
|
||||||
|
str_split
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1046,3 +1047,43 @@ 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
|
compute instance and the root password is going to be set based on a user
|
||||||
provided parameter. The script for doing this is provided as userdata to the
|
provided parameter. The script for doing this is provided as userdata to the
|
||||||
compute instance, leveraging the ``str_replace`` function.
|
compute instance, leveraging the ``str_replace`` function.
|
||||||
|
|
||||||
|
str_split
|
||||||
|
---------
|
||||||
|
The *str_split* function allows for splitting a string into a list by providing
|
||||||
|
an arbitrary delimiter, the opposite of list_join.
|
||||||
|
|
||||||
|
The syntax of the str_split function is as follows:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
str_split:
|
||||||
|
- ','
|
||||||
|
- string,to,split
|
||||||
|
Or:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
str_split: [',', 'string,to,split']
|
||||||
|
|
||||||
|
The result of which is:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
['string', 'to', 'split']
|
||||||
|
|
||||||
|
Optionally, an index may be provided to select a specific entry from the
|
||||||
|
resulting list, similar to get_attr/get_param:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
str_split: [',', 'string,to,split', 0]
|
||||||
|
|
||||||
|
The result of which is:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
'string'
|
||||||
|
|
||||||
|
Note: The index starts at zero, and any value outside the maximum (e.g the
|
||||||
|
length of the list minus one) will cause an error.
|
||||||
|
|
|
@ -424,3 +424,66 @@ class Digest(function.Function):
|
||||||
self.validate_usage(args)
|
self.validate_usage(args)
|
||||||
|
|
||||||
return self.digest(*args)
|
return self.digest(*args)
|
||||||
|
|
||||||
|
|
||||||
|
class StrSplit(function.Function):
|
||||||
|
'''
|
||||||
|
A function for splitting delimited strings into a list
|
||||||
|
and optionally extracting a specific list member by index.
|
||||||
|
|
||||||
|
Takes the form::
|
||||||
|
|
||||||
|
str_split: [delimiter, string, <index> ]
|
||||||
|
|
||||||
|
or::
|
||||||
|
|
||||||
|
str_split:
|
||||||
|
- delimiter
|
||||||
|
- string
|
||||||
|
- <index>
|
||||||
|
If <index> is specified, the specified list item will be returned
|
||||||
|
otherwise, the whole list is returned, similar to get_attr with
|
||||||
|
path based attributes accessing lists.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, stack, fn_name, args):
|
||||||
|
super(StrSplit, self).__init__(stack, fn_name, args)
|
||||||
|
example = '"%s" : [ ",", "apples,pears", <index>]' % fn_name
|
||||||
|
self.fmt_data = {'fn_name': fn_name,
|
||||||
|
'example': example}
|
||||||
|
self.fn_name = fn_name
|
||||||
|
|
||||||
|
if isinstance(args, (six.string_types, collections.Mapping)):
|
||||||
|
raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
|
||||||
|
'should be: %(example)s') % self.fmt_data)
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
args = function.resolve(self.args)
|
||||||
|
|
||||||
|
try:
|
||||||
|
delim = args.pop(0)
|
||||||
|
str_to_split = args.pop(0)
|
||||||
|
except (AttributeError, IndexError):
|
||||||
|
raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
|
||||||
|
'should be: %(example)s') % self.fmt_data)
|
||||||
|
split_list = str_to_split.split(delim)
|
||||||
|
|
||||||
|
# Optionally allow an index to be specified
|
||||||
|
if args:
|
||||||
|
try:
|
||||||
|
index = int(args.pop(0))
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(_('Incorrect index to "%(fn_name)s" '
|
||||||
|
'should be: %(example)s') % self.fmt_data)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
res = split_list[index]
|
||||||
|
except IndexError:
|
||||||
|
raise ValueError(_('Incorrect index to "%(fn_name)s" '
|
||||||
|
'should be between 0 and '
|
||||||
|
'%(max_index)s')
|
||||||
|
% {'fn_name': self.fn_name,
|
||||||
|
'max_index': len(split_list) - 1})
|
||||||
|
else:
|
||||||
|
res = split_list
|
||||||
|
return res
|
||||||
|
|
|
@ -339,6 +339,9 @@ class HOTemplate20151015(HOTemplate20150430):
|
||||||
'resource_facade': hot_funcs.ResourceFacade,
|
'resource_facade': hot_funcs.ResourceFacade,
|
||||||
'str_replace': hot_funcs.Replace,
|
'str_replace': hot_funcs.Replace,
|
||||||
|
|
||||||
|
# functions added since 20150430
|
||||||
|
'str_split': hot_funcs.StrSplit,
|
||||||
|
|
||||||
# functions removed from 20150430
|
# functions removed from 20150430
|
||||||
'Fn::Select': hot_funcs.Removed,
|
'Fn::Select': hot_funcs.Removed,
|
||||||
|
|
||||||
|
|
|
@ -746,6 +746,51 @@ class HOTemplateTest(common.HeatTestCase):
|
||||||
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||||
self.assertIn('Algorithm must be one of', six.text_type(exc))
|
self.assertIn('Algorithm must be one of', six.text_type(exc))
|
||||||
|
|
||||||
|
def test_str_split(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',', 'bar,baz']}
|
||||||
|
snippet_resolved = ['bar', 'baz']
|
||||||
|
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
|
||||||
|
|
||||||
|
def test_str_split_index(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',', 'bar,baz', 1]}
|
||||||
|
snippet_resolved = 'baz'
|
||||||
|
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
|
||||||
|
|
||||||
|
def test_str_split_index_str(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',', 'bar,baz', '1']}
|
||||||
|
snippet_resolved = 'baz'
|
||||||
|
self.assertEqual(snippet_resolved, self.resolve(snippet, tmpl))
|
||||||
|
|
||||||
|
def test_str_split_index_bad(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',', 'bar,baz', 'bad']}
|
||||||
|
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||||
|
self.assertIn('Incorrect index to \"str_split\"', six.text_type(exc))
|
||||||
|
|
||||||
|
def test_str_split_index_out_of_range(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',', 'bar,baz', '2']}
|
||||||
|
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||||
|
expected = 'Incorrect index to \"str_split\" should be between 0 and 1'
|
||||||
|
self.assertEqual(expected, six.text_type(exc))
|
||||||
|
|
||||||
|
def test_str_split_bad_novalue(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': [',']}
|
||||||
|
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||||
|
self.assertIn('Incorrect arguments to \"str_split\"',
|
||||||
|
six.text_type(exc))
|
||||||
|
|
||||||
|
def test_str_split_bad_empty(self):
|
||||||
|
tmpl = template.Template(hot_liberty_tpl_empty)
|
||||||
|
snippet = {'str_split': []}
|
||||||
|
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||||
|
self.assertIn('Incorrect arguments to \"str_split\"',
|
||||||
|
six.text_type(exc))
|
||||||
|
|
||||||
def test_prevent_parameters_access(self):
|
def test_prevent_parameters_access(self):
|
||||||
"""
|
"""
|
||||||
Test that the parameters section can't be accessed using the template
|
Test that the parameters section can't be accessed using the template
|
||||||
|
|
Loading…
Reference in New Issue