Add Customer Gateway Support. Closes #465

This commit is contained in:
Steve Pulec 2016-01-08 16:48:01 -05:00
parent d6d6ff56af
commit d2302bae21
5 changed files with 167 additions and 9 deletions

View File

@ -92,6 +92,14 @@ class InvalidVpnConnectionIdError(EC2ClientError):
.format(network_acl_id))
class InvalidCustomerGatewayIdError(EC2ClientError):
def __init__(self, customer_gateway_id):
super(InvalidCustomerGatewayIdError, self).__init__(
"InvalidCustomerGatewayID.NotFound",
"The customer gateway ID '{0}' does not exist"
.format(customer_gateway_id))
class InvalidNetworkInterfaceIdError(EC2ClientError):
def __init__(self, eni_id):
super(InvalidNetworkInterfaceIdError, self).__init__(

View File

@ -55,7 +55,8 @@ from .exceptions import (
InvalidCIDRSubnetError,
InvalidNetworkAclIdError,
InvalidVpnGatewayIdError,
InvalidVpnConnectionIdError
InvalidVpnConnectionIdError,
InvalidCustomerGatewayIdError,
)
from .utils import (
EC2_RESOURCE_TO_PREFIX,
@ -95,6 +96,7 @@ from .utils import (
random_network_acl_subnet_association_id,
random_vpn_gateway_id,
random_vpn_connection_id,
random_customer_gateway_id,
is_tag_filter,
)
@ -2798,6 +2800,45 @@ class VpnGatewayBackend(object):
return detached
class CustomerGateway(TaggedEC2Resource):
def __init__(self, ec2_backend, id, type, ip_address, bgp_asn):
self.ec2_backend = ec2_backend
self.id = id
self.type = type
self.ip_address = ip_address
self.bgp_asn = bgp_asn
self.attachments = {}
super(CustomerGateway, self).__init__()
class CustomerGatewayBackend(object):
def __init__(self):
self.customer_gateways = {}
super(CustomerGatewayBackend, self).__init__()
def create_customer_gateway(self, type='ipsec.1', ip_address=None, bgp_asn=None):
customer_gateway_id = random_customer_gateway_id()
customer_gateway = CustomerGateway(self, customer_gateway_id, type, ip_address, bgp_asn)
self.customer_gateways[customer_gateway_id] = customer_gateway
return customer_gateway
def get_all_customer_gateways(self, filters=None):
customer_gateways = self.customer_gateways.values()
return generic_filter(filters, customer_gateways)
def get_customer_gateway(self, customer_gateway_id):
customer_gateway = self.customer_gateways.get(customer_gateway_id, None)
if not customer_gateway:
raise InvalidCustomerGatewayIdError(customer_gateway_id)
return customer_gateway
def delete_customer_gateway(self, customer_gateway_id):
deleted = self.customer_gateways.pop(customer_gateway_id, None)
if not deleted:
raise InvalidCustomerGatewayIdError(customer_gateway_id)
return deleted
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
@ -2806,7 +2847,7 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
RouteTableBackend, RouteBackend, InternetGatewayBackend,
VPCGatewayAttachmentBackend, SpotRequestBackend,
ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend,
NetworkAclBackend, VpnGatewayBackend):
NetworkAclBackend, VpnGatewayBackend, CustomerGatewayBackend):
def __init__(self, region_name):
super(EC2Backend, self).__init__()
@ -2831,7 +2872,7 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
for resource_id in resource_ids:
resource_prefix = get_prefix(resource_id)
if resource_prefix == EC2_RESOURCE_TO_PREFIX['customer-gateway']:
self.raise_not_implemented_error('DescribeCustomerGateways')
self.get_customer_gateway(customer_gateway_id=resource_id)
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['dhcp-options']:
self.describe_dhcp_options(options_ids=[resource_id])
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['image']:

View File

