We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
cloudformation deploy fails if new parameters are not overridden even if they have default value
After adding new parameters to the template, it has to be deployed with --parameters-override for all the new parameters even if they have default value, otherwise deploy fails with: 

> An error occurred (ValidationError) when calling the CreateChangeSet operation: Invalid input for parameter key Param2. Cannot specify usePreviousValue as true for a parameter key not in the previous template

To reproduce, deploy simple template:
```
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A hello world application.
Parameters:
  Param1:
    Default: 123
    Type: String
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs4.3
      CodeUri: ./hello.zip
```

add some parameter to it:

```
...
Parameters:
  Param1:
    Default: 123
    Type: String
  Param2:
    Default: 123
    Type: String
...
```

Try to deploy again, it fails with aforementioned error. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `awscli/customizations/cloudformation/deployer.py`
Content:
```
1 # Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"). You
4 # may not use this file except in compliance with the License. A copy of
5 # the License is located at
6 #
7 # http://aws.amazon.com/apache2.0/
8 #
9 # or in the "license" file accompanying this file. This file is
10 # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 # ANY KIND, either express or implied. See the License for the specific
12 # language governing permissions and limitations under the License.
13 
14 import sys
15 import time
16 import logging
17 import botocore
18 import collections
19 
20 from awscli.customizations.cloudformation import exceptions
21 from datetime import datetime
22 
23 LOG = logging.getLogger(__name__)
24 
25 ChangeSetResult = collections.namedtuple(
26                 "ChangeSetResult", ["changeset_id", "changeset_type"])
27 
28 
29 class Deployer(object):
30 
31     def __init__(self, cloudformation_client,
32                  changeset_prefix="awscli-cloudformation-package-deploy-"):
33         self._client = cloudformation_client
34         self.changeset_prefix = changeset_prefix
35 
36     def has_stack(self, stack_name):
37         """
38         Checks if a CloudFormation stack with given name exists
39 
40         :param stack_name: Name or ID of the stack
41         :return: True if stack exists. False otherwise
42         """
43         try:
44             resp = self._client.describe_stacks(StackName=stack_name)
45             if len(resp["Stacks"]) != 1:
46                 return False
47 
48             # When you run CreateChangeSet on a a stack that does not exist,
49             # CloudFormation will create a stack and set it's status
50             # REVIEW_IN_PROGRESS. However this stack is cannot be manipulated
51             # by "update" commands. Under this circumstances, we treat like
52             # this stack does not exist and call CreateChangeSet will
53             # ChangeSetType set to CREATE and not UPDATE.
54             stack = resp["Stacks"][0]
55             return stack["StackStatus"] != "REVIEW_IN_PROGRESS"
56 
57         except botocore.exceptions.ClientError as e:
58             # If a stack does not exist, describe_stacks will throw an
59             # exception. Unfortunately we don't have a better way than parsing
60             # the exception msg to understand the nature of this exception.
61             msg = str(e)
62 
63             if "Stack with id {0} does not exist".format(stack_name) in msg:
64                 LOG.debug("Stack with id {0} does not exist".format(
65                     stack_name))
66                 return False
67             else:
68                 # We don't know anything about this exception. Don't handle
69                 LOG.debug("Unable to get stack details.", exc_info=e)
70                 raise e
71 
72     def create_changeset(self, stack_name, cfn_template,
73                          parameter_values, capabilities, role_arn,
74                          notification_arns):
75         """
76         Call Cloudformation to create a changeset and wait for it to complete
77 
78         :param stack_name: Name or ID of stack
79         :param cfn_template: CloudFormation template string
80         :param parameter_values: Template parameters object
81         :param capabilities: Array of capabilities passed to CloudFormation
82         :return:
83         """
84 
85         now = datetime.utcnow().isoformat()
86         description = "Created by AWS CLI at {0} UTC".format(now)
87 
88         # Each changeset will get a unique name based on time
89         changeset_name = self.changeset_prefix + str(int(time.time()))
90 
91         changeset_type = "UPDATE"
92         if not self.has_stack(stack_name):
93             changeset_type = "CREATE"
94             # When creating a new stack, UsePreviousValue=True is invalid.
95             # For such parameters, users should either override with new value,
96             # or set a Default value in template to successfully create a stack.
97             parameter_values = [x for x in parameter_values
98                                 if not x.get("UsePreviousValue", False)]
99 
100         kwargs = {
101             'ChangeSetName': changeset_name,
102             'StackName': stack_name,
103             'TemplateBody': cfn_template,
104             'ChangeSetType': changeset_type,
105             'Parameters': parameter_values,
106             'Capabilities': capabilities,
107             'Description': description,
108         }
109         # don't set these arguments if not specified to use existing values
110         if role_arn is not None:
111             kwargs['RoleARN'] = role_arn
112         if notification_arns is not None:
113             kwargs['NotificationARNs'] = notification_arns
114         try:
115             resp = self._client.create_change_set(**kwargs)
116             return ChangeSetResult(resp["Id"], changeset_type)
117         except Exception as ex:
118             LOG.debug("Unable to create changeset", exc_info=ex)
119             raise ex
120 
121     def wait_for_changeset(self, changeset_id, stack_name):
122         """
123         Waits until the changeset creation completes
124 
125         :param changeset_id: ID or name of the changeset
126         :param stack_name:   Stack name
127         :return: Latest status of the create-change-set operation
128         """
129         sys.stdout.write("Waiting for changeset to be created..\n")
130         sys.stdout.flush()
131 
132         # Wait for changeset to be created
133         waiter = self._client.get_waiter("change_set_create_complete")
134         # Poll every 5 seconds. Changeset creation should be fast
135         waiter_config = {'Delay': 5}
136         try:
137             waiter.wait(ChangeSetName=changeset_id, StackName=stack_name,
138                         WaiterConfig=waiter_config)
139         except botocore.exceptions.WaiterError as ex:
140             LOG.debug("Create changeset waiter exception", exc_info=ex)
141 
142             resp = ex.last_response
143             status = resp["Status"]
144             reason = resp["StatusReason"]
145 
146             if status == "FAILED" and \
147                "The submitted information didn't contain changes." in reason:
148                     raise exceptions.ChangeEmptyError(stack_name=stack_name)
149 
150             raise RuntimeError("Failed to create the changeset: {0} "
151                                "Status: {1}. Reason: {2}"
152                                .format(ex, status, reason))
153 
154     def execute_changeset(self, changeset_id, stack_name):
155         """
156         Calls CloudFormation to execute changeset
157 
158         :param changeset_id: ID of the changeset
159         :param stack_name: Name or ID of the stack
160         :return: Response from execute-change-set call
161         """
162         return self._client.execute_change_set(
163                 ChangeSetName=changeset_id,
164                 StackName=stack_name)
165 
166     def wait_for_execute(self, stack_name, changeset_type):
167 
168         sys.stdout.write("Waiting for stack create/update to complete\n")
169         sys.stdout.flush()
170 
171         # Pick the right waiter
172         if changeset_type == "CREATE":
173             waiter = self._client.get_waiter("stack_create_complete")
174         elif changeset_type == "UPDATE":
175             waiter = self._client.get_waiter("stack_update_complete")
176         else:
177             raise RuntimeError("Invalid changeset type {0}"
178                                .format(changeset_type))
179 
180         # Poll every 5 seconds. Optimizing for the case when the stack has only
181         # minimal changes, such the Code for Lambda Function
182         waiter_config = {
183             'Delay': 5,
184             'MaxAttempts': 720,
185         }
186 
187         try:
188             waiter.wait(StackName=stack_name, WaiterConfig=waiter_config)
189         except botocore.exceptions.WaiterError as ex:
190             LOG.debug("Execute changeset waiter exception", exc_info=ex)
191 
192             raise exceptions.DeployFailedError(stack_name=stack_name)
193 
194     def create_and_wait_for_changeset(self, stack_name, cfn_template,
195                                       parameter_values, capabilities, role_arn,
196                                       notification_arns):
197 
198         result = self.create_changeset(
199                 stack_name, cfn_template, parameter_values, capabilities,
200                 role_arn, notification_arns)
201 
202         self.wait_for_changeset(result.changeset_id, stack_name)
203 
204         return result
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/awscli/customizations/cloudformation/deployer.py b/awscli/customizations/cloudformation/deployer.py
--- a/awscli/customizations/cloudformation/deployer.py
+++ b/awscli/customizations/cloudformation/deployer.py
@@ -88,7 +88,6 @@
         # Each changeset will get a unique name based on time
         changeset_name = self.changeset_prefix + str(int(time.time()))
 
-        changeset_type = "UPDATE"
         if not self.has_stack(stack_name):
             changeset_type = "CREATE"
             # When creating a new stack, UsePreviousValue=True is invalid.
@@ -96,6 +95,15 @@
             # or set a Default value in template to successfully create a stack.
             parameter_values = [x for x in parameter_values
                                 if not x.get("UsePreviousValue", False)]
+        else:
+            changeset_type = "UPDATE"
+            # UsePreviousValue not valid if parameter is new
+            summary = self._client.get_template_summary(StackName=stack_name)
+            existing_parameters = [parameter['ParameterKey'] for parameter in \
+                                   summary['Parameters']]
+            parameter_values = [x for x in parameter_values
+                                if not (x.get("UsePreviousValue", False) and \
+                                x["ParameterKey"] not in existing_parameters)]
 
         kwargs = {
             'ChangeSetName': changeset_name,

{"golden_diff": "diff --git a/awscli/customizations/cloudformation/deployer.py b/awscli/customizations/cloudformation/deployer.py\n--- a/awscli/customizations/cloudformation/deployer.py\n+++ b/awscli/customizations/cloudformation/deployer.py\n@@ -88,7 +88,6 @@\n         # Each changeset will get a unique name based on time\n         changeset_name = self.changeset_prefix + str(int(time.time()))\n \n-        changeset_type = \"UPDATE\"\n         if not self.has_stack(stack_name):\n             changeset_type = \"CREATE\"\n             # When creating a new stack, UsePreviousValue=True is invalid.\n@@ -96,6 +95,15 @@\n             # or set a Default value in template to successfully create a stack.\n             parameter_values = [x for x in parameter_values\n                                 if not x.get(\"UsePreviousValue\", False)]\n+        else:\n+            changeset_type = \"UPDATE\"\n+            # UsePreviousValue not valid if parameter is new\n+            summary = self._client.get_template_summary(StackName=stack_name)\n+            existing_parameters = [parameter['ParameterKey'] for parameter in \\\n+                                   summary['Parameters']]\n+            parameter_values = [x for x in parameter_values\n+                                if not (x.get(\"UsePreviousValue\", False) and \\\n+                                x[\"ParameterKey\"] not in existing_parameters)]\n \n         kwargs = {\n             'ChangeSetName': changeset_name,\n", "issue": "cloudformation deploy fails if new parameters are not overridden even if they have default value\nAfter adding new parameters to the template, it has to be deployed with --parameters-override for all the new parameters even if they have default value, otherwise deploy fails with: \r\n\r\n> An error occurred (ValidationError) when calling the CreateChangeSet operation: Invalid input for parameter key Param2. Cannot specify usePreviousValue as true for a parameter key not in the previous template\r\n\r\nTo reproduce, deploy simple template:\r\n```\r\nAWSTemplateFormatVersion : '2010-09-09'\r\nTransform: AWS::Serverless-2016-10-31\r\nDescription: A hello world application.\r\nParameters:\r\n  Param1:\r\n    Default: 123\r\n    Type: String\r\nResources:\r\n  HelloWorldFunction:\r\n    Type: AWS::Serverless::Function\r\n    Properties:\r\n      Handler: index.handler\r\n      Runtime: nodejs4.3\r\n      CodeUri: ./hello.zip\r\n```\r\n\r\nadd some parameter to it:\r\n\r\n```\r\n...\r\nParameters:\r\n  Param1:\r\n    Default: 123\r\n    Type: String\r\n  Param2:\r\n    Default: 123\r\n    Type: String\r\n...\r\n```\r\n\r\nTry to deploy again, it fails with aforementioned error. \n", "before_files": [{"content": "# Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n# http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\n\nimport sys\nimport time\nimport logging\nimport botocore\nimport collections\n\nfrom awscli.customizations.cloudformation import exceptions\nfrom datetime import datetime\n\nLOG = logging.getLogger(__name__)\n\nChangeSetResult = collections.namedtuple(\n                \"ChangeSetResult\", [\"changeset_id\", \"changeset_type\"])\n\n\nclass Deployer(object):\n\n    def __init__(self, cloudformation_client,\n                 changeset_prefix=\"awscli-cloudformation-package-deploy-\"):\n        self._client = cloudformation_client\n        self.changeset_prefix = changeset_prefix\n\n    def has_stack(self, stack_name):\n        \"\"\"\n        Checks if a CloudFormation stack with given name exists\n\n        :param stack_name: Name or ID of the stack\n        :return: True if stack exists. False otherwise\n        \"\"\"\n        try:\n            resp = self._client.describe_stacks(StackName=stack_name)\n            if len(resp[\"Stacks\"]) != 1:\n                return False\n\n            # When you run CreateChangeSet on a a stack that does not exist,\n            # CloudFormation will create a stack and set it's status\n            # REVIEW_IN_PROGRESS. However this stack is cannot be manipulated\n            # by \"update\" commands. Under this circumstances, we treat like\n            # this stack does not exist and call CreateChangeSet will\n            # ChangeSetType set to CREATE and not UPDATE.\n            stack = resp[\"Stacks\"][0]\n            return stack[\"StackStatus\"] != \"REVIEW_IN_PROGRESS\"\n\n        except botocore.exceptions.ClientError as e:\n            # If a stack does not exist, describe_stacks will throw an\n            # exception. Unfortunately we don't have a better way than parsing\n            # the exception msg to understand the nature of this exception.\n            msg = str(e)\n\n            if \"Stack with id {0} does not exist\".format(stack_name) in msg:\n                LOG.debug(\"Stack with id {0} does not exist\".format(\n                    stack_name))\n                return False\n            else:\n                # We don't know anything about this exception. Don't handle\n                LOG.debug(\"Unable to get stack details.\", exc_info=e)\n                raise e\n\n    def create_changeset(self, stack_name, cfn_template,\n                         parameter_values, capabilities, role_arn,\n                         notification_arns):\n        \"\"\"\n        Call Cloudformation to create a changeset and wait for it to complete\n\n        :param stack_name: Name or ID of stack\n        :param cfn_template: CloudFormation template string\n        :param parameter_values: Template parameters object\n        :param capabilities: Array of capabilities passed to CloudFormation\n        :return:\n        \"\"\"\n\n        now = datetime.utcnow().isoformat()\n        description = \"Created by AWS CLI at {0} UTC\".format(now)\n\n        # Each changeset will get a unique name based on time\n        changeset_name = self.changeset_prefix + str(int(time.time()))\n\n        changeset_type = \"UPDATE\"\n        if not self.has_stack(stack_name):\n            changeset_type = \"CREATE\"\n            # When creating a new stack, UsePreviousValue=True is invalid.\n            # For such parameters, users should either override with new value,\n            # or set a Default value in template to successfully create a stack.\n            parameter_values = [x for x in parameter_values\n                                if not x.get(\"UsePreviousValue\", False)]\n\n        kwargs = {\n            'ChangeSetName': changeset_name,\n            'StackName': stack_name,\n            'TemplateBody': cfn_template,\n            'ChangeSetType': changeset_type,\n            'Parameters': parameter_values,\n            'Capabilities': capabilities,\n            'Description': description,\n        }\n        # don't set these arguments if not specified to use existing values\n        if role_arn is not None:\n            kwargs['RoleARN'] = role_arn\n        if notification_arns is not None:\n            kwargs['NotificationARNs'] = notification_arns\n        try:\n            resp = self._client.create_change_set(**kwargs)\n            return ChangeSetResult(resp[\"Id\"], changeset_type)\n        except Exception as ex:\n            LOG.debug(\"Unable to create changeset\", exc_info=ex)\n            raise ex\n\n    def wait_for_changeset(self, changeset_id, stack_name):\n        \"\"\"\n        Waits until the changeset creation completes\n\n        :param changeset_id: ID or name of the changeset\n        :param stack_name:   Stack name\n        :return: Latest status of the create-change-set operation\n        \"\"\"\n        sys.stdout.write(\"Waiting for changeset to be created..\\n\")\n        sys.stdout.flush()\n\n        # Wait for changeset to be created\n        waiter = self._client.get_waiter(\"change_set_create_complete\")\n        # Poll every 5 seconds. Changeset creation should be fast\n        waiter_config = {'Delay': 5}\n        try:\n            waiter.wait(ChangeSetName=changeset_id, StackName=stack_name,\n                        WaiterConfig=waiter_config)\n        except botocore.exceptions.WaiterError as ex:\n            LOG.debug(\"Create changeset waiter exception\", exc_info=ex)\n\n            resp = ex.last_response\n            status = resp[\"Status\"]\n            reason = resp[\"StatusReason\"]\n\n            if status == \"FAILED\" and \\\n               \"The submitted information didn't contain changes.\" in reason:\n                    raise exceptions.ChangeEmptyError(stack_name=stack_name)\n\n            raise RuntimeError(\"Failed to create the changeset: {0} \"\n                               \"Status: {1}. Reason: {2}\"\n                               .format(ex, status, reason))\n\n    def execute_changeset(self, changeset_id, stack_name):\n        \"\"\"\n        Calls CloudFormation to execute changeset\n\n        :param changeset_id: ID of the changeset\n        :param stack_name: Name or ID of the stack\n        :return: Response from execute-change-set call\n        \"\"\"\n        return self._client.execute_change_set(\n                ChangeSetName=changeset_id,\n                StackName=stack_name)\n\n    def wait_for_execute(self, stack_name, changeset_type):\n\n        sys.stdout.write(\"Waiting for stack create/update to complete\\n\")\n        sys.stdout.flush()\n\n        # Pick the right waiter\n        if changeset_type == \"CREATE\":\n            waiter = self._client.get_waiter(\"stack_create_complete\")\n        elif changeset_type == \"UPDATE\":\n            waiter = self._client.get_waiter(\"stack_update_complete\")\n        else:\n            raise RuntimeError(\"Invalid changeset type {0}\"\n                               .format(changeset_type))\n\n        # Poll every 5 seconds. Optimizing for the case when the stack has only\n        # minimal changes, such the Code for Lambda Function\n        waiter_config = {\n            'Delay': 5,\n            'MaxAttempts': 720,\n        }\n\n        try:\n            waiter.wait(StackName=stack_name, WaiterConfig=waiter_config)\n        except botocore.exceptions.WaiterError as ex:\n            LOG.debug(\"Execute changeset waiter exception\", exc_info=ex)\n\n            raise exceptions.DeployFailedError(stack_name=stack_name)\n\n    def create_and_wait_for_changeset(self, stack_name, cfn_template,\n                                      parameter_values, capabilities, role_arn,\n                                      notification_arns):\n\n        result = self.create_changeset(\n                stack_name, cfn_template, parameter_values, capabilities,\n                role_arn, notification_arns)\n\n        self.wait_for_changeset(result.changeset_id, stack_name)\n\n        return result\n", "path": "awscli/customizations/cloudformation/deployer.py"}], "after_files": [{"content": "# Copyright 2012-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\"). You\n# may not use this file except in compliance with the License. A copy of\n# the License is located at\n#\n# http://aws.amazon.com/apache2.0/\n#\n# or in the \"license\" file accompanying this file. This file is\n# distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF\n# ANY KIND, either express or implied. See the License for the specific\n# language governing permissions and limitations under the License.\n\nimport sys\nimport time\nimport logging\nimport botocore\nimport collections\n\nfrom awscli.customizations.cloudformation import exceptions\nfrom datetime import datetime\n\nLOG = logging.getLogger(__name__)\n\nChangeSetResult = collections.namedtuple(\n                \"ChangeSetResult\", [\"changeset_id\", \"changeset_type\"])\n\n\nclass Deployer(object):\n\n    def __init__(self, cloudformation_client,\n                 changeset_prefix=\"awscli-cloudformation-package-deploy-\"):\n        self._client = cloudformation_client\n        self.changeset_prefix = changeset_prefix\n\n    def has_stack(self, stack_name):\n        \"\"\"\n        Checks if a CloudFormation stack with given name exists\n\n        :param stack_name: Name or ID of the stack\n        :return: True if stack exists. False otherwise\n        \"\"\"\n        try:\n            resp = self._client.describe_stacks(StackName=stack_name)\n            if len(resp[\"Stacks\"]) != 1:\n                return False\n\n            # When you run CreateChangeSet on a a stack that does not exist,\n            # CloudFormation will create a stack and set it's status\n            # REVIEW_IN_PROGRESS. However this stack is cannot be manipulated\n            # by \"update\" commands. Under this circumstances, we treat like\n            # this stack does not exist and call CreateChangeSet will\n            # ChangeSetType set to CREATE and not UPDATE.\n            stack = resp[\"Stacks\"][0]\n            return stack[\"StackStatus\"] != \"REVIEW_IN_PROGRESS\"\n\n        except botocore.exceptions.ClientError as e:\n            # If a stack does not exist, describe_stacks will throw an\n            # exception. Unfortunately we don't have a better way than parsing\n            # the exception msg to understand the nature of this exception.\n            msg = str(e)\n\n            if \"Stack with id {0} does not exist\".format(stack_name) in msg:\n                LOG.debug(\"Stack with id {0} does not exist\".format(\n                    stack_name))\n                return False\n            else:\n                # We don't know anything about this exception. Don't handle\n                LOG.debug(\"Unable to get stack details.\", exc_info=e)\n                raise e\n\n    def create_changeset(self, stack_name, cfn_template,\n                         parameter_values, capabilities, role_arn,\n                         notification_arns):\n        \"\"\"\n        Call Cloudformation to create a changeset and wait for it to complete\n\n        :param stack_name: Name or ID of stack\n        :param cfn_template: CloudFormation template string\n        :param parameter_values: Template parameters object\n        :param capabilities: Array of capabilities passed to CloudFormation\n        :return:\n        \"\"\"\n\n        now = datetime.utcnow().isoformat()\n        description = \"Created by AWS CLI at {0} UTC\".format(now)\n\n        # Each changeset will get a unique name based on time\n        changeset_name = self.changeset_prefix + str(int(time.time()))\n\n        if not self.has_stack(stack_name):\n            changeset_type = \"CREATE\"\n            # When creating a new stack, UsePreviousValue=True is invalid.\n            # For such parameters, users should either override with new value,\n            # or set a Default value in template to successfully create a stack.\n            parameter_values = [x for x in parameter_values\n                                if not x.get(\"UsePreviousValue\", False)]\n        else:\n            changeset_type = \"UPDATE\"\n            # UsePreviousValue not valid if parameter is new\n            summary = self._client.get_template_summary(StackName=stack_name)\n            existing_parameters = [parameter['ParameterKey'] for parameter in \\\n                                   summary['Parameters']]\n            parameter_values = [x for x in parameter_values\n                                if not (x.get(\"UsePreviousValue\", False) and \\\n                                x[\"ParameterKey\"] not in existing_parameters)]\n\n        kwargs = {\n            'ChangeSetName': changeset_name,\n            'StackName': stack_name,\n            'TemplateBody': cfn_template,\n            'ChangeSetType': changeset_type,\n            'Parameters': parameter_values,\n            'Capabilities': capabilities,\n            'Description': description,\n        }\n        # don't set these arguments if not specified to use existing values\n        if role_arn is not None:\n            kwargs['RoleARN'] = role_arn\n        if notification_arns is not None:\n            kwargs['NotificationARNs'] = notification_arns\n        try:\n            resp = self._client.create_change_set(**kwargs)\n            return ChangeSetResult(resp[\"Id\"], changeset_type)\n        except Exception as ex:\n            LOG.debug(\"Unable to create changeset\", exc_info=ex)\n            raise ex\n\n    def wait_for_changeset(self, changeset_id, stack_name):\n        \"\"\"\n        Waits until the changeset creation completes\n\n        :param changeset_id: ID or name of the changeset\n        :param stack_name:   Stack name\n        :return: Latest status of the create-change-set operation\n        \"\"\"\n        sys.stdout.write(\"Waiting for changeset to be created..\\n\")\n        sys.stdout.flush()\n\n        # Wait for changeset to be created\n        waiter = self._client.get_waiter(\"change_set_create_complete\")\n        # Poll every 5 seconds. Changeset creation should be fast\n        waiter_config = {'Delay': 5}\n        try:\n            waiter.wait(ChangeSetName=changeset_id, StackName=stack_name,\n                        WaiterConfig=waiter_config)\n        except botocore.exceptions.WaiterError as ex:\n            LOG.debug(\"Create changeset waiter exception\", exc_info=ex)\n\n            resp = ex.last_response\n            status = resp[\"Status\"]\n            reason = resp[\"StatusReason\"]\n\n            if status == \"FAILED\" and \\\n               \"The submitted information didn't contain changes.\" in reason:\n                    raise exceptions.ChangeEmptyError(stack_name=stack_name)\n\n            raise RuntimeError(\"Failed to create the changeset: {0} \"\n                               \"Status: {1}. Reason: {2}\"\n                               .format(ex, status, reason))\n\n    def execute_changeset(self, changeset_id, stack_name):\n        \"\"\"\n        Calls CloudFormation to execute changeset\n\n        :param changeset_id: ID of the changeset\n        :param stack_name: Name or ID of the stack\n        :return: Response from execute-change-set call\n        \"\"\"\n        return self._client.execute_change_set(\n                ChangeSetName=changeset_id,\n                StackName=stack_name)\n\n    def wait_for_execute(self, stack_name, changeset_type):\n\n        sys.stdout.write(\"Waiting for stack create/update to complete\\n\")\n        sys.stdout.flush()\n\n        # Pick the right waiter\n        if changeset_type == \"CREATE\":\n            waiter = self._client.get_waiter(\"stack_create_complete\")\n        elif changeset_type == \"UPDATE\":\n            waiter = self._client.get_waiter(\"stack_update_complete\")\n        else:\n            raise RuntimeError(\"Invalid changeset type {0}\"\n                               .format(changeset_type))\n\n        # Poll every 5 seconds. Optimizing for the case when the stack has only\n        # minimal changes, such the Code for Lambda Function\n        waiter_config = {\n            'Delay': 5,\n            'MaxAttempts': 720,\n        }\n\n        try:\n            waiter.wait(StackName=stack_name, WaiterConfig=waiter_config)\n        except botocore.exceptions.WaiterError as ex:\n            LOG.debug(\"Execute changeset waiter exception\", exc_info=ex)\n\n            raise exceptions.DeployFailedError(stack_name=stack_name)\n\n    def create_and_wait_for_changeset(self, stack_name, cfn_template,\n                                      parameter_values, capabilities, role_arn,\n                                      notification_arns):\n\n        result = self.create_changeset(\n                stack_name, cfn_template, parameter_values, capabilities,\n                role_arn, notification_arns)\n\n        self.wait_for_changeset(result.changeset_id, stack_name)\n\n        return result\n", "path": "awscli/customizations/cloudformation/deployer.py"}]}