From bc830e2e548c68ad55141baf52c076ed50f67813 Mon Sep 17 00:00:00 2001 From: Geoff Lee Date: Wed, 13 Jun 2018 13:25:45 -0700 Subject: [PATCH] Cast all parameters to strings boto3 only supports strings for parameters, even if the parameter itself is non a string type On branch support-non-string-type-parameters - Wed 13 Jun 2018 13:25:46 PDT by Geoff Lee --- sceptre/plan/actions.py | 19 +++++++++++--- tests/test_actions.py | 56 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 9 deletions(-) diff --git a/sceptre/plan/actions.py b/sceptre/plan/actions.py index c4439cf4b..c14943613 100644 --- a/sceptre/plan/actions.py +++ b/sceptre/plan/actions.py @@ -639,15 +639,28 @@ def _format_parameters(self, parameters): for name, value in parameters.items(): if value is None: continue - if isinstance(value, list): - value = ",".join(value) formatted_parameters.append({ "ParameterKey": name, - "ParameterValue": value + "ParameterValue": self._format_value(value) }) return formatted_parameters + def _format_value(self, value): + """ + Converts CloudFormation value to the format used by Boto3. + """ + if isinstance(value, list): + # recurse + new_list = [self._format_value(item) for item in value] + return ",".join(new_list) + if value is True: + return "true" + elif value is False: + return "false" + else: + return str(value) + def _get_role_arn(self): """ Returns the Role ARN assumed by CloudFormation when building a Stack. diff --git a/tests/test_actions.py b/tests/test_actions.py index c6c689f5b..57c9b98b8 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -726,12 +726,7 @@ def test_format_parameters_with_none_values(self): "key2": None, "key3": None } - formatted_parameters = self.actions._format_parameters(parameters) - sorted_formatted_parameters = sorted( - formatted_parameters, - key=lambda x: x["ParameterKey"] - ) - assert sorted_formatted_parameters == [] + assert self.stack._format_parameters(parameters) == [] def test_format_parameters_with_none_and_string_values(self): parameters = { @@ -749,6 +744,38 @@ def test_format_parameters_with_none_and_string_values(self): {"ParameterKey": "key3", "ParameterValue": "value3"} ] + def test_format_parameters_with_number_values(self): + parameters = { + "key1": 0.0, + "key2": 2.349520, + "key3": 2173540618439890, + } + formatted_parameters = self.stack._format_parameters(parameters) + sorted_formatted_parameters = sorted( + formatted_parameters, + key=lambda x: x["ParameterKey"] + ) + assert sorted_formatted_parameters == [ + {"ParameterKey": "key1", "ParameterValue": "0.0"}, + {"ParameterKey": "key2", "ParameterValue": "2.34952"}, + {"ParameterKey": "key3", "ParameterValue": "2173540618439890"} + ] + + def test_format_parameters_with_boolean_values(self): + parameters = { + "key1": True, + "key2": False + } + formatted_parameters = self.stack._format_parameters(parameters) + sorted_formatted_parameters = sorted( + formatted_parameters, + key=lambda x: x["ParameterKey"] + ) + assert sorted_formatted_parameters == [ + {"ParameterKey": "key1", "ParameterValue": "true"}, + {"ParameterKey": "key2", "ParameterValue": "false"} + ] + def test_format_parameters_with_list_values(self): parameters = { "key1": ["value1", "value2", "value3"], @@ -766,6 +793,23 @@ def test_format_parameters_with_list_values(self): {"ParameterKey": "key3", "ParameterValue": "value7,value8,value9"} ] + def test_format_parameters_with_list_values_containing_mixed_values(self): + parameters = { + "key1": ["value1", 2.3, True], + "key2": ["value4", 5123.58, False], + "key3": ["value7", 0, "value9"] + } + formatted_parameters = self.stack._format_parameters(parameters) + sorted_formatted_parameters = sorted( + formatted_parameters, + key=lambda x: x["ParameterKey"] + ) + assert sorted_formatted_parameters == [ + {"ParameterKey": "key1", "ParameterValue": "value1,2.3,true"}, + {"ParameterKey": "key2", "ParameterValue": "value4,5123.58,false"}, + {"ParameterKey": "key3", "ParameterValue": "value7,0,value9"} + ] + def test_format_parameters_with_none_and_list_values(self): parameters = { "key1": ["value1", "value2", "value3"],