2018-11-02 23:04:17 +00:00
|
|
|
import json
|
|
|
|
import boto3
|
|
|
|
import botocore
|
2021-10-18 19:44:29 +00:00
|
|
|
import sure # noqa # pylint: disable=unused-import
|
2018-11-02 23:04:17 +00:00
|
|
|
|
2021-10-18 19:44:29 +00:00
|
|
|
from moto import mock_cloudformation, mock_s3
|
2021-01-13 09:02:11 +00:00
|
|
|
from tests import EXAMPLE_AMI_ID
|
2018-11-02 23:04:17 +00:00
|
|
|
|
|
|
|
json_template = {
|
|
|
|
"AWSTemplateFormatVersion": "2010-09-09",
|
|
|
|
"Description": "Stack 1",
|
|
|
|
"Resources": {
|
|
|
|
"EC2Instance1": {
|
|
|
|
"Type": "AWS::EC2::Instance",
|
|
|
|
"Properties": {
|
2021-01-13 09:02:11 +00:00
|
|
|
"ImageId": EXAMPLE_AMI_ID,
|
2018-11-02 23:04:17 +00:00
|
|
|
"KeyName": "dummy",
|
|
|
|
"InstanceType": "t2.micro",
|
|
|
|
"Tags": [
|
2019-10-31 15:44:26 +00:00
|
|
|
{"Key": "Description", "Value": "Test tag"},
|
|
|
|
{"Key": "Name", "Value": "Name tag for tests"},
|
|
|
|
],
|
|
|
|
},
|
2018-11-02 23:04:17 +00:00
|
|
|
}
|
2019-10-31 15:44:26 +00:00
|
|
|
},
|
2018-11-02 23:04:17 +00:00
|
|
|
}
|
|
|
|
|
2020-06-30 21:35:47 +00:00
|
|
|
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}
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
# One resource is required
|
2019-10-31 15:44:26 +00:00
|
|
|
json_bad_template = {"AWSTemplateFormatVersion": "2010-09-09", "Description": "Stack 1"}
|
2018-11-02 23:04:17 +00:00
|
|
|
|
|
|
|
dummy_template_json = json.dumps(json_template)
|
|
|
|
dummy_bad_template_json = json.dumps(json_bad_template)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_cloudformation
|
|
|
|
def test_boto3_json_validate_successful():
|
2019-10-31 15:44:26 +00:00
|
|
|
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
|
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
|
2020-06-30 21:35:47 +00:00
|
|
|
@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
|
|
|
|
|
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
@mock_cloudformation
|
|
|
|
def test_boto3_json_invalid_missing_resource():
|
2019-10-31 15:44:26 +00:00
|
|
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
2018-11-02 23:04:17 +00:00
|
|
|
try:
|
2019-10-31 15:44:26 +00:00
|
|
|
cf_conn.validate_template(TemplateBody=dummy_bad_template_json)
|
2018-11-02 23:04:17 +00:00
|
|
|
assert False
|
|
|
|
except botocore.exceptions.ClientError as e:
|
2020-05-24 07:51:45 +00:00
|
|
|
str(e).should.contain(
|
|
|
|
"An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack"
|
|
|
|
" with id Missing top level"
|
2019-10-31 15:44:26 +00:00
|
|
|
)
|
2018-11-02 23:04:17 +00:00
|
|
|
assert True
|
|
|
|
|
|
|
|
|
|
|
|
yaml_template = """
|
|
|
|
AWSTemplateFormatVersion: '2010-09-09'
|
|
|
|
Description: Simple CloudFormation Test Template
|
|
|
|
Resources:
|
|
|
|
S3Bucket:
|
|
|
|
Type: AWS::S3::Bucket
|
|
|
|
Properties:
|
|
|
|
AccessControl: PublicRead
|
|
|
|
BucketName: cf-test-bucket-1
|
|
|
|
"""
|
|
|
|
|
|
|
|
yaml_bad_template = """
|
|
|
|
AWSTemplateFormatVersion: '2010-09-09'
|
|
|
|
Description: Simple CloudFormation Test Template
|
|
|
|
"""
|
|
|
|
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
@mock_cloudformation
|
|
|
|
def test_boto3_yaml_validate_successful():
|
2019-10-31 15:44:26 +00:00
|
|
|
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
|
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
|
2020-06-26 13:01:57 +00:00
|
|
|
@mock_cloudformation
|
|
|
|
@mock_s3
|
|
|
|
def test_boto3_yaml_validate_template_url_successful():
|
2020-08-27 09:11:47 +00:00
|
|
|
s3 = boto3.client("s3", region_name="us-east-1")
|
2020-06-26 13:01:57 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2018-11-02 23:04:17 +00:00
|
|
|
@mock_cloudformation
|
|
|
|
def test_boto3_yaml_invalid_missing_resource():
|
2019-10-31 15:44:26 +00:00
|
|
|
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
|
2018-11-02 23:04:17 +00:00
|
|
|
try:
|
2019-10-31 15:44:26 +00:00
|
|
|
cf_conn.validate_template(TemplateBody=yaml_bad_template)
|
2018-11-02 23:04:17 +00:00
|
|
|
assert False
|
|
|
|
except botocore.exceptions.ClientError as e:
|
2020-05-24 07:51:45 +00:00
|
|
|
str(e).should.contain(
|
|
|
|
"An error occurred (ValidationError) when calling the ValidateTemplate operation: Stack"
|
|
|
|
" with id Missing top level"
|
2019-10-31 15:44:26 +00:00
|
|
|
)
|
2018-11-02 23:04:17 +00:00
|
|
|
assert True
|