diff --git a/moto/cloudformation/responses.py b/moto/cloudformation/responses.py index cceedc86..c4a08570 100644 --- a/moto/cloudformation/responses.py +++ b/moto/cloudformation/responses.py @@ -351,18 +351,21 @@ class CloudFormationResponse(BaseResponse): return template.render(exports=exports, next_token=next_token) def validate_template(self): - cfn_lint = self.cloudformation_backend.validate_template( - self._get_param("TemplateBody") - ) + template_body = self._get_param("TemplateBody") + template_url = self._get_param("TemplateURL") + if template_url: + template_body = self._get_stack_from_s3_url(template_url) + + cfn_lint = self.cloudformation_backend.validate_template(template_body) if cfn_lint: raise ValidationError(cfn_lint[0].message) description = "" try: - description = json.loads(self._get_param("TemplateBody"))["Description"] + description = json.loads(template_body)["Description"] except (ValueError, KeyError): pass try: - description = yaml.load(self._get_param("TemplateBody"))["Description"] + description = yaml.load(template_body)["Description"] except (yaml.ParserError, KeyError): pass template = self.response_template(VALIDATE_STACK_RESPONSE_TEMPLATE) diff --git a/tests/test_cloudformation/test_validate.py b/tests/test_cloudformation/test_validate.py index 5ffaeafb..19dec46e 100644 --- a/tests/test_cloudformation/test_validate.py +++ b/tests/test_cloudformation/test_validate.py @@ -96,6 +96,25 @@ def test_boto3_yaml_validate_successful(): assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 +@mock_cloudformation +@mock_s3 +def test_boto3_yaml_validate_template_url_successful(): + s3 = boto3.client("s3") + s3_conn = boto3.resource("s3", region_name="us-east-1") + s3_conn.create_bucket(Bucket="foobar") + + s3_conn.Object("foobar", "template-key").put(Body=yaml_template) + key_url = s3.generate_presigned_url( + ClientMethod="get_object", Params={"Bucket": "foobar", "Key": "template-key"} + ) + + cf_conn = boto3.client("cloudformation", region_name="us-east-1") + response = cf_conn.validate_template(TemplateURL=key_url) + assert response["Description"] == "Simple CloudFormation Test Template" + assert response["Parameters"] == [] + assert response["ResponseMetadata"]["HTTPStatusCode"] == 200 + + @mock_cloudformation def test_boto3_yaml_invalid_missing_resource(): cf_conn = boto3.client("cloudformation", region_name="us-east-1")