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
|
||||
resource_facade
|
||||
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
|
||||
provided parameter. The script for doing this is provided as userdata to the
|
||||
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)
|
||||
|
||||
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,
|
||||
'str_replace': hot_funcs.Replace,
|
||||
|
||||
# functions added since 20150430
|
||||
'str_split': hot_funcs.StrSplit,
|
||||
|
||||
# functions removed from 20150430
|
||||
'Fn::Select': hot_funcs.Removed,
|
||||
|
||||
|
|
|
@ -746,6 +746,51 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
exc = self.assertRaises(ValueError, self.resolve, snippet, tmpl)
|
||||
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):
|
||||
"""
|
||||
Test that the parameters section can't be accessed using the template
|
||||
|
|
Loading…
Reference in New Issue