# under the License.
import collections
+import json
from heat.db import api as db_api
from heat.common import exception
return _resolve(lambda k, v: k == 'Fn::Join', handle_join, s)
+ @staticmethod
+ def resolve_select(s):
+ '''
+ Resolve constructs of the form:
+ (for a list lookup)
+ { "Fn::Select" : [ "2", [ "apples", "grapes", "mangoes" ] ] }
+ returns "mangoes"
+
+ (for a dict lookup)
+ { "Fn::Select" : [ "red", {"red": "a", "flu": "b"} ] }
+ returns "a"
+
+ Note: can raise IndexError, KeyError, ValueError and TypeError
+ '''
+ def handle_select(args):
+ if not isinstance(args, (list, tuple)):
+ raise TypeError('Arguments to "Fn::Select" must be a list')
+
+ try:
+ lookup, strings = args
+ except ValueError as ex:
+ example = '"Fn::Select" : [ "4", [ "str1", "str2"]]'
+ raise ValueError('Incorrect arguments to "Fn::Select" %s: %s' %
+ ('should be', example))
+
+ try:
+ index = int(lookup)
+ except ValueError as ex:
+ index = lookup
+
+ if isinstance(strings, basestring):
+ # might be serialized json.
+ # if not allow it to raise a ValueError
+ strings = json.loads(strings)
+
+ if isinstance(strings, (list, tuple)) and isinstance(index, int):
+ return strings[index]
+ if isinstance(strings, dict) and isinstance(index, basestring):
+ return strings[index]
+
+ raise TypeError('Arguments to "Fn::Select" not fully resolved')
+
+ return _resolve(lambda k, v: k == 'Fn::Select', handle_select, s)
+
@staticmethod
def resolve_joins(s):
'''
# License for the specific language governing permissions and limitations
# under the License.
+import json
import mox
-
import time
import uuid
resources),
p_snippet)
+ def test_select_from_list(self):
+ data = {"Fn::Select": ["1", ["foo", "bar"]]}
+ self.assertEqual(parser.Template.resolve_select(data), "bar")
+
+ def test_select_from_list_not_int(self):
+ data = {"Fn::Select": ["one", ["foo", "bar"]]}
+ self.assertRaises(TypeError, parser.Template.resolve_select,
+ data)
+
+ def test_select_from_list_out_of_bound(self):
+ data = {"Fn::Select": ["3", ["foo", "bar"]]}
+ self.assertRaises(IndexError, parser.Template.resolve_select,
+ data)
+
+ def test_select_from_dict(self):
+ data = {"Fn::Select": ["red", {"red": "robin", "re": "foo"}]}
+ self.assertEqual(parser.Template.resolve_select(data), "robin")
+
+ def test_select_from_dict_not_str(self):
+ data = {"Fn::Select": ["1", {"red": "robin", "re": "foo"}]}
+ self.assertRaises(TypeError, parser.Template.resolve_select,
+ data)
+
+ def test_select_from_dict_not_existing(self):
+ data = {"Fn::Select": ["green", {"red": "robin", "re": "foo"}]}
+ self.assertRaises(KeyError, parser.Template.resolve_select,
+ data)
+
+ def test_select_from_serialized_json_map(self):
+ js = json.dumps({"red": "robin", "re": "foo"})
+ data = {"Fn::Select": ["re", js]}
+ self.assertEqual(parser.Template.resolve_select(data), "foo")
+
+ def test_select_from_serialized_json_list(self):
+ js = json.dumps(["foo", "fee", "fum"])
+ data = {"Fn::Select": ["0", js]}
+ self.assertEqual(parser.Template.resolve_select(data), "foo")
+
+ def test_select_from_serialized_json_wrong(self):
+ js = "this is really not serialized json"
+ data = {"Fn::Select": ["not", js]}
+ self.assertRaises(ValueError, parser.Template.resolve_select,
+ data)
+
+ def test_select_wrong_num_args(self):
+ join0 = {"Fn::Select": []}
+ self.assertRaises(ValueError, parser.Template.resolve_select,
+ join0)
+ join1 = {"Fn::Select": ["4"]}
+ self.assertRaises(ValueError, parser.Template.resolve_select,
+ join1)
+ join3 = {"Fn::Select": ["foo", {"foo": "bar"}, ""]}
+ self.assertRaises(ValueError, parser.Template.resolve_select,
+ join3)
+
def test_join_reduce(self):
join = {"Fn::Join": [" ", ["foo", "bar", "baz", {'Ref': 'baz'},
"bink", "bonk"]]}