@ -1,13 +1,82 @@
from __future__ import unicode_literals
from moto.core.responses import BaseResponse
from moto.ec2.utils import filters_from_querystring
class CustomerGateways(BaseResponse):
def create_customer_gateway(self):
raise NotImplementedError('CustomerGateways(AmazonVPC).create_customer_gateway is not yet implemented')
# raise NotImplementedError('CustomerGateways(AmazonVPC).create_customer_gateway is not yet implemented')
type = self.querystring.get('Type', None)[0]
ip_address = self.querystring.get('IpAddress', None)[0]
bgp_asn = self.querystring.get('BgpAsn', None)[0]
customer_gateway = self.ec2_backend.create_customer_gateway(type, ip_address=ip_address, bgp_asn=bgp_asn)
template = self.response_template(CREATE_CUSTOMER_GATEWAY_RESPONSE)
return template.render(customer_gateway=customer_gateway)
def delete_customer_gateway(self):
raise NotImplementedError('CustomerGateways(AmazonVPC).delete_customer_gateway is not yet implemented')
customer_gateway_id = self.querystring.get('CustomerGatewayId')[0]
delete_status = self.ec2_backend.delete_customer_gateway(customer_gateway_id)
template = self.response_template(DELETE_CUSTOMER_GATEWAY_RESPONSE)
return template.render(customer_gateway=delete_status)
def describe_customer_gateways(self):
raise NotImplementedError('CustomerGateways(AmazonVPC).describe_customer_gateways is not yet implemented')
filters = filters_from_querystring(self.querystring)
customer_gateways = self.ec2_backend.get_all_customer_gateways(filters)
template = self.response_template(DESCRIBE_CUSTOMER_GATEWAYS_RESPONSE)
return template.render(customer_gateways=customer_gateways)
CREATE_CUSTOMER_GATEWAY_RESPONSE = """
<CreateCustomerGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
<customerGateway>
<customerGatewayId>{{ customer_gateway.id }}</customerGatewayId>
<state>pending</state>
<type>{{ customer_gateway.type }}</type>
<ipAddress>{{ customer_gateway.ip_address }}</ipAddress>
<bgpAsn>{{ customer_gateway.bgp_asn }}</bgpAsn>
<tagSet>
{% for tag in customer_gateway.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</customerGateway>
</CreateCustomerGatewayResponse>"""
DELETE_CUSTOMER_GATEWAY_RESPONSE = """
<DeleteCustomerGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
<return>{{ delete_status }}</return>
</DeleteCustomerGatewayResponse>"""
DESCRIBE_CUSTOMER_GATEWAYS_RESPONSE = """
<DescribeCustomerGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2014-10- 01/">
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
<customerGatewaySet>
{% for customer_gateway in customer_gateways %}
<item>
<customerGatewayId>{{ customer_gateway.id }}</customerGatewayId>
<state>{{ customer_gateway.state }}</state>
<type>available</type>
<ipAddress>{{ customer_gateway.ip_address }}</ipAddress>
<bgpAsn>{{ customer_gateway.bgp_asn }}</bgpAsn>
<tagSet>
{% for tag in customer_gateway.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</item>
{% endfor %}
</customerGatewaySet>
</DescribeCustomerGatewaysResponse>"""

View File

@ -89,6 +89,10 @@ def random_vpn_connection_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['vpn-connection'])
def random_customer_gateway_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['customer-gateway'])
def random_volume_id():
return random_id(prefix=EC2_RESOURCE_TO_PREFIX['volume'])
@ -314,7 +318,7 @@ def get_object_value(obj, attr):
def is_tag_filter(filter_name):
return (filter_name.startswith('tag:') or
return (filter_name.startswith('tag:') or
filter_name.startswith('tag-value') or
filter_name.startswith('tag-key'))

View File

@ -1,10 +1,46 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from nose.tools import assert_raises
from nose.tools import assert_false
from boto.exception import EC2ResponseError
from moto import mock_ec2
@mock_ec2
def test_customer_gateways():
pass
def test_create_customer_gateways():
conn = boto.connect_vpc('the_key', 'the_secret')
customer_gateway = conn.create_customer_gateway('ipsec.1', '205.251.242.54', 65534)
customer_gateway.should_not.be.none
customer_gateway.id.should.match(r'cgw-\w+')
customer_gateway.type.should.equal('ipsec.1')
customer_gateway.bgp_asn.should.equal(65534)
customer_gateway.ip_address.should.equal('205.251.242.54')
@mock_ec2
def test_describe_customer_gateways():
conn = boto.connect_vpc('the_key', 'the_secret')
customer_gateway = conn.create_customer_gateway('ipsec.1', '205.251.242.54', 65534)
cgws = conn.get_all_customer_gateways()
cgws.should.have.length_of(1)
cgws[0].id.should.match(customer_gateway.id)
@mock_ec2
def test_delete_customer_gateways():
conn = boto.connect_vpc('the_key', 'the_secret')
customer_gateway = conn.create_customer_gateway('ipsec.1', '205.251.242.54', 65534)
customer_gateway.should_not.be.none
cgws = conn.get_all_customer_gateways()
cgws[0].id.should.match(customer_gateway.id)
deleted = conn.delete_customer_gateway(customer_gateway.id)
cgws = conn.get_all_customer_gateways()
cgws.should.have.length_of(0)
@mock_ec2
def test_delete_customer_gateways_bad_id():
conn = boto.connect_vpc('the_key', 'the_secret')
with assert_raises(EC2ResponseError) as cm:
conn.delete_customer_gateway('cgw-0123abcd')