1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
import json
import boto3
import botocore
import pytest
from moto import mock_aws
from tests import EXAMPLE_AMI_ID, aws_verified
json_template = {
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Stack 1",
"Resources": {
"EC2Instance1": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": EXAMPLE_AMI_ID,
"KeyName": "dummy",
"InstanceType": "t2.micro",
"Tags": [
{"Key": "Description", "Value": "Test tag"},
{"Key": "Name", "Value": "Name tag for tests"},
],
},
}
},
}
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"}
dummy_template_json = json.dumps(json_template)
dummy_bad_template_json = json.dumps(json_bad_template)
@mock_aws
def test_json_validate_successful():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
response = cf_conn.validate_template(TemplateBody=dummy_template_json)
assert response["Description"] == "Stack 1"
assert response["Parameters"] == []
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
@mock_aws
def test_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_aws
def test_json_invalid_missing_resource():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
with pytest.raises(botocore.exceptions.ClientError) as exc:
cf_conn.validate_template(TemplateBody=dummy_bad_template_json)
err = exc.value.response["Error"]
assert (
err["Message"]
in (
"Stack with id Missing top level template section Resources does not exist", # cfn-lint 0.x
"Stack with id 'Resources' is a required property does not exist", # cfn-lint 1.x
)
)
yaml_template = """
AWSTemplateFormatVersion: '2010-09-09'
Description: Simple CloudFormation Test Template
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: cf-test-bucket-1
"""
yaml_bad_template = """
AWSTemplateFormatVersion: '2010-09-09'
Description: Simple CloudFormation Test Template
"""
@mock_aws
def test_yaml_validate_successful():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
response = cf_conn.validate_template(TemplateBody=yaml_template)
assert response["Description"] == "Simple CloudFormation Test Template"
assert response["Parameters"] == []
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
@mock_aws
def test_yaml_validate_template_url_successful():
s3 = boto3.client("s3", region_name="us-east-1")
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_aws
def test_yaml_invalid_missing_resource():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
with pytest.raises(botocore.exceptions.ClientError) as exc:
cf_conn.validate_template(TemplateBody=yaml_bad_template)
err = exc.value.response["Error"]
assert (
err["Message"]
in (
"Stack with id Missing top level template section Resources does not exist", # cfn-lint 0.x
"Stack with id 'Resources' is a required property does not exist", # cfn-lint 1.x
)
)
@aws_verified
@pytest.mark.aws_verified
def test_validate_yaml_using_short_func_refs():
"""Template using !Sub as a key, which is not valid YAML"""
cf_client = boto3.client("cloudformation", region_name="us-east-1")
template = """AWSTemplateFormatVersion: '2010-09-09'
Description: Test template
Parameters:
BucketName:
Type: String
Resources:
TestBucket:
Type: AWS::S3::Bucket
Properties:
BucketName:
!Sub "${AWS::StackName}-${BucketName}"
Outputs:
BucketName:
Value:
!Sub "${TestBucket}"
"""
response = cf_client.validate_template(TemplateBody=template)
assert response["ResponseMetadata"]["HTTPStatusCode"] == 200
|