diff --git a/sceptre/cli/update.py b/sceptre/cli/update.py index 35d4239ae..150242299 100644 --- a/sceptre/cli/update.py +++ b/sceptre/cli/update.py @@ -41,6 +41,7 @@ def update_command( :type verbose: bool :param yes: A flag to answer 'yes' to all CLI questions. :type yes: bool + :param disable_rollback: A flag to disable cloudformation rollback. """ context = SceptreContext( diff --git a/sceptre/plan/actions.py b/sceptre/plan/actions.py index 7b7fd5718..b44af91af 100644 --- a/sceptre/plan/actions.py +++ b/sceptre/plan/actions.py @@ -139,6 +139,10 @@ def update(self): {"Key": str(k), "Value": str(v)} for k, v in self.stack.tags.items() ], } + + if self.stack.disable_rollback: + update_stack_kwargs.update({"DisableRollback": self.stack.disable_rollback}) + update_stack_kwargs.update(self.stack.template.get_boto_call_parameter()) update_stack_kwargs.update(self._get_role_arn()) response = self.connection_manager.call( diff --git a/tests/test_actions.py b/tests/test_actions.py index 9e66b7601..b8688d09c 100644 --- a/tests/test_actions.py +++ b/tests/test_actions.py @@ -275,6 +275,42 @@ def test_update_sends_correct_request(self, mock_wait_for_completion): sentinel.stack_timeout, boto_response=ANY ) + @patch("sceptre.plan.actions.StackActions._wait_for_completion") + @patch("sceptre.plan.actions.StackActions._get_stack_timeout") + def test_update_disable_rollback_overrides_on_failure( + self, mock_get_stack_timeout, mock_wait_for_completion + ): + self.actions.stack._template = Mock(spec=Template) + self.actions.stack._template.get_boto_call_parameter.return_value = { + "Template": sentinel.template + } + + self.actions.stack.on_failure = "ROLLBACK" + self.actions.stack.disable_rollback = True + + mock_get_stack_timeout.return_value = {"TimeoutInMinutes": sentinel.timeout} + + self.actions.update() + self.actions.connection_manager.call.assert_called_with( + service="cloudformation", + command="update_stack", + kwargs={ + "StackName": sentinel.external_name, + "Template": sentinel.template, + "Parameters": [{"ParameterKey": "key1", "ParameterValue": "val1"}], + "Capabilities": [ + "CAPABILITY_IAM", + "CAPABILITY_NAMED_IAM", + "CAPABILITY_AUTO_EXPAND", + ], + "RoleARN": sentinel.cloudformation_service_role, + "NotificationARNs": [sentinel.notification], + "Tags": [{"Key": "tag1", "Value": "val1"}], + "DisableRollback": True, + }, + ) + mock_wait_for_completion.assert_called_once_with(sentinel.stack_timeout, boto_response=ANY) + @patch("sceptre.plan.actions.StackActions._wait_for_completion") def test_update_cancels_after_timeout(self, mock_wait_for_completion): self.actions.stack._template = Mock(spec=Template)