Repository: Sceptre/sceptre

Issue:
DisableRollback not fully implemented in stack updates
### Subject of the issue
DisableRollback is handled only during the creation of a stack and not for stack updates. This appears to be an oversight. It is already half-implemented in the CLI.

### Your environment
* version of sceptre (sceptre --version)
* version of python (python --version)
* which OS/distro

### Steps to reproduce
Tell us how to reproduce this issue. Please provide sceptre projct files if possible,
you can use https://plnkr.co/edit/ANFHm61Ilt4mQVgF as a base.

### Expected behaviour
Update stack should handle DisableRollback if passed. 
### Actual behaviour
Nothing.

Discussion:

Patch:
diff --git a/sceptre/cli/update.py b/sceptre/cli/update.py
index 35d4239..1502422 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 7b7fd57..08994c4 100644
--- a/sceptre/plan/actions.py
+++ b/sceptre/plan/actions.py
@@ -139,6 +139,12 @@ class StackActions:
                     {"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(


Test patch:
diff --git a/tests/test_actions.py b/tests/test_actions.py
index 9e66b76..877ed39 100644
--- a/tests/test_actions.py
+++ b/tests/test_actions.py
@@ -275,6 +275,44 @@ class TestStackActions(object):
             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)