Merge pull request #156 from DreadPirateShawn/VPCPeeringConnections
Add support for VPCPeeringConnections.
This commit is contained in:
commit
9d06ccf0cd
@ -4,6 +4,7 @@ python:
|
|||||||
- 2.7
|
- 2.7
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
|
- BOTO_VERSION=2.32.1
|
||||||
- BOTO_VERSION=2.31.1
|
- BOTO_VERSION=2.31.1
|
||||||
- BOTO_VERSION=2.25.0
|
- BOTO_VERSION=2.25.0
|
||||||
- BOTO_VERSION=2.19.0
|
- BOTO_VERSION=2.19.0
|
||||||
|
@ -37,6 +37,22 @@ class InvalidVPCIdError(EC2ClientError):
|
|||||||
.format(vpc_id))
|
.format(vpc_id))
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidVPCPeeringConnectionIdError(EC2ClientError):
|
||||||
|
def __init__(self, vpc_peering_connection_id):
|
||||||
|
super(InvalidVPCPeeringConnectionIdError, self).__init__(
|
||||||
|
"InvalidVpcPeeringConnectionId.NotFound",
|
||||||
|
"VpcPeeringConnectionID {0} does not exist."
|
||||||
|
.format(vpc_peering_connection_id))
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidVPCPeeringConnectionStateTransitionError(EC2ClientError):
|
||||||
|
def __init__(self, vpc_peering_connection_id):
|
||||||
|
super(InvalidVPCPeeringConnectionStateTransitionError, self).__init__(
|
||||||
|
"InvalidStateTransition",
|
||||||
|
"VpcPeeringConnectionID {0} is not in the correct state for the request."
|
||||||
|
.format(vpc_peering_connection_id))
|
||||||
|
|
||||||
|
|
||||||
class InvalidParameterValueError(EC2ClientError):
|
class InvalidParameterValueError(EC2ClientError):
|
||||||
def __init__(self, parameter_value):
|
def __init__(self, parameter_value):
|
||||||
super(InvalidParameterValueError, self).__init__(
|
super(InvalidParameterValueError, self).__init__(
|
||||||
|
@ -15,7 +15,9 @@ from .exceptions import (
|
|||||||
InvalidInternetGatewayIDError,
|
InvalidInternetGatewayIDError,
|
||||||
GatewayNotAttachedError,
|
GatewayNotAttachedError,
|
||||||
ResourceAlreadyAssociatedError,
|
ResourceAlreadyAssociatedError,
|
||||||
InvalidVPCIdError
|
InvalidVPCIdError,
|
||||||
|
InvalidVPCPeeringConnectionIdError,
|
||||||
|
InvalidVPCPeeringConnectionStateTransitionError
|
||||||
)
|
)
|
||||||
from .utils import (
|
from .utils import (
|
||||||
random_ami_id,
|
random_ami_id,
|
||||||
@ -35,6 +37,7 @@ from .utils import (
|
|||||||
random_subnet_id,
|
random_subnet_id,
|
||||||
random_volume_id,
|
random_volume_id,
|
||||||
random_vpc_id,
|
random_vpc_id,
|
||||||
|
random_vpc_peering_connection_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -715,6 +718,89 @@ class VPCBackend(object):
|
|||||||
return vpc
|
return vpc
|
||||||
|
|
||||||
|
|
||||||
|
class VPCPeeringConnectionStatus(object):
|
||||||
|
def __init__(self, code='initiating-request', message=''):
|
||||||
|
self.code = code
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
def initiating(self):
|
||||||
|
self.code = 'initiating-request'
|
||||||
|
self.message = 'Initiating Request to {accepter ID}'
|
||||||
|
|
||||||
|
def pending(self):
|
||||||
|
self.code = 'pending-acceptance'
|
||||||
|
self.message = 'Pending Acceptance by {accepter ID}'
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
self.code = 'active'
|
||||||
|
self.message = 'Active'
|
||||||
|
|
||||||
|
def reject(self):
|
||||||
|
self.code = 'rejected'
|
||||||
|
self.message = 'Inactive'
|
||||||
|
|
||||||
|
|
||||||
|
class VPCPeeringConnection(TaggedEC2Instance):
|
||||||
|
def __init__(self, vpc_pcx_id, vpc, peer_vpc):
|
||||||
|
self.id = vpc_pcx_id
|
||||||
|
self.vpc = vpc
|
||||||
|
self.peer_vpc = peer_vpc
|
||||||
|
self._status = VPCPeeringConnectionStatus()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
|
||||||
|
properties = cloudformation_json['Properties']
|
||||||
|
|
||||||
|
vpc = self.get_vpc(properties['VpcId'])
|
||||||
|
peer_vpc = self.get_vpc(properties['PeerVpcId'])
|
||||||
|
|
||||||
|
vpc_pcx = ec2_backend.create_vpc_peering_connection(vpc, peer_vpc)
|
||||||
|
|
||||||
|
return vpc_pcx
|
||||||
|
|
||||||
|
@property
|
||||||
|
def physical_resource_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
|
||||||
|
class VPCPeeringConnectionBackend(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.vpc_pcxs = {}
|
||||||
|
super(VPCPeeringConnectionBackend, self).__init__()
|
||||||
|
|
||||||
|
def create_vpc_peering_connection(self, vpc, peer_vpc):
|
||||||
|
vpc_pcx_id = random_vpc_peering_connection_id()
|
||||||
|
vpc_pcx = VPCPeeringConnection(vpc_pcx_id, vpc, peer_vpc)
|
||||||
|
vpc_pcx._status.pending()
|
||||||
|
self.vpc_pcxs[vpc_pcx_id] = vpc_pcx
|
||||||
|
return vpc_pcx
|
||||||
|
|
||||||
|
def get_all_vpc_peering_connections(self):
|
||||||
|
return self.vpc_pcxs.values()
|
||||||
|
|
||||||
|
def get_vpc_peering_connection(self, vpc_pcx_id):
|
||||||
|
if vpc_pcx_id not in self.vpc_pcxs:
|
||||||
|
raise InvalidVPCPeeringConnectionIdError(vpc_pcx_id)
|
||||||
|
return self.vpc_pcxs.get(vpc_pcx_id)
|
||||||
|
|
||||||
|
def delete_vpc_peering_connection(self, vpc_pcx_id):
|
||||||
|
return self.vpc_pcxs.pop(vpc_pcx_id, None)
|
||||||
|
|
||||||
|
def accept_vpc_peering_connection(self, vpc_pcx_id):
|
||||||
|
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
||||||
|
if vpc_pcx._status.code != 'pending-acceptance':
|
||||||
|
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
||||||
|
vpc_pcx._status.accept()
|
||||||
|
return vpc_pcx
|
||||||
|
|
||||||
|
def reject_vpc_peering_connection(self, vpc_pcx_id):
|
||||||
|
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
||||||
|
if vpc_pcx._status.code != 'pending-acceptance':
|
||||||
|
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
||||||
|
vpc_pcx._status.reject()
|
||||||
|
return vpc_pcx
|
||||||
|
|
||||||
|
|
||||||
class Subnet(TaggedEC2Instance):
|
class Subnet(TaggedEC2Instance):
|
||||||
def __init__(self, subnet_id, vpc_id, cidr_block):
|
def __init__(self, subnet_id, vpc_id, cidr_block):
|
||||||
self.id = subnet_id
|
self.id = subnet_id
|
||||||
@ -1176,6 +1262,7 @@ class DHCPOptionsSetBackend(object):
|
|||||||
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
|
||||||
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
|
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
|
||||||
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
|
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
|
||||||
|
VPCPeeringConnectionBackend,
|
||||||
RouteTableBackend, RouteBackend, InternetGatewayBackend,
|
RouteTableBackend, RouteBackend, InternetGatewayBackend,
|
||||||
VPCGatewayAttachmentBackend, SpotRequestBackend,
|
VPCGatewayAttachmentBackend, SpotRequestBackend,
|
||||||
ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend):
|
ElasticAddressBackend, KeyPairBackend, DHCPOptionsSetBackend):
|
||||||
|
@ -24,6 +24,7 @@ from .virtual_private_gateways import VirtualPrivateGateways
|
|||||||
from .vm_export import VMExport
|
from .vm_export import VMExport
|
||||||
from .vm_import import VMImport
|
from .vm_import import VMImport
|
||||||
from .vpcs import VPCs
|
from .vpcs import VPCs
|
||||||
|
from .vpc_peering_connections import VPCPeeringConnections
|
||||||
from .vpn_connections import VPNConnections
|
from .vpn_connections import VPNConnections
|
||||||
from .windows import Windows
|
from .windows import Windows
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ class EC2Response(
|
|||||||
VMExport,
|
VMExport,
|
||||||
VMImport,
|
VMImport,
|
||||||
VPCs,
|
VPCs,
|
||||||
|
VPCPeeringConnections,
|
||||||
VPNConnections,
|
VPNConnections,
|
||||||
Windows,
|
Windows,
|
||||||
):
|
):
|
||||||
|
137
moto/ec2/responses/vpc_peering_connections.py
Normal file
137
moto/ec2/responses/vpc_peering_connections.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
from jinja2 import Template
|
||||||
|
|
||||||
|
from moto.core.responses import BaseResponse
|
||||||
|
from moto.ec2.models import ec2_backend
|
||||||
|
|
||||||
|
|
||||||
|
class VPCPeeringConnections(BaseResponse):
|
||||||
|
def create_vpc_peering_connection(self):
|
||||||
|
vpc = ec2_backend.get_vpc(self.querystring.get('VpcId')[0])
|
||||||
|
peer_vpc = ec2_backend.get_vpc(self.querystring.get('PeerVpcId')[0])
|
||||||
|
vpc_pcx = ec2_backend.create_vpc_peering_connection(vpc, peer_vpc)
|
||||||
|
template = Template(CREATE_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
|
return template.render(vpc_pcx=vpc_pcx)
|
||||||
|
|
||||||
|
def delete_vpc_peering_connection(self):
|
||||||
|
vpc_pcx_id = self.querystring.get('VpcPeeringConnectionId')[0]
|
||||||
|
vpc_pcx = ec2_backend.delete_vpc_peering_connection(vpc_pcx_id)
|
||||||
|
if vpc_pcx:
|
||||||
|
template = Template(DELETE_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
|
return template.render(vpc_pcx=vpc_pcx)
|
||||||
|
else:
|
||||||
|
return "", dict(status=404)
|
||||||
|
|
||||||
|
def describe_vpc_peering_connections(self):
|
||||||
|
vpc_pcxs = ec2_backend.get_all_vpc_peering_connections()
|
||||||
|
template = Template(DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE)
|
||||||
|
return template.render(vpc_pcxs=vpc_pcxs)
|
||||||
|
|
||||||
|
def accept_vpc_peering_connection(self):
|
||||||
|
vpc_pcx_id = self.querystring.get('VpcPeeringConnectionId')[0]
|
||||||
|
vpc_pcx = ec2_backend.accept_vpc_peering_connection(vpc_pcx_id)
|
||||||
|
if vpc_pcx:
|
||||||
|
template = Template(ACCEPT_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
|
return template.render(vpc_pcx=vpc_pcx)
|
||||||
|
else:
|
||||||
|
return "", dict(status=404)
|
||||||
|
|
||||||
|
def reject_vpc_peering_connection(self):
|
||||||
|
vpc_pcx_id = self.querystring.get('VpcPeeringConnectionId')[0]
|
||||||
|
vpc_pcx = ec2_backend.reject_vpc_peering_connection(vpc_pcx_id)
|
||||||
|
if vpc_pcx:
|
||||||
|
template = Template(REJECT_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
|
return template.render()
|
||||||
|
else:
|
||||||
|
return "", dict(status=404)
|
||||||
|
|
||||||
|
|
||||||
|
CREATE_VPC_PEERING_CONNECTION_RESPONSE = """
|
||||||
|
<CreateVpcPeeringConnectionResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
|
||||||
|
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||||
|
<vpcPeeringConnection>
|
||||||
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
|
<requesterVpcInfo>
|
||||||
|
<ownerId>777788889999</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
|
</requesterVpcInfo>
|
||||||
|
<accepterVpcInfo>
|
||||||
|
<ownerId>123456789012</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
|
</accepterVpcInfo>
|
||||||
|
<status>
|
||||||
|
<code>initiating-request</code>
|
||||||
|
<message>Initiating request to {accepter ID}.</message>
|
||||||
|
</status>
|
||||||
|
<expirationTime>2014-02-18T14:37:25.000Z</expirationTime>
|
||||||
|
<tagSet/>
|
||||||
|
</vpcPeeringConnection>
|
||||||
|
</CreateVpcPeeringConnectionResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE = """
|
||||||
|
<DescribeVpcPeeringConnectionsResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
|
||||||
|
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||||
|
<vpcPeeringConnectionSet>
|
||||||
|
{% for vpc_pcx in vpc_pcxs %}
|
||||||
|
<item>
|
||||||
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
|
<requesterVpcInfo>
|
||||||
|
<ownerId>777788889999</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
|
</requesterVpcInfo>
|
||||||
|
<accepterVpcInfo>
|
||||||
|
<ownerId>111122223333</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
|
</accepterVpcInfo>
|
||||||
|
<status>
|
||||||
|
<code>{{ vpc_pcx._status.code }}</code>
|
||||||
|
<message>{{ vpc_pcx._status.message }}</message>
|
||||||
|
</status>
|
||||||
|
<expirationTime>2014-02-17T16:00:50.000Z</expirationTime>
|
||||||
|
<tagSet/>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</vpcPeeringConnectionSet>
|
||||||
|
</DescribeVpcPeeringConnectionsResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
DELETE_VPC_PEERING_CONNECTION_RESPONSE = """
|
||||||
|
<DeleteVpcPeeringConnectionResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
|
||||||
|
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||||
|
<return>true</return>
|
||||||
|
</DeleteVpcPeeringConnectionResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
ACCEPT_VPC_PEERING_CONNECTION_RESPONSE = """
|
||||||
|
<AcceptVpcPeeringConnectionResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
|
||||||
|
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||||
|
<vpcPeeringConnection>
|
||||||
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
|
<requesterVpcInfo>
|
||||||
|
<ownerId>123456789012</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
|
</requesterVpcInfo>
|
||||||
|
<accepterVpcInfo>
|
||||||
|
<ownerId>777788889999</ownerId>
|
||||||
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
|
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
||||||
|
</accepterVpcInfo>
|
||||||
|
<status>
|
||||||
|
<code>{{ vpc_pcx._status.code }}</code>
|
||||||
|
<message>{{ vpc_pcx._status.message }}</message>
|
||||||
|
</status>
|
||||||
|
<tagSet/>
|
||||||
|
</vpcPeeringConnection>
|
||||||
|
</AcceptVpcPeeringConnectionResponse>
|
||||||
|
"""
|
||||||
|
|
||||||
|
REJECT_VPC_PEERING_CONNECTION_RESPONSE = """
|
||||||
|
<RejectVpcPeeringConnectionResponse xmlns="http://ec2.amazonaws.com/doc/2014-06-15/">
|
||||||
|
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||||
|
<return>true</return>
|
||||||
|
</RejectVpcPeeringConnectionResponse>
|
||||||
|
"""
|
||||||
|
|
@ -46,6 +46,10 @@ def random_vpc_id():
|
|||||||
return random_id(prefix='vpc')
|
return random_id(prefix='vpc')
|
||||||
|
|
||||||
|
|
||||||
|
def random_vpc_peering_connection_id():
|
||||||
|
return random_id(prefix='pcx')
|
||||||
|
|
||||||
|
|
||||||
def random_eip_association_id():
|
def random_eip_association_id():
|
||||||
return random_id(prefix='eipassoc')
|
return random_id(prefix='eipassoc')
|
||||||
|
|
||||||
|
82
tests/test_ec2/test_vpc_peering.py
Normal file
82
tests/test_ec2/test_vpc_peering.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import boto
|
||||||
|
from boto.exception import EC2ResponseError
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
|
from moto import mock_ec2
|
||||||
|
from tests.helpers import requires_boto_gte
|
||||||
|
|
||||||
|
|
||||||
|
@requires_boto_gte("2.32.0")
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_peering_connections():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc = conn.create_vpc("10.0.0.0/16")
|
||||||
|
peer_vpc = conn.create_vpc("11.0.0.0/16")
|
||||||
|
|
||||||
|
vpc_pcx = conn.create_vpc_peering_connection(vpc.id, peer_vpc.id)
|
||||||
|
vpc_pcx._status.code.should.equal('initiating-request')
|
||||||
|
|
||||||
|
return vpc_pcx
|
||||||
|
|
||||||
|
|
||||||
|
@requires_boto_gte("2.32.0")
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_peering_connections_get_all():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc_pcx = test_vpc_peering_connections()
|
||||||
|
vpc_pcx._status.code.should.equal('initiating-request')
|
||||||
|
|
||||||
|
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
|
||||||
|
all_vpc_pcxs.should.have.length_of(1)
|
||||||
|
all_vpc_pcxs[0]._status.code.should.equal('pending-acceptance')
|
||||||
|
|
||||||
|
|
||||||
|
@requires_boto_gte("2.32.0")
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_peering_connections_accept():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc_pcx = test_vpc_peering_connections()
|
||||||
|
|
||||||
|
vpc_pcx = conn.accept_vpc_peering_connection(vpc_pcx.id)
|
||||||
|
vpc_pcx._status.code.should.equal('active')
|
||||||
|
|
||||||
|
conn.reject_vpc_peering_connection.when.called_with(
|
||||||
|
vpc_pcx.id).should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
|
||||||
|
all_vpc_pcxs.should.have.length_of(1)
|
||||||
|
all_vpc_pcxs[0]._status.code.should.equal('active')
|
||||||
|
|
||||||
|
|
||||||
|
@requires_boto_gte("2.32.0")
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_peering_connections_reject():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc_pcx = test_vpc_peering_connections()
|
||||||
|
|
||||||
|
verdict = conn.reject_vpc_peering_connection(vpc_pcx.id)
|
||||||
|
verdict.should.equal(True)
|
||||||
|
|
||||||
|
conn.accept_vpc_peering_connection.when.called_with(
|
||||||
|
vpc_pcx.id).should.throw(EC2ResponseError)
|
||||||
|
|
||||||
|
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
|
||||||
|
all_vpc_pcxs.should.have.length_of(1)
|
||||||
|
all_vpc_pcxs[0]._status.code.should.equal('rejected')
|
||||||
|
|
||||||
|
|
||||||
|
@requires_boto_gte("2.32.1")
|
||||||
|
@mock_ec2
|
||||||
|
def test_vpc_peering_connections_delete():
|
||||||
|
conn = boto.connect_vpc('the_key', 'the_secret')
|
||||||
|
vpc_pcx = test_vpc_peering_connections()
|
||||||
|
|
||||||
|
verdict = vpc_pcx.delete()
|
||||||
|
verdict.should.equal(True)
|
||||||
|
|
||||||
|
all_vpc_pcxs = conn.get_all_vpc_peering_connections()
|
||||||
|
all_vpc_pcxs.should.have.length_of(0)
|
||||||
|
|
||||||
|
conn.delete_vpc_peering_connection.when.called_with(
|
||||||
|
"pcx-1234abcd").should.throw(EC2ResponseError)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user