diff --git a/tests/test_cloudformation/test_cloudformation_custom_resources.py b/tests/test_cloudformation/test_cloudformation_custom_resources.py index f2d457bfaa16..33e058f7b8f2 100644 --- a/tests/test_cloudformation/test_cloudformation_custom_resources.py +++ b/tests/test_cloudformation/test_cloudformation_custom_resources.py @@ -1,7 +1,6 @@ import boto3 import json import requests -import sure # noqa # pylint: disable=unused-import import time import pytest @@ -69,9 +68,9 @@ def test_create_custom_lambda_resource(): # Verify the correct Output was returned outputs = get_outputs(cf, stack_name) - outputs.should.have.length_of(1) - outputs[0].should.have.key("OutputKey").equals("infokey") - outputs[0].should.have.key("OutputValue").equals("special value") + assert len(outputs) == 1 + assert outputs[0]["OutputKey"] == "infokey" + assert outputs[0]["OutputValue"] == "special value" @mock_cloudformation @@ -104,25 +103,25 @@ def test_create_custom_lambda_resource__verify_cfnresponse_failed(): execution_failed, logs = wait_for_log_msg( expected_msg="failed executing http.request", log_group=log_group_name ) - execution_failed.should.equal(True) + assert execution_failed is True printed_events = [ line for line in logs if line.startswith("{'RequestType': 'Create'") ] - printed_events.should.have.length_of(1) + assert len(printed_events) == 1 original_event = json.loads(printed_events[0].replace("'", '"')) - original_event.should.have.key("RequestType").equals("Create") - original_event.should.have.key("ServiceToken") # Should equal Lambda ARN - original_event.should.have.key("ResponseURL") - original_event.should.have.key("StackId") - original_event.should.have.key("RequestId") # type UUID - original_event.should.have.key("LogicalResourceId").equals("CustomInfo") - original_event.should.have.key("ResourceType").equals("Custom::Info") - original_event.should.have.key("ResourceProperties") - original_event["ResourceProperties"].should.have.key( - "ServiceToken" + assert original_event["RequestType"] == "Create" + assert "ServiceToken" in original_event # Should equal Lambda ARN + assert "ResponseURL" in original_event + assert "StackId" in original_event + assert "RequestId" in original_event # type UUID + assert original_event["LogicalResourceId"] == "CustomInfo" + assert original_event["ResourceType"] == "Custom::Info" + assert "ResourceProperties" in original_event + assert ( + "ServiceToken" in original_event["ResourceProperties"] ) # Should equal Lambda ARN - original_event["ResourceProperties"].should.have.key("MyProperty").equals("stuff") + assert original_event["ResourceProperties"]["MyProperty"] == "stuff" @mock_cloudformation @@ -155,8 +154,8 @@ def test_create_custom_lambda_resource__verify_manual_request(): ) stack_id = stack["StackId"] stack = cf.describe_stacks(StackName=stack_id)["Stacks"][0] - stack["Outputs"].should.equal([]) - stack["StackStatus"].should.equal("CREATE_IN_PROGRESS") + assert stack["Outputs"] == [] + assert stack["StackStatus"] == "CREATE_IN_PROGRESS" callback_url = f"http://cloudformation.{region_name}.amazonaws.com/cloudformation_{region_name}/cfnresponse?stack={stack_id}" data = { @@ -168,10 +167,10 @@ def test_create_custom_lambda_resource__verify_manual_request(): requests.post(callback_url, json=data) stack = cf.describe_stacks(StackName=stack_id)["Stacks"][0] - stack["StackStatus"].should.equal("CREATE_COMPLETE") - stack["Outputs"].should.equal( - [{"OutputKey": "infokey", "OutputValue": "resultfromthirdpartysystem"}] - ) + assert stack["StackStatus"] == "CREATE_COMPLETE" + assert stack["Outputs"] == [ + {"OutputKey": "infokey", "OutputValue": "resultfromthirdpartysystem"} + ] @mock_cloudformation @@ -186,9 +185,10 @@ def test_create_custom_lambda_resource__unknown_arn(): Capabilities=["CAPABILITY_IAM"], ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "Template error: instance of Fn::GetAtt references undefined resource InfoFunction" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == "Template error: instance of Fn::GetAtt references undefined resource InfoFunction" ) diff --git a/tests/test_cloudformation/test_cloudformation_multi_accounts.py b/tests/test_cloudformation/test_cloudformation_multi_accounts.py index 05901c7ccce1..a01bd35ef494 100644 --- a/tests/test_cloudformation/test_cloudformation_multi_accounts.py +++ b/tests/test_cloudformation/test_cloudformation_multi_accounts.py @@ -94,11 +94,11 @@ def _verify_stack_instance(self, accnt, region=None): StackInstanceAccount=accnt, StackInstanceRegion=region or "us-east-1", )["StackInstance"] - resp.should.have.key("Account").equals(accnt) + assert resp["Account"] == accnt def _verify_queues(self, accnt, expected, region=None): - list(sqs_backends[accnt][region or "us-east-1"].queues.keys()).should.equal( - expected + assert ( + list(sqs_backends[accnt][region or "us-east-1"].queues.keys()) == expected ) @@ -122,9 +122,10 @@ def test_create_instances__specifying_accounts(self): StackSetName=self.name, Accounts=["888781156701"], Regions=["us-east-1"] ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "StackSets with SERVICE_MANAGED permission model can only have OrganizationalUnit as target" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == "StackSets with SERVICE_MANAGED permission model can only have OrganizationalUnit as target" ) def test_create_instances__specifying_only_accounts_in_deployment_targets(self): @@ -137,8 +138,8 @@ def test_create_instances__specifying_only_accounts_in_deployment_targets(self): Regions=["us-east-1"], ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal("OrganizationalUnitIds are required") + assert err["Code"] == "ValidationError" + assert err["Message"] == "OrganizationalUnitIds are required" def test_create_instances___with_invalid_ou(self): with pytest.raises(ClientError) as exc: @@ -148,9 +149,10 @@ def test_create_instances___with_invalid_ou(self): Regions=["us-east-1"], ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "1 validation error detected: Value '[unknown]' at 'deploymentTargets.organizationalUnitIds' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 68, Member must have length greater than or equal to 6, Member must satisfy regular expression pattern: ^(ou-[a-z0-9]{4,32}-[a-z0-9]{8,32}|r-[a-z0-9]{4,32})$]" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == "1 validation error detected: Value '[unknown]' at 'deploymentTargets.organizationalUnitIds' failed to satisfy constraint: Member must satisfy constraint: [Member must have length less than or equal to 68, Member must have length greater than or equal to 6, Member must satisfy regular expression pattern: ^(ou-[a-z0-9]{4,32}-[a-z0-9]{8,32}|r-[a-z0-9]{4,32})$]" ) def test_create_instances__single_ou(self): @@ -210,12 +212,12 @@ def test_create_instances__specifying_accounts(self): self._verify_stack_instance(self.acct01, region="us-east-2") # acct01 has a Stack - cf_backends[self.acct01]["us-east-2"].stacks.should.have.length_of(1) + assert len(cf_backends[self.acct01]["us-east-2"].stacks) == 1 # Other acounts do not - cf_backends[self.acct02]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[self.acct21]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[self.acct22]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks.should.have.length_of(0) + assert len(cf_backends[self.acct02]["us-east-2"].stacks) == 0 + assert len(cf_backends[self.acct21]["us-east-2"].stacks) == 0 + assert len(cf_backends[self.acct22]["us-east-2"].stacks) == 0 + assert len(cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks) == 0 # acct01 has a queue self._verify_queues(self.acct01, ["testqueue"], region="us-east-2") @@ -233,12 +235,12 @@ def test_create_instances__multiple_accounts(self): ) # acct01 and 02 have a Stack - cf_backends[self.acct01]["us-east-2"].stacks.should.have.length_of(1) - cf_backends[self.acct02]["us-east-2"].stacks.should.have.length_of(1) + assert len(cf_backends[self.acct01]["us-east-2"].stacks) == 1 + assert len(cf_backends[self.acct02]["us-east-2"].stacks) == 1 # Other acounts do not - cf_backends[self.acct21]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[self.acct22]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks.should.have.length_of(0) + assert len(cf_backends[self.acct21]["us-east-2"].stacks) == 0 + assert len(cf_backends[self.acct22]["us-east-2"].stacks) == 0 + assert len(cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks) == 0 # acct01 and 02 have the queue self._verify_queues(self.acct01, ["testqueue"], region="us-east-2") @@ -265,12 +267,12 @@ def test_delete_instances(self): ) # Act02 still has it's stack - cf_backends[self.acct02]["us-east-2"].stacks.should.have.length_of(1) + assert len(cf_backends[self.acct02]["us-east-2"].stacks) == 1 # Other Stacks are removed - cf_backends[self.acct01]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[self.acct21]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[self.acct22]["us-east-2"].stacks.should.have.length_of(0) - cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks.should.have.length_of(0) + assert len(cf_backends[self.acct01]["us-east-2"].stacks) == 0 + assert len(cf_backends[self.acct21]["us-east-2"].stacks) == 0 + assert len(cf_backends[self.acct22]["us-east-2"].stacks) == 0 + assert len(cf_backends[DEFAULT_ACCOUNT_ID]["us-east-2"].stacks) == 0 # Acct02 still has it's queue as well self._verify_queues(self.acct02, ["testqueue"], region="us-east-2") @@ -288,7 +290,8 @@ def test_create_instances__single_ou(self): Regions=["us-east-1"], ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "StackSets with SELF_MANAGED permission model can only have accounts as target" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == "StackSets with SELF_MANAGED permission model can only have accounts as target" ) diff --git a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py index 9fa6bef0a9da..b2bdb76493aa 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py +++ b/tests/test_cloudformation/test_cloudformation_stack_crud_boto3.py @@ -1,12 +1,14 @@ +import boto3 import copy import json -from collections import OrderedDict -from datetime import datetime, timedelta, timezone import os import pytest -from unittest import SkipTest -import boto3 + from botocore.exceptions import ClientError +from collections import OrderedDict +from datetime import datetime, timedelta, timezone +from unittest import SkipTest + from moto import ( mock_cloudformation, mock_dynamodb, @@ -22,7 +24,6 @@ from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID from tests import EXAMPLE_AMI_ID -from tests.helpers import match_dict # noqa # pylint: disable=unused-import dummy_template = { "AWSTemplateFormatVersion": "2010-09-09", @@ -310,79 +311,65 @@ @mock_cloudformation @mock_ec2 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) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + stack = cf.describe_stacks()["Stacks"][0] + assert stack["StackName"] == "test_stack" + assert stack["EnableTerminationProtection"] is False - template = cf_conn.get_template(StackName="test_stack")["TemplateBody"] - template.should.equal(dummy_template) + template = cf.get_template(StackName="test_stack")["TemplateBody"] + assert template == dummy_template @mock_cloudformation def test_create_stack_with_additional_properties(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( StackName="test_stack", TemplateBody=dummy_template_json, EnableTerminationProtection=True, TimeoutInMinutes=25, ) - stack = cf_conn.describe_stacks()["Stacks"][0] - stack.should.have.key("StackName").equal("test_stack") - stack.should.have.key("EnableTerminationProtection").equal(True) - stack.should.have.key("TimeoutInMinutes").equals(25) + stack = cf.describe_stacks()["Stacks"][0] + assert stack["StackName"] == "test_stack" + assert stack["EnableTerminationProtection"] is True + assert stack["TimeoutInMinutes"] == 25 @mock_cloudformation @mock_ec2 def test_describe_stack_instances(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2"], ) - usw2_instance = cf_conn.describe_stack_instance( + usw2_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-west-2", ) - use1_instance = cf_conn.describe_stack_instance( + use1_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-east-1", ) - usw2_instance["StackInstance"].should.have.key("Region").which.should.equal( - "us-west-2" - ) - usw2_instance["StackInstance"].should.have.key("Account").which.should.equal( - ACCOUNT_ID - ) - use1_instance["StackInstance"].should.have.key("Region").which.should.equal( - "us-east-1" - ) - use1_instance["StackInstance"].should.have.key("Account").which.should.equal( - ACCOUNT_ID - ) + assert usw2_instance["StackInstance"]["Region"] == "us-west-2" + assert usw2_instance["StackInstance"]["Account"] == ACCOUNT_ID + assert use1_instance["StackInstance"]["Region"] == "us-east-1" + assert use1_instance["StackInstance"]["Account"] == ACCOUNT_ID @mock_cloudformation def test_list_stacksets_length(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_set( - StackSetName="teststackset2", TemplateBody=dummy_template_yaml - ) - stacksets = cf_conn.list_stack_sets() - stacksets.should.have.length_of(2) + cf = boto3.client("cloudformation", region_name="us-east-1") + 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() + assert len(stacksets) == 2 @mock_cloudformation @@ -393,106 +380,92 @@ def test_filter_stacks(): conn.update_stack(StackName="test_stack", TemplateBody=dummy_template_json2) stacks = conn.list_stacks(StackStatusFilter=["CREATE_COMPLETE"]) - stacks.get("StackSummaries").should.have.length_of(1) + assert len(stacks.get("StackSummaries")) == 1 stacks = conn.list_stacks(StackStatusFilter=["UPDATE_COMPLETE"]) - stacks.get("StackSummaries").should.have.length_of(1) + assert len(stacks.get("StackSummaries")) == 1 @mock_cloudformation def test_list_stacksets_contents(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - stacksets = cf_conn.list_stack_sets() - stacksets["Summaries"][0].should.have.key("StackSetName").which.should.equal( - "teststackset" - ) - stacksets["Summaries"][0].should.have.key("Status").which.should.equal("ACTIVE") + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + stacksets = cf.list_stack_sets() + assert stacksets["Summaries"][0]["StackSetName"] == "teststackset" + assert stacksets["Summaries"][0]["Status"] == "ACTIVE" @mock_cloudformation def test_stop_stack_set_operation(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-1", "us-west-2"], ) - operation_id = cf_conn.list_stack_set_operations(StackSetName="teststackset")[ + operation_id = cf.list_stack_set_operations(StackSetName="teststackset")[ "Summaries" ][-1]["OperationId"] - cf_conn.stop_stack_set_operation( - StackSetName="teststackset", OperationId=operation_id - ) - list_operation = cf_conn.list_stack_set_operations(StackSetName="teststackset") - list_operation["Summaries"][-1]["Status"].should.equal("STOPPED") + cf.stop_stack_set_operation(StackSetName="teststackset", OperationId=operation_id) + list_operation = cf.list_stack_set_operations(StackSetName="teststackset") + assert list_operation["Summaries"][-1]["Status"] == "STOPPED" @mock_cloudformation def test_describe_stack_set_operation(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set(StackSetName="name", TemplateBody=dummy_template_json) - operation_id = cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="name", TemplateBody=dummy_template_json) + operation_id = cf.create_stack_instances( StackSetName="name", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-1", "us-west-2"], )["OperationId"] - cf_conn.stop_stack_set_operation(StackSetName="name", OperationId=operation_id) - response = cf_conn.describe_stack_set_operation( + cf.stop_stack_set_operation(StackSetName="name", OperationId=operation_id) + response = cf.describe_stack_set_operation( StackSetName="name", OperationId=operation_id ) - response["StackSetOperation"]["Status"].should.equal("STOPPED") - response["StackSetOperation"]["Action"].should.equal("CREATE") + assert response["StackSetOperation"]["Status"] == "STOPPED" + assert response["StackSetOperation"]["Action"] == "CREATE" with pytest.raises(ClientError) as exp: - cf_conn.describe_stack_set_operation( + cf.describe_stack_set_operation( StackSetName="name", OperationId="non_existing_operation" ) exp_err = exp.value.response.get("Error") exp_metadata = exp.value.response.get("ResponseMetadata") - exp_err.get("Code").should.match(r"ValidationError") - exp_err.get("Message").should.match( - r"Stack with id non_existing_operation does not exist" - ) - exp_metadata.get("HTTPStatusCode").should.equal(400) + assert exp_err["Code"] == "ValidationError" + assert exp_err["Message"] == "Stack with id non_existing_operation does not exist" + assert exp_metadata.get("HTTPStatusCode") == 400 @mock_cloudformation def test_list_stack_set_operation_results(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-1", "us-west-2"], ) - operation_id = cf_conn.list_stack_set_operations(StackSetName="teststackset")[ + operation_id = cf.list_stack_set_operations(StackSetName="teststackset")[ "Summaries" ][-1]["OperationId"] - cf_conn.stop_stack_set_operation( - StackSetName="teststackset", OperationId=operation_id - ) - response = cf_conn.list_stack_set_operation_results( + cf.stop_stack_set_operation(StackSetName="teststackset", OperationId=operation_id) + response = cf.list_stack_set_operation_results( StackSetName="teststackset", OperationId=operation_id ) - response["Summaries"].should.have.length_of(3) - response["Summaries"][0].should.have.key("Account").which.should.equal(ACCOUNT_ID) - response["Summaries"][1].should.have.key("Status").which.should.equal("STOPPED") + assert len(response["Summaries"]) == 3 + assert response["Summaries"][0]["Account"] == ACCOUNT_ID + assert response["Summaries"][1]["Status"] == "STOPPED" @mock_cloudformation def test_update_stack_instances(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -501,80 +474,66 @@ def test_update_stack_instances(): {"ParameterKey": "TagDescription", "ParameterValue": "OverrideValue"}, {"ParameterKey": "TagName", "ParameterValue": "OverrideValue2"}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param, ) - cf_conn.create_stack_instances( + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-1", "us-west-2"], ) - cf_conn.update_stack_instances( + cf.update_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-west-1", "us-west-2"], ParameterOverrides=param_overrides, ) - usw2_instance = cf_conn.describe_stack_instance( + usw2_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-west-2", ) - usw1_instance = cf_conn.describe_stack_instance( + usw1_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-west-1", ) - use1_instance = cf_conn.describe_stack_instance( + use1_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-east-1", ) - usw2_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterKey" - ].should.equal(param_overrides[0]["ParameterKey"]) - usw2_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterValue" - ].should.equal(param_overrides[0]["ParameterValue"]) - usw2_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterKey" - ].should.equal(param_overrides[1]["ParameterKey"]) - usw2_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterValue" - ].should.equal(param_overrides[1]["ParameterValue"]) - - usw1_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterKey" - ].should.equal(param_overrides[0]["ParameterKey"]) - usw1_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterValue" - ].should.equal(param_overrides[0]["ParameterValue"]) - usw1_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterKey" - ].should.equal(param_overrides[1]["ParameterKey"]) - usw1_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterValue" - ].should.equal(param_overrides[1]["ParameterValue"]) - - use1_instance["StackInstance"]["ParameterOverrides"].should.equal([]) + usw2_overrides = usw2_instance["StackInstance"]["ParameterOverrides"] + assert usw2_overrides[0]["ParameterKey"] == param_overrides[0]["ParameterKey"] + assert usw2_overrides[0]["ParameterValue"] == param_overrides[0]["ParameterValue"] + assert usw2_overrides[1]["ParameterKey"] == param_overrides[1]["ParameterKey"] + assert usw2_overrides[1]["ParameterValue"] == param_overrides[1]["ParameterValue"] + + usw1_overrides = usw1_instance["StackInstance"]["ParameterOverrides"] + assert usw1_overrides[0]["ParameterKey"] == param_overrides[0]["ParameterKey"] + assert usw1_overrides[0]["ParameterValue"] == param_overrides[0]["ParameterValue"] + assert usw1_overrides[1]["ParameterKey"] == param_overrides[1]["ParameterKey"] + assert usw1_overrides[1]["ParameterValue"] == param_overrides[1]["ParameterValue"] + + assert use1_instance["StackInstance"]["ParameterOverrides"] == [] @mock_cloudformation def test_delete_stack_instances(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") tss = "teststackset" - cf_conn.create_stack_set(StackSetName=tss, TemplateBody=dummy_template_json) - cf_conn.create_stack_instances( + cf.create_stack_set(StackSetName=tss, TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName=tss, Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2", "eu-north-1"], ) # Delete just one - cf_conn.delete_stack_instances( + cf.delete_stack_instances( StackSetName=tss, Accounts=[ACCOUNT_ID], # Also delete unknown region for good measure - that should be a no-op @@ -583,7 +542,7 @@ def test_delete_stack_instances(): ) # Some should remain - remaining_stacks = cf_conn.list_stack_instances(StackSetName=tss)["Summaries"] + remaining_stacks = cf.list_stack_instances(StackSetName=tss)["Summaries"] assert len(remaining_stacks) == 2 assert [stack["Region"] for stack in remaining_stacks] == [ "us-west-2", @@ -591,7 +550,7 @@ def test_delete_stack_instances(): ] # Delete all - cf_conn.delete_stack_instances( + cf.delete_stack_instances( StackSetName=tss, Accounts=[ACCOUNT_ID], # Also delete unknown region for good measure - that should be a no-op @@ -599,33 +558,28 @@ def test_delete_stack_instances(): RetainStacks=False, ) - remaining_stacks = cf_conn.list_stack_instances(StackSetName=tss)["Summaries"] + remaining_stacks = cf.list_stack_instances(StackSetName=tss)["Summaries"] assert len(remaining_stacks) == 0 @mock_cloudformation def test_create_stack_instances(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2"], ) - cf_conn.list_stack_instances(StackSetName="teststackset")[ - "Summaries" - ].should.have.length_of(2) - cf_conn.list_stack_instances(StackSetName="teststackset")["Summaries"][0][ - "Account" - ].should.equal(ACCOUNT_ID) + summaries = cf.list_stack_instances(StackSetName="teststackset")["Summaries"] + assert len(summaries) == 2 + assert summaries[0]["Account"] == ACCOUNT_ID @mock_cloudformation def test_create_stack_instances_with_param_overrides(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -634,40 +588,33 @@ def test_create_stack_instances_with_param_overrides(): {"ParameterKey": "TagDescription", "ParameterValue": "OverrideValue"}, {"ParameterKey": "TagName", "ParameterValue": "OverrideValue2"}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param, ) - cf_conn.create_stack_instances( + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2"], ParameterOverrides=param_overrides, ) - usw2_instance = cf_conn.describe_stack_instance( + usw2_instance = cf.describe_stack_instance( StackSetName="teststackset", StackInstanceAccount=ACCOUNT_ID, StackInstanceRegion="us-west-2", ) - usw2_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterKey" - ].should.equal(param_overrides[0]["ParameterKey"]) - usw2_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterKey" - ].should.equal(param_overrides[1]["ParameterKey"]) - usw2_instance["StackInstance"]["ParameterOverrides"][0][ - "ParameterValue" - ].should.equal(param_overrides[0]["ParameterValue"]) - usw2_instance["StackInstance"]["ParameterOverrides"][1][ - "ParameterValue" - ].should.equal(param_overrides[1]["ParameterValue"]) + usw2_overrides = usw2_instance["StackInstance"]["ParameterOverrides"] + assert usw2_overrides[0]["ParameterKey"] == param_overrides[0]["ParameterKey"] + assert usw2_overrides[1]["ParameterKey"] == param_overrides[1]["ParameterKey"] + assert usw2_overrides[0]["ParameterValue"] == param_overrides[0]["ParameterValue"] + assert usw2_overrides[1]["ParameterValue"] == param_overrides[1]["ParameterValue"] @mock_cloudformation def test_update_stack_set(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -676,35 +623,28 @@ def test_update_stack_set(): {"ParameterKey": "TagDescription", "ParameterValue": "OverrideValue"}, {"ParameterKey": "TagName", "ParameterValue": "OverrideValue2"}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param, ) - cf_conn.update_stack_set( + cf.update_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param_overrides, ) - stackset = cf_conn.describe_stack_set(StackSetName="teststackset") + stackset = cf.describe_stack_set(StackSetName="teststackset") - stackset["StackSet"]["Parameters"][0]["ParameterValue"].should.equal( - param_overrides[0]["ParameterValue"] - ) - stackset["StackSet"]["Parameters"][1]["ParameterValue"].should.equal( - param_overrides[1]["ParameterValue"] - ) - stackset["StackSet"]["Parameters"][0]["ParameterKey"].should.equal( - param_overrides[0]["ParameterKey"] - ) - stackset["StackSet"]["Parameters"][1]["ParameterKey"].should.equal( - param_overrides[1]["ParameterKey"] - ) + stack_params = stackset["StackSet"]["Parameters"] + assert stack_params[0]["ParameterValue"] == param_overrides[0]["ParameterValue"] + assert stack_params[1]["ParameterValue"] == param_overrides[1]["ParameterValue"] + assert stack_params[0]["ParameterKey"] == param_overrides[0]["ParameterKey"] + assert stack_params[1]["ParameterKey"] == param_overrides[1]["ParameterKey"] @mock_cloudformation def test_update_stack_set_with_previous_value(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") param = [ {"ParameterKey": "TagDescription", "ParameterValue": "StackSetValue"}, {"ParameterKey": "TagName", "ParameterValue": "StackSetValue2"}, @@ -713,113 +653,102 @@ def test_update_stack_set_with_previous_value(): {"ParameterKey": "TagDescription", "ParameterValue": "OverrideValue"}, {"ParameterKey": "TagName", "UsePreviousValue": True}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param, ) - cf_conn.update_stack_set( + cf.update_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_yaml_with_ref, Parameters=param_overrides, ) - stackset = cf_conn.describe_stack_set(StackSetName="teststackset") + stackset = cf.describe_stack_set(StackSetName="teststackset") - stackset["StackSet"]["Parameters"][0]["ParameterValue"].should.equal( - param_overrides[0]["ParameterValue"] - ) - stackset["StackSet"]["Parameters"][1]["ParameterValue"].should.equal( - param[1]["ParameterValue"] - ) - stackset["StackSet"]["Parameters"][0]["ParameterKey"].should.equal( - param_overrides[0]["ParameterKey"] - ) - stackset["StackSet"]["Parameters"][1]["ParameterKey"].should.equal( - param_overrides[1]["ParameterKey"] - ) + stack_params = stackset["StackSet"]["Parameters"] + assert stack_params[0]["ParameterValue"] == param_overrides[0]["ParameterValue"] + assert stack_params[1]["ParameterValue"] == param[1]["ParameterValue"] + assert stack_params[0]["ParameterKey"] == param_overrides[0]["ParameterKey"] + assert stack_params[1]["ParameterKey"] == param_overrides[1]["ParameterKey"] @mock_cloudformation def test_list_stack_set_operations(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.create_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2"], ) - cf_conn.update_stack_instances( + cf.update_stack_instances( StackSetName="teststackset", Accounts=[ACCOUNT_ID], Regions=["us-east-1", "us-west-2"], ) - list_operation = cf_conn.list_stack_set_operations(StackSetName="teststackset") - list_operation["Summaries"].should.have.length_of(2) - list_operation["Summaries"][-1]["Action"].should.equal("UPDATE") + list_operation = cf.list_stack_set_operations(StackSetName="teststackset") + assert len(list_operation["Summaries"]) == 2 + assert list_operation["Summaries"][-1]["Action"] == "UPDATE" @mock_cloudformation def test_bad_list_stack_resources(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") with pytest.raises(ClientError): - cf_conn.list_stack_resources(StackName="teststackset") + cf.list_stack_resources(StackName="teststackset") @mock_cloudformation def test_delete_stack_set_by_name(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_json - ) - cf_conn.delete_stack_set(StackSetName="teststackset") + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="teststackset", TemplateBody=dummy_template_json) + cf.delete_stack_set(StackSetName="teststackset") - stacks = cf_conn.list_stack_sets()["Summaries"] - stacks.should.have.length_of(1) - stacks[0].should.have.key("StackSetName").equals("teststackset") - stacks[0].should.have.key("Status").equals("DELETED") + stacks = cf.list_stack_sets()["Summaries"] + assert len(stacks) == 1 + assert stacks[0]["StackSetName"] == "teststackset" + assert stacks[0]["Status"] == "DELETED" with pytest.raises(ClientError) as exc: - cf_conn.describe_stack_set(StackSetName="teststackset") + cf.describe_stack_set(StackSetName="teststackset") err = exc.value.response["Error"] - err["Code"].should.equal("StackSetNotFoundException") - err["Message"].should.equal("StackSet teststackset not found") + assert err["Code"] == "StackSetNotFoundException" + assert err["Message"] == "StackSet teststackset not found" @mock_cloudformation def test_delete_stack_set_by_id(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - response = cf_conn.create_stack_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + response = cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_json ) stack_set_id = response["StackSetId"] - cf_conn.delete_stack_set(StackSetName=stack_set_id) + cf.delete_stack_set(StackSetName=stack_set_id) - stacks = cf_conn.list_stack_sets()["Summaries"] - stacks.should.have.length_of(1) - stacks[0].should.have.key("StackSetName").equals("teststackset") - stacks[0].should.have.key("Status").equals("DELETED") + stacks = cf.list_stack_sets()["Summaries"] + assert len(stacks) == 1 + assert stacks[0]["StackSetName"] == "teststackset" + assert stacks[0]["Status"] == "DELETED" @mock_cloudformation def test_delete_stack_set__while_instances_are_running(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set(StackSetName="a", TemplateBody=json.dumps(dummy_template3)) - cf_conn.create_stack_instances( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="a", TemplateBody=json.dumps(dummy_template3)) + cf.create_stack_instances( StackSetName="a", Accounts=[ACCOUNT_ID], Regions=["us-east-1"], ) with pytest.raises(ClientError) as exc: - cf_conn.delete_stack_set(StackSetName="a") + cf.delete_stack_set(StackSetName="a") err = exc.value.response["Error"] - err["Code"].should.equal("StackSetNotEmptyException") - err["Message"].should.equal("StackSet is not empty") + assert err["Code"] == "StackSetNotEmptyException" + assert err["Message"] == "StackSet is not empty" - cf_conn.delete_stack_instances( + cf.delete_stack_instances( StackSetName="a", Accounts=[ACCOUNT_ID], Regions=["us-east-1"], @@ -827,26 +756,24 @@ def test_delete_stack_set__while_instances_are_running(): ) # This will succeed when no StackInstances are left - cf_conn.delete_stack_set(StackSetName="a") + cf.delete_stack_set(StackSetName="a") @mock_cloudformation def test_create_stack_set(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - response = cf_conn.create_stack_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + response = cf.create_stack_set( StackSetName="teststackset", TemplateBody=dummy_template_json, Description="desc", AdministrationRoleARN="admin/role/arn:asdfasdfadsf", ) - response["StackSetId"].should_not.equal(None) + assert response["StackSetId"] is not None - stack_set = cf_conn.describe_stack_set(StackSetName="teststackset")["StackSet"] - stack_set["TemplateBody"].should.equal(dummy_template_json) - stack_set.should.have.key("AdministrationRoleARN").should.equal( - "admin/role/arn:asdfasdfadsf" - ) - stack_set.should.have.key("Description").equals("desc") + stack_set = cf.describe_stack_set(StackSetName="teststackset")["StackSet"] + assert stack_set["TemplateBody"] == dummy_template_json + assert stack_set["AdministrationRoleARN"] == "admin/role/arn:asdfasdfadsf" + assert stack_set["Description"] == "desc" @mock_cloudformation @@ -856,22 +783,20 @@ def test_create_stack_set__invalid_name(name): with pytest.raises(ClientError) as exc: client.create_stack_set(StackSetName=name) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - f"1 validation error detected: Value '{name}' at 'stackSetName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == f"1 validation error detected: Value '{name}' at 'stackSetName' failed to satisfy constraint: Member must satisfy regular expression pattern: [a-zA-Z][-a-zA-Z0-9]*" ) @mock_cloudformation def test_create_stack_set_with_yaml(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack_set( - StackSetName="teststackset", TemplateBody=dummy_template_yaml - ) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack_set(StackSetName="tss", TemplateBody=dummy_template_yaml) - cf_conn.describe_stack_set(StackSetName="teststackset")["StackSet"][ - "TemplateBody" - ].should.equal(dummy_template_yaml) + tmplt = cf.describe_stack_set(StackSetName="tss")["StackSet"]["TemplateBody"] + assert tmplt == dummy_template_yaml @mock_cloudformation @@ -886,118 +811,106 @@ def test_create_stack_set_from_s3_url(): ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"} ) - cf_conn = boto3.client("cloudformation", region_name="us-west-1") - cf_conn.create_stack_set(StackSetName="stackfromurl", TemplateURL=key_url) - cf_conn.describe_stack_set(StackSetName="stackfromurl")["StackSet"][ - "TemplateBody" - ].should.equal(dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-west-1") + cf.create_stack_set(StackSetName="urlStack", TemplateURL=key_url) + tmplt = cf.describe_stack_set(StackSetName="urlStack")["StackSet"]["TemplateBody"] + assert tmplt == dummy_template_json @mock_cloudformation def test_create_stack_set_with_ref_yaml(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststack", TemplateBody=dummy_template_yaml_with_ref, Parameters=params, ) - cf_conn.describe_stack_set(StackSetName="teststack")["StackSet"][ - "TemplateBody" - ].should.equal(dummy_template_yaml_with_ref) + tmplt = cf.describe_stack_set(StackSetName="teststack")["StackSet"]["TemplateBody"] + assert tmplt == dummy_template_yaml_with_ref @mock_cloudformation def test_describe_stack_set_params(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, ] - cf_conn.create_stack_set( + cf.create_stack_set( StackSetName="teststack", TemplateBody=dummy_template_yaml_with_ref, Parameters=params, ) - cf_conn.describe_stack_set(StackSetName="teststack")["StackSet"][ - "Parameters" - ].should.equal(params) + stack_set = cf.describe_stack_set(StackSetName="teststack")["StackSet"] + assert stack_set["Parameters"] == params @mock_cloudformation def test_describe_stack_set_by_id(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - response = cf_conn.create_stack_set( - StackSetName="teststack", TemplateBody=dummy_template_json - ) + cf = boto3.client("cloudformation", region_name="us-east-1") + ss_id = cf.create_stack_set(StackSetName="s", TemplateBody=dummy_template_json)[ + "StackSetId" + ] - stack_set_id = response["StackSetId"] - cf_conn.describe_stack_set(StackSetName=stack_set_id)["StackSet"][ - "TemplateBody" - ].should.equal(dummy_template_json) + stack_set = cf.describe_stack_set(StackSetName=ss_id)["StackSet"] + assert stack_set["TemplateBody"] == dummy_template_json @mock_cloudformation def test_create_stack_fail_missing_parameter(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") with pytest.raises(ClientError, match="Missing parameter KeyName"): - - cf_conn.create_stack( - StackName="test_stack", TemplateBody=dummy_parametrized_template_json - ) + cf.create_stack(StackName="ts", TemplateBody=dummy_parametrized_template_json) @mock_cloudformation def test_create_stack_s3_long_name(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") stack_name = "MyLongStackName01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012" template = '{"Resources":{"HelloBucket":{"Type":"AWS::S3::Bucket"}}}' - cf_conn.create_stack(StackName=stack_name, TemplateBody=template) + cf.create_stack(StackName=stack_name, TemplateBody=template) - cf_conn.get_template(StackName=stack_name)["TemplateBody"].should.equal( - json.loads(template, object_pairs_hook=OrderedDict) - ) - provisioned_resource = cf_conn.list_stack_resources(StackName=stack_name)[ + tmplt = cf.get_template(StackName=stack_name)["TemplateBody"] + assert tmplt == json.loads(template, object_pairs_hook=OrderedDict) + provisioned_resource = cf.list_stack_resources(StackName=stack_name)[ "StackResourceSummaries" ][0] provisioned_bucket_name = provisioned_resource["PhysicalResourceId"] - len(provisioned_bucket_name).should.be.lower_than(64) + assert len(provisioned_bucket_name) < 64 logical_name_lower_case = provisioned_resource["LogicalResourceId"].lower() bucket_name_stack_name_prefix = provisioned_bucket_name[ : provisioned_bucket_name.index("-" + logical_name_lower_case) ] - stack_name.lower().should.contain(bucket_name_stack_name_prefix) + assert bucket_name_stack_name_prefix in stack_name.lower() @mock_cloudformation def test_create_stack_with_yaml(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_yaml) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="ts", TemplateBody=dummy_template_yaml) - cf_conn.get_template(StackName="test_stack")["TemplateBody"].should.equal( - dummy_template_yaml - ) + assert cf.get_template(StackName="ts")["TemplateBody"] == dummy_template_yaml @mock_cloudformation def test_create_stack_with_short_form_func_yaml(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( - StackName="test_stack", TemplateBody=dummy_template_yaml_with_short_form_func + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( + StackName="ts", TemplateBody=dummy_template_yaml_with_short_form_func ) - cf_conn.get_template(StackName="test_stack")["TemplateBody"].should.equal( - dummy_template_yaml_with_short_form_func - ) + template_body = cf.get_template(StackName="ts")["TemplateBody"] + assert template_body == dummy_template_yaml_with_short_form_func @mock_s3 @@ -1009,18 +922,18 @@ def test_get_template_summary(): # json template conn = boto3.client("cloudformation", region_name="us-east-1") result = conn.get_template_summary(TemplateBody=json.dumps(dummy_template3)) - result["ResourceTypes"].should.equal(["AWS::EC2::VPC"]) - result["Version"].should.equal("2010-09-09") - result["Description"].should.equal("Stack 3") - result["Parameters"].should.equal([]) + assert result["ResourceTypes"] == ["AWS::EC2::VPC"] + assert result["Version"] == "2010-09-09" + assert result["Description"] == "Stack 3" + assert result["Parameters"] == [] # existing stack conn.create_stack(StackName="test_stack", TemplateBody=json.dumps(dummy_template3)) result = conn.get_template_summary(StackName="test_stack") - result["ResourceTypes"].should.equal(["AWS::EC2::VPC"]) - result["Version"].should.equal("2010-09-09") - result["Description"].should.equal("Stack 3") - result["Parameters"].should.equal([]) + assert result["ResourceTypes"] == ["AWS::EC2::VPC"] + assert result["Version"] == "2010-09-09" + assert result["Description"] == "Stack 3" + assert result["Parameters"] == [] # json template from s3 s3_conn.create_bucket(Bucket="foobar") @@ -1030,16 +943,16 @@ def test_get_template_summary(): ) conn.create_stack(StackName="stackfromurl", TemplateURL=key_url) result = conn.get_template_summary(TemplateURL=key_url) - result["ResourceTypes"].should.equal(["AWS::EC2::VPC"]) - result["Version"].should.equal("2010-09-09") - result["Description"].should.equal("Stack 3") + assert result["ResourceTypes"] == ["AWS::EC2::VPC"] + assert result["Version"] == "2010-09-09" + assert result["Description"] == "Stack 3" # yaml template conn = boto3.client("cloudformation", region_name="us-east-1") result = conn.get_template_summary(TemplateBody=dummy_template_yaml) - result["ResourceTypes"].should.equal(["AWS::EC2::Instance"]) - result["Version"].should.equal("2010-09-09") - result["Description"].should.equal("Stack1 with yaml template") + assert result["ResourceTypes"] == ["AWS::EC2::Instance"] + assert result["Version"] == "2010-09-09" + assert result["Description"] == "Stack1 with yaml template" @mock_cloudformation @@ -1058,9 +971,9 @@ def test_get_template_summary_for_stack_created_by_changeset_execution(): conn.get_template_summary(StackName="stack_from_changeset") conn.execute_change_set(ChangeSetName="test_changeset") result = conn.get_template_summary(StackName="stack_from_changeset") - result["ResourceTypes"].should.equal(["AWS::EC2::VPC"]) - result["Version"].should.equal("2010-09-09") - result["Description"].should.equal("Stack 3") + assert result["ResourceTypes"] == ["AWS::EC2::VPC"] + assert result["Version"] == "2010-09-09" + assert result["Description"] == "Stack 3" @mock_s3 @@ -1071,57 +984,55 @@ def test_get_template_summary_for_template_containing_parameters(): StackName="test_stack", TemplateBody=json.dumps(dummy_template_with_parameters) ) result = conn.get_template_summary(StackName="test_stack") - result.should.match_dict( - { - "Parameters": [ - { - "ParameterKey": "Name", - "DefaultValue": "SomeValue", - "ParameterType": "String", - "NoEcho": False, - "Description": "", - "ParameterConstraints": {}, - }, - { - "ParameterKey": "Another", - "DefaultValue": "A", - "ParameterType": "String", - "NoEcho": False, - "Description": "Chose A or B", - "ParameterConstraints": {"AllowedValues": ["A", "B"]}, - }, - ], - "Description": "A simple CloudFormation template", - "ResourceTypes": ["AWS::S3::Bucket"], - "Version": "2010-09-09", - # TODO: get_template_summary should support ResourceIdentifierSummaries - # "ResourceIdentifierSummaries": [ - # { - # "ResourceType": "AWS::S3::Bucket", - # "LogicalResourceIds": ["Bucket"], - # "ResourceIdentifiers": ["BucketName"], - # } - # ], - } - ) + del result["ResponseMetadata"] + assert result == { + "Parameters": [ + { + "ParameterKey": "Name", + "DefaultValue": "SomeValue", + "ParameterType": "String", + "NoEcho": False, + "Description": "", + "ParameterConstraints": {}, + }, + { + "ParameterKey": "Another", + "DefaultValue": "A", + "ParameterType": "String", + "NoEcho": False, + "Description": "Chose A or B", + "ParameterConstraints": {"AllowedValues": ["A", "B"]}, + }, + ], + "Description": "A simple CloudFormation template", + "ResourceTypes": ["AWS::S3::Bucket"], + "Version": "2010-09-09", + # TODO: get_template_summary should support ResourceIdentifierSummaries + # "ResourceIdentifierSummaries": [ + # { + # "ResourceType": "AWS::S3::Bucket", + # "LogicalResourceIds": ["Bucket"], + # "ResourceIdentifiers": ["BucketName"], + # } + # ], + } @mock_cloudformation def test_create_stack_with_ref_yaml(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") params = [ {"ParameterKey": "TagDescription", "ParameterValue": "desc_ref"}, {"ParameterKey": "TagName", "ParameterValue": "name_ref"}, ] - cf_conn.create_stack( + cf.create_stack( StackName="test_stack", TemplateBody=dummy_template_yaml_with_ref, Parameters=params, ) - cf_conn.get_template(StackName="test_stack")["TemplateBody"].should.equal( - dummy_template_yaml_with_ref - ) + template_body = cf.get_template(StackName="test_stack")["TemplateBody"] + assert template_body == dummy_template_yaml_with_ref @mock_cloudformation @@ -1131,13 +1042,15 @@ def test_creating_stacks_across_regions(): west1_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) west2_cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - list(west1_cf.stacks.all()).should.have.length_of(1) - list(west2_cf.stacks.all()).should.have.length_of(1) + west1_stacks = list(west1_cf.stacks.all()) + west2_stacks = list(west2_cf.stacks.all()) + assert len(west1_stacks) == 1 + assert len(west2_stacks) == 1 - list(west1_cf.stacks.all())[0].stack_id.should.contain( + assert west1_stacks[0].stack_id.startswith( f"arn:aws:cloudformation:us-west-1:{ACCOUNT_ID}:stack/test_stack/" ) - list(west2_cf.stacks.all())[0].stack_id.should.contain( + assert west2_stacks[0].stack_id.startswith( f"arn:aws:cloudformation:us-west-2:{ACCOUNT_ID}:stack/test_stack/" ) @@ -1164,44 +1077,44 @@ def test_create_stack_with_notification_arn(): ) stack = list(cf.stacks.all())[0] - stack.notification_arns.should.contain(topic_arn) + assert topic_arn in stack.notification_arns messages = queue.receive_messages() - messages.should.have.length_of(1) + assert len(messages) == 1 msg = json.loads(messages[0].body) - msg["Subject"].should.equal("AWS CloudFormation Notification") - msg["Message"].should.contain(f"StackId='{stack.stack_id}'\n") - msg["Message"].should.contain("LogicalResourceId='test_stack_with_notifications'\n") - msg["Message"].should.contain("ResourceStatus='CREATE_IN_PROGRESS'\n") - msg["Message"].should.contain("ResourceStatusReason='User Initiated'\n") - msg["Message"].should.contain("ResourceType='AWS::CloudFormation::Stack'\n") - msg["Message"].should.contain("StackName='test_stack_with_notifications'\n") - msg.should.have.key("MessageId") - msg.should.have.key("Signature") - msg.should.have.key("SignatureVersion") - msg.should.have.key("Subject") - msg.should.have.key("Timestamp") - msg["TopicArn"].should.equal(topic_arn) - msg.should.have.key("Type") - msg.should.have.key("UnsubscribeURL") + assert msg["Subject"] == "AWS CloudFormation Notification" + assert f"StackId='{stack.stack_id}'\n" in msg["Message"] + assert "LogicalResourceId='test_stack_with_notifications'\n" in msg["Message"] + assert "ResourceStatus='CREATE_IN_PROGRESS'\n" in msg["Message"] + assert "ResourceStatusReason='User Initiated'\n" in msg["Message"] + assert "ResourceType='AWS::CloudFormation::Stack'\n" in msg["Message"] + assert "StackName='test_stack_with_notifications'\n" in msg["Message"] + assert "MessageId" in msg + assert "Signature" in msg + assert "SignatureVersion" in msg + assert "Subject" in msg + assert "Timestamp" in msg + assert msg["TopicArn"] == topic_arn + assert "Type" in msg + assert "UnsubscribeURL" in msg messages = queue.receive_messages() - messages.should.have.length_of(1) + assert len(messages) == 1 msg = json.loads(messages[0].body) - msg["Message"].should.contain(f"StackId='{stack.stack_id}'\n") - msg["Message"].should.contain("LogicalResourceId='test_stack_with_notifications'\n") - msg["Message"].should.contain("ResourceStatus='CREATE_COMPLETE'\n") - msg["Message"].should.contain("ResourceStatusReason='None'\n") - msg["Message"].should.contain("ResourceType='AWS::CloudFormation::Stack'\n") - msg["Message"].should.contain("StackName='test_stack_with_notifications'\n") - msg.should.have.key("MessageId") - msg.should.have.key("Signature") - msg.should.have.key("SignatureVersion") - msg.should.have.key("Subject") - msg.should.have.key("Timestamp") - msg["TopicArn"].should.equal(topic_arn) - msg.should.have.key("Type") - msg.should.have.key("UnsubscribeURL") + assert f"StackId='{stack.stack_id}'\n" in msg["Message"] + assert "LogicalResourceId='test_stack_with_notifications'\n" in msg["Message"] + assert "ResourceStatus='CREATE_COMPLETE'\n" in msg["Message"] + assert "ResourceStatusReason='None'\n" in msg["Message"] + assert "ResourceType='AWS::CloudFormation::Stack'\n" in msg["Message"] + assert "StackName='test_stack_with_notifications'\n" in msg["Message"] + assert "MessageId" in msg + assert "Signature" in msg + assert "SignatureVersion" in msg + assert "Subject" in msg + assert "Timestamp" in msg + assert msg["TopicArn"] == topic_arn + assert "Type" in msg + assert "UnsubscribeURL" in msg @mock_cloudformation @@ -1213,7 +1126,7 @@ def test_create_stack_with_role_arn(): RoleARN=f"arn:aws:iam::{ACCOUNT_ID}:role/moto", ) stack = list(cf.stacks.all())[0] - stack.role_arn.should.equal(f"arn:aws:iam::{ACCOUNT_ID}:role/moto") + assert stack.role_arn == f"arn:aws:iam::{ACCOUNT_ID}:role/moto" @mock_cloudformation @@ -1228,54 +1141,49 @@ def test_create_stack_from_s3_url(): ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"} ) - cf_conn = boto3.client("cloudformation", region_name="us-west-1") - cf_conn.create_stack(StackName="stackfromurl", TemplateURL=key_url) - cf_conn.get_template(StackName="stackfromurl")["TemplateBody"].should.equal( - json.loads(dummy_template_json, object_pairs_hook=OrderedDict) - ) + cf = boto3.client("cloudformation", region_name="us-west-1") + cf.create_stack(StackName="stackfromurl", TemplateURL=key_url) + tmplt = cf.get_template(StackName="stackfromurl")["TemplateBody"] + assert tmplt == json.loads(dummy_template_json, object_pairs_hook=OrderedDict) @mock_cloudformation def test_update_stack_fail_missing_new_parameter(): - name = "update_stack_fail_missing_new_parameter" - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName=name, TemplateBody=dummy_empty_template_json) + cf.create_stack(StackName=name, TemplateBody=dummy_empty_template_json) with pytest.raises(ClientError, match="Missing parameter KeyName"): - - cf_conn.update_stack( - StackName=name, TemplateBody=dummy_parametrized_template_json - ) + cf.update_stack(StackName=name, TemplateBody=dummy_parametrized_template_json) @mock_cloudformation def test_update_stack_fail_update_same_template_body(): name = "update_stack_with_previous_value" - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") params = [ {"ParameterKey": "TagName", "ParameterValue": "foo"}, {"ParameterKey": "TagDescription", "ParameterValue": "bar"}, ] - cf_conn.create_stack( + cf.create_stack( StackName=name, TemplateBody=dummy_template_yaml_with_ref, Parameters=params ) with pytest.raises(ClientError) as exp: - cf_conn.update_stack( + cf.update_stack( StackName=name, TemplateBody=dummy_template_yaml_with_ref, Parameters=params ) exp_err = exp.value.response.get("Error") exp_metadata = exp.value.response.get("ResponseMetadata") - exp_err.get("Code").should.equal("ValidationError") - exp_err.get("Message").should.equal("No updates are to be performed.") - exp_metadata.get("HTTPStatusCode").should.equal(400) + assert exp_err.get("Code") == "ValidationError" + assert exp_err.get("Message") == "No updates are to be performed." + assert exp_metadata.get("HTTPStatusCode") == 400 - cf_conn.update_stack( + cf.update_stack( StackName=name, TemplateBody=dummy_template_yaml_with_ref, Parameters=[ @@ -1287,10 +1195,9 @@ def test_update_stack_fail_update_same_template_body(): @mock_cloudformation def test_update_stack_deleted_resources_can_reference_deleted_parameters(): - name = "update_stack_deleted_resources_can_reference_deleted_parameters" - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") template_json = json.dumps( { @@ -1305,23 +1212,22 @@ def test_update_stack_deleted_resources_can_reference_deleted_parameters(): } ) - cf_conn.create_stack(StackName=name, TemplateBody=template_json) + cf.create_stack(StackName=name, TemplateBody=template_json) - response = cf_conn.describe_stack_resources(StackName=name) - len(response["StackResources"]).should.equal(1) + response = cf.describe_stack_resources(StackName=name) + assert len(response["StackResources"]) == 1 - cf_conn.update_stack(StackName=name, TemplateBody=dummy_empty_template_json) + cf.update_stack(StackName=name, TemplateBody=dummy_empty_template_json) - response = cf_conn.describe_stack_resources(StackName=name) - len(response["StackResources"]).should.equal(0) + response = cf.describe_stack_resources(StackName=name) + assert len(response["StackResources"]) == 0 @mock_cloudformation def test_update_stack_deleted_resources_can_reference_deleted_resources(): - name = "update_stack_deleted_resources_can_reference_deleted_resources" - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") template_json = json.dumps( { @@ -1340,22 +1246,22 @@ def test_update_stack_deleted_resources_can_reference_deleted_resources(): } ) - cf_conn.create_stack(StackName=name, TemplateBody=template_json) + cf.create_stack(StackName=name, TemplateBody=template_json) - response = cf_conn.describe_stack_resources(StackName=name) - len(response["StackResources"]).should.equal(2) + response = cf.describe_stack_resources(StackName=name) + assert len(response["StackResources"]) == 2 - cf_conn.update_stack(StackName=name, TemplateBody=dummy_empty_template_json) + cf.update_stack(StackName=name, TemplateBody=dummy_empty_template_json) - response = cf_conn.describe_stack_resources(StackName=name) - len(response["StackResources"]).should.equal(0) + response = cf.describe_stack_resources(StackName=name) + assert len(response["StackResources"]) == 0 @mock_cloudformation def test_update_stack_with_previous_value(): name = "update_stack_with_previous_value" - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( StackName=name, TemplateBody=dummy_template_yaml_with_ref, Parameters=[ @@ -1363,7 +1269,7 @@ def test_update_stack_with_previous_value(): {"ParameterKey": "TagDescription", "ParameterValue": "bar"}, ], ) - cf_conn.update_stack( + cf.update_stack( StackName=name, UsePreviousTemplate=True, Parameters=[ @@ -1371,7 +1277,7 @@ def test_update_stack_with_previous_value(): {"ParameterKey": "TagDescription", "ParameterValue": "not bar"}, ], ) - stack = cf_conn.describe_stacks(StackName=name)["Stacks"][0] + stack = cf.describe_stacks(StackName=name)["Stacks"][0] tag_name = [ x["ParameterValue"] for x in stack["Parameters"] @@ -1393,8 +1299,8 @@ 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") - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( StackName="update_stack_from_url", TemplateBody=dummy_template_json, Tags=[{"Key": "foo", "Value": "bar"}], @@ -1407,16 +1313,15 @@ def test_update_stack_from_s3_url(): ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"} ) - cf_conn.update_stack( + cf.update_stack( StackName="update_stack_from_url", TemplateURL=key_url, Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], ) - cf_conn.get_template(StackName="update_stack_from_url")[ - "TemplateBody" - ].should.equal( - json.loads(dummy_update_template_json, object_pairs_hook=OrderedDict) + tmplt = cf.get_template(StackName="update_stack_from_url")["TemplateBody"] + assert tmplt == json.loads( + dummy_update_template_json, object_pairs_hook=OrderedDict ) @@ -1431,8 +1336,8 @@ def test_create_change_set_from_s3_url(): key_url = s3.generate_presigned_url( ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"} ) - cf_conn = boto3.client("cloudformation", region_name="us-west-1") - response = cf_conn.create_change_set( + cf = boto3.client("cloudformation", region_name="us-west-1") + response = cf.create_change_set( StackName="NewStack", TemplateURL=key_url, ChangeSetName="NewChangeSet", @@ -1452,54 +1357,50 @@ def test_create_change_set_from_s3_url(): @mock_cloudformation @mock_ec2 def test_describe_change_set(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_change_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, ChangeSetName="NewChangeSet", ChangeSetType="CREATE", ) - stack = cf_conn.describe_change_set(ChangeSetName="NewChangeSet") + stack = cf.describe_change_set(ChangeSetName="NewChangeSet") - stack["ChangeSetName"].should.equal("NewChangeSet") - stack["StackName"].should.equal("NewStack") - stack["Status"].should.equal("CREATE_COMPLETE") - stack["ExecutionStatus"].should.equal("AVAILABLE") + assert stack["ChangeSetName"] == "NewChangeSet" + assert stack["StackName"] == "NewStack" + assert stack["Status"] == "CREATE_COMPLETE" + assert stack["ExecutionStatus"] == "AVAILABLE" two_secs_ago = datetime.now(tz=timezone.utc) - timedelta(seconds=2) assert ( two_secs_ago < stack["CreationTime"] < datetime.now(tz=timezone.utc) ), "Change set should have been created recently" - stack["Changes"].should.have.length_of(1) - stack["Changes"][0].should.equal( - dict( - { - "Type": "Resource", - "ResourceChange": { - "Action": "Add", - "LogicalResourceId": "EC2Instance1", - "ResourceType": "AWS::EC2::Instance", - }, - } - ) - ) + assert len(stack["Changes"]) == 1 + assert stack["Changes"][0] == { + "Type": "Resource", + "ResourceChange": { + "Action": "Add", + "LogicalResourceId": "EC2Instance1", + "ResourceType": "AWS::EC2::Instance", + }, + } # Execute change set - cf_conn.execute_change_set(ChangeSetName="NewChangeSet") + cf.execute_change_set(ChangeSetName="NewChangeSet") # Verify that the changes have been applied ec2 = boto3.client("ec2", region_name="us-east-1") - ec2.describe_instances()["Reservations"].should.have.length_of(1) + assert len(ec2.describe_instances()["Reservations"]) == 1 - change_set = cf_conn.describe_change_set(ChangeSetName="NewChangeSet") - change_set["Changes"].should.have.length_of(1) - change_set["ExecutionStatus"].should.equal("EXECUTE_COMPLETE") + change_set = cf.describe_change_set(ChangeSetName="NewChangeSet") + assert len(change_set["Changes"]) == 1 + assert change_set["ExecutionStatus"] == "EXECUTE_COMPLETE" - stack = cf_conn.describe_stacks(StackName="NewStack")["Stacks"][0] - stack["StackStatus"].should.equal("CREATE_COMPLETE") + stack = cf.describe_stacks(StackName="NewStack")["Stacks"][0] + assert stack["StackStatus"] == "CREATE_COMPLETE" # create another change set to update the stack - cf_conn.create_change_set( + cf.create_change_set( StackName="NewStack", TemplateBody=dummy_update_template_json, ChangeSetName="NewChangeSet2", @@ -1507,56 +1408,52 @@ def test_describe_change_set(): Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], ) - stack = cf_conn.describe_change_set(ChangeSetName="NewChangeSet2") - stack["ChangeSetName"].should.equal("NewChangeSet2") - stack["StackName"].should.equal("NewStack") - stack["Changes"].should.have.length_of(2) + stack = cf.describe_change_set(ChangeSetName="NewChangeSet2") + assert stack["ChangeSetName"] == "NewChangeSet2" + assert stack["StackName"] == "NewStack" + assert len(stack["Changes"]) == 2 # Execute change set - cf_conn.execute_change_set(ChangeSetName="NewChangeSet2") + cf.execute_change_set(ChangeSetName="NewChangeSet2") # Verify that the changes have been applied - stack = cf_conn.describe_stacks(StackName="NewStack")["Stacks"][0] - stack["StackStatus"].should.equal("UPDATE_COMPLETE") + stack = cf.describe_stacks(StackName="NewStack")["Stacks"][0] + assert stack["StackStatus"] == "UPDATE_COMPLETE" @mock_cloudformation @mock_ec2 def test_execute_change_set_w_arn(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1") # Verify no instances exist at the moment - ec2.describe_instances()["Reservations"].should.have.length_of(0) + assert len(ec2.describe_instances()["Reservations"]) == 0 # Create a Change set, and verify no resources have been created yet - change_set = cf_conn.create_change_set( + change_set = cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, - ChangeSetName="NewChangeSet", + ChangeSetName="NewCS", ChangeSetType="CREATE", ) - ec2.describe_instances()["Reservations"].should.have.length_of(0) - cf_conn.describe_change_set(ChangeSetName="NewChangeSet")["Status"].should.equal( - "CREATE_COMPLETE" - ) + assert len(ec2.describe_instances()["Reservations"]) == 0 + assert cf.describe_change_set(ChangeSetName="NewCS")["Status"] == "CREATE_COMPLETE" # Execute change set - cf_conn.execute_change_set(ChangeSetName=change_set["Id"]) + cf.execute_change_set(ChangeSetName=change_set["Id"]) # Verify that the status has changed, and the appropriate resources have been created - cf_conn.describe_change_set(ChangeSetName="NewChangeSet")["Status"].should.equal( - "CREATE_COMPLETE" - ) - ec2.describe_instances()["Reservations"].should.have.length_of(1) + assert cf.describe_change_set(ChangeSetName="NewCS")["Status"] == "CREATE_COMPLETE" + assert len(ec2.describe_instances()["Reservations"]) == 1 @mock_cloudformation def test_execute_change_set_w_name(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_change_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, ChangeSetName="NewChangeSet", ChangeSetType="CREATE", ) - cf_conn.execute_change_set(ChangeSetName="NewChangeSet", StackName="NewStack") + cf.execute_change_set(ChangeSetName="NewChangeSet", StackName="NewStack") @mock_cloudformation @@ -1567,68 +1464,68 @@ def test_describe_stack_pagination(): resp = conn.describe_stacks() stacks = resp["Stacks"] - stacks.should.have.length_of(50) + assert len(stacks) == 50 next_token = resp["NextToken"] - next_token.should_not.equal(None) + assert next_token is not None resp2 = conn.describe_stacks(NextToken=next_token) stacks.extend(resp2["Stacks"]) - stacks.should.have.length_of(100) + assert len(stacks) == 100 assert "NextToken" not in resp2.keys() @mock_cloudformation def test_describe_stack_resource(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - response = cf_conn.describe_stack_resource( + response = cf.describe_stack_resource( StackName=stack["StackName"], LogicalResourceId="EC2Instance1" ) resource = response["StackResourceDetail"] - resource["LogicalResourceId"].should.equal("EC2Instance1") - resource["ResourceStatus"].should.equal("CREATE_COMPLETE") - resource["ResourceType"].should.equal("AWS::EC2::Instance") - resource["StackId"].should.equal(stack["StackId"]) + assert resource["LogicalResourceId"] == "EC2Instance1" + assert resource["ResourceStatus"] == "CREATE_COMPLETE" + assert resource["ResourceType"] == "AWS::EC2::Instance" + assert resource["StackId"] == stack["StackId"] @mock_cloudformation def test_describe_stack_resource_when_resource_does_not_exist(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] with pytest.raises(ClientError, match="does not exist for stack"): - cf_conn.describe_stack_resource( + cf.describe_stack_resource( StackName=stack["StackName"], LogicalResourceId="DoesNotExist" ) @mock_cloudformation def test_describe_stack_resources(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - response = cf_conn.describe_stack_resources(StackName=stack["StackName"]) + response = cf.describe_stack_resources(StackName=stack["StackName"]) resource = response["StackResources"][0] - resource["LogicalResourceId"].should.equal("EC2Instance1") - resource["ResourceStatus"].should.equal("CREATE_COMPLETE") - resource["ResourceType"].should.equal("AWS::EC2::Instance") - resource["StackId"].should.equal(stack["StackId"]) + assert resource["LogicalResourceId"] == "EC2Instance1" + assert resource["ResourceStatus"] == "CREATE_COMPLETE" + assert resource["ResourceType"] == "AWS::EC2::Instance" + assert resource["StackId"] == stack["StackId"] @mock_cloudformation def test_describe_stack_by_name(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] - stack["StackName"].should.equal("test_stack") + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + assert stack["StackName"] == "test_stack" two_secs_ago = datetime.now(tz=timezone.utc) - timedelta(seconds=2) assert ( two_secs_ago < stack["CreationTime"] < datetime.now(tz=timezone.utc) @@ -1637,28 +1534,28 @@ def test_describe_stack_by_name(): @mock_cloudformation def test_describe_stack_by_stack_id(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] - stack_by_id = cf_conn.describe_stacks(StackName=stack["StackId"])["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + stack_by_id = cf.describe_stacks(StackName=stack["StackId"])["Stacks"][0] - stack_by_id["StackId"].should.equal(stack["StackId"]) - stack_by_id["StackName"].should.equal("test_stack") + assert stack_by_id["StackId"] == stack["StackId"] + assert stack_by_id["StackName"] == "test_stack" @mock_cloudformation def test_list_change_sets(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_change_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_change_set( StackName="NewStack2", TemplateBody=dummy_template_json, ChangeSetName="NewChangeSet2", ChangeSetType="CREATE", ) - change_set = cf_conn.list_change_sets(StackName="NewStack2")["Summaries"][0] - change_set["StackName"].should.equal("NewStack2") - change_set["ChangeSetName"].should.equal("NewChangeSet2") + change_set = cf.list_change_sets(StackName="NewStack2")["Summaries"][0] + assert change_set["StackName"] == "NewStack2" + assert change_set["ChangeSetName"] == "NewChangeSet2" @mock_cloudformation @@ -1668,10 +1565,10 @@ def test_list_stacks(): cf.create_stack(StackName="test_stack2", TemplateBody=dummy_template_json) stacks = list(cf.stacks.all()) - stacks.should.have.length_of(2) + assert len(stacks) == 2 stack_names = [stack.stack_name for stack in stacks] - stack_names.should.contain("test_stack") - stack_names.should.contain("test_stack2") + assert "test_stack" in stack_names + assert "test_stack2" in stack_names @mock_cloudformation @@ -1679,35 +1576,35 @@ 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) - list(cf.stacks.all()).should.have.length_of(1) + assert len(list(cf.stacks.all())) == 1 stack.delete() - list(cf.stacks.all()).should.have.length_of(0) + assert len(list(cf.stacks.all())) == 0 @mock_cloudformation @mock_ec2 def test_delete_change_set(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_change_set( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, ChangeSetName="NewChangeSet", ChangeSetType="CREATE", ) - cf_conn.list_change_sets(StackName="NewStack")["Summaries"].should.have.length_of(1) - cf_conn.delete_change_set(ChangeSetName="NewChangeSet", StackName="NewStack") - cf_conn.list_change_sets(StackName="NewStack")["Summaries"].should.have.length_of(0) + assert len(cf.list_change_sets(StackName="NewStack")["Summaries"]) == 1 + cf.delete_change_set(ChangeSetName="NewChangeSet", StackName="NewStack") + assert len(cf.list_change_sets(StackName="NewStack")["Summaries"]) == 0 # Testing deletion by arn - result = cf_conn.create_change_set( + result = cf.create_change_set( StackName="NewStack", TemplateBody=dummy_template_json, ChangeSetName="NewChangeSet1", ChangeSetType="CREATE", ) - cf_conn.delete_change_set(ChangeSetName=result.get("Id"), StackName="NewStack") - cf_conn.list_change_sets(StackName="NewStack")["Summaries"].should.have.length_of(0) + cf.delete_change_set(ChangeSetName=result.get("Id"), StackName="NewStack") + assert len(cf.list_change_sets(StackName="NewStack")["Summaries"]) == 0 @mock_cloudformation @@ -1734,10 +1631,11 @@ def test_create_change_set_twice__no_changes(): execution = cf_client.describe_change_set(ChangeSetName=change_set_id) # Assert - execution["ExecutionStatus"].should.equal("UNAVAILABLE") - execution["Status"].should.equal("FAILED") - execution["StatusReason"].should.equal( - "The submitted information didn't contain changes. Submit different information to create a change set." + assert execution["ExecutionStatus"] == "UNAVAILABLE" + assert execution["Status"] == "FAILED" + assert ( + execution["StatusReason"] + == "The submitted information didn't contain changes. Submit different information to create a change set." ) @@ -1780,22 +1678,23 @@ def test_create_change_set_twice__using_s3__no_changes(): execution = cf_client.describe_change_set(ChangeSetName=change_set_id) # Assert - execution["ExecutionStatus"].should.equal("UNAVAILABLE") - execution["Status"].should.equal("FAILED") - execution["StatusReason"].should.equal( - "The submitted information didn't contain changes. Submit different information to create a change set." + assert execution["ExecutionStatus"] == "UNAVAILABLE" + assert execution["Status"] == "FAILED" + assert ( + execution["StatusReason"] + == "The submitted information didn't contain changes. Submit different information to create a change set." ) @mock_cloudformation @mock_ec2 def test_delete_stack_by_name(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - cf_conn.describe_stacks()["Stacks"].should.have.length_of(1) - cf_conn.delete_stack(StackName="test_stack") - cf_conn.describe_stacks()["Stacks"].should.have.length_of(0) + assert len(cf.describe_stacks()["Stacks"]) == 1 + cf.delete_stack(StackName="test_stack") + assert len(cf.describe_stacks()["Stacks"]) == 0 @mock_cloudformation @@ -1810,9 +1709,7 @@ def test_delete_stack(): cf.delete_stack(StackName="test_stack") stacks = cf.list_stacks() assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE" - ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"].shouldnt.equal( - state - ) + assert ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] != state @mock_cloudformation @@ -1838,34 +1735,32 @@ def test_delete_stack_delete_not_implemented(monkeypatch): stacks = cf.list_stacks() assert stacks["StackSummaries"][0]["StackStatus"] == "DELETE_COMPLETE" # But the underlying resource is untouched - ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"].should.equal( - state - ) + assert ec2.describe_instances()["Reservations"][0]["Instances"][0]["State"] == state @mock_cloudformation def test_describe_deleted_stack(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] stack_id = stack["StackId"] - cf_conn.delete_stack(StackName=stack["StackId"]) - stack_by_id = cf_conn.describe_stacks(StackName=stack_id)["Stacks"][0] - stack_by_id["StackId"].should.equal(stack["StackId"]) - stack_by_id["StackName"].should.equal("test_stack") - stack_by_id["StackStatus"].should.equal("DELETE_COMPLETE") + 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["StackStatus"] == "DELETE_COMPLETE" @mock_cloudformation def test_describe_stack_with_special_chars(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( StackName="test_stack_spl", TemplateBody=dummy_template_special_chars_in_description_json, ) - stack = cf_conn.describe_stacks(StackName="test_stack_spl")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack_spl")["Stacks"][0] assert stack.get("StackName") == "test_stack_spl" assert stack.get("Description") == "Stack 1 " @@ -1873,14 +1768,14 @@ def test_describe_stack_with_special_chars(): @mock_cloudformation @mock_ec2 def test_describe_updated_stack(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack( + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack( StackName="test_stack", TemplateBody=dummy_template_json, Tags=[{"Key": "foo", "Value": "bar"}], ) - cf_conn.update_stack( + cf.update_stack( StackName="test_stack", RoleARN=f"arn:aws:iam::{ACCOUNT_ID}:role/moto", TemplateBody=dummy_update_template_json, @@ -1888,45 +1783,43 @@ def test_describe_updated_stack(): Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "value"}], ) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] stack_id = stack["StackId"] - stack_by_id = cf_conn.describe_stacks(StackName=stack_id)["Stacks"][0] - stack_by_id["StackId"].should.equal(stack["StackId"]) - stack_by_id["StackName"].should.equal("test_stack") - stack_by_id["StackStatus"].should.equal("UPDATE_COMPLETE") - stack_by_id["RoleARN"].should.equal(f"arn:aws:iam::{ACCOUNT_ID}:role/moto") - stack_by_id["Tags"].should.equal([{"Key": "foo", "Value": "baz"}]) + 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["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_conn.get_template(StackName="test_stack")["TemplateBody"] - template.should.equal(dummy_update_template) + template = cf.get_template(StackName="test_stack")["TemplateBody"] + assert template == dummy_update_template @mock_cloudformation def test_update_stack_with_previous_template(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) - cf_conn.update_stack(StackName="test_stack", UsePreviousTemplate=True) + 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) - stack = cf_conn.describe_stacks(StackName="test_stack")["Stacks"][0] - stack["StackName"].should.equal("test_stack") - stack["StackStatus"].should.equal("UPDATE_COMPLETE") + stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] + assert stack["StackName"] == "test_stack" + assert stack["StackStatus"] == "UPDATE_COMPLETE" # Verify the original template is persisted - template = cf_conn.get_template(StackName="test_stack")["TemplateBody"] - template.should.equal(dummy_template) + template = cf.get_template(StackName="test_stack")["TemplateBody"] + assert template == dummy_template @mock_cloudformation def test_bad_describe_stack(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") with pytest.raises(ClientError) as exc: - cf_conn.describe_stacks(StackName="non_existent_stack") + cf.describe_stacks(StackName="non_existent_stack") err = exc.value.response["Error"] - err.should.have.key("Code").being.equal("ValidationError") - err.should.have.key("Message").being.equal( - "Stack with id non_existent_stack does not exist" - ) + assert err["Code"] == "ValidationError" + assert err["Message"] == "Stack with id non_existent_stack does not exist" @mock_cloudformation @@ -1952,10 +1845,10 @@ def test_cloudformation_params(): Parameters=[{"ParameterKey": "APPNAME", "ParameterValue": "testing123"}], ) - stack.parameters.should.have.length_of(1) + assert len(stack.parameters) == 1 param = stack.parameters[0] - param["ParameterKey"].should.equal("APPNAME") - param["ParameterValue"].should.equal("testing123") + assert param["ParameterKey"] == "APPNAME" + assert param["ParameterValue"] == "testing123" @mock_cloudformation @@ -1986,10 +1879,11 @@ def test_update_stack_with_parameters(): ) stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - stack["Parameters"].should.have.length_of(1) - stack["Parameters"][0].should.equal( - {"ParameterKey": "Bar", "ParameterValue": "192.168.0.1/16"} - ) + assert len(stack["Parameters"]) == 1 + assert stack["Parameters"][0] == { + "ParameterKey": "Bar", + "ParameterValue": "192.168.0.1/16", + } @mock_cloudformation @@ -2008,8 +1902,8 @@ def test_update_stack_replace_tags(): ) stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] - stack["StackStatus"].should.equal("UPDATE_COMPLETE") - stack["Tags"].should.equal([{"Key": "foo", "Value": "baz"}]) + assert stack["StackStatus"] == "UPDATE_COMPLETE" + assert stack["Tags"] == [{"Key": "foo", "Value": "baz"}] @mock_cloudformation @@ -2028,10 +1922,8 @@ def test_update_stack_when_rolled_back(): cf.update_stack(StackName="test_stack", TemplateBody=dummy_template_json) err = ex.value.response["Error"] - err.should.have.key("Code").being.equal("ValidationError") - err.should.have.key("Message").match( - rf"Stack:arn:aws:cloudformation:us-east-1:{ACCOUNT_ID}:stack/test_stack/[a-z0-9-]+ is in ROLLBACK_COMPLETE state and can not be updated." - ) + assert err["Code"] == "ValidationError" + assert "is in ROLLBACK_COMPLETE state and can not be updated." in err["Message"] @mock_cloudformation @@ -2121,7 +2013,7 @@ def test_stack_tags(): expected_tag_items = set( item for items in [tag.items() for tag in tags] for item in items ) - observed_tag_items.should.equal(expected_tag_items) + assert observed_tag_items == expected_tag_items @mock_cloudformation @@ -2138,8 +2030,8 @@ def test_stack_events(): # assert begins and ends with stack events events = list(stack.events.all()) - events[0].resource_type.should.equal("AWS::CloudFormation::Stack") - events[-1].resource_type.should.equal("AWS::CloudFormation::Stack") + assert events[0].resource_type == "AWS::CloudFormation::Stack" + assert events[-1].resource_type == "AWS::CloudFormation::Stack" # testing ordering of stack events without assuming resource events will not exist # the AWS API returns events in reverse chronological order @@ -2155,22 +2047,21 @@ def test_stack_events(): ) try: for event in events: - event.stack_id.should.equal(stack.stack_id) - event.stack_name.should.equal("test_stack") - event.event_id.should.match(r"[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}") + assert event.stack_id == stack.stack_id + assert event.stack_name == "test_stack" if event.resource_type == "AWS::CloudFormation::Stack": - event.logical_resource_id.should.equal("test_stack") - event.physical_resource_id.should.equal(stack.stack_id) + assert event.logical_resource_id == "test_stack" + assert event.physical_resource_id == stack.stack_id status_to_look_for, reason_to_look_for = next(stack_events_to_look_for) - event.resource_status.should.equal(status_to_look_for) + assert event.resource_status == status_to_look_for if reason_to_look_for is not None: - event.resource_status_reason.should.equal(reason_to_look_for) + assert event.resource_status_reason == reason_to_look_for except StopIteration: assert False, "Too many stack events" - list(stack_events_to_look_for).should.be.empty + assert list(stack_events_to_look_for) == [] with pytest.raises(ClientError) as exp: stack = cf.Stack("non_existing_stack") @@ -2179,11 +2070,9 @@ def test_stack_events(): exp_err = exp.value.response.get("Error") exp_metadata = exp.value.response.get("ResponseMetadata") - exp_err.get("Code").should.match(r"ValidationError") - exp_err.get("Message").should.match( - r"Stack with id non_existing_stack does not exist" - ) - exp_metadata.get("HTTPStatusCode").should.equal(400) + assert exp_err["Code"] == "ValidationError" + assert exp_err["Message"] == "Stack with id non_existing_stack does not exist" + assert exp_metadata.get("HTTPStatusCode") == 400 @mock_cloudformation @@ -2196,13 +2085,13 @@ def test_list_exports(): output_value = "VPCID" exports = cf_client.list_exports()["Exports"] - stack.outputs.should.have.length_of(1) - stack.outputs[0]["OutputValue"].should.equal(output_value) + assert len(stack.outputs) == 1 + assert stack.outputs[0]["OutputValue"] == output_value - exports.should.have.length_of(1) - exports[0]["ExportingStackId"].should.equal(stack.stack_id) - exports[0]["Name"].should.equal("My VPC ID") - exports[0]["Value"].should.equal(output_value) + assert len(exports) == 1 + assert exports[0]["ExportingStackId"] == stack.stack_id + assert exports[0]["Name"] == "My VPC ID" + assert exports[0]["Value"] == output_value @mock_cloudformation @@ -2216,12 +2105,12 @@ def test_list_exports_with_token(): TemplateBody=json.dumps(dummy_output_template), ) exports = cf.list_exports() - exports["Exports"].should.have.length_of(100) - exports.get("NextToken").should_not.be.none + assert len(exports["Exports"]) == 100 + assert exports.get("NextToken") is not None more_exports = cf.list_exports(NextToken=exports["NextToken"]) - more_exports["Exports"].should.have.length_of(1) - more_exports.get("NextToken").should.be.none + assert len(more_exports["Exports"]) == 1 + assert more_exports.get("NextToken") is None @mock_cloudformation @@ -2233,10 +2122,10 @@ def test_delete_stack_with_export(): stack_id = stack["StackId"] exports = cf.list_exports()["Exports"] - exports.should.have.length_of(1) + assert len(exports) == 1 cf.delete_stack(StackName=stack_id) - cf.list_exports()["Exports"].should.have.length_of(0) + assert len(cf.list_exports()["Exports"]) == 0 @mock_cloudformation @@ -2258,10 +2147,9 @@ def test_stack_with_imports(): ) cf.create_stack(StackName="test_stack2", TemplateBody=dummy_import_template_json) - output_stack.outputs.should.have.length_of(1) + assert len(output_stack.outputs) == 1 output = output_stack.outputs[0]["OutputValue"] - queue = ec2_resource.get_queue_by_name(QueueName=output) - queue.should_not.equal(None) + assert ec2_resource.get_queue_by_name(QueueName=output) @mock_sqs @@ -2273,17 +2161,17 @@ def test_non_json_redrive_policy(): StackName="test_stack1", TemplateBody=dummy_redrive_template_json ) - stack.Resource("MainQueue").resource_status.should.equal("CREATE_COMPLETE") - stack.Resource("DeadLetterQueue").resource_status.should.equal("CREATE_COMPLETE") + assert stack.Resource("MainQueue").resource_status == "CREATE_COMPLETE" + assert stack.Resource("DeadLetterQueue").resource_status == "CREATE_COMPLETE" @mock_cloudformation def test_create_duplicate_stack(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf = boto3.client("cloudformation", region_name="us-east-1") + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) with pytest.raises(ClientError): - cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) + cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) @mock_dynamodb @@ -2293,10 +2181,10 @@ def test_delete_stack_dynamo_template(): dynamodb_client = boto3.client("dynamodb", region_name="us-east-1") conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4) table_desc = dynamodb_client.list_tables() - len(table_desc.get("TableNames")).should.equal(1) + assert len(table_desc.get("TableNames")) == 1 conn.delete_stack(StackName="test_stack") table_desc = dynamodb_client.list_tables() - len(table_desc.get("TableNames")).should.equal(0) + assert len(table_desc.get("TableNames")) == 0 conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json4) @@ -2367,46 +2255,44 @@ def test_create_stack_lambda_and_dynamodb(): resources = cf.list_stack_resources(StackName="test_stack_lambda")[ "StackResourceSummaries" ] - resources.should.have.length_of(4) + assert len(resources) == 4 resource_types = [r["ResourceType"] for r in resources] - resource_types.should.contain("AWS::Lambda::Function") - resource_types.should.contain("AWS::Lambda::Version") - resource_types.should.contain("AWS::DynamoDB::Table") - resource_types.should.contain("AWS::Lambda::EventSourceMapping") + assert "AWS::Lambda::Function" in resource_types + assert "AWS::Lambda::Version" in resource_types + assert "AWS::DynamoDB::Table" in resource_types + assert "AWS::Lambda::EventSourceMapping" in resource_types @mock_cloudformation @mock_ec2 def test_create_and_update_stack_with_unknown_resource(): - cf_conn = boto3.client("cloudformation", region_name="us-east-1") + cf = boto3.client("cloudformation", region_name="us-east-1") # 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_conn.create_stack( + cf.create_stack( StackName="test_stack", TemplateBody=dummy_unknown_template_json ) else: with pytest.warns(UserWarning, match=expected_err): - cf_conn.create_stack( + cf.create_stack( StackName="test_stack", TemplateBody=dummy_unknown_template_json ) # The stack should exist though - stacks = cf_conn.describe_stacks()["Stacks"] - stacks.should.have.length_of(1) - stacks[0].should.have.key("StackName").equal("test_stack") + stacks = cf.describe_stacks()["Stacks"] + assert len(stacks) == 1 + assert stacks[0]["StackName"] == "test_stack" # 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_conn.update_stack( - StackName="test_stack", TemplateBody=json.dumps(new_template) - ) + cf.update_stack(StackName="test_stack", TemplateBody=json.dumps(new_template)) else: with pytest.warns(UserWarning, match=expected_err): - cf_conn.update_stack( + cf.update_stack( StackName="test_stack", TemplateBody=json.dumps(new_template) ) diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index 26326b3fdd3c..8266353d5020 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -1,13 +1,11 @@ +import boto3 import json import io +import pytest import zipfile -from decimal import Decimal - from botocore.exceptions import ClientError -import boto3 -import sure # noqa # pylint: disable=unused-import -import pytest +from decimal import Decimal from string import Template from moto import ( @@ -29,9 +27,6 @@ from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2 from tests.markers import requires_docker from tests.test_cloudformation.fixtures import fn_join, single_instance_with_ebs_volume -from tests.helpers import ( # noqa # pylint: disable=unused-import - containing_item_with_attributes, -) @mock_cloudformation @@ -41,8 +36,8 @@ def test_create_template_without_required_param_boto3(): with pytest.raises(ClientError) as ex: cf.create_stack(StackName="test_stack", TemplateBody=template_json) err = ex.value.response["Error"] - err.should.have.key("Code").equal("Missing Parameter") - err.should.have.key("Message").equal("Missing parameter KeyName") + assert err["Code"] == "Missing Parameter" + assert err["Message"] == "Missing parameter KeyName" @mock_ec2 @@ -56,7 +51,7 @@ def test_fn_join_boto3(): stack = cf.describe_stacks()["Stacks"][0] fn_join_output = stack["Outputs"][0] - fn_join_output["OutputValue"].should.equal(f"test eip:{eip['PublicIp']}") + assert fn_join_output["OutputValue"] == f"test eip:{eip['PublicIp']}" @mock_cloudformation @@ -85,14 +80,14 @@ def test_conditional_resources_boto3(): Parameters=[{"ParameterKey": "EnvType", "ParameterValue": "staging"}], ) sqs = boto3.client("sqs", region_name="us-west-1") - sqs.list_queues().shouldnt.have.key("QueueUrls") + assert "QueueUrls" not in sqs.list_queues() cf.create_stack( StackName="test_stack_with_queue", TemplateBody=sqs_template_json, Parameters=[{"ParameterKey": "EnvType", "ParameterValue": "prod"}], ) - sqs.list_queues()["QueueUrls"].should.have.length_of(1) + assert len(sqs.list_queues()["QueueUrls"]) == 1 @mock_cloudformation @@ -126,7 +121,7 @@ def test_conditional_if_handling_boto3(): cf.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) ec2 = boto3.client("ec2", region_name="us-west-1") ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] - ec2_instance["ImageId"].should.equal(EXAMPLE_AMI_ID2) + assert ec2_instance["ImageId"] == EXAMPLE_AMI_ID2 cf = boto3.client("cloudformation", region_name="us-west-2") cf.create_stack( @@ -136,7 +131,7 @@ def test_conditional_if_handling_boto3(): ) ec2 = boto3.client("ec2", region_name="us-west-2") ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] - ec2_instance["ImageId"].should.equal(EXAMPLE_AMI_ID) + assert ec2_instance["ImageId"] == EXAMPLE_AMI_ID @mock_cloudformation @@ -172,13 +167,13 @@ def test_cloudformation_mapping_boto3(): cf.create_stack(StackName="test_stack1", TemplateBody=dummy_template_json) ec2 = boto3.client("ec2", region_name="us-east-1") ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] - ec2_instance["ImageId"].should.equal(EXAMPLE_AMI_ID) + assert ec2_instance["ImageId"] == EXAMPLE_AMI_ID cf = boto3.client("cloudformation", region_name="us-west-1") cf.create_stack(StackName="test_stack1", TemplateBody=dummy_template_json) ec2 = boto3.client("ec2", region_name="us-west-1") ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] - ec2_instance["ImageId"].should.equal(EXAMPLE_AMI_ID2) + assert ec2_instance["ImageId"] == EXAMPLE_AMI_ID2 @mock_cloudformation @@ -232,23 +227,23 @@ def lambda_handler(event, context): conn = boto3.client("lambda", "us-east-1") result = conn.list_functions() - result["Functions"].should.have.length_of(1) - result["Functions"][0]["Description"].should.equal("Test function") - result["Functions"][0]["Handler"].should.equal("index.lambda_handler") - result["Functions"][0]["MemorySize"].should.equal(128) - result["Functions"][0]["Runtime"].should.equal("python2.7") - result["Functions"][0]["Environment"].should.equal( - {"Variables": {"TEST_ENV_KEY": "test-env-val"}} - ) + assert len(result["Functions"]) == 1 + assert result["Functions"][0]["Description"] == "Test function" + assert result["Functions"][0]["Handler"] == "index.lambda_handler" + assert result["Functions"][0]["MemorySize"] == 128 + assert result["Functions"][0]["Runtime"] == "python2.7" + assert result["Functions"][0]["Environment"] == { + "Variables": {"TEST_ENV_KEY": "test-env-val"} + } function_name = result["Functions"][0]["FunctionName"] result = conn.get_function(FunctionName=function_name) - result["Concurrency"]["ReservedConcurrentExecutions"].should.equal(10) + assert result["Concurrency"]["ReservedConcurrentExecutions"] == 10 response = conn.invoke(FunctionName=function_name) result = json.loads(response["Payload"].read()) - result.should.equal({"event": "{}"}) + assert result == {"event": "{}"} def _make_zipfile(func_str): @@ -302,18 +297,16 @@ def lambda_handler(event, context): layer_name = result["Layers"][0]["LayerName"] result = lambda_conn.list_layer_versions(LayerName=layer_name) result["LayerVersions"][0].pop("CreatedDate") - result["LayerVersions"].should.equal( - [ - { - "Version": 1, - "LayerVersionArn": f"arn:aws:lambda:{region}:{ACCOUNT_ID}:layer:{layer_name}:1", - "CompatibleRuntimes": ["python2.7", "python3.6"], - "Description": "Test Layer", - "LicenseInfo": "MIT", - "CompatibleArchitectures": [], - } - ] - ) + assert result["LayerVersions"] == [ + { + "Version": 1, + "LayerVersionArn": f"arn:aws:lambda:{region}:{ACCOUNT_ID}:layer:{layer_name}:1", + "CompatibleRuntimes": ["python2.7", "python3.6"], + "Description": "Test Layer", + "LicenseInfo": "MIT", + "CompatibleArchitectures": [], + } + ] @mock_cloudformation @@ -370,14 +363,13 @@ def test_nat_gateway(): route_resource = resource result = ec2_conn.describe_nat_gateways() - result["NatGateways"].should.have.length_of(1) - result["NatGateways"][0]["VpcId"].should.equal(vpc_id) - result["NatGateways"][0]["SubnetId"].should.equal(subnet_id) - result["NatGateways"][0]["State"].should.equal("available") - result["NatGateways"][0]["NatGatewayId"].should.equal( - nat_gateway_resource.get("PhysicalResourceId") - ) - route_resource.get("PhysicalResourceId").should.contain("rtb-") + assert len(result["NatGateways"]) == 1 + assert result["NatGateways"][0]["VpcId"] == vpc_id + assert result["NatGateways"][0]["SubnetId"] == subnet_id + assert result["NatGateways"][0]["State"] == "available" + physical_id = nat_gateway_resource.get("PhysicalResourceId") + assert result["NatGateways"][0]["NatGatewayId"] == physical_id + assert "rtb-" in route_resource["PhysicalResourceId"] @mock_cloudformation() @@ -403,11 +395,11 @@ def test_stack_kms(): kms_conn = boto3.client("kms", "us-east-1") keys = kms_conn.list_keys()["Keys"] - len(keys).should.equal(1) + assert len(keys) == 1 result = kms_conn.describe_key(KeyId=keys[0]["KeyId"]) - result["KeyMetadata"]["Enabled"].should.equal(True) - result["KeyMetadata"]["KeyUsage"].should.equal("ENCRYPT_DECRYPT") + assert result["KeyMetadata"]["Enabled"] is True + assert result["KeyMetadata"]["KeyUsage"] == "ENCRYPT_DECRYPT" @mock_cloudformation() @@ -467,34 +459,32 @@ def test_stack_spot_fleet(): )["StackId"] stack_resources = cf_conn.list_stack_resources(StackName=stack_id) - stack_resources["StackResourceSummaries"].should.have.length_of(1) + assert len(stack_resources["StackResourceSummaries"]) == 1 spot_fleet_id = stack_resources["StackResourceSummaries"][0]["PhysicalResourceId"] spot_fleet_requests = conn.describe_spot_fleet_requests( SpotFleetRequestIds=[spot_fleet_id] )["SpotFleetRequestConfigs"] - len(spot_fleet_requests).should.equal(1) + assert len(spot_fleet_requests) == 1 spot_fleet_request = spot_fleet_requests[0] - spot_fleet_request["SpotFleetRequestState"].should.equal("active") + assert spot_fleet_request["SpotFleetRequestState"] == "active" spot_fleet_config = spot_fleet_request["SpotFleetRequestConfig"] - spot_fleet_config["SpotPrice"].should.equal("0.12") - spot_fleet_config["TargetCapacity"].should.equal(6) - spot_fleet_config["IamFleetRole"].should.equal( - f"arn:aws:iam::{ACCOUNT_ID}:role/fleet" - ) - spot_fleet_config["AllocationStrategy"].should.equal("diversified") - spot_fleet_config["FulfilledCapacity"].should.equal(6.0) + assert spot_fleet_config["SpotPrice"] == "0.12" + assert spot_fleet_config["TargetCapacity"] == 6 + assert spot_fleet_config["IamFleetRole"] == f"arn:aws:iam::{ACCOUNT_ID}:role/fleet" + assert spot_fleet_config["AllocationStrategy"] == "diversified" + assert spot_fleet_config["FulfilledCapacity"] == 6.0 - len(spot_fleet_config["LaunchSpecifications"]).should.equal(2) + assert len(spot_fleet_config["LaunchSpecifications"]) == 2 launch_spec = spot_fleet_config["LaunchSpecifications"][0] - launch_spec["EbsOptimized"].should.equal(False) - launch_spec["ImageId"].should.equal(EXAMPLE_AMI_ID) - launch_spec["InstanceType"].should.equal("t2.small") - launch_spec["SubnetId"].should.equal(subnet_id) - launch_spec["SpotPrice"].should.equal("0.13") - launch_spec["WeightedCapacity"].should.equal(2.0) + assert launch_spec["EbsOptimized"] is False + assert launch_spec["ImageId"] == EXAMPLE_AMI_ID + assert launch_spec["InstanceType"] == "t2.small" + assert launch_spec["SubnetId"] == subnet_id + assert launch_spec["SpotPrice"] == "0.13" + assert launch_spec["WeightedCapacity"] == 2.0 @mock_cloudformation() @@ -551,19 +541,19 @@ def test_stack_spot_fleet_should_figure_out_default_price(): )["StackId"] stack_resources = cf_conn.list_stack_resources(StackName=stack_id) - stack_resources["StackResourceSummaries"].should.have.length_of(1) + assert len(stack_resources["StackResourceSummaries"]) == 1 spot_fleet_id = stack_resources["StackResourceSummaries"][0]["PhysicalResourceId"] spot_fleet_requests = conn.describe_spot_fleet_requests( SpotFleetRequestIds=[spot_fleet_id] )["SpotFleetRequestConfigs"] - len(spot_fleet_requests).should.equal(1) + assert len(spot_fleet_requests) == 1 spot_fleet_request = spot_fleet_requests[0] - spot_fleet_request["SpotFleetRequestState"].should.equal("active") + assert spot_fleet_request["SpotFleetRequestState"] == "active" spot_fleet_config = spot_fleet_request["SpotFleetRequestConfig"] assert "SpotPrice" not in spot_fleet_config - len(spot_fleet_config["LaunchSpecifications"]).should.equal(2) + assert len(spot_fleet_config["LaunchSpecifications"]) == 2 launch_spec1 = spot_fleet_config["LaunchSpecifications"][0] launch_spec2 = spot_fleet_config["LaunchSpecifications"][1] @@ -575,7 +565,6 @@ def test_stack_spot_fleet_should_figure_out_default_price(): @mock_elbv2 @mock_cloudformation def test_invalid_action_type_listener_rule(): - invalid_listener_template = { "AWSTemplateFormatVersion": "2010-09-09", "Resources": { @@ -634,9 +623,10 @@ def test_invalid_action_type_listener_rule(): listener_template_json = json.dumps(invalid_listener_template) cfn_conn = boto3.client("cloudformation", "us-west-1") - cfn_conn.create_stack.when.called_with( - StackName="listener_stack", TemplateBody=listener_template_json - ).should.throw(ClientError) + with pytest.raises(ClientError) as exc: + cfn_conn.create_stack(StackName="s", TemplateBody=listener_template_json) + err = exc.value.response["Error"] + assert err["Code"] == "ValidationError" @mock_ec2 @@ -644,7 +634,6 @@ def test_invalid_action_type_listener_rule(): @mock_cloudformation @mock_events def test_update_stack_listener_and_rule(): - initial_template = { "AWSTemplateFormatVersion": "2010-09-09", "Resources": { @@ -731,15 +720,11 @@ def test_update_stack_listener_and_rule(): listeners = elbv2_conn.describe_listeners( LoadBalancerArn=load_balancers[0]["LoadBalancerArn"] )["Listeners"] - listeners[0]["Port"].should.equal(90) + assert listeners[0]["Port"] == 90 - listener_rule = elbv2_conn.describe_rules(ListenerArn=listeners[0]["ListenerArn"])[ - "Rules" - ] + l_rule = elbv2_conn.describe_rules(ListenerArn=listeners[0]["ListenerArn"])["Rules"] - listener_rule[0]["Conditions"].should.equal( - [{"Field": "host-header", "Values": ["*"]}] - ) + assert l_rule[0]["Conditions"] == [{"Field": "host-header", "Values": ["*"]}] @mock_ec2 @@ -887,96 +872,88 @@ def test_stack_elbv2_resources_integration(): elbv2_conn = boto3.client("elbv2", "us-west-1") - load_balancers = elbv2_conn.describe_load_balancers()["LoadBalancers"] - len(load_balancers).should.equal(1) - load_balancers[0]["LoadBalancerName"].should.equal("myelbv2") - load_balancers[0]["Scheme"].should.equal("internet-facing") - load_balancers[0]["Type"].should.equal("application") - load_balancers[0]["IpAddressType"].should.equal("ipv4") - - target_groups = sorted( - elbv2_conn.describe_target_groups()["TargetGroups"], - key=lambda tg: tg["TargetGroupName"], - ) # sort to do comparison with indexes - len(target_groups).should.equal(2) - target_groups[0]["HealthCheckIntervalSeconds"].should.equal(30) - target_groups[0]["HealthCheckPath"].should.equal("/status") - target_groups[0]["HealthCheckPort"].should.equal("80") - target_groups[0]["HealthCheckProtocol"].should.equal("HTTP") - target_groups[0]["HealthCheckTimeoutSeconds"].should.equal(5) - target_groups[0]["HealthyThresholdCount"].should.equal(30) - target_groups[0]["UnhealthyThresholdCount"].should.equal(5) - target_groups[0]["Matcher"].should.equal({"HttpCode": "200,201"}) - target_groups[0]["TargetGroupName"].should.equal("mytargetgroup1") - target_groups[0]["Port"].should.equal(80) - target_groups[0]["Protocol"].should.equal("HTTP") - target_groups[0]["TargetType"].should.equal("instance") - - target_groups[1]["HealthCheckIntervalSeconds"].should.equal(30) - target_groups[1]["HealthCheckPath"].should.equal("/status") - target_groups[1]["HealthCheckPort"].should.equal("8080") - target_groups[1]["HealthCheckProtocol"].should.equal("HTTP") - target_groups[1]["HealthCheckTimeoutSeconds"].should.equal(5) - target_groups[1]["HealthyThresholdCount"].should.equal(30) - target_groups[1]["UnhealthyThresholdCount"].should.equal(5) - target_groups[1]["Matcher"].should.equal({"HttpCode": "200"}) - target_groups[1]["TargetGroupName"].should.equal("mytargetgroup2") - target_groups[1]["Port"].should.equal(8080) - target_groups[1]["Protocol"].should.equal("HTTP") - target_groups[1]["TargetType"].should.equal("instance") - - listeners = elbv2_conn.describe_listeners( - LoadBalancerArn=load_balancers[0]["LoadBalancerArn"] - )["Listeners"] - len(listeners).should.equal(1) - listeners[0]["LoadBalancerArn"].should.equal(load_balancers[0]["LoadBalancerArn"]) - listeners[0]["Port"].should.equal(80) - listeners[0]["Protocol"].should.equal("HTTP") - listeners[0]["DefaultActions"].should.equal( - [{"Type": "forward", "TargetGroupArn": target_groups[0]["TargetGroupArn"]}] - ) + lbs = elbv2_conn.describe_load_balancers()["LoadBalancers"] + assert len(lbs) == 1 + assert lbs[0]["LoadBalancerName"] == "myelbv2" + assert lbs[0]["Scheme"] == "internet-facing" + assert lbs[0]["Type"] == "application" + assert lbs[0]["IpAddressType"] == "ipv4" + + target_groups = elbv2_conn.describe_target_groups()["TargetGroups"] + # sort to do comparison with indexes + target_groups = sorted(target_groups, key=lambda tg: tg["TargetGroupName"]) + assert len(target_groups) == 2 + assert target_groups[0]["HealthCheckIntervalSeconds"] == 30 + assert target_groups[0]["HealthCheckPath"] == "/status" + assert target_groups[0]["HealthCheckPort"] == "80" + assert target_groups[0]["HealthCheckProtocol"] == "HTTP" + assert target_groups[0]["HealthCheckTimeoutSeconds"] == 5 + assert target_groups[0]["HealthyThresholdCount"] == 30 + assert target_groups[0]["UnhealthyThresholdCount"] == 5 + assert target_groups[0]["Matcher"] == {"HttpCode": "200,201"} + assert target_groups[0]["TargetGroupName"] == "mytargetgroup1" + assert target_groups[0]["Port"] == 80 + assert target_groups[0]["Protocol"] == "HTTP" + assert target_groups[0]["TargetType"] == "instance" + + assert target_groups[1]["HealthCheckIntervalSeconds"] == 30 + assert target_groups[1]["HealthCheckPath"] == "/status" + assert target_groups[1]["HealthCheckPort"] == "8080" + assert target_groups[1]["HealthCheckProtocol"] == "HTTP" + assert target_groups[1]["HealthCheckTimeoutSeconds"] == 5 + assert target_groups[1]["HealthyThresholdCount"] == 30 + assert target_groups[1]["UnhealthyThresholdCount"] == 5 + assert target_groups[1]["Matcher"] == {"HttpCode": "200"} + assert target_groups[1]["TargetGroupName"] == "mytargetgroup2" + assert target_groups[1]["Port"] == 8080 + assert target_groups[1]["Protocol"] == "HTTP" + assert target_groups[1]["TargetType"] == "instance" + + lstnrs = elbv2_conn.describe_listeners(LoadBalancerArn=lbs[0]["LoadBalancerArn"])[ + "Listeners" + ] + assert len(lstnrs) == 1 + assert lstnrs[0]["LoadBalancerArn"] == lbs[0]["LoadBalancerArn"] + assert lstnrs[0]["Port"] == 80 + assert lstnrs[0]["Protocol"] == "HTTP" + assert lstnrs[0]["DefaultActions"] == [ + {"Type": "forward", "TargetGroupArn": target_groups[0]["TargetGroupArn"]} + ] - listener_rule = elbv2_conn.describe_rules(ListenerArn=listeners[0]["ListenerArn"])[ - "Rules" + rule = elbv2_conn.describe_rules(ListenerArn=lstnrs[0]["ListenerArn"])["Rules"] + assert len(rule) == 3 + assert rule[0]["Priority"] == "2" + assert rule[0]["Actions"] == [ + { + "Type": "forward", + "ForwardConfig": { + "TargetGroups": [ + { + "TargetGroupArn": target_groups[1]["TargetGroupArn"], + "Weight": 1, + }, + { + "TargetGroupArn": target_groups[0]["TargetGroupArn"], + "Weight": 2, + }, + ], + "TargetGroupStickinessConfig": {"Enabled": False}, + }, + } ] - len(listener_rule).should.equal(3) - listener_rule[0]["Priority"].should.equal("2") - listener_rule[0]["Actions"].should.equal( - [ - { - "Type": "forward", - "ForwardConfig": { - "TargetGroups": [ - { - "TargetGroupArn": target_groups[1]["TargetGroupArn"], - "Weight": 1, - }, - { - "TargetGroupArn": target_groups[0]["TargetGroupArn"], - "Weight": 2, - }, - ], - "TargetGroupStickinessConfig": {"Enabled": False}, - }, - } - ], - [{"Type": "forward", "TargetGroupArn": target_groups[1]["TargetGroupArn"]}], - ) - listener_rule[0]["Conditions"].should.equal( - [{"Field": "path-pattern", "Values": ["/*"]}] - ) + assert rule[0]["Conditions"] == [{"Field": "path-pattern", "Values": ["/*"]}] - listener_rule[1]["Priority"].should.equal("30") - listener_rule[1]["Actions"].should.equal( - [{"Type": "forward", "TargetGroupArn": target_groups[1]["TargetGroupArn"]}] - ) - listener_rule[1]["Conditions"].should.equal( - [{"Field": "host-header", "Values": ["example.com"]}] - ) + assert rule[1]["Priority"] == "30" + assert rule[1]["Actions"] == [ + {"Type": "forward", "TargetGroupArn": target_groups[1]["TargetGroupArn"]} + ] + assert rule[1]["Conditions"] == [ + {"Field": "host-header", "Values": ["example.com"]} + ] # test outputs stacks = cfn_conn.describe_stacks(StackName="elb_stack")["Stacks"] - len(stacks).should.equal(1) + assert len(stacks) == 1 dns = list( filter(lambda item: item["OutputKey"] == "albdns", stacks[0]["Outputs"]) @@ -985,8 +962,8 @@ def test_stack_elbv2_resources_integration(): filter(lambda item: item["OutputKey"] == "albname", stacks[0]["Outputs"]) )[0] - dns["OutputValue"].should.equal(load_balancers[0]["DNSName"]) - name["OutputValue"].should.equal(load_balancers[0]["LoadBalancerName"]) + assert dns["OutputValue"] == lbs[0]["DNSName"] + assert name["OutputValue"] == lbs[0]["LoadBalancerName"] @mock_dynamodb @@ -1073,13 +1050,14 @@ def test_stack_dynamodb_resources_integration(): dynamodb_client = boto3.client("dynamodb", region_name="us-east-1") table_desc = dynamodb_client.describe_table(TableName="myTableName")["Table"] - table_desc["StreamSpecification"].should.equal( - {"StreamEnabled": True, "StreamViewType": "KEYS_ONLY"} - ) + assert table_desc["StreamSpecification"] == { + "StreamEnabled": True, + "StreamViewType": "KEYS_ONLY", + } dynamodb_conn = boto3.resource("dynamodb", region_name="us-east-1") table = dynamodb_conn.Table("myTableName") - table.name.should.equal("myTableName") + assert table.name == "myTableName" table.put_item( Item={"Album": "myAlbum", "Artist": "myArtist", "Sales": 10, "NumberOfSongs": 5} @@ -1087,10 +1065,10 @@ def test_stack_dynamodb_resources_integration(): response = table.get_item(Key={"Album": "myAlbum", "Artist": "myArtist"}) - response["Item"]["Album"].should.equal("myAlbum") - response["Item"]["Sales"].should.equal(Decimal("10")) - response["Item"]["NumberOfSongs"].should.equal(Decimal("5")) - response["Item"]["Album"].should.equal("myAlbum") + assert response["Item"]["Album"] == "myAlbum" + assert response["Item"]["Sales"] == Decimal("10") + assert response["Item"]["NumberOfSongs"] == Decimal("5") + assert response["Item"]["Album"] == "myAlbum" @mock_cloudformation @@ -1133,7 +1111,7 @@ def test_create_log_group_using_fntransform(): logs_conn = boto3.client("logs", region_name="us-west-2") log_group = logs_conn.describe_log_groups()["logGroups"][0] - log_group["logGroupName"].should.equal("some-log-group") + assert log_group["logGroupName"] == "some-log-group" @mock_cloudformation @@ -1188,27 +1166,30 @@ def test_create_cloudwatch_logs_resource_policy(): logs_conn = boto3.client("logs", region_name="us-east-1") policies = logs_conn.describe_resource_policies()["resourcePolicies"] - policies.should.have.length_of(1) - policies.should.be.containing_item_with_attributes( - policyName="TestPolicyA", policyDocument=policy_document - ) + assert len(policies) == 1 + + assert policies[0]["policyName"] == "TestPolicyA" + assert policies[0]["policyDocument"] == policy_document cf_conn.update_stack(StackName="test_stack", TemplateBody=json.dumps(template2)) policies = logs_conn.describe_resource_policies()["resourcePolicies"] - policies.should.have.length_of(2) - policies.should.be.containing_item_with_attributes( - policyName="TestPolicyB", policyDocument=policy_document - ) - policies.should.be.containing_item_with_attributes( - policyName="TestPolicyC", policyDocument=policy_document - ) + assert len(policies) == 2 + + policy_b = [pol for pol in policies if pol["policyName"] == "TestPolicyB"][0][ + "policyDocument" + ] + assert policy_b == policy_document + + policy_c = [pol for pol in policies if pol["policyName"] == "TestPolicyC"][0][ + "policyDocument" + ] + assert policy_c == policy_document cf_conn.update_stack(StackName="test_stack", TemplateBody=json.dumps(template1)) policies = logs_conn.describe_resource_policies()["resourcePolicies"] - policies.should.have.length_of(1) - policies.should.be.containing_item_with_attributes( - policyName="TestPolicyA", policyDocument=policy_document - ) + assert len(policies) == 1 + assert policies[0]["policyName"] == "TestPolicyA" + assert policies[0]["policyDocument"] == policy_document @mock_cloudformation @@ -1232,11 +1213,11 @@ def test_delete_stack_containing_cloudwatch_logs_resource_policy(): logs_conn = boto3.client("logs", region_name="us-east-1") policies = logs_conn.describe_resource_policies()["resourcePolicies"] - policies.should.have.length_of(1) + assert len(policies) == 1 cf_conn.delete_stack(StackName="test_stack") policies = logs_conn.describe_resource_policies()["resourcePolicies"] - policies.should.have.length_of(0) + assert len(policies) == 0 @mock_cloudformation @@ -1261,12 +1242,10 @@ def test_delete_stack_with_deletion_policy_boto3(): TemplateBody=sqs_template_json, ) sqs = boto3.client("sqs", region_name="us-west-1") - sqs.list_queues()["QueueUrls"].should.have.length_of(1) + assert len(sqs.list_queues()["QueueUrls"]) == 1 - cf.delete_stack( - StackName="test_stack", - ) - sqs.list_queues()["QueueUrls"].should.have.length_of(1) + cf.delete_stack(StackName="test_stack") + assert len(sqs.list_queues()["QueueUrls"]) == 1 @mock_cloudformation @@ -1291,10 +1270,10 @@ def test_stack_events_create_rule_integration(): ) rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"].should.have.length_of(1) - rules["Rules"][0]["Name"].should.equal("quick-fox") - rules["Rules"][0]["State"].should.equal("ENABLED") - rules["Rules"][0]["ScheduleExpression"].should.equal("rate(5 minutes)") + assert len(rules["Rules"]) == 1 + assert rules["Rules"][0]["Name"] == "quick-fox" + assert rules["Rules"][0]["State"] == "ENABLED" + assert rules["Rules"][0]["ScheduleExpression"] == "rate(5 minutes)" @mock_cloudformation @@ -1319,12 +1298,12 @@ def test_stack_events_delete_rule_integration(): ) rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"].should.have.length_of(1) + assert len(rules["Rules"]) == 1 cf_conn.delete_stack(StackName="test_stack") rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"].should.have.length_of(0) + assert len(rules["Rules"]) == 0 @mock_cloudformation @@ -1348,7 +1327,7 @@ def test_stack_events_create_rule_without_name_integration(): ) rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"][0]["Name"].should.contain("test_stack-Event-") + assert "test_stack-Event-" in rules["Rules"][0]["Name"] @mock_cloudformation @@ -1382,10 +1361,10 @@ def test_stack_events_create_rule_as_target(): rules = boto3.client("events", "us-west-2").list_rules() log_groups = boto3.client("logs", "us-west-2").describe_log_groups() - rules["Rules"][0]["Name"].should.contain("test_stack-Event-") + assert "test_stack-Event-" in rules["Rules"][0]["Name"] - log_groups["logGroups"][0]["logGroupName"].should.equal(rules["Rules"][0]["Arn"]) - log_groups["logGroups"][0]["retentionInDays"].should.equal(3) + assert log_groups["logGroups"][0]["logGroupName"] == rules["Rules"][0]["Arn"] + assert log_groups["logGroups"][0]["retentionInDays"] == 3 @mock_cloudformation @@ -1413,18 +1392,18 @@ def test_stack_events_update_rule_integration(): cf_conn.create_stack(StackName="test_stack", TemplateBody=original_template) rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"].should.have.length_of(1) - rules["Rules"][0]["Name"].should.equal("Foo") - rules["Rules"][0]["State"].should.equal("ENABLED") + assert len(rules["Rules"]) == 1 + assert rules["Rules"][0]["Name"] == "Foo" + assert rules["Rules"][0]["State"] == "ENABLED" update_template = events_template.substitute(Name="Bar", State="DISABLED") cf_conn.update_stack(StackName="test_stack", TemplateBody=update_template) rules = boto3.client("events", "us-west-2").list_rules() - rules["Rules"].should.have.length_of(1) - rules["Rules"][0]["Name"].should.equal("Bar") - rules["Rules"][0]["State"].should.equal("DISABLED") + assert len(rules["Rules"]) == 1 + assert rules["Rules"][0]["Name"] == "Bar" + assert rules["Rules"][0]["State"] == "DISABLED" @mock_cloudformation @@ -1519,8 +1498,8 @@ def test_stack_eventbus_create_from_cfn_integration(): NamePrefix="MyCustom" ) - event_buses["EventBuses"].should.have.length_of(1) - event_buses["EventBuses"][0]["Name"].should.equal("MyCustomEventBus") + assert len(event_buses["EventBuses"]) == 1 + assert event_buses["EventBuses"][0]["Name"] == "MyCustomEventBus" @mock_cloudformation @@ -1543,14 +1522,14 @@ def test_stack_events_delete_eventbus_integration(): event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="MyCustom" ) - event_buses["EventBuses"].should.have.length_of(1) + assert len(event_buses["EventBuses"]) == 1 cf_conn.delete_stack(StackName="test_stack") event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="MyCustom" ) - event_buses["EventBuses"].should.have.length_of(0) + assert len(event_buses["EventBuses"]) == 0 @mock_cloudformation @@ -1580,7 +1559,7 @@ def test_stack_events_delete_from_cfn_integration(): original_event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="MyCustom" ) - original_event_buses["EventBuses"].should.have.length_of(1) + assert len(original_event_buses["EventBuses"]) == 1 original_eventbus = original_event_buses["EventBuses"][0] @@ -1592,8 +1571,8 @@ def test_stack_events_delete_from_cfn_integration(): update_event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="AnotherEventBus" ) - update_event_buses["EventBuses"].should.have.length_of(1) - update_event_buses["EventBuses"][0]["Arn"].shouldnt.equal(original_eventbus["Arn"]) + assert len(update_event_buses["EventBuses"]) == 1 + assert update_event_buses["EventBuses"][0]["Arn"] != original_eventbus["Arn"] @mock_cloudformation @@ -1621,7 +1600,7 @@ def test_stack_events_update_from_cfn_integration(): original_event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="MyCustom" ) - original_event_buses["EventBuses"].should.have.length_of(1) + assert len(original_event_buses["EventBuses"]) == 1 original_eventbus = original_event_buses["EventBuses"][0] @@ -1631,9 +1610,9 @@ def test_stack_events_update_from_cfn_integration(): update_event_buses = boto3.client("events", "us-west-2").list_event_buses( NamePrefix="NewEventBus" ) - update_event_buses["EventBuses"].should.have.length_of(1) - update_event_buses["EventBuses"][0]["Name"].should.equal("NewEventBus") - update_event_buses["EventBuses"][0]["Arn"].shouldnt.equal(original_eventbus["Arn"]) + assert len(update_event_buses["EventBuses"]) == 1 + assert update_event_buses["EventBuses"][0]["Name"] == "NewEventBus" + assert update_event_buses["EventBuses"][0]["Arn"] != original_eventbus["Arn"] @mock_cloudformation @@ -1668,8 +1647,8 @@ def test_stack_events_get_attribute_integration(): event_bus = events.list_event_buses(NamePrefix="MyEventBus")["EventBuses"][0] - output_arn["OutputValue"].should.equal(event_bus["Arn"]) - output_name["OutputValue"].should.equal(event_bus["Name"]) + assert output_arn["OutputValue"] == event_bus["Arn"] + assert output_name["OutputValue"] == event_bus["Name"] @mock_cloudformation @@ -1699,13 +1678,13 @@ def test_dynamodb_table_creation(): # Verify the TableName is part of the outputs stack = cfn.describe_stacks(StackName=stack_name)["Stacks"][0] outputs = stack["Outputs"] - outputs.should.have.length_of(1) - outputs[0]["OutputKey"].should.equal("MyTableName") - outputs[0]["OutputValue"].should.contain("foobar") + assert len(outputs) == 1 + assert outputs[0]["OutputKey"] == "MyTableName" + assert "foobar" in outputs[0]["OutputValue"] # Assert the table is created ddb = boto3.client("dynamodb", "us-west-2") table_names = ddb.list_tables()["TableNames"] - table_names.should.equal([outputs[0]["OutputValue"]]) + assert table_names == [outputs[0]["OutputValue"]] @mock_cloudformation @@ -1735,15 +1714,15 @@ def test_ssm_parameter(): stack_resources = cfn.list_stack_resources(StackName=stack_name) ssm_resource = stack_resources.get("StackResourceSummaries")[0] - ssm_resource.get("PhysicalResourceId").should.equal("test_ssm") + assert ssm_resource.get("PhysicalResourceId") == "test_ssm" ssm_client = boto3.client("ssm", region_name="us-west-2") parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(1) - parameters[0]["Name"].should.equal("test_ssm") - parameters[0]["Value"].should.equal("Test SSM Parameter") + assert len(parameters) == 1 + assert parameters[0]["Name"] == "test_ssm" + assert parameters[0]["Value"] == "Test SSM Parameter" @mock_cloudformation @@ -1775,9 +1754,9 @@ def test_ssm_parameter_update_stack(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(1) - parameters[0]["Name"].should.equal("test_ssm") - parameters[0]["Value"].should.equal("Test SSM Parameter") + assert len(parameters) == 1 + assert parameters[0]["Name"] == "test_ssm" + assert parameters[0]["Value"] == "Test SSM Parameter" parameter_template["Resources"]["BasicParameter"]["Properties"][ "Value" @@ -1788,9 +1767,9 @@ def test_ssm_parameter_update_stack(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(1) - parameters[0]["Name"].should.equal("test_ssm") - parameters[0]["Value"].should.equal("Test SSM Parameter Updated") + assert len(parameters) == 1 + assert parameters[0]["Name"] == "test_ssm" + assert parameters[0]["Value"] == "Test SSM Parameter Updated" @mock_cloudformation @@ -1822,9 +1801,9 @@ def test_ssm_parameter_update_stack_and_remove_resource(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(1) - parameters[0]["Name"].should.equal("test_ssm") - parameters[0]["Value"].should.equal("Test SSM Parameter") + assert len(parameters) == 1 + assert parameters[0]["Name"] == "test_ssm" + assert parameters[0]["Value"] == "Test SSM Parameter" parameter_template["Resources"].pop("BasicParameter") cfn.update_stack(StackName=stack_name, TemplateBody=json.dumps(parameter_template)) @@ -1833,7 +1812,7 @@ def test_ssm_parameter_update_stack_and_remove_resource(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(0) + assert len(parameters) == 0 @mock_cloudformation @@ -1851,7 +1830,7 @@ def test_ssm_parameter_update_stack_and_add_resource(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(0) + assert len(parameters) == 0 parameter_template = { "AWSTemplateFormatVersion": "2010-09-09", @@ -1874,6 +1853,6 @@ def test_ssm_parameter_update_stack_and_add_resource(): parameters = ssm_client.get_parameters(Names=["test_ssm"], WithDecryption=False)[ "Parameters" ] - parameters.should.have.length_of(1) - parameters[0]["Name"].should.equal("test_ssm") - parameters[0]["Value"].should.equal("Test SSM Parameter") + assert len(parameters) == 1 + assert parameters[0]["Name"] == "test_ssm" + assert parameters[0]["Value"] == "Test SSM Parameter" diff --git a/tests/test_cloudformation/test_cloudformation_stack_policies.py b/tests/test_cloudformation/test_cloudformation_stack_policies.py index 067ab17b1fc7..5f5ea0a08c6d 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_policies.py +++ b/tests/test_cloudformation/test_cloudformation_stack_policies.py @@ -15,9 +15,9 @@ def test_set_stack_policy_on_nonexisting_stack(): with pytest.raises(ClientError) as exc: cf_conn.set_stack_policy(StackName="unknown", StackPolicyBody="{}") err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal("Stack: unknown does not exist") - err["Type"].should.equal("Sender") + assert err["Code"] == "ValidationError" + assert err["Message"] == "Stack: unknown does not exist" + assert err["Type"] == "Sender" @mock_cloudformation @@ -27,9 +27,9 @@ def test_get_stack_policy_on_nonexisting_stack(): with pytest.raises(ClientError) as exc: cf_conn.get_stack_policy(StackName="unknown") err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal("Stack: unknown does not exist") - err["Type"].should.equal("Sender") + assert err["Code"] == "ValidationError" + assert err["Message"] == "Stack: unknown does not exist" + assert err["Type"] == "Sender" @mock_cloudformation @@ -38,7 +38,7 @@ def test_get_stack_policy_on_stack_without_policy(): cf_conn.create_stack(StackName="test_stack", TemplateBody=dummy_template_json) resp = cf_conn.get_stack_policy(StackName="test_stack") - resp.shouldnt.have.key("StackPolicyBody") + assert "StackPolicyBody" not in resp @mock_cloudformation @@ -51,11 +51,11 @@ def test_set_stack_policy_with_both_body_and_url(): StackName="test_stack", StackPolicyBody="{}", StackPolicyURL="..." ) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "You cannot specify both StackPolicyURL and StackPolicyBody" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] == "You cannot specify both StackPolicyURL and StackPolicyBody" ) - err["Type"].should.equal("Sender") + assert err["Type"] == "Sender" @mock_cloudformation @@ -68,7 +68,7 @@ def test_set_stack_policy_with_body(): cf_conn.set_stack_policy(StackName="test_stack", StackPolicyBody=policy) resp = cf_conn.get_stack_policy(StackName="test_stack") - resp.should.have.key("StackPolicyBody").equals(policy) + assert resp["StackPolicyBody"] == policy @mock_cloudformation @@ -81,7 +81,7 @@ def test_set_stack_policy_on_create(): ) resp = cf_conn.get_stack_policy(StackName="test_stack") - resp.should.have.key("StackPolicyBody").equals("stack_policy_body") + assert resp["StackPolicyBody"] == "stack_policy_body" @mock_cloudformation @@ -101,7 +101,7 @@ def test_set_stack_policy_with_url(): cf_conn.set_stack_policy(StackName="test_stack", StackPolicyURL=key_url) resp = cf_conn.get_stack_policy(StackName="test_stack") - resp.should.have.key("StackPolicyBody").equals(policy) + assert resp["StackPolicyBody"] == policy @mock_cloudformation @@ -113,6 +113,6 @@ def test_set_stack_policy_with_url_pointing_to_unknown_key(): with pytest.raises(ClientError) as exc: cf_conn.set_stack_policy(StackName="test_stack", StackPolicyURL="...") err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.contain("S3 error: Access Denied") - err["Type"].should.equal("Sender") + assert err["Code"] == "ValidationError" + assert "S3 error: Access Denied" in err["Message"] + assert err["Type"] == "Sender" diff --git a/tests/test_cloudformation/test_server.py b/tests/test_cloudformation/test_server.py index e09d5b7d8104..2733093be3ef 100644 --- a/tests/test_cloudformation/test_server.py +++ b/tests/test_cloudformation/test_server.py @@ -1,6 +1,5 @@ import json import re -import sure # noqa # pylint: disable=unused-import import moto.server as server @@ -17,17 +16,15 @@ def test_cloudformation_server_get(): create_stack_resp = test_client.action_data( "CreateStack", StackName=stack_name, TemplateBody=json.dumps(template_body) ) - create_stack_resp.should.match( - r".*.*.*.*.*", - re.DOTALL, - ) - stack_id_from_create_response = re.search( + assert "" in create_stack_resp + assert "" in create_stack_resp + stack_id_from_create = re.search( "(.*)", create_stack_resp ).groups()[0] list_stacks_resp = test_client.action_data("ListStacks") - stack_id_from_list_response = re.search( + stack_id_from_list = re.search( "(.*)", list_stacks_resp ).groups()[0] - stack_id_from_create_response.should.equal(stack_id_from_list_response) + assert stack_id_from_create == stack_id_from_list diff --git a/tests/test_cloudformation/test_stack_parsing.py b/tests/test_cloudformation/test_stack_parsing.py index 7e9a337dfb2a..d046cc640e85 100644 --- a/tests/test_cloudformation/test_stack_parsing.py +++ b/tests/test_cloudformation/test_stack_parsing.py @@ -3,7 +3,6 @@ import yaml import pytest -import sure # noqa # pylint: disable=unused-import from botocore.exceptions import ClientError from unittest.mock import patch @@ -259,15 +258,15 @@ def test_parse_stack_resources(): region_name="us-west-1", ) - stack.resource_map.should.have.length_of(2) + assert len(stack.resource_map) == 2 queue = stack.resource_map["Queue"] - queue.should.be.a(Queue) - queue.name.should.equal("my-queue") + assert isinstance(queue, Queue) + assert queue.name == "my-queue" bucket = stack.resource_map["S3Bucket"] - bucket.should.be.a(FakeBucket) - bucket.physical_resource_id.should.equal(bucket.name) + assert isinstance(bucket, FakeBucket) + assert bucket.physical_resource_id == bucket.name @patch("moto.cloudformation.parsing.logger") @@ -286,10 +285,10 @@ def test_parse_stack_with_name_type_resource(): region_name="us-west-1", ) - stack.resource_map.should.have.length_of(1) - list(stack.resource_map.keys())[0].should.equal("Queue") + assert len(stack.resource_map) == 1 + assert list(stack.resource_map.keys())[0] == "Queue" queue = list(stack.resource_map.values())[0] - queue.should.be.a(Queue) + assert isinstance(queue, Queue) def test_parse_stack_with_tabbed_json_template(): @@ -302,10 +301,10 @@ def test_parse_stack_with_tabbed_json_template(): region_name="us-west-1", ) - stack.resource_map.should.have.length_of(1) - list(stack.resource_map.keys())[0].should.equal("Queue") + assert len(stack.resource_map) == 1 + assert list(stack.resource_map.keys())[0] == "Queue" queue = list(stack.resource_map.values())[0] - queue.should.be.a(Queue) + assert isinstance(queue, Queue) def test_parse_stack_with_yaml_template(): @@ -318,10 +317,10 @@ def test_parse_stack_with_yaml_template(): region_name="us-west-1", ) - stack.resource_map.should.have.length_of(1) - list(stack.resource_map.keys())[0].should.equal("Queue") + assert len(stack.resource_map) == 1 + assert list(stack.resource_map.keys())[0] == "Queue" queue = list(stack.resource_map.values())[0] - queue.should.be.a(Queue) + assert isinstance(queue, Queue) def test_parse_stack_with_outputs(): @@ -334,11 +333,11 @@ def test_parse_stack_with_outputs(): region_name="us-west-1", ) - stack.output_map.should.have.length_of(1) - list(stack.output_map.keys())[0].should.equal("Output1") + assert len(stack.output_map) == 1 + assert list(stack.output_map.keys())[0] == "Output1" output = list(stack.output_map.values())[0] - output.should.be.a(Output) - output.description.should.equal("This is a description.") + assert isinstance(output, Output) + assert output.description == "This is a description." def test_parse_stack_with_get_attribute_outputs(): @@ -351,11 +350,11 @@ def test_parse_stack_with_get_attribute_outputs(): region_name="us-west-1", ) - stack.output_map.should.have.length_of(1) - list(stack.output_map.keys())[0].should.equal("Output1") + assert len(stack.output_map) == 1 + assert list(stack.output_map.keys())[0] == "Output1" output = list(stack.output_map.values())[0] - output.should.be.a(Output) - output.value.should.equal("my-queue") + assert isinstance(output, Output) + assert output.value == "my-queue" def test_parse_stack_with_get_attribute_kms(): @@ -371,10 +370,10 @@ def test_parse_stack_with_get_attribute_kms(): region_name="us-west-1", ) - stack.output_map.should.have.length_of(1) - list(stack.output_map.keys())[0].should.equal("KeyArn") + assert len(stack.output_map) == 1 + assert list(stack.output_map.keys())[0] == "KeyArn" output = list(stack.output_map.values())[0] - output.should.be.a(Output) + assert isinstance(output, Output) def test_parse_stack_with_get_availability_zones(): @@ -387,11 +386,11 @@ def test_parse_stack_with_get_availability_zones(): region_name="us-east-1", ) - stack.output_map.should.have.length_of(1) - list(stack.output_map.keys())[0].should.equal("Output1") + assert len(stack.output_map) == 1 + assert list(stack.output_map.keys())[0] == "Output1" output = list(stack.output_map.values())[0] - output.should.be.a(Output) - output.value.should.equal(["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d"]) + assert isinstance(output, Output) + assert output.value == ["us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d"] @mock_sqs @@ -401,9 +400,10 @@ def test_parse_stack_with_bad_get_attribute_outputs_using_boto3(): with pytest.raises(ClientError) as exc: conn.create_stack(StackName="teststack", TemplateBody=bad_output_template_json) err = exc.value.response["Error"] - err["Code"].should.equal("ValidationError") - err["Message"].should.equal( - "Template error: resource Queue does not support attribute type InvalidAttribute in Fn::GetAtt" + assert err["Code"] == "ValidationError" + assert ( + err["Message"] + == "Template error: resource Queue does not support attribute type InvalidAttribute in Fn::GetAtt" ) @@ -417,8 +417,7 @@ def test_parse_stack_with_null_outputs_section(): account_id=ACCOUNT_ID, region_name="us-west-1", ) - err = str(exc.value) - err.should.contain("[/Outputs] 'null' values are not allowed in templates") + assert "[/Outputs] 'null' values are not allowed in templates" in str(exc.value) def test_parse_stack_with_parameters(): @@ -436,98 +435,123 @@ def test_parse_stack_with_parameters(): region_name="us-west-1", ) - stack.resource_map.no_echo_parameter_keys.should.have("NoEchoParam") - stack.resource_map.no_echo_parameter_keys.should_not.have("Param") - stack.resource_map.no_echo_parameter_keys.should_not.have("NumberParam") - stack.resource_map.no_echo_parameter_keys.should_not.have("NumberListParam") - stack.resource_map.resolved_parameters["NumberParam"].should.equal(42) - stack.resource_map.resolved_parameters["NumberListParam"].should.equal( - [42, 3.14159] - ) + assert "NoEchoParam" in stack.resource_map.no_echo_parameter_keys + assert "Param" not in stack.resource_map.no_echo_parameter_keys + assert "NumberParam" not in stack.resource_map.no_echo_parameter_keys + assert "NumberListParam" not in stack.resource_map.no_echo_parameter_keys + assert stack.resource_map.resolved_parameters["NumberParam"] == 42 + assert stack.resource_map.resolved_parameters["NumberListParam"] == [42, 3.14159] def test_parse_equals_condition(): - parse_condition( - condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(True) + assert ( + parse_condition( + condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is True + ) - parse_condition( - condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - resources_map={"EnvType": "staging"}, - condition_map={}, - ).should.equal(False) + assert ( + parse_condition( + condition={"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + resources_map={"EnvType": "staging"}, + condition_map={}, + ) + is False + ) def test_parse_not_condition(): - parse_condition( - condition={"Fn::Not": [{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}]}, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(False) + assert ( + parse_condition( + condition={"Fn::Not": [{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}]}, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is False + ) - parse_condition( - condition={"Fn::Not": [{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}]}, - resources_map={"EnvType": "staging"}, - condition_map={}, - ).should.equal(True) + assert ( + parse_condition( + condition={"Fn::Not": [{"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}]}, + resources_map={"EnvType": "staging"}, + condition_map={}, + ) + is True + ) def test_parse_and_condition(): - parse_condition( - condition={ - "Fn::And": [ - {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, - ] - }, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(False) - - parse_condition( - condition={ - "Fn::And": [ - {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - ] - }, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(True) + assert ( + parse_condition( + condition={ + "Fn::And": [ + {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, + ] + }, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is False + ) + + assert ( + parse_condition( + condition={ + "Fn::And": [ + {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + ] + }, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is True + ) def test_parse_or_condition(): - parse_condition( - condition={ - "Fn::Or": [ - {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, - {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, - ] - }, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(True) - - parse_condition( - condition={ - "Fn::Or": [ - {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, - {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, - ] - }, - resources_map={"EnvType": "prod"}, - condition_map={}, - ).should.equal(False) + assert ( + parse_condition( + condition={ + "Fn::Or": [ + {"Fn::Equals": [{"Ref": "EnvType"}, "prod"]}, + {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, + ] + }, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is True + ) + + assert ( + parse_condition( + condition={ + "Fn::Or": [ + {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, + {"Fn::Equals": [{"Ref": "EnvType"}, "staging"]}, + ] + }, + resources_map={"EnvType": "prod"}, + condition_map={}, + ) + is False + ) def test_reference_other_conditions(): - parse_condition( - condition={"Fn::Not": [{"Condition": "OtherCondition"}]}, - resources_map={}, - condition_map={"OtherCondition": True}, - ).should.equal(False) + assert ( + parse_condition( + condition={"Fn::Not": [{"Condition": "OtherCondition"}]}, + resources_map={}, + condition_map={"OtherCondition": True}, + ) + is False + ) def test_parse_split_and_select(): @@ -540,9 +564,9 @@ def test_parse_split_and_select(): region_name="us-west-1", ) - stack.resource_map.should.have.length_of(1) + assert len(stack.resource_map) == 1 queue = stack.resource_map["Queue"] - queue.name.should.equal("myqueue") + assert queue.name == "myqueue" def test_sub(): @@ -557,7 +581,7 @@ def test_sub(): queue1 = stack.resource_map["Queue1"] queue2 = stack.resource_map["Queue2"] - queue2.name.should.equal(queue1.name) + assert queue2.name == queue1.name def test_sub_num(): @@ -572,7 +596,7 @@ def test_sub_num(): # Errors on moto<=4.0.10 because int(42) is used with str.replace queue = stack.resource_map["Queue"] - queue.name.should.equal("test_stack-queue-42") + assert queue.name == "test_stack-queue-42" def test_sub_mapping(): @@ -585,7 +609,7 @@ def test_sub_mapping(): region_name="us-west-1", ) queue = stack.resource_map["Queue"] - queue.name.should.equal("test_stack-queue-apple-yes") + assert queue.name == "test_stack-queue-apple-yes" stack = FakeStack( stack_id="test_id", @@ -596,7 +620,7 @@ def test_sub_mapping(): region_name="us-west-1", ) queue = stack.resource_map["Queue"] - queue.name.should.equal("test_stack-queue-banana-no") + assert queue.name == "test_stack-queue-banana-no" def test_import(): @@ -619,7 +643,7 @@ def test_import(): ) queue = import_stack.resource_map["Queue"] - queue.name.should.equal("value") + assert queue.name == "value" def test_to_json_string(): @@ -632,8 +656,8 @@ def test_to_json_string(): region_name="us-west-1", ) queue = stack.resource_map["Queue"] - queue.name.should.equal("test") - queue.dead_letter_queue.name.should.equal("deadletter") + assert queue.name == "test" + assert queue.dead_letter_queue.name == "deadletter" def test_short_form_func_in_yaml_teamplate(): @@ -676,7 +700,7 @@ def test_short_form_func_in_yaml_teamplate(): ["KeySub", {"Fn::Sub": "A"}], ] for k, v in key_and_expects: - template_dict.should.have.key(k).which.should.be.equal(v) + assert template_dict[k] == v @mock_ssm @@ -700,10 +724,9 @@ def test_ssm_parameter_parsing(): region_name="us-west-1", ) - stack.resource_map.resolved_parameters["SingleParamCfn"].should.equal("string") - stack.resource_map.resolved_parameters["ListParamCfn"].should.equal( - ["comma", "separated", "string"] - ) + params = stack.resource_map.resolved_parameters + assert params["SingleParamCfn"] == "string" + assert params["ListParamCfn"] == ["comma", "separated", "string"] # Not passing in a value for ListParamCfn to test Default value if not settings.TEST_SERVER_MODE: @@ -716,7 +739,6 @@ def test_ssm_parameter_parsing(): region_name="us-west-1", ) - stack.resource_map.resolved_parameters["SingleParamCfn"].should.equal("string") - stack.resource_map.resolved_parameters["ListParamCfn"].should.equal( - ["comma", "separated", "string"] - ) + params = stack.resource_map.resolved_parameters + assert params["SingleParamCfn"] == "string" + assert params["ListParamCfn"] == ["comma", "separated", "string"] diff --git a/tests/test_cloudformation/test_validate.py b/tests/test_cloudformation/test_validate.py index baf96555db62..cf305efb3b10 100644 --- a/tests/test_cloudformation/test_validate.py +++ b/tests/test_cloudformation/test_validate.py @@ -1,7 +1,7 @@ import json import boto3 import botocore -import sure # noqa # pylint: disable=unused-import +import pytest from moto import mock_cloudformation, mock_s3 from tests import EXAMPLE_AMI_ID @@ -63,15 +63,13 @@ def test_boto3_json_with_tabs_validate_successful(): @mock_cloudformation def test_boto3_json_invalid_missing_resource(): cf_conn = boto3.client("cloudformation", region_name="us-east-1") - try: + with pytest.raises(botocore.exceptions.ClientError) as exc: cf_conn.validate_template(TemplateBody=dummy_bad_template_json) - assert False - except botocore.exceptions.ClientError as e: - str(e).should.contain( - "An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack" - " with id Missing top level" - ) - assert True + err = exc.value.response["Error"] + assert ( + err["Message"] + == "Stack with id Missing top level template section Resources does not exist" + ) yaml_template = """ @@ -122,12 +120,10 @@ def test_boto3_yaml_validate_template_url_successful(): @mock_cloudformation def test_boto3_yaml_invalid_missing_resource(): cf_conn = boto3.client("cloudformation", region_name="us-east-1") - try: + with pytest.raises(botocore.exceptions.ClientError) as exc: cf_conn.validate_template(TemplateBody=yaml_bad_template) - assert False - except botocore.exceptions.ClientError as e: - str(e).should.contain( - "An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack" - " with id Missing top level" - ) - assert True + err = exc.value.response["Error"] + assert ( + err["Message"] + == "Stack with id Missing top level template section Resources does not exist" + )