From 57107f8eadc3bed5615ef558fe2edfea00e7722d Mon Sep 17 00:00:00 2001 From: Pepe Fagoaga Date: Wed, 9 Nov 2022 20:42:14 +0100 Subject: [PATCH] CloudFormation: Include EnableTerminationProtection (#5647) --- moto/cloudformation/models.py | 6 ++++++ moto/cloudformation/responses.py | 3 +++ .../test_cloudformation_stack_crud_boto3.py | 18 +++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index 010ae36b3..7c8c030ad 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -242,6 +242,7 @@ class FakeStack(BaseModel): tags: Optional[Dict[str, str]] = None, role_arn: Optional[str] = None, cross_stack_resources: Optional[Dict[str, Export]] = None, + enable_termination_protection: Optional[bool] = False, ): self.stack_id = stack_id self.name = name @@ -262,6 +263,9 @@ class FakeStack(BaseModel): self.policy = "" self.cross_stack_resources: Dict[str, Export] = cross_stack_resources or {} + self.enable_termination_protection: bool = ( + enable_termination_protection or False + ) self.resource_map = self._create_resource_map() self.custom_resources: Dict[str, CustomModel] = dict() @@ -701,6 +705,7 @@ class CloudFormationBackend(BaseBackend): notification_arns: Optional[List[str]] = None, tags: Optional[Dict[str, str]] = None, role_arn: Optional[str] = None, + enable_termination_protection: Optional[bool] = False, ) -> FakeStack: stack_id = generate_stack_id(name, self.region_name, self.account_id) new_stack = FakeStack( @@ -714,6 +719,7 @@ class CloudFormationBackend(BaseBackend): tags=tags, role_arn=role_arn, cross_stack_resources=self.exports, + enable_termination_protection=enable_termination_protection, ) self.stacks[stack_id] = new_stack self._validate_export_uniqueness(new_stack) diff --git a/moto/cloudformation/responses.py b/moto/cloudformation/responses.py index f0be4aeea..eece82f9e 100644 --- a/moto/cloudformation/responses.py +++ b/moto/cloudformation/responses.py @@ -123,6 +123,7 @@ class CloudFormationResponse(BaseResponse): stack_body = self._get_param("TemplateBody") template_url = self._get_param("TemplateURL") role_arn = self._get_param("RoleARN") + enable_termination_protection = self._get_param("EnableTerminationProtection") parameters_list = self._get_list_prefix("Parameters.member") tags = dict( (item["key"], item["value"]) @@ -148,6 +149,7 @@ class CloudFormationResponse(BaseResponse): notification_arns=stack_notification_arns, tags=tags, role_arn=role_arn, + enable_termination_protection=enable_termination_protection, ) if self.request_json: return json.dumps( @@ -835,6 +837,7 @@ DESCRIBE_STACKS_TEMPLATE = """ {% endfor %} + {{ stack.enable_termination_protection }} {% endfor %} diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py index 657446b4c..4fe403d6a 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py @@ -312,9 +312,25 @@ dummy_unknown_template_json = json.dumps(dummy_unknown_template) def test_create_stack(): cf_conn = boto3.client("cloudformation", region_name="us-east-1") cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks()["Stacks"][0] stack.should.have.key("StackName").equal("test_stack") + stack.should.have.key("EnableTerminationProtection").equal(False) + + template = cf_conn.get_template(StackName="test_stack")["TemplateBody"] + template.should.equal(dummy_template) + + +@mock_cloudformation +def test_create_stack_with_termination_protection(): + cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf_conn.create_stack( + StackName="test_stack", + TemplateBody=dummy_template_json, + EnableTerminationProtection=True, + ) + stack = cf_conn.describe_stacks()["Stacks"][0] + stack.should.have.key("StackName").equal("test_stack") + stack.should.have.key("EnableTerminationProtection").equal(True) template = cf_conn.get_template(StackName="test_stack")["TemplateBody"] template.should.equal(dummy_template)