diff options
-rw-r--r-- | boto/cloudformation/connection.py | 18 | ||||
-rw-r--r-- | tests/integration/cloudformation/test_connection.py | 57 | ||||
-rw-r--r-- | tests/unit/cloudformation/test_connection.py | 12 |
3 files changed, 77 insertions, 10 deletions
diff --git a/boto/cloudformation/connection.py b/boto/cloudformation/connection.py index 1407c570..ee850b30 100644 --- a/boto/cloudformation/connection.py +++ b/boto/cloudformation/connection.py @@ -135,7 +135,8 @@ class CloudFormationConnection(AWSQueryConnection): :type parameters: list :param parameters: A list of key/value tuples that specify input - parameters for the stack. + parameters for the stack. A 3-tuple (key, value, bool) may be used to + specify the `UsePreviousValue` option. :type disable_rollback: boolean :param disable_rollback: Set to `True` to disable rollback of the stack @@ -235,9 +236,17 @@ class CloudFormationConnection(AWSQueryConnection): boto.log.warning("If both TemplateBody and TemplateURL are" " specified, only TemplateBody will be honored by the API") if parameters and len(parameters) > 0: - for i, (key, value) in enumerate(parameters): + for i, parameter_tuple in enumerate(parameters): + key, value = parameter_tuple[:2] + use_previous = (parameter_tuple[2] + if len(parameter_tuple) > 2 else False) params['Parameters.member.%d.ParameterKey' % (i + 1)] = key - params['Parameters.member.%d.ParameterValue' % (i + 1)] = value + if use_previous: + params['Parameters.member.%d.UsePreviousValue' + % (i + 1)] = self.encode_bool(use_previous) + else: + params['Parameters.member.%d.ParameterValue' % (i + 1)] = value + if capabilities: for i, value in enumerate(capabilities): params['Capabilities.member.%d' % (i + 1)] = value @@ -459,7 +468,8 @@ class CloudFormationConnection(AWSQueryConnection): :type parameters: list :param parameters: A list of key/value tuples that specify input - parameters for the stack. + parameters for the stack. A 3-tuple (key, value, bool) may be used to + specify the `UsePreviousValue` option. :type notification_arns: list :param notification_arns: The Simple Notification Service (SNS) topic diff --git a/tests/integration/cloudformation/test_connection.py b/tests/integration/cloudformation/test_connection.py index 6529cc37..4cafb0fe 100644 --- a/tests/integration/cloudformation/test_connection.py +++ b/tests/integration/cloudformation/test_connection.py @@ -10,6 +10,14 @@ BASIC_EC2_TEMPLATE = { "AWSTemplateFormatVersion": "2010-09-09", "Description": "AWS CloudFormation Sample Template EC2InstanceSample", "Parameters": { + "Parameter1": { + "Description": "Test Parameter 1", + "Type": "String" + }, + "Parameter2": { + "Description": "Test Parameter 2", + "Type": "String" + } }, "Mappings": { "RegionMap": { @@ -32,7 +40,14 @@ BASIC_EC2_TEMPLATE = { ] }, "UserData": { - "Fn::Base64": "a" * 15000 + "Fn::Base64": { + "Fn::Join":[ + "", + [{"Ref": "Parameter1"}, + {"Ref": "Parameter2"}] + ] + } + } } } @@ -102,7 +117,9 @@ class TestCloudformationConnection(unittest.TestCase): # See https://github.com/boto/boto/issues/1037 body = self.connection.create_stack( self.stack_name, - template_body=json.dumps(BASIC_EC2_TEMPLATE)) + template_body=json.dumps(BASIC_EC2_TEMPLATE), + parameters=[('Parameter1', 'initial_value'), + ('Parameter2', 'initial_value')]) self.addCleanup(self.connection.delete_stack, self.stack_name) # A newly created stack should have events @@ -114,9 +131,39 @@ class TestCloudformationConnection(unittest.TestCase): self.assertEqual(None, policy) # Our new stack should show up in the stack list - stacks = self.connection.describe_stacks() - self.assertEqual(self.stack_name, stacks[0].stack_name) - + stacks = self.connection.describe_stacks(self.stack_name) + stack = stacks[0] + self.assertEqual(self.stack_name, stack.stack_name) + + params = [(p.key, p.value) for p in stack.parameters] + self.assertEquals([('Parameter1', 'initial_value'), + ('Parameter2', 'initial_value')], params) + + for _ in range(30): + stack.update() + if stack.stack_status.find("PROGRESS") == -1: + break + time.sleep(5) + + body = self.connection.update_stack( + self.stack_name, + template_body=json.dumps(BASIC_EC2_TEMPLATE), + parameters=[('Parameter1', '', True), + ('Parameter2', 'updated_value')]) + + stacks = self.connection.describe_stacks(self.stack_name) + stack = stacks[0] + params = [(p.key, p.value) for p in stacks[0].parameters] + self.assertEquals([('Parameter1', 'initial_value'), + ('Parameter2', 'updated_value')], params) + # Waiting for the update to complete to unblock the delete_stack in the + # cleanup. + for _ in range(30): + stack.update() + if stack.stack_status.find("PROGRESS") == -1: + break + time.sleep(5) + if __name__ == '__main__': unittest.main() diff --git a/tests/unit/cloudformation/test_connection.py b/tests/unit/cloudformation/test_connection.py index f4e23f37..613e3d2a 100644 --- a/tests/unit/cloudformation/test_connection.py +++ b/tests/unit/cloudformation/test_connection.py @@ -134,7 +134,9 @@ class TestCloudFormationUpdateStack(CloudFormationConnectionBase): api_response = self.service_connection.update_stack( 'stack_name', template_url='http://url', template_body=SAMPLE_TEMPLATE, - parameters=[('KeyName', 'myKeyName')], + parameters=[('KeyName', 'myKeyName'), ('KeyName2', "", True), + ('KeyName3', "", False), ('KeyName4', None, True), + ('KeyName5', "Ignore Me", True)], tags={'TagKey': 'TagValue'}, notification_arns=['arn:notify1', 'arn:notify2'], disable_rollback=True, @@ -149,6 +151,14 @@ class TestCloudFormationUpdateStack(CloudFormationConnectionBase): 'NotificationARNs.member.2': 'arn:notify2', 'Parameters.member.1.ParameterKey': 'KeyName', 'Parameters.member.1.ParameterValue': 'myKeyName', + 'Parameters.member.2.ParameterKey': 'KeyName2', + 'Parameters.member.2.UsePreviousValue': 'true', + 'Parameters.member.3.ParameterKey': 'KeyName3', + 'Parameters.member.3.ParameterValue': '', + 'Parameters.member.4.UsePreviousValue': 'true', + 'Parameters.member.4.ParameterKey': 'KeyName4', + 'Parameters.member.5.UsePreviousValue': 'true', + 'Parameters.member.5.ParameterKey': 'KeyName5', 'Tags.member.1.Key': 'TagKey', 'Tags.member.1.Value': 'TagValue', 'StackName': 'stack_name', |