diff --git a/moto/cloudformation/exceptions.py b/moto/cloudformation/exceptions.py index 8e34b84a8..de672d8b8 100644 --- a/moto/cloudformation/exceptions.py +++ b/moto/cloudformation/exceptions.py @@ -9,12 +9,15 @@ class UnformattedGetAttTemplateException(Exception): class ValidationError(BadRequest): - def __init__(self, name_or_id): + def __init__(self, name_or_id, message=None): + if message is None: + messgae="Stack:{0} does not exist".format(name_or_id), + template = Template(ERROR_RESPONSE) super(ValidationError, self).__init__() self.description = template.render( code="ValidationError", - message="Stack:{0} does not exist".format(name_or_id), + message=message, ) diff --git a/moto/cloudformation/responses.py b/moto/cloudformation/responses.py index 711d6f82e..e407be9d2 100644 --- a/moto/cloudformation/responses.py +++ b/moto/cloudformation/responses.py @@ -129,6 +129,10 @@ class CloudFormationResponse(BaseResponse): else: stack_body = self._get_param('TemplateBody') + stack = self.cloudformation_backend.get_stack(stack_name) + if stack.status == 'ROLLBACK_COMPLETE': + raise ValidationError(stack.stack_id, message="Stack:{0} is in ROLLBACK_COMPLETE state and can not be updated.".format(stack.stack_id)) + stack = self.cloudformation_backend.update_stack( name=stack_name, template=stack_body, diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud.py b/tests/test_cloudformation/test_cloudformation_stack_crud.py index 26084c7b4..e516d92dc 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud.py @@ -13,6 +13,7 @@ import tests.backport_assert_raises # noqa from nose.tools import assert_raises from moto import mock_cloudformation, mock_s3 +from moto.cloudformation import cloudformation_backends dummy_template = { "AWSTemplateFormatVersion": "2010-09-09", @@ -286,6 +287,7 @@ def test_update_stack(): } }) + @mock_cloudformation def test_update_stack(): conn = boto.connect_cloudformation() @@ -307,3 +309,20 @@ def test_update_stack(): } } }) + + +@mock_cloudformation +def test_update_stack_when_rolled_back(): + conn = boto.connect_cloudformation() + stack_id = conn.create_stack("test_stack", template_body=dummy_template_json) + + cloudformation_backends[conn.region.name].stacks[stack_id].status = 'ROLLBACK_COMPLETE' + + with assert_raises(BotoServerError) as err: + conn.update_stack("test_stack", dummy_template_json) + + ex = err.exception + ex.body.should.match(r'is in ROLLBACK_COMPLETE state and can not be updated') + ex.error_code.should.equal('ValidationError') + ex.reason.should.equal('Bad Request') + ex.status.should.equal(400)