diff --git a/moto/cloudformation/responses.py b/moto/cloudformation/responses.py index c4a085705..92a8b1cab 100644 --- a/moto/cloudformation/responses.py +++ b/moto/cloudformation/responses.py @@ -365,8 +365,8 @@ class CloudFormationResponse(BaseResponse): except (ValueError, KeyError): pass try: - description = yaml.load(template_body)["Description"] - except (yaml.ParserError, KeyError): + description = yaml.load(template_body, Loader=yaml.Loader)["Description"] + except (yaml.parser.ParserError, yaml.scanner.ScannerError, KeyError): pass template = self.response_template(VALIDATE_STACK_RESPONSE_TEMPLATE) return template.render(description=description) diff --git a/tests/test_cloudformation/test_validate.py b/tests/test_cloudformation/test_validate.py index 19dec46ef..081ceee54 100644 --- a/tests/test_cloudformation/test_validate.py +++ b/tests/test_cloudformation/test_validate.py @@ -40,6 +40,16 @@ json_template = { }, } +json_valid_template_with_tabs = """ +{ +\t"AWSTemplateFormatVersion": "2010-09-09", +\t"Description": "Stack 2", +\t"Resources": { +\t\t"Queue": {"Type": "AWS::SQS::Queue", "Properties": {"VisibilityTimeout": 60}} +\t} +} +""" + # One resource is required json_bad_template = {"AWSTemplateFormatVersion": "2010-09-09", "Description": "Stack 1"} @@ -56,6 +66,15 @@ def test_boto3_json_validate_successful(): assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 +@mock_cloudformation +def test_boto3_json_with_tabs_validate_successful(): + cf_conn = boto3.client("cloudformation", region_name="us-east-1") + response = cf_conn.validate_template(TemplateBody=json_valid_template_with_tabs) + assert response["Description"] == "Stack 2" + assert response["Parameters"] == [] + assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 + + @mock_cloudformation def test_boto3_json_invalid_missing_resource(): cf_conn = boto3.client("cloudformation", region_name="us-east-1")