From 1c8f5f4949bb350183506810d2c581dc590f70c2 Mon Sep 17 00:00:00 2001 From: rafcio19 Date: Thu, 4 Jan 2024 16:27:24 +0100 Subject: [PATCH] Cloudformation: broken changeset update (#7180) --- moto/cloudformation/models.py | 19 +- moto/s3control/config.py | 2 +- .../test_cloudformation_stack_crud_boto3.py | 405 ++++++++++-------- 3 files changed, 230 insertions(+), 196 deletions(-) diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index 296919853..1d6e18053 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -384,11 +384,12 @@ class FakeStack(CloudFormationModel): self.name = name self.account_id = account_id self.template = template + self.template_dict: Dict[str, Any] if template != {}: self._parse_template() self.description = self.template_dict.get("Description") else: - self.template_dict: Dict[str, Any] = {} + self.template_dict = {} self.description = None self.parameters = parameters self.region_name = region_name @@ -412,12 +413,8 @@ class FakeStack(CloudFormationModel): self.status = "CREATE_PENDING" def has_template(self, other_template: str) -> bool: - our_template = ( - self.template - if isinstance(self.template, dict) - else json.loads(self.template) - ) - return our_template == json.loads(other_template) + self._parse_template() + return self.template_dict == self.parse_template(other_template) def has_parameters(self, other_parameters: Dict[str, Any]) -> bool: return self.parameters == other_parameters @@ -465,11 +462,15 @@ class FakeStack(CloudFormationModel): self.events.append(event) def _parse_template(self) -> None: + self.template_dict = self.parse_template(self.template) # type: ignore[arg-type] + + @staticmethod + def parse_template(template: str) -> Dict[str, Any]: # type: ignore[misc] yaml.add_multi_constructor("", yaml_tag_constructor) try: - self.template_dict = yaml.load(self.template, Loader=yaml.Loader) # type: ignore[arg-type] + return yaml.load(template, Loader=yaml.Loader) except (ParserError, ScannerError): - self.template_dict = json.loads(self.template) # type: ignore[arg-type] + return json.loads(template) @property def stack_parameters(self) -> Dict[str, Any]: # type: ignore[misc] diff --git a/moto/s3control/config.py b/moto/s3control/config.py index 0f17b4a88..203b5e845 100644 --- a/moto/s3control/config.py +++ b/moto/s3control/config.py @@ -131,7 +131,7 @@ class S3AccountPublicAccessBlockConfigQuery(ConfigQueryModel[S3ControlBackend]): # Format the PAB to the AWS Config format: creation_time = utcnow() - config_data = { + config_data: Dict[str, Any] = { "version": "1.3", "accountId": account_id, "configurationItemCaptureTime": str(creation_time), diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py index fcbfac2c0..9e3002b5d 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py @@ -24,6 +24,9 @@ from moto.cloudformation import cloudformation_backends from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID from tests import EXAMPLE_AMI_ID +TEST_STACK_NAME = "test_stack" +REGION_NAME = "us-east-1" + dummy_template = { "AWSTemplateFormatVersion": "2010-09-09", "Description": "Stack 1", @@ -120,6 +123,21 @@ Resources: Parameters: """ +dummy_update_template_yaml = """--- +AWSTemplateFormatVersion: '2010-09-09' +Parameters: + KeyName: + Description: Name of an existing EC2 KeyPair + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: must be the name of an existing EC2 KeyPair. +Resources: + Instance: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-12c6146b + +""" + dummy_template_yaml_with_short_form_func = """--- AWSTemplateFormatVersion: 2010-09-09 Description: Stack1 with yaml template @@ -310,27 +328,27 @@ dummy_unknown_template_json = json.dumps(dummy_unknown_template) @mock_cloudformation @mock_ec2 def test_create_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) stack = cf.describe_stacks()["Stacks"][0] - assert stack["StackName"] == "test_stack" + assert stack["StackName"] == TEST_STACK_NAME assert stack["EnableTerminationProtection"] is False - template = cf.get_template(StackName="test_stack")["TemplateBody"] + template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"] assert template == dummy_template @mock_cloudformation def test_create_stack_with_additional_properties(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, EnableTerminationProtection=True, TimeoutInMinutes=25, ) stack = cf.describe_stacks()["Stacks"][0] - assert stack["StackName"] == "test_stack" + assert stack["StackName"] == TEST_STACK_NAME assert stack["EnableTerminationProtection"] is True assert stack["TimeoutInMinutes"] == 25 @@ -338,7 +356,7 @@ def test_create_stack_with_additional_properties(): @mock_cloudformation @mock_ec2 def test_describe_stack_instances(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_instances( StackSetName="teststackset", @@ -366,7 +384,7 @@ def test_describe_stack_instances(): @mock_cloudformation def test_list_stacksets_length(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_set(StackSetName="teststackset2", TemplateBody=dummy_template_yaml) stacksets = cf.list_stack_sets() @@ -375,10 +393,10 @@ def test_list_stacksets_length(): @mock_cloudformation def test_filter_stacks(): - conn = boto3.client("cloudformation", region_name="us-east-1") - conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + conn = boto3.client("cloudformation", region_name=REGION_NAME) + conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) conn.create_stack(StackName="test_stack2", TemplateBody=dummy_template_json) - conn.update_stack(StackName="test_stack", TemplateBody=dummy_template_json2) + conn.update_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json2) stacks = conn.list_stacks(StackStatusFilter=["CREATE_COMPLETE"]) assert len(stacks.get("StackSummaries")) == 1 @@ -388,7 +406,7 @@ def test_filter_stacks(): @mock_cloudformation def test_list_stacksets_contents(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) stacksets = cf.list_stack_sets() assert stacksets["Summaries"][0]["StackSetName"] == "teststackset" @@ -397,7 +415,7 @@ def test_list_stacksets_contents(): @mock_cloudformation def test_stop_stack_set_operation(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_instances( StackSetName="teststackset", @@ -414,7 +432,7 @@ def test_stop_stack_set_operation(): @mock_cloudformation def test_describe_stack_set_operation(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="name", TemplateBody=dummy_template_json) operation_id = cf.create_stack_instances( StackSetName="name", @@ -443,7 +461,7 @@ def test_describe_stack_set_operation(): @mock_cloudformation def test_list_stack_set_operation_results(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_instances( StackSetName="teststackset", @@ -466,7 +484,7 @@ def test_list_stack_set_operation_results(): @mock_cloudformation def test_update_stack_instances(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -524,7 +542,7 @@ def test_update_stack_instances(): @mock_cloudformation def test_delete_stack_instances(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) tss = "teststackset" cf.create_stack_set(StackSetName=tss, TemplateBody=dummy_template_json) cf.create_stack_instances( @@ -565,7 +583,7 @@ def test_delete_stack_instances(): @mock_cloudformation def test_create_stack_instances(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_instances( StackSetName="teststackset", @@ -580,7 +598,7 @@ def test_create_stack_instances(): @mock_cloudformation def test_create_stack_instances_with_param_overrides(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -615,7 +633,7 @@ def test_create_stack_instances_with_param_overrides(): @mock_cloudformation def test_update_stack_set(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -645,7 +663,7 @@ def test_update_stack_set(): @mock_cloudformation def test_update_stack_set_with_previous_value(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -675,7 +693,7 @@ def test_update_stack_set_with_previous_value(): @mock_cloudformation def test_list_stack_set_operations(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.create_stack_instances( StackSetName="teststackset", @@ -695,7 +713,7 @@ def test_list_stack_set_operations(): @mock_cloudformation def test_bad_list_stack_resources(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) with pytest.raises(ClientError): cf.list_stack_resources(StackName="teststackset") @@ -703,7 +721,7 @@ def test_bad_list_stack_resources(): @mock_cloudformation def test_delete_stack_set_by_name(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) cf.delete_stack_set(StackSetName="teststackset") @@ -721,7 +739,7 @@ def test_delete_stack_set_by_name(): @mock_cloudformation def test_delete_stack_set_by_id(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) response = cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_json ) @@ -736,7 +754,7 @@ def test_delete_stack_set_by_id(): @mock_cloudformation def test_delete_stack_set__while_instances_are_running(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="a", TemplateBody=json.dumps(dummy_template3)) cf.create_stack_instances( StackSetName="a", @@ -762,7 +780,7 @@ def test_delete_stack_set__while_instances_are_running(): @mock_cloudformation def test_create_stack_set(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) response = cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_json, @@ -780,7 +798,7 @@ def test_create_stack_set(): @mock_cloudformation @pytest.mark.parametrize("name", ["1234", "stack_set", "-set"]) def test_create_stack_set__invalid_name(name): - client = boto3.client("cloudformation", region_name="us-east-1") + client = boto3.client("cloudformation", region_name=REGION_NAME) with pytest.raises(ClientError) as exc: client.create_stack_set(StackSetName=name) err = exc.value.response["Error"] @@ -793,7 +811,7 @@ def test_create_stack_set__invalid_name(name): @mock_cloudformation def test_create_stack_set_with_yaml(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack_set(StackSetName="tss", TemplateBody=dummy_template_yaml) tmplt = cf.describe_stack_set(StackSetName="tss")["StackSet"]["TemplateBody"] @@ -803,8 +821,8 @@ def test_create_stack_set_with_yaml(): @mock_cloudformation @mock_s3 def test_create_stack_set_from_s3_url(): - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) s3_conn.create_bucket(Bucket="foobar") s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json) @@ -820,7 +838,7 @@ def test_create_stack_set_from_s3_url(): @mock_cloudformation def test_create_stack_set_with_ref_yaml(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, @@ -837,7 +855,7 @@ def test_create_stack_set_with_ref_yaml(): @mock_cloudformation def test_describe_stack_set_params(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, @@ -854,7 +872,7 @@ def test_describe_stack_set_params(): @mock_cloudformation def test_describe_stack_set_by_id(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) ss_id = cf.create_stack_set(StackSetName="s", TemplateBody=dummy_template_json)[ "StackSetId" ] @@ -865,7 +883,7 @@ def test_describe_stack_set_by_id(): @mock_cloudformation def test_create_stack_fail_missing_parameter(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) with pytest.raises(ClientError, match="Missing parameter KeyName"): cf.create_stack(StackName="ts", TemplateBody=dummy_parametrized_template_json) @@ -873,7 +891,7 @@ def test_create_stack_fail_missing_parameter(): @mock_cloudformation def test_create_stack_s3_long_name(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) stack_name = "MyLongStackName01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" @@ -897,7 +915,7 @@ def test_create_stack_s3_long_name(): @mock_cloudformation def test_create_stack_with_yaml(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack(StackName="ts", TemplateBody=dummy_template_yaml) assert cf.get_template(StackName="ts")["TemplateBody"] == dummy_template_yaml @@ -905,7 +923,7 @@ def test_create_stack_with_yaml(): @mock_cloudformation def test_create_stack_with_short_form_func_yaml(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="ts", TemplateBody=dummy_template_yaml_with_short_form_func ) @@ -917,11 +935,11 @@ def test_create_stack_with_short_form_func_yaml(): @mock_s3 @mock_cloudformation def test_get_template_summary(): - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) # json template - conn = boto3.client("cloudformation", region_name="us-east-1") + conn = boto3.client("cloudformation", region_name=REGION_NAME) result = conn.get_template_summary(TemplateBody=json.dumps(dummy_template3)) assert result["ResourceTypes"] == ["AWS::EC2::VPC"] assert result["Version"] == "2010-09-09" @@ -929,8 +947,10 @@ def test_get_template_summary(): assert result["Parameters"] == [] # existing stack - conn.create_stack(StackName="test_stack", TemplateBody=json.dumps(dummy_template3)) - result = conn.get_template_summary(StackName="test_stack") + conn.create_stack( + StackName=TEST_STACK_NAME, TemplateBody=json.dumps(dummy_template3) + ) + result = conn.get_template_summary(StackName=TEST_STACK_NAME) assert result["ResourceTypes"] == ["AWS::EC2::VPC"] assert result["Version"] == "2010-09-09" assert result["Description"] == "Stack 3" @@ -949,7 +969,7 @@ def test_get_template_summary(): assert result["Description"] == "Stack 3" # yaml template - conn = boto3.client("cloudformation", region_name="us-east-1") + conn = boto3.client("cloudformation", region_name=REGION_NAME) result = conn.get_template_summary(TemplateBody=dummy_template_yaml) assert result["ResourceTypes"] == ["AWS::EC2::Instance"] assert result["Version"] == "2010-09-09" @@ -958,7 +978,7 @@ def test_get_template_summary(): @mock_cloudformation def test_get_template_summary_for_stack_created_by_changeset_execution(): - conn = boto3.client("cloudformation", region_name="us-east-1") + conn = boto3.client("cloudformation", region_name=REGION_NAME) conn.create_change_set( StackName="stack_from_changeset", TemplateBody=json.dumps(dummy_template3), @@ -980,11 +1000,12 @@ def test_get_template_summary_for_stack_created_by_changeset_execution(): @mock_s3 @mock_cloudformation def test_get_template_summary_for_template_containing_parameters(): - conn = boto3.client("cloudformation", region_name="us-east-1") + conn = boto3.client("cloudformation", region_name=REGION_NAME) conn.create_stack( - StackName="test_stack", TemplateBody=json.dumps(dummy_template_with_parameters) + StackName=TEST_STACK_NAME, + TemplateBody=json.dumps(dummy_template_with_parameters), ) - result = conn.get_template_summary(StackName="test_stack") + result = conn.get_template_summary(StackName=TEST_STACK_NAME) del result["ResponseMetadata"] assert result == { "Parameters": [ @@ -1021,18 +1042,18 @@ def test_get_template_summary_for_template_containing_parameters(): @mock_cloudformation def test_create_stack_with_ref_yaml(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, ] cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_yaml_with_ref, Parameters=params, ) - template_body = cf.get_template(StackName="test_stack")["TemplateBody"] + template_body = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"] assert template_body == dummy_template_yaml_with_ref @@ -1040,8 +1061,8 @@ def test_create_stack_with_ref_yaml(): def test_creating_stacks_across_regions(): west1_cf = boto3.resource("cloudformation", region_name="us-west-1") west2_cf = boto3.resource("cloudformation", region_name="us-west-2") - west1_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - west2_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + west1_cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) + west2_cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) west1_stacks = list(west1_cf.stacks.all()) west2_stacks = list(west2_cf.stacks.all()) @@ -1060,17 +1081,17 @@ def test_creating_stacks_across_regions(): @mock_sns @mock_sqs def test_create_stack_with_notification_arn(): - sqs = boto3.resource("sqs", region_name="us-east-1") + sqs = boto3.resource("sqs", region_name=REGION_NAME) queue = sqs.create_queue(QueueName="fake-queue") queue_arn = queue.attributes["QueueArn"] - sns = boto3.client("sns", region_name="us-east-1") + sns = boto3.client("sns", region_name=REGION_NAME) topic = sns.create_topic(Name="fake-topic") topic_arn = topic["TopicArn"] sns.subscribe(TopicArn=topic_arn, Protocol="sqs", Endpoint=queue_arn) - cf = boto3.resource("cloudformation", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="test_stack_with_notifications", TemplateBody=dummy_template_json, @@ -1120,7 +1141,7 @@ def test_create_stack_with_notification_arn(): @mock_cloudformation def test_create_stack_with_role_arn(): - cf = boto3.resource("cloudformation", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="test_stack_with_notifications", TemplateBody=dummy_template_json, @@ -1133,8 +1154,8 @@ def test_create_stack_with_role_arn(): @mock_cloudformation @mock_s3 def test_create_stack_from_s3_url(): - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) s3_conn.create_bucket(Bucket="foobar") s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json) @@ -1152,7 +1173,7 @@ def test_create_stack_from_s3_url(): def test_update_stack_fail_missing_new_parameter(): name = "update_stack_fail_missing_new_parameter" - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack(StackName=name, TemplateBody=dummy_empty_template_json) @@ -1163,7 +1184,7 @@ def test_update_stack_fail_missing_new_parameter(): @mock_cloudformation def test_update_stack_fail_update_same_template_body(): name = "update_stack_with_previous_value" - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) params = [ {"ParameterKey": "TagName", "ParameterValue": "foo"}, {"ParameterKey": "TagDescription", "ParameterValue": "bar"}, @@ -1198,7 +1219,7 @@ def test_update_stack_fail_update_same_template_body(): def test_update_stack_deleted_resources_can_reference_deleted_parameters(): name = "update_stack_deleted_resources_can_reference_deleted_parameters" - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) template_json = json.dumps( { @@ -1228,7 +1249,7 @@ def test_update_stack_deleted_resources_can_reference_deleted_parameters(): def test_update_stack_deleted_resources_can_reference_deleted_resources(): name = "update_stack_deleted_resources_can_reference_deleted_resources" - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) template_json = json.dumps( { @@ -1261,7 +1282,7 @@ def test_update_stack_deleted_resources_can_reference_deleted_resources(): @mock_cloudformation def test_update_stack_with_previous_value(): name = "update_stack_with_previous_value" - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName=name, TemplateBody=dummy_template_yaml_with_ref, @@ -1297,10 +1318,10 @@ def test_update_stack_with_previous_value(): @mock_s3 @mock_ec2 def test_update_stack_from_s3_url(): - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="update_stack_from_url", TemplateBody=dummy_template_json, @@ -1329,8 +1350,8 @@ def test_update_stack_from_s3_url(): @mock_cloudformation @mock_s3 def test_create_change_set_from_s3_url(): - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) s3_conn.create_bucket(Bucket="foobar") s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json) @@ -1355,13 +1376,21 @@ def test_create_change_set_from_s3_url(): ) +@pytest.mark.parametrize( + "stack_template,change_template", + [ + pytest.param(dummy_template_yaml, dummy_update_template_json), + pytest.param(dummy_template_json, dummy_update_template_json), + pytest.param(dummy_template_yaml, dummy_update_template_yaml), + ], +) @mock_cloudformation @mock_ec2 -def test_describe_change_set(): - cf = boto3.client("cloudformation", region_name="us-east-1") +def test_describe_change_set(stack_template, change_template): + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_change_set( StackName="NewStack", - TemplateBody=dummy_template_json, + TemplateBody=stack_template, ChangeSetName="NewChangeSet", ChangeSetType="CREATE", ) @@ -1390,7 +1419,7 @@ def test_describe_change_set(): cf.execute_change_set(ChangeSetName="NewChangeSet") # Verify that the changes have been applied - ec2 = boto3.client("ec2", region_name="us-east-1") + ec2 = boto3.client("ec2", region_name=REGION_NAME) assert len(ec2.describe_instances()["Reservations"]) == 1 change_set = cf.describe_change_set(ChangeSetName="NewChangeSet") @@ -1403,7 +1432,7 @@ def test_describe_change_set(): # create another change set to update the stack cf.create_change_set( StackName="NewStack", - TemplateBody=dummy_update_template_json, + TemplateBody=change_template, ChangeSetName="NewChangeSet2", ChangeSetType="UPDATE", Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], @@ -1425,8 +1454,8 @@ def test_describe_change_set(): @mock_cloudformation @mock_ec2 def test_execute_change_set_w_arn(): - cf = boto3.client("cloudformation", region_name="us-east-1") - ec2 = boto3.client("ec2", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) + ec2 = boto3.client("ec2", region_name=REGION_NAME) # Verify no instances exist at the moment assert len(ec2.describe_instances()["Reservations"]) == 0 # Create a Change set, and verify no resources have been created yet @@ -1447,7 +1476,7 @@ def test_execute_change_set_w_arn(): @mock_cloudformation def test_execute_change_set_w_name(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, @@ -1459,7 +1488,7 @@ def test_execute_change_set_w_name(): @mock_cloudformation def test_describe_stack_pagination(): - conn = boto3.client("cloudformation", region_name="us-east-1") + conn = boto3.client("cloudformation", region_name=REGION_NAME) for i in range(100): conn.create_stack(StackName=f"test_stack_{i}", TemplateBody=dummy_template_json) @@ -1476,10 +1505,10 @@ def test_describe_stack_pagination(): @mock_cloudformation def test_describe_stack_resource(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] response = cf.describe_stack_resource( StackName=stack["StackName"], LogicalResourceId="EC2Instance1" @@ -1494,10 +1523,10 @@ def test_describe_stack_resource(): @mock_cloudformation def test_describe_stack_resource_when_resource_does_not_exist(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] with pytest.raises(ClientError, match="does not exist for stack"): cf.describe_stack_resource( @@ -1507,10 +1536,10 @@ def test_describe_stack_resource_when_resource_does_not_exist(): @mock_cloudformation def test_describe_stack_resources(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] response = cf.describe_stack_resources(StackName=stack["StackName"]) resource = response["StackResources"][0] @@ -1522,11 +1551,11 @@ def test_describe_stack_resources(): @mock_cloudformation def test_describe_stack_by_name(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - assert stack["StackName"] == "test_stack" + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] + assert stack["StackName"] == TEST_STACK_NAME two_secs_ago = datetime.now(tz=timezone.utc) - timedelta(seconds=2) assert ( two_secs_ago < stack["CreationTime"] < datetime.now(tz=timezone.utc) @@ -1535,19 +1564,19 @@ def test_describe_stack_by_name(): @mock_cloudformation def test_describe_stack_by_stack_id(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] stack_by_id = cf.describe_stacks(StackName=stack["StackId"])["Stacks"][0] assert stack_by_id["StackId"] == stack["StackId"] - assert stack_by_id["StackName"] == "test_stack" + assert stack_by_id["StackName"] == TEST_STACK_NAME @mock_cloudformation def test_list_change_sets(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_change_set( StackName="NewStack2", TemplateBody=dummy_template_json, @@ -1561,21 +1590,21 @@ def test_list_change_sets(): @mock_cloudformation def test_list_stacks(): - cf = boto3.resource("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.resource("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) cf.create_stack(StackName="test_stack2", TemplateBody=dummy_template_json) stacks = list(cf.stacks.all()) assert len(stacks) == 2 stack_names = [stack.stack_name for stack in stacks] - assert "test_stack" in stack_names + assert TEST_STACK_NAME in stack_names assert "test_stack2" in stack_names @mock_cloudformation def test_delete_stack_from_resource(): - cf = boto3.resource("cloudformation", region_name="us-east-1") - stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.resource("cloudformation", region_name=REGION_NAME) + stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) assert len(list(cf.stacks.all())) == 1 stack.delete() @@ -1585,7 +1614,7 @@ def test_delete_stack_from_resource(): @mock_cloudformation @mock_ec2 def test_delete_change_set(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, @@ -1611,7 +1640,7 @@ def test_delete_change_set(): @mock_cloudformation @mock_ec2 def test_create_change_set_twice__no_changes(): - cf_client = boto3.client("cloudformation", region_name="us-east-1") + cf_client = boto3.client("cloudformation", region_name=REGION_NAME) # Execute once change_set_id = cf_client.create_change_set( @@ -1644,9 +1673,9 @@ def test_create_change_set_twice__no_changes(): @mock_ec2 @mock_s3 def test_create_change_set_twice__using_s3__no_changes(): - cf_client = boto3.client("cloudformation", region_name="us-east-1") - s3 = boto3.client("s3", region_name="us-east-1") - s3_conn = boto3.resource("s3", region_name="us-east-1") + cf_client = boto3.client("cloudformation", region_name=REGION_NAME) + s3 = boto3.client("s3", region_name=REGION_NAME) + s3_conn = boto3.resource("s3", region_name=REGION_NAME) s3_conn.create_bucket(Bucket="foobar") s3_conn.Object("foobar", "template-key").put(Body=dummy_template_json) @@ -1690,24 +1719,24 @@ def test_create_change_set_twice__using_s3__no_changes(): @mock_cloudformation @mock_ec2 def test_delete_stack_by_name(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) assert len(cf.describe_stacks()["Stacks"]) == 1 - cf.delete_stack(StackName="test_stack") + cf.delete_stack(StackName=TEST_STACK_NAME) assert len(cf.describe_stacks()["Stacks"]) == 0 @mock_cloudformation @mock_ec2 def test_delete_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") - ec2 = boto3.client("ec2", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) + ec2 = boto3.client("ec2", region_name=REGION_NAME) - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) state = ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] - cf.delete_stack(StackName="test_stack") + cf.delete_stack(StackName=TEST_STACK_NAME) stacks = cf.list_stacks() assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE" assert ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] != state @@ -1725,14 +1754,14 @@ def test_delete_stack_delete_not_implemented(monkeypatch): ) monkeypatch.delattr("moto.ec2.models.instances.Instance.delete") - cf = boto3.client("cloudformation", region_name="us-east-1") - ec2 = boto3.client("ec2", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) + ec2 = boto3.client("ec2", region_name=REGION_NAME) - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) state = ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] # Mock stack deletion succeeds - cf.delete_stack(StackName="test_stack") + cf.delete_stack(StackName=TEST_STACK_NAME) stacks = cf.list_stacks() assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE" # But the underlying resource is untouched @@ -1741,21 +1770,21 @@ def test_delete_stack_delete_not_implemented(monkeypatch): @mock_cloudformation def test_describe_deleted_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] stack_id = stack["StackId"] cf.delete_stack(StackName=stack["StackId"]) stack_by_id = cf.describe_stacks(StackName=stack_id)["Stacks"][0] assert stack_by_id["StackId"] == stack["StackId"] - assert stack_by_id["StackName"] == "test_stack" + assert stack_by_id["StackName"] == TEST_STACK_NAME assert stack_by_id["StackStatus"] == "DELETE_COMPLETE" @mock_cloudformation def test_describe_stack_with_special_chars(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="test_stack_spl", TemplateBody=dummy_template_special_chars_in_description_json, @@ -1769,53 +1798,53 @@ def test_describe_stack_with_special_chars(): @mock_cloudformation @mock_ec2 def test_describe_updated_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, Tags=[{"Key": "foo", "Value": "bar"}], ) cf.update_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, RoleARN=f"arn:aws:iam::{ACCOUNT_ID}:role/moto", TemplateBody=dummy_update_template_json, Tags=[{"Key": "foo", "Value": "baz"}], Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], ) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] stack_id = stack["StackId"] stack_by_id = cf.describe_stacks(StackName=stack_id)["Stacks"][0] assert stack_by_id["StackId"] == stack["StackId"] - assert stack_by_id["StackName"] == "test_stack" + assert stack_by_id["StackName"] == TEST_STACK_NAME assert stack_by_id["StackStatus"] == "UPDATE_COMPLETE" assert stack_by_id["RoleARN"] == f"arn:aws:iam::{ACCOUNT_ID}:role/moto" assert stack_by_id["Tags"] == [{"Key": "foo", "Value": "baz"}] # Verify the updated template is persisted - template = cf.get_template(StackName="test_stack")["TemplateBody"] + template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"] assert template == dummy_update_template @mock_cloudformation def test_update_stack_with_previous_template(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - cf.update_stack(StackName="test_stack", UsePreviousTemplate=True) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) + cf.update_stack(StackName=TEST_STACK_NAME, UsePreviousTemplate=True) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - assert stack["StackName"] == "test_stack" + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] + assert stack["StackName"] == TEST_STACK_NAME assert stack["StackStatus"] == "UPDATE_COMPLETE" # Verify the original template is persisted - template = cf.get_template(StackName="test_stack")["TemplateBody"] + template = cf.get_template(StackName=TEST_STACK_NAME)["TemplateBody"] assert template == dummy_template @mock_cloudformation def test_bad_describe_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) with pytest.raises(ClientError) as exc: cf.describe_stacks(StackName="non_existent_stack") err = exc.value.response["Error"] @@ -1839,9 +1868,9 @@ def test_cloudformation_params(): } dummy_template_with_params_json = json.dumps(dummy_template_with_params) - cf = boto3.resource("cloudformation", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) stack = cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_with_params_json, Parameters=[{"ParameterKey": "APPNAME", "ParameterValue": "testing123"}], ) @@ -1867,19 +1896,19 @@ def test_update_stack_with_parameters(): "Parameters": {"Bar": {"Type": "String"}}, } template_json = json.dumps(template) - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=template_json, Parameters=[{"ParameterKey": "Bar", "ParameterValue": "192.168.0.0/16"}], ) cf.update_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=template_json, Parameters=[{"ParameterKey": "Bar", "ParameterValue": "192.168.0.1/16"}], ) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] assert len(stack["Parameters"]) == 1 assert stack["Parameters"][0] == { "ParameterKey": "Bar", @@ -1890,19 +1919,19 @@ def test_update_stack_with_parameters(): @mock_cloudformation @mock_ec2 def test_update_stack_replace_tags(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, Tags=[{"Key": "foo", "Value": "bar"}], ) cf.update_stack( - StackName="test_stack", + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, Tags=[{"Key": "foo", "Value": "baz"}], ) - stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName=TEST_STACK_NAME)["Stacks"][0] assert stack["StackStatus"] == "UPDATE_COMPLETE" assert stack["Tags"] == [{"Key": "foo", "Value": "baz"}] @@ -1911,8 +1940,8 @@ def test_update_stack_replace_tags(): def test_update_stack_when_rolled_back(): if settings.TEST_SERVER_MODE: raise SkipTest("Cant manipulate backend in server mode") - cf = boto3.client("cloudformation", region_name="us-east-1") - stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) stack_id = stack["StackId"] cloudformation_backends[ACCOUNT_ID]["us-east-1"].stacks[ @@ -1920,7 +1949,7 @@ def test_update_stack_when_rolled_back(): ].status = "ROLLBACK_COMPLETE" with pytest.raises(ClientError) as ex: - cf.update_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf.update_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) err = ex.value.response["Error"] assert err["Code"] == "ValidationError" @@ -1951,7 +1980,7 @@ def test_cloudformation_params_conditions_and_resources_are_distinct(): }, } template_with_conditions = json.dumps(template_with_conditions) - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="test_stack1", TemplateBody=template_with_conditions, @@ -1968,7 +1997,7 @@ def test_cloudformation_params_conditions_and_resources_are_distinct(): @mock_cloudformation @mock_ec2 def test_cloudformation_conditions_yaml_equals(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="teststack2", TemplateBody=dummy_yaml_template_with_equals, @@ -1987,7 +2016,7 @@ def test_cloudformation_conditions_yaml_equals(): def test_cloudformation_conditions_yaml_equals_shortform(): _template = dummy_yaml_template_with_equals _template = _template.replace("Fn::Equals:", "!Equals") - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) cf.create_stack( StackName="teststack2", TemplateBody=_template, @@ -2004,9 +2033,9 @@ def test_cloudformation_conditions_yaml_equals_shortform(): @mock_cloudformation def test_stack_tags(): tags = [{"Key": "foo", "Value": "bar"}, {"Key": "baz", "Value": "bleh"}] - cf = boto3.resource("cloudformation", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) stack = cf.create_stack( - StackName="test_stack", TemplateBody=dummy_template_json, Tags=tags + StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json, Tags=tags ) observed_tag_items = set( item for items in [tag.items() for tag in stack.tags] for item in items @@ -2020,8 +2049,8 @@ def test_stack_tags(): @mock_cloudformation @mock_ec2 def test_stack_events(): - cf = boto3.resource("cloudformation", region_name="us-east-1") - stack = cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.resource("cloudformation", region_name=REGION_NAME) + stack = cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) stack.update( TemplateBody=dummy_update_template_json, Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], @@ -2049,10 +2078,10 @@ def test_stack_events(): try: for event in events: assert event.stack_id == stack.stack_id - assert event.stack_name == "test_stack" + assert event.stack_name == TEST_STACK_NAME if event.resource_type == "AWS::CloudFormation::Stack": - assert event.logical_resource_id == "test_stack" + assert event.logical_resource_id == TEST_STACK_NAME assert event.physical_resource_id == stack.stack_id status_to_look_for, reason_to_look_for = next(stack_events_to_look_for) @@ -2078,10 +2107,10 @@ def test_stack_events(): @mock_cloudformation def test_list_exports(): - cf_client = boto3.client("cloudformation", region_name="us-east-1") - cf_resource = boto3.resource("cloudformation", region_name="us-east-1") + cf_client = boto3.client("cloudformation", region_name=REGION_NAME) + cf_resource = boto3.resource("cloudformation", region_name=REGION_NAME) stack = cf_resource.create_stack( - StackName="test_stack", TemplateBody=dummy_output_template_json + StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json ) output_value = "VPCID" exports = cf_client.list_exports()["Exports"] @@ -2097,7 +2126,7 @@ def test_list_exports(): @mock_cloudformation def test_list_exports_with_token(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) for i in range(101): # Add index to ensure name is unique dummy_output_template["Outputs"]["StackVPC"]["Export"]["Name"] += str(i) @@ -2116,9 +2145,9 @@ def test_list_exports_with_token(): @mock_cloudformation def test_delete_stack_with_export(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) stack = cf.create_stack( - StackName="test_stack", TemplateBody=dummy_output_template_json + StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json ) stack_id = stack["StackId"] @@ -2131,17 +2160,19 @@ def test_delete_stack_with_export(): @mock_cloudformation def test_export_names_must_be_unique(): - cf = boto3.resource("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json) + cf = boto3.resource("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json) with pytest.raises(ClientError): - cf.create_stack(StackName="test_stack", TemplateBody=dummy_output_template_json) + cf.create_stack( + StackName=TEST_STACK_NAME, TemplateBody=dummy_output_template_json + ) @mock_sqs @mock_cloudformation def test_stack_with_imports(): - cf = boto3.resource("cloudformation", region_name="us-east-1") - ec2_resource = boto3.resource("sqs", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) + ec2_resource = boto3.resource("sqs", region_name=REGION_NAME) output_stack = cf.create_stack( StackName="test_stack1", TemplateBody=dummy_output_template_json @@ -2156,7 +2187,7 @@ def test_stack_with_imports(): @mock_sqs @mock_cloudformation def test_non_json_redrive_policy(): - cf = boto3.resource("cloudformation", region_name="us-east-1") + cf = boto3.resource("cloudformation", region_name=REGION_NAME) stack = cf.create_stack( StackName="test_stack1", TemplateBody=dummy_redrive_template_json @@ -2168,25 +2199,25 @@ def test_non_json_redrive_policy(): @mock_cloudformation def test_create_duplicate_stack(): - cf = boto3.client("cloudformation", region_name="us-east-1") - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name=REGION_NAME) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) with pytest.raises(ClientError): - cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json) @mock_dynamodb @mock_cloudformation def test_delete_stack_dynamo_template(): - conn = boto3.client("cloudformation", region_name="us-east-1") - dynamodb_client = boto3.client("dynamodb", region_name="us-east-1") - conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4) + conn = boto3.client("cloudformation", region_name=REGION_NAME) + dynamodb_client = boto3.client("dynamodb", region_name=REGION_NAME) + conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json4) table_desc = dynamodb_client.list_tables() assert len(table_desc.get("TableNames")) == 1 - conn.delete_stack(StackName="test_stack") + conn.delete_stack(StackName=TEST_STACK_NAME) table_desc = dynamodb_client.list_tables() assert len(table_desc.get("TableNames")) == 0 - conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4) + conn.create_stack(StackName=TEST_STACK_NAME, TemplateBody=dummy_template_json4) @mock_dynamodb @@ -2195,7 +2226,7 @@ def test_delete_stack_dynamo_template(): def test_create_stack_lambda_and_dynamodb(): if settings.TEST_SERVER_MODE: raise SkipTest("Cant set environment variables in server mode") - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) template = { "AWSTemplateFormatVersion": "2010-09-09", "Description": "Stack Lambda Test 1", @@ -2267,40 +2298,42 @@ def test_create_stack_lambda_and_dynamodb(): @mock_cloudformation @mock_ec2 def test_create_and_update_stack_with_unknown_resource(): - cf = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name=REGION_NAME) # Creating a stack with an unknown resource should throw a warning expected_err = "Tried to parse AWS::Cloud9::EnvironmentEC2 but it's not supported by moto's CloudFormation implementation" if settings.TEST_SERVER_MODE: # Can't verify warnings in ServerMode though cf.create_stack( - StackName="test_stack", TemplateBody=dummy_unknown_template_json + StackName=TEST_STACK_NAME, TemplateBody=dummy_unknown_template_json ) else: with pytest.warns(UserWarning, match=expected_err): cf.create_stack( - StackName="test_stack", TemplateBody=dummy_unknown_template_json + StackName=TEST_STACK_NAME, TemplateBody=dummy_unknown_template_json ) # The stack should exist though stacks = cf.describe_stacks()["Stacks"] assert len(stacks) == 1 - assert stacks[0]["StackName"] == "test_stack" + assert stacks[0]["StackName"] == TEST_STACK_NAME # Updating an unknown resource should throw a warning, but not fail new_template = copy.deepcopy(dummy_unknown_template) new_template["Resources"]["UnknownResource"]["Properties"]["Sth"] = "other" if settings.TEST_SERVER_MODE: - cf.update_stack(StackName="test_stack", TemplateBody=json.dumps(new_template)) + cf.update_stack( + StackName=TEST_STACK_NAME, TemplateBody=json.dumps(new_template) + ) else: with pytest.warns(UserWarning, match=expected_err): cf.update_stack( - StackName="test_stack", TemplateBody=json.dumps(new_template) + StackName=TEST_STACK_NAME, TemplateBody=json.dumps(new_template) ) def get_role_name(): with mock_iam(): - iam = boto3.client("iam", region_name="us-east-1") + iam = boto3.client("iam", region_name=REGION_NAME) try: return iam.get_role(RoleName="my-role")["Role"]["Arn"] except ClientError: