diff --git a/.changes/next-release/bugfix-CloudFormation-69529.json b/.changes/next-release/bugfix-CloudFormation-69529.json new file mode 100644 index 000000000000..e1409b03ca57 --- /dev/null +++ b/.changes/next-release/bugfix-CloudFormation-69529.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "CloudFormation", + "description": "CloudFormation will no longer fail for deploys that take longer than 10 minutes. Fixes `#2754 `__" +} diff --git a/awscli/customizations/cloudformation/deployer.py b/awscli/customizations/cloudformation/deployer.py index b918961947d8..03026d25a0ea 100644 --- a/awscli/customizations/cloudformation/deployer.py +++ b/awscli/customizations/cloudformation/deployer.py @@ -132,9 +132,10 @@ def wait_for_changeset(self, changeset_id, stack_name): # Wait for changeset to be created waiter = self._client.get_waiter("change_set_create_complete") # Poll every 5 seconds. Changeset creation should be fast - waiter.config.delay = 5 + waiter_config = {'Delay': 5} try: - waiter.wait(ChangeSetName=changeset_id, StackName=stack_name) + waiter.wait(ChangeSetName=changeset_id, StackName=stack_name, + WaiterConfig=waiter_config) except botocore.exceptions.WaiterError as ex: LOG.debug("Create changeset waiter exception", exc_info=ex) @@ -178,10 +179,13 @@ def wait_for_execute(self, stack_name, changeset_type): # Poll every 5 seconds. Optimizing for the case when the stack has only # minimal changes, such the Code for Lambda Function - waiter.config.delay = 5 + waiter_config = { + 'Delay': 5, + 'MaxAttempts': 720, + } try: - waiter.wait(StackName=stack_name) + waiter.wait(StackName=stack_name, WaiterConfig=waiter_config) except botocore.exceptions.WaiterError as ex: LOG.debug("Execute changeset waiter exception", exc_info=ex) diff --git a/tests/unit/customizations/cloudformation/test_deployer.py b/tests/unit/customizations/cloudformation/test_deployer.py index 0c85259ccad7..e4299f0c6911 100644 --- a/tests/unit/customizations/cloudformation/test_deployer.py +++ b/tests/unit/customizations/cloudformation/test_deployer.py @@ -254,8 +254,10 @@ def test_wait_for_changeset_no_changes(self): with self.assertRaises(exceptions.ChangeEmptyError): mock_deployer.wait_for_changeset(changeset_id, stack_name) + waiter_config = {'Delay': 5} mock_waiter.wait.assert_called_once_with(ChangeSetName=changeset_id, - StackName=stack_name) + StackName=stack_name, + WaiterConfig=waiter_config) mock_client.get_waiter.assert_called_once_with( "change_set_create_complete") @@ -282,8 +284,10 @@ def test_wait_for_changeset_failed_to_create_changeset(self): with self.assertRaises(RuntimeError): mock_deployer.wait_for_changeset(changeset_id, stack_name) + waiter_config = {'Delay': 5} mock_waiter.wait.assert_called_once_with(ChangeSetName=changeset_id, - StackName=stack_name) + StackName=stack_name, + WaiterConfig=waiter_config) mock_client.get_waiter.assert_called_once_with( "change_set_create_complete") @@ -305,7 +309,12 @@ def test_wait_for_execute_no_changes(self): with self.assertRaises(exceptions.DeployFailedError): mock_deployer.wait_for_execute(stack_name, changeset_type) - mock_waiter.wait.assert_called_once_with(StackName=stack_name) + waiter_config = { + 'Delay': 5, + 'MaxAttempts': 720, + } + mock_waiter.wait.assert_called_once_with(StackName=stack_name, + WaiterConfig=waiter_config) mock_client.get_waiter.assert_called_once_with( "stack_create_complete")