Fixed CF creation to trap imports of non-existent values

This commit is contained in:
Theodore Wong 2018-05-30 11:59:25 -07:00
parent b6909ff64c
commit da8bd545bf
4 changed files with 101 additions and 2 deletions

View File

@ -33,6 +33,18 @@ class MissingParameterError(BadRequest):
)
class ExportNotFound(BadRequest):
"""Exception to raise if a template tries to import a non-existent export"""
def __init__(self, export_name):
template = Template(ERROR_RESPONSE)
super(ExportNotFound, self).__init__()
self.description = template.render(
code='ExportNotFound',
message="No export named {0} found.".format(export_name)
)
ERROR_RESPONSE = """<ErrorResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<Error>
<Type>Sender</Type>

View File

@ -38,7 +38,7 @@ class FakeStack(BaseModel):
resource_status_reason="User Initiated")
self.description = self.template_dict.get('Description')
self.cross_stack_resources = cross_stack_resources or []
self.cross_stack_resources = cross_stack_resources or {}
self.resource_map = self._create_resource_map()
self.output_map = self._create_output_map()
self._add_stack_event("CREATE_COMPLETE")

View File

@ -28,7 +28,7 @@ from moto.s3 import models as s3_models
from moto.sns import models as sns_models
from moto.sqs import models as sqs_models
from .utils import random_suffix
from .exceptions import MissingParameterError, UnformattedGetAttTemplateException, ValidationError
from .exceptions import ExportNotFound, MissingParameterError, UnformattedGetAttTemplateException, ValidationError
from boto.cloudformation.stack import Output
MODEL_MAP = {
@ -206,6 +206,8 @@ def clean_json(resource_json, resources_map):
values = [x.value for x in resources_map.cross_stack_resources.values() if x.name == cleaned_val]
if any(values):
return values[0]
else:
raise ExportNotFound(cleaned_val)
if 'Fn::GetAZs' in resource_json:
region = resource_json.get('Fn::GetAZs') or DEFAULT_REGION

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
# Standard library modules
import unittest
# Third-party modules
import boto3
from botocore.exceptions import ClientError
# Package modules
from moto import mock_cloudformation
SG_STACK_NAME = 'simple-sg-stack'
SG_TEMPLATE = """
AWSTemplateFormatVersion: 2010-09-09
Description: Simple test CF template for moto_cloudformation
Resources:
SimpleSecurityGroup:
Type: AWS::EC2::SecurityGroup
Description: "A simple security group"
Properties:
GroupName: simple-security-group
GroupDescription: "A simple security group"
SecurityGroupEgress:
-
Description: "Egress to remote HTTPS servers"
CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 443
ToPort: 443
Outputs:
SimpleSecurityGroupName:
Value: !GetAtt SimpleSecurityGroup.GroupId
Export:
Name: "SimpleSecurityGroup"
"""
EC2_STACK_NAME = 'simple-ec2-stack'
EC2_TEMPLATE = """
---
# The latest template format version is "2010-09-09" and as of 2018-04-09
# is currently the only valid value.
AWSTemplateFormatVersion: 2010-09-09
Description: Simple test CF template for moto_cloudformation
Resources:
SimpleInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-03cf127a
InstanceType: t2.micro
SecurityGroups: !Split [',', !ImportValue SimpleSecurityGroup]
"""
class TestSimpleInstance(unittest.TestCase):
def test_simple_instance(self):
"""Test that we can create a simple CloudFormation stack that imports values from an existing CloudFormation stack"""
with mock_cloudformation():
client = boto3.client('cloudformation')
client.create_stack(StackName=SG_STACK_NAME, TemplateBody=SG_TEMPLATE)
response = client.create_stack(StackName=EC2_STACK_NAME, TemplateBody=EC2_TEMPLATE)
self.assertIn('StackId', response)
response = client.describe_stacks(StackName=response['StackId'])
self.assertIn('Stacks', response)
stack_info = response['Stacks']
self.assertEqual(1, len(stack_info))
self.assertIn('StackName', stack_info[0])
self.assertEqual(EC2_STACK_NAME, stack_info[0]['StackName'])
def test_simple_instance_missing_export(self):
"""Test that we get an exception if a CloudFormation stack tries to imports a non-existent export value"""
with mock_cloudformation():
client = boto3.client('cloudformation')
with self.assertRaises(ClientError) as e:
client.create_stack(StackName=EC2_STACK_NAME, TemplateBody=EC2_TEMPLATE)
self.assertIn('Error', e.exception.response)
self.assertIn('Code', e.exception.response['Error'])
self.assertEqual('ExportNotFound', e.exception.response['Error']['Code'])