EC2: Cross-account VPC peering connections (#6826)
This commit is contained in:
parent
643759bd64
commit
5f1fb65038
@ -632,21 +632,23 @@ class InvalidVPCRangeError(EC2ClientError):
|
|||||||
super().__init__("InvalidVpc.Range", f"The CIDR '{cidr_block}' is invalid.")
|
super().__init__("InvalidVpc.Range", f"The CIDR '{cidr_block}' is invalid.")
|
||||||
|
|
||||||
|
|
||||||
# accept exception
|
# Raised when attempting to accept a VPC peering connection request in own account but in the requester region
|
||||||
class OperationNotPermitted2(EC2ClientError):
|
class OperationNotPermitted2(EC2ClientError):
|
||||||
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
|
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"OperationNotPermitted",
|
"OperationNotPermitted",
|
||||||
f"Incorrect region ({client_region}) specified for this request.VPC peering connection {pcx_id} must be accepted in region {acceptor_region}",
|
f"Incorrect region ({client_region}) specified for this request. "
|
||||||
|
f"VPC peering connection {pcx_id} must be accepted in region {acceptor_region}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# reject exception
|
# Raised when attempting to reject a VPC peering connection request in own account but in the requester region
|
||||||
class OperationNotPermitted3(EC2ClientError):
|
class OperationNotPermitted3(EC2ClientError):
|
||||||
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
|
def __init__(self, client_region: str, pcx_id: str, acceptor_region: str):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
"OperationNotPermitted",
|
"OperationNotPermitted",
|
||||||
f"Incorrect region ({client_region}) specified for this request.VPC peering connection {pcx_id} must be accepted or rejected in region {acceptor_region}",
|
f"Incorrect region ({client_region}) specified for this request. "
|
||||||
|
f"VPC peering connection {pcx_id} must be accepted or rejected in region {acceptor_region}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -658,6 +660,15 @@ class OperationNotPermitted4(EC2ClientError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Raised when attempting to accept or reject a VPC peering connection request for a VPC not belonging to self
|
||||||
|
class OperationNotPermitted5(EC2ClientError):
|
||||||
|
def __init__(self, account_id: str, pcx_id: str, operation: str):
|
||||||
|
super().__init__(
|
||||||
|
"OperationNotPermitted",
|
||||||
|
f"User ({account_id}) cannot {operation} peering {pcx_id}",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class InvalidLaunchTemplateNameAlreadyExistsError(EC2ClientError):
|
class InvalidLaunchTemplateNameAlreadyExistsError(EC2ClientError):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
@ -95,7 +95,7 @@ class TransitGatewayPeeringAttachment(TransitGatewayAttachment):
|
|||||||
"region": region_name,
|
"region": region_name,
|
||||||
"transitGatewayId": transit_gateway_id,
|
"transitGatewayId": transit_gateway_id,
|
||||||
}
|
}
|
||||||
self.status = PeeringConnectionStatus()
|
self.status = PeeringConnectionStatus(accepter_id=peer_account_id)
|
||||||
|
|
||||||
|
|
||||||
class TransitGatewayAttachmentBackend:
|
class TransitGatewayAttachmentBackend:
|
||||||
@ -342,5 +342,5 @@ class TransitGatewayAttachmentBackend:
|
|||||||
transit_gateway_attachment_id
|
transit_gateway_attachment_id
|
||||||
]
|
]
|
||||||
transit_gateway_attachment.state = "deleted"
|
transit_gateway_attachment.state = "deleted"
|
||||||
transit_gateway_attachment.status.deleted() # type: ignore[attr-defined]
|
transit_gateway_attachment.status.deleted(deleter_id=self.account_id) # type: ignore[attr-defined]
|
||||||
return transit_gateway_attachment
|
return transit_gateway_attachment
|
||||||
|
@ -7,6 +7,7 @@ from ..exceptions import (
|
|||||||
InvalidVPCPeeringConnectionStateTransitionError,
|
InvalidVPCPeeringConnectionStateTransitionError,
|
||||||
OperationNotPermitted2,
|
OperationNotPermitted2,
|
||||||
OperationNotPermitted3,
|
OperationNotPermitted3,
|
||||||
|
OperationNotPermitted5,
|
||||||
)
|
)
|
||||||
from .core import TaggedEC2Resource
|
from .core import TaggedEC2Resource
|
||||||
from .vpcs import VPC
|
from .vpcs import VPC
|
||||||
@ -14,21 +15,24 @@ from ..utils import random_vpc_peering_connection_id
|
|||||||
|
|
||||||
|
|
||||||
class PeeringConnectionStatus:
|
class PeeringConnectionStatus:
|
||||||
def __init__(self, code: str = "initiating-request", message: str = ""):
|
def __init__(
|
||||||
|
self, accepter_id: str, code: str = "initiating-request", message: str = ""
|
||||||
|
):
|
||||||
|
self.accepter_id = accepter_id
|
||||||
self.code = code
|
self.code = code
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
def deleted(self) -> None:
|
def deleted(self, deleter_id: str) -> None:
|
||||||
self.code = "deleted"
|
self.code = "deleted"
|
||||||
self.message = "Deleted by {deleter ID}"
|
self.message = f"Deleted by {deleter_id}"
|
||||||
|
|
||||||
def initiating(self) -> None:
|
def initiating(self) -> None:
|
||||||
self.code = "initiating-request"
|
self.code = "initiating-request"
|
||||||
self.message = "Initiating Request to {accepter ID}"
|
self.message = f"Initiating Request to {self.accepter_id}"
|
||||||
|
|
||||||
def pending(self) -> None:
|
def pending(self) -> None:
|
||||||
self.code = "pending-acceptance"
|
self.code = "pending-acceptance"
|
||||||
self.message = "Pending Acceptance by {accepter ID}"
|
self.message = f"Pending Acceptance by {self.accepter_id}"
|
||||||
|
|
||||||
def accept(self) -> None:
|
def accept(self) -> None:
|
||||||
self.code = "active"
|
self.code = "active"
|
||||||
@ -61,7 +65,7 @@ class VPCPeeringConnection(TaggedEC2Resource, CloudFormationModel):
|
|||||||
self.requester_options = self.DEFAULT_OPTIONS.copy()
|
self.requester_options = self.DEFAULT_OPTIONS.copy()
|
||||||
self.accepter_options = self.DEFAULT_OPTIONS.copy()
|
self.accepter_options = self.DEFAULT_OPTIONS.copy()
|
||||||
self.add_tags(tags or {})
|
self.add_tags(tags or {})
|
||||||
self._status = PeeringConnectionStatus()
|
self._status = PeeringConnectionStatus(accepter_id=peer_vpc.owner_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_name_type() -> str:
|
def cloudformation_name_type() -> str:
|
||||||
@ -79,7 +83,7 @@ class VPCPeeringConnection(TaggedEC2Resource, CloudFormationModel):
|
|||||||
cloudformation_json: Any,
|
cloudformation_json: Any,
|
||||||
account_id: str,
|
account_id: str,
|
||||||
region_name: str,
|
region_name: str,
|
||||||
**kwargs: Any
|
**kwargs: Any,
|
||||||
) -> "VPCPeeringConnection":
|
) -> "VPCPeeringConnection":
|
||||||
from ..models import ec2_backends
|
from ..models import ec2_backends
|
||||||
|
|
||||||
@ -120,11 +124,15 @@ class VPCPeeringConnectionBackend:
|
|||||||
vpc_pcx = VPCPeeringConnection(self, vpc_pcx_id, vpc, peer_vpc, tags)
|
vpc_pcx = VPCPeeringConnection(self, vpc_pcx_id, vpc, peer_vpc, tags)
|
||||||
vpc_pcx._status.pending()
|
vpc_pcx._status.pending()
|
||||||
self.vpc_pcxs[vpc_pcx_id] = vpc_pcx
|
self.vpc_pcxs[vpc_pcx_id] = vpc_pcx
|
||||||
# insert cross region peering info
|
# insert cross-account/cross-region peering info
|
||||||
if vpc.ec2_backend.region_name != peer_vpc.ec2_backend.region_name:
|
if vpc.owner_id != peer_vpc.owner_id or vpc.region != peer_vpc.region:
|
||||||
for vpc_pcx_cx in peer_vpc.ec2_backend.get_vpc_pcx_refs():
|
for backend in peer_vpc.ec2_backend.get_vpc_pcx_refs():
|
||||||
if vpc_pcx_cx.region_name == peer_vpc.ec2_backend.region_name:
|
if (
|
||||||
vpc_pcx_cx.vpc_pcxs[vpc_pcx_id] = vpc_pcx
|
backend.account_id == peer_vpc.owner_id
|
||||||
|
and backend.region_name == peer_vpc.region
|
||||||
|
):
|
||||||
|
backend.vpc_pcxs[vpc_pcx_id] = vpc_pcx
|
||||||
|
|
||||||
return vpc_pcx
|
return vpc_pcx
|
||||||
|
|
||||||
def describe_vpc_peering_connections(
|
def describe_vpc_peering_connections(
|
||||||
@ -142,16 +150,24 @@ class VPCPeeringConnectionBackend:
|
|||||||
|
|
||||||
def delete_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
def delete_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
||||||
deleted = self.get_vpc_peering_connection(vpc_pcx_id)
|
deleted = self.get_vpc_peering_connection(vpc_pcx_id)
|
||||||
deleted._status.deleted()
|
deleted._status.deleted(deleter_id=self.account_id) # type: ignore[attr-defined]
|
||||||
return deleted
|
return deleted
|
||||||
|
|
||||||
def accept_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
def accept_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
||||||
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
||||||
# if cross region need accepter from another region
|
|
||||||
pcx_req_region = vpc_pcx.vpc.ec2_backend.region_name
|
# validate cross-account acceptance
|
||||||
pcx_acp_region = vpc_pcx.peer_vpc.ec2_backend.region_name
|
req_account_id = vpc_pcx.vpc.owner_id
|
||||||
|
acp_account_id = vpc_pcx.peer_vpc.owner_id
|
||||||
|
if req_account_id != acp_account_id and self.account_id != acp_account_id: # type: ignore[attr-defined]
|
||||||
|
raise OperationNotPermitted5(self.account_id, vpc_pcx_id, "accept") # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
# validate cross-region acceptance
|
||||||
|
pcx_req_region = vpc_pcx.vpc.region
|
||||||
|
pcx_acp_region = vpc_pcx.peer_vpc.region
|
||||||
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
|
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
|
||||||
raise OperationNotPermitted2(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
|
raise OperationNotPermitted2(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
|
||||||
|
|
||||||
if vpc_pcx._status.code != "pending-acceptance":
|
if vpc_pcx._status.code != "pending-acceptance":
|
||||||
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
||||||
vpc_pcx._status.accept()
|
vpc_pcx._status.accept()
|
||||||
@ -159,11 +175,19 @@ class VPCPeeringConnectionBackend:
|
|||||||
|
|
||||||
def reject_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
def reject_vpc_peering_connection(self, vpc_pcx_id: str) -> VPCPeeringConnection:
|
||||||
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
vpc_pcx = self.get_vpc_peering_connection(vpc_pcx_id)
|
||||||
# if cross region need accepter from another region
|
|
||||||
pcx_req_region = vpc_pcx.vpc.ec2_backend.region_name
|
# validate cross-account rejection
|
||||||
pcx_acp_region = vpc_pcx.peer_vpc.ec2_backend.region_name
|
req_account_id = vpc_pcx.vpc.owner_id
|
||||||
|
acp_account_id = vpc_pcx.peer_vpc.owner_id
|
||||||
|
if req_account_id != acp_account_id and self.account_id != acp_account_id: # type: ignore[attr-defined]
|
||||||
|
raise OperationNotPermitted5(self.account_id, vpc_pcx_id, "reject") # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
# validate cross-region acceptance
|
||||||
|
pcx_req_region = vpc_pcx.vpc.region
|
||||||
|
pcx_acp_region = vpc_pcx.peer_vpc.region
|
||||||
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
|
if pcx_req_region != pcx_acp_region and self.region_name == pcx_req_region: # type: ignore[attr-defined]
|
||||||
raise OperationNotPermitted3(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
|
raise OperationNotPermitted3(self.region_name, vpc_pcx.id, pcx_acp_region) # type: ignore[attr-defined]
|
||||||
|
|
||||||
if vpc_pcx._status.code != "pending-acceptance":
|
if vpc_pcx._status.code != "pending-acceptance":
|
||||||
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
raise InvalidVPCPeeringConnectionStateTransitionError(vpc_pcx.id)
|
||||||
vpc_pcx._status.reject()
|
vpc_pcx._status.reject()
|
||||||
|
@ -205,6 +205,10 @@ class VPC(TaggedEC2Resource, CloudFormationModel):
|
|||||||
def owner_id(self) -> str:
|
def owner_id(self) -> str:
|
||||||
return self.ec2_backend.account_id
|
return self.ec2_backend.account_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def region(self) -> str:
|
||||||
|
return self.ec2_backend.region_name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def cloudformation_name_type() -> str:
|
def cloudformation_name_type() -> str:
|
||||||
return ""
|
return ""
|
||||||
|
@ -3,21 +3,23 @@ from ._base_response import EC2BaseResponse
|
|||||||
|
|
||||||
class VPCPeeringConnections(EC2BaseResponse):
|
class VPCPeeringConnections(EC2BaseResponse):
|
||||||
def create_vpc_peering_connection(self) -> str:
|
def create_vpc_peering_connection(self) -> str:
|
||||||
peer_region = self._get_param("PeerRegion")
|
|
||||||
tags = self._parse_tag_specification().get("vpc-peering-connection", {})
|
tags = self._parse_tag_specification().get("vpc-peering-connection", {})
|
||||||
|
|
||||||
if peer_region == self.region or peer_region is None:
|
account_id = self._get_param("PeerOwnerId") or self.current_account
|
||||||
peer_vpc = self.ec2_backend.get_vpc(self._get_param("PeerVpcId"))
|
region_name = self._get_param("PeerRegion") or self.region
|
||||||
else:
|
|
||||||
|
vpc = self.ec2_backend.get_vpc(self._get_param("VpcId"))
|
||||||
|
|
||||||
|
# Peer VPC could belong to another account or region
|
||||||
from moto.ec2.models import ec2_backends
|
from moto.ec2.models import ec2_backends
|
||||||
|
|
||||||
peer_vpc = ec2_backends[self.current_account][peer_region].get_vpc(
|
peer_vpc = ec2_backends[account_id][region_name].get_vpc(
|
||||||
self._get_param("PeerVpcId")
|
self._get_param("PeerVpcId")
|
||||||
)
|
)
|
||||||
vpc = self.ec2_backend.get_vpc(self._get_param("VpcId"))
|
|
||||||
vpc_pcx = self.ec2_backend.create_vpc_peering_connection(vpc, peer_vpc, tags)
|
vpc_pcx = self.ec2_backend.create_vpc_peering_connection(vpc, peer_vpc, tags)
|
||||||
template = self.response_template(CREATE_VPC_PEERING_CONNECTION_RESPONSE)
|
template = self.response_template(CREATE_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
return template.render(account_id=self.current_account, vpc_pcx=vpc_pcx)
|
return template.render(vpc_pcx=vpc_pcx)
|
||||||
|
|
||||||
def delete_vpc_peering_connection(self) -> str:
|
def delete_vpc_peering_connection(self) -> str:
|
||||||
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
||||||
@ -31,13 +33,13 @@ class VPCPeeringConnections(EC2BaseResponse):
|
|||||||
vpc_peering_ids=ids
|
vpc_peering_ids=ids
|
||||||
)
|
)
|
||||||
template = self.response_template(DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE)
|
template = self.response_template(DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE)
|
||||||
return template.render(account_id=self.current_account, vpc_pcxs=vpc_pcxs)
|
return template.render(vpc_pcxs=vpc_pcxs)
|
||||||
|
|
||||||
def accept_vpc_peering_connection(self) -> str:
|
def accept_vpc_peering_connection(self) -> str:
|
||||||
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
||||||
vpc_pcx = self.ec2_backend.accept_vpc_peering_connection(vpc_pcx_id)
|
vpc_pcx = self.ec2_backend.accept_vpc_peering_connection(vpc_pcx_id)
|
||||||
template = self.response_template(ACCEPT_VPC_PEERING_CONNECTION_RESPONSE)
|
template = self.response_template(ACCEPT_VPC_PEERING_CONNECTION_RESPONSE)
|
||||||
return template.render(account_id=self.current_account, vpc_pcx=vpc_pcx)
|
return template.render(vpc_pcx=vpc_pcx)
|
||||||
|
|
||||||
def reject_vpc_peering_connection(self) -> str:
|
def reject_vpc_peering_connection(self) -> str:
|
||||||
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
vpc_pcx_id = self._get_param("VpcPeeringConnectionId")
|
||||||
@ -70,9 +72,12 @@ CREATE_VPC_PEERING_CONNECTION_RESPONSE = """
|
|||||||
<vpcPeeringConnection>
|
<vpcPeeringConnection>
|
||||||
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
<requesterVpcInfo>
|
<requesterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
<peeringOptions>
|
<peeringOptions>
|
||||||
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
@ -80,8 +85,12 @@ CREATE_VPC_PEERING_CONNECTION_RESPONSE = """
|
|||||||
</peeringOptions>
|
</peeringOptions>
|
||||||
</requesterVpcInfo>
|
</requesterVpcInfo>
|
||||||
<accepterVpcInfo>
|
<accepterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.peer_vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.peer_vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
|
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
||||||
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
<peeringOptions>
|
<peeringOptions>
|
||||||
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
@ -90,7 +99,7 @@ CREATE_VPC_PEERING_CONNECTION_RESPONSE = """
|
|||||||
</accepterVpcInfo>
|
</accepterVpcInfo>
|
||||||
<status>
|
<status>
|
||||||
<code>initiating-request</code>
|
<code>initiating-request</code>
|
||||||
<message>Initiating Request to {accepter ID}</message>
|
<message>Initiating Request to {{ vpc_pcx.peer_vpc.owner_id }}</message>
|
||||||
</status>
|
</status>
|
||||||
<expirationTime>2014-02-18T14:37:25.000Z</expirationTime>
|
<expirationTime>2014-02-18T14:37:25.000Z</expirationTime>
|
||||||
<tagSet>
|
<tagSet>
|
||||||
@ -113,10 +122,12 @@ DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE = """
|
|||||||
<item>
|
<item>
|
||||||
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
<requesterVpcInfo>
|
<requesterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
<region>{{ vpc_pcx.vpc.ec2_backend.region_name }}</region>
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
<peeringOptions>
|
<peeringOptions>
|
||||||
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
@ -124,10 +135,12 @@ DESCRIBE_VPC_PEERING_CONNECTIONS_RESPONSE = """
|
|||||||
</peeringOptions>
|
</peeringOptions>
|
||||||
</requesterVpcInfo>
|
</requesterVpcInfo>
|
||||||
<accepterVpcInfo>
|
<accepterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.peer_vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.peer_vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
||||||
<region>{{ vpc_pcx.peer_vpc.ec2_backend.region_name }}</region>
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
<peeringOptions>
|
<peeringOptions>
|
||||||
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
@ -165,21 +178,30 @@ ACCEPT_VPC_PEERING_CONNECTION_RESPONSE = """
|
|||||||
<vpcPeeringConnection>
|
<vpcPeeringConnection>
|
||||||
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
<vpcPeeringConnectionId>{{ vpc_pcx.id }}</vpcPeeringConnectionId>
|
||||||
<requesterVpcInfo>
|
<requesterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.vpc.id }}</vpcId>
|
||||||
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc_pcx.vpc.cidr_block }}</cidrBlock>
|
||||||
<region>{{ vpc_pcx.vpc.ec2_backend.region_name }}</region>
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
|
<peeringOptions>
|
||||||
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.requester_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.requester_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
|
<allowDnsResolutionFromRemoteVpc>{{ vpc_pcx.requester_options.AllowDnsResolutionFromRemoteVpc or '' }}</allowDnsResolutionFromRemoteVpc>
|
||||||
|
</peeringOptions>
|
||||||
</requesterVpcInfo>
|
</requesterVpcInfo>
|
||||||
<accepterVpcInfo>
|
<accepterVpcInfo>
|
||||||
<ownerId>{{ account_id }}</ownerId>
|
<ownerId>{{ vpc_pcx.peer_vpc.owner_id }}</ownerId>
|
||||||
|
<region>{{ vpc_pcx.peer_vpc.region }}</region>
|
||||||
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
<vpcId>{{ vpc_pcx.peer_vpc.id }}</vpcId>
|
||||||
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ vpc_pcx.peer_vpc.cidr_block }}</cidrBlock>
|
||||||
|
<cidrBlockSet></cidrBlockSet>
|
||||||
|
<ipv6CidrBlockSet></ipv6CidrBlockSet>
|
||||||
<peeringOptions>
|
<peeringOptions>
|
||||||
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
<allowEgressFromLocalClassicLinkToRemoteVpc>{{ vpc_pcx.accepter_options.AllowEgressFromLocalClassicLinkToRemoteVpc or '' }}</allowEgressFromLocalClassicLinkToRemoteVpc>
|
||||||
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
<allowEgressFromLocalVpcToRemoteClassicLink>{{ vpc_pcx.accepter_options.AllowEgressFromLocalVpcToRemoteClassicLink or '' }}</allowEgressFromLocalVpcToRemoteClassicLink>
|
||||||
<allowDnsResolutionFromRemoteVpc>{{ vpc_pcx.accepter_options.AllowDnsResolutionFromRemoteVpc or '' }}</allowDnsResolutionFromRemoteVpc>
|
<allowDnsResolutionFromRemoteVpc>{{ vpc_pcx.accepter_options.AllowDnsResolutionFromRemoteVpc or '' }}</allowDnsResolutionFromRemoteVpc>
|
||||||
</peeringOptions>
|
</peeringOptions>
|
||||||
<region>{{ vpc_pcx.peer_vpc.ec2_backend.region_name }}</region>
|
|
||||||
</accepterVpcInfo>
|
</accepterVpcInfo>
|
||||||
<status>
|
<status>
|
||||||
<code>{{ vpc_pcx._status.code }}</code>
|
<code>{{ vpc_pcx._status.code }}</code>
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
|
import os
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto import mock_ec2
|
from moto import mock_ec2, settings
|
||||||
|
|
||||||
|
|
||||||
def create_vpx_pcx(ec2, client):
|
def create_vpx_pcx(ec2, client):
|
||||||
@ -40,6 +43,7 @@ def test_vpc_peering_connections_get_all_boto3():
|
|||||||
if vpc_pcx["VpcPeeringConnectionId"] == vpc_pcx_id
|
if vpc_pcx["VpcPeeringConnectionId"] == vpc_pcx_id
|
||||||
][0]
|
][0]
|
||||||
assert my_vpc_pcx["Status"]["Code"] == "pending-acceptance"
|
assert my_vpc_pcx["Status"]["Code"] == "pending-acceptance"
|
||||||
|
assert my_vpc_pcx["Status"]["Message"] == "Pending Acceptance by 123456789012"
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
@ -115,24 +119,84 @@ def test_vpc_peering_connections_delete_boto3():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
assert vpc_pcx_usw1.status["Code"] == "initiating-request"
|
|
||||||
assert vpc_pcx_usw1.requester_vpc.id == vpc_usw1.id
|
assert (
|
||||||
assert vpc_pcx_usw1.accepter_vpc.id == vpc_apn1.id
|
vpc_pcx_usw1["VpcPeeringConnection"]["Status"]["Code"] == "initiating-request"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["Status"]["Message"]
|
||||||
|
== f"Initiating Request to {account2}"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["VpcId"] == vpc_usw1.id
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["CidrBlock"]
|
||||||
|
== "10.90.0.0/16"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["OwnerId"] == account1
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["RequesterVpcInfo"]["Region"]
|
||||||
|
== "us-west-1"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["VpcId"] == vpc_apn1.id
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["CidrBlock"]
|
||||||
|
== "10.20.0.0/16"
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["OwnerId"] == account2
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["AccepterVpcInfo"]["Region"]
|
||||||
|
== "ap-northeast-1"
|
||||||
|
)
|
||||||
|
|
||||||
# test cross region vpc peering connection exist
|
# test cross region vpc peering connection exist
|
||||||
vpc_pcx_apn1 = ec2_apn1.VpcPeeringConnection(vpc_pcx_usw1.id)
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
assert vpc_pcx_apn1.id == vpc_pcx_usw1.id
|
vpc_pcx_apn1 = ec2_apn1.VpcPeeringConnection(
|
||||||
|
vpc_pcx_usw1["VpcPeeringConnection"]["VpcPeeringConnectionId"]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
vpc_pcx_apn1.id
|
||||||
|
== vpc_pcx_usw1["VpcPeeringConnection"]["VpcPeeringConnectionId"]
|
||||||
|
)
|
||||||
assert vpc_pcx_apn1.requester_vpc.id == vpc_usw1.id
|
assert vpc_pcx_apn1.requester_vpc.id == vpc_usw1.id
|
||||||
assert vpc_pcx_apn1.accepter_vpc.id == vpc_apn1.id
|
assert vpc_pcx_apn1.accepter_vpc.id == vpc_apn1.id
|
||||||
|
|
||||||
# Quick check to verify the options have a default value
|
# Quick check to verify the options have a default value
|
||||||
accepter_options = vpc_pcx_apn1.accepter_vpc_info["PeeringOptions"]
|
accepter_options = vpc_pcx_apn1.accepter_vpc_info["PeeringOptions"]
|
||||||
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
|
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
|
||||||
@ -145,28 +209,50 @@ def test_vpc_peering_connections_cross_region():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_modify_vpc_peering_connections_accepter_only():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_modify_vpc_peering_connections_accepter_only(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
client = boto3.client("ec2", region_name="us-west-1")
|
client = boto3.client("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
#
|
|
||||||
|
# modify peering connection options
|
||||||
client.modify_vpc_peering_connection_options(
|
client.modify_vpc_peering_connection_options(
|
||||||
VpcPeeringConnectionId=vpc_pcx_usw1.id,
|
VpcPeeringConnectionId=vpc_pcx_usw1.id,
|
||||||
AccepterPeeringConnectionOptions={"AllowDnsResolutionFromRemoteVpc": True},
|
AccepterPeeringConnectionOptions={"AllowDnsResolutionFromRemoteVpc": True},
|
||||||
)
|
)
|
||||||
|
|
||||||
# Accepter options are different
|
# Accepter options are different
|
||||||
vpc_pcx_usw1.reload()
|
vpc_pcx_usw1.reload()
|
||||||
|
|
||||||
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
|
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
|
||||||
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is True
|
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is True
|
||||||
assert accepter_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
|
assert accepter_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
|
||||||
assert accepter_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is False
|
assert accepter_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is False
|
||||||
|
|
||||||
# Requester options are untouched
|
# Requester options are untouched
|
||||||
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
|
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
|
||||||
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
|
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
|
||||||
@ -175,16 +261,34 @@ def test_modify_vpc_peering_connections_accepter_only():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_modify_vpc_peering_connections_requester_only():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_modify_vpc_peering_connections_requester_only(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
client = boto3.client("ec2", region_name="us-west-1")
|
client = boto3.client("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
#
|
#
|
||||||
client.modify_vpc_peering_connection_options(
|
client.modify_vpc_peering_connection_options(
|
||||||
@ -195,10 +299,12 @@ def test_modify_vpc_peering_connections_requester_only():
|
|||||||
)
|
)
|
||||||
# Requester options are different
|
# Requester options are different
|
||||||
vpc_pcx_usw1.reload()
|
vpc_pcx_usw1.reload()
|
||||||
|
|
||||||
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
|
requester_options = vpc_pcx_usw1.requester_vpc_info["PeeringOptions"]
|
||||||
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
|
assert requester_options["AllowDnsResolutionFromRemoteVpc"] is False
|
||||||
assert requester_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
|
assert requester_options["AllowEgressFromLocalClassicLinkToRemoteVpc"] is False
|
||||||
assert requester_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is True
|
assert requester_options["AllowEgressFromLocalVpcToRemoteClassicLink"] is True
|
||||||
|
|
||||||
# Accepter options are untouched
|
# Accepter options are untouched
|
||||||
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
|
accepter_options = vpc_pcx_usw1.accepter_vpc_info["PeeringOptions"]
|
||||||
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
|
assert accepter_options["AllowDnsResolutionFromRemoteVpc"] is False
|
||||||
@ -207,21 +313,40 @@ def test_modify_vpc_peering_connections_requester_only():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_modify_vpc_peering_connections_unknown_vpc():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_modify_vpc_peering_connections_unknown_vpc(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
client = boto3.client("ec2", region_name="us-west-1")
|
client = boto3.client("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1.create_vpc_peering_connection(
|
ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
#
|
|
||||||
with pytest.raises(ClientError) as ex:
|
with pytest.raises(ClientError) as ex:
|
||||||
client.modify_vpc_peering_connection_options(
|
client.modify_vpc_peering_connection_options(
|
||||||
VpcPeeringConnectionId="vpx-unknown", RequesterPeeringConnectionOptions={}
|
VpcPeeringConnectionId="vpx-unknown",
|
||||||
|
RequesterPeeringConnectionOptions={},
|
||||||
)
|
)
|
||||||
err = ex.value.response["Error"]
|
err = ex.value.response["Error"]
|
||||||
assert err["Code"] == "InvalidVpcPeeringConnectionId.NotFound"
|
assert err["Code"] == "InvalidVpcPeeringConnectionId.NotFound"
|
||||||
@ -229,37 +354,78 @@ def test_modify_vpc_peering_connections_unknown_vpc():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region_fail():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_fail(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering wrong region with no vpc
|
# create peering wrong region with no vpc
|
||||||
with pytest.raises(ClientError) as cm:
|
with pytest.raises(ClientError) as cm:
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1.create_vpc_peering_connection(
|
ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-2"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-2",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
assert cm.value.response["Error"]["Code"] == "InvalidVpcID.NotFound"
|
assert cm.value.response["Error"]["Code"] == "InvalidVpcID.NotFound"
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_describe_vpc_peering_connections_only_returns_requested_id():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_describe_vpc_peering_connections_only_returns_requested_id(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
vpc_pcx_usw2 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw2 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# describe peering
|
# describe peering
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
our_vpcx = [vpcx["VpcPeeringConnectionId"] for vpcx in retrieve_all(ec2_usw1)]
|
our_vpcx = [vpcx["VpcPeeringConnectionId"] for vpcx in retrieve_all(ec2_usw1)]
|
||||||
|
|
||||||
assert vpc_pcx_usw1.id in our_vpcx
|
assert vpc_pcx_usw1.id in our_vpcx
|
||||||
assert vpc_pcx_usw2.id in our_vpcx
|
assert vpc_pcx_usw2.id in our_vpcx
|
||||||
assert vpc_apn1.id not in our_vpcx
|
assert vpc_apn1.id not in our_vpcx
|
||||||
@ -276,28 +442,51 @@ def test_describe_vpc_peering_connections_only_returns_requested_id():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region_accept():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_accept(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# accept peering from ap-northeast-1
|
# accept peering from ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
|
||||||
acp_pcx_apn1 = ec2_apn1.accept_vpc_peering_connection(
|
acp_pcx_apn1 = ec2_apn1.accept_vpc_peering_connection(
|
||||||
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
||||||
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
||||||
)
|
)
|
||||||
des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
|
des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
|
||||||
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
||||||
)
|
)
|
||||||
|
|
||||||
assert acp_pcx_apn1["VpcPeeringConnection"]["Status"]["Code"] == "active"
|
assert acp_pcx_apn1["VpcPeeringConnection"]["Status"]["Code"] == "active"
|
||||||
assert (
|
assert (
|
||||||
acp_pcx_apn1["VpcPeeringConnection"]["AccepterVpcInfo"]["Region"]
|
acp_pcx_apn1["VpcPeeringConnection"]["AccepterVpcInfo"]["Region"]
|
||||||
@ -328,22 +517,44 @@ def test_vpc_peering_connections_cross_region_accept():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region_reject():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_reject(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# reject peering from ap-northeast-1
|
# reject peering from ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
|
||||||
rej_pcx_apn1 = ec2_apn1.reject_vpc_peering_connection(
|
rej_pcx_apn1 = ec2_apn1.reject_vpc_peering_connection(
|
||||||
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
||||||
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
||||||
)
|
)
|
||||||
@ -356,75 +567,182 @@ def test_vpc_peering_connections_cross_region_reject():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region_delete():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_delete(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
# reject peering from ap-northeast-1
|
# reject peering from ap-northeast-1
|
||||||
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
|
||||||
del_pcx_apn1 = ec2_apn1.delete_vpc_peering_connection(
|
del_pcx_apn1 = ec2_apn1.delete_vpc_peering_connection(
|
||||||
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
des_pcx_apn1 = ec2_usw1.describe_vpc_peering_connections(
|
||||||
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
||||||
)
|
)
|
||||||
des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
|
des_pcx_usw1 = ec2_usw1.describe_vpc_peering_connections(
|
||||||
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
VpcPeeringConnectionIds=[vpc_pcx_usw1.id]
|
||||||
)
|
)
|
||||||
|
|
||||||
assert del_pcx_apn1["Return"] is True
|
assert del_pcx_apn1["Return"] is True
|
||||||
assert des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
|
assert des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
|
||||||
|
assert (
|
||||||
|
des_pcx_apn1["VpcPeeringConnections"][0]["Status"]["Message"]
|
||||||
|
== f"Deleted by {account2}"
|
||||||
|
)
|
||||||
|
|
||||||
assert des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
|
assert des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Code"] == "deleted"
|
||||||
|
assert (
|
||||||
|
des_pcx_usw1["VpcPeeringConnections"][0]["Status"]["Message"]
|
||||||
|
== f"Deleted by {account2}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_vpc_peering_connections_cross_region_accept_wrong_region():
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_accept_wrong_region(account1, account2):
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
# create peering
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# accept wrong peering from us-west-1 which will raise error
|
# accept wrong peering from us-west-1 which will raise error
|
||||||
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
# only applicable for cross-region intra-account peering.
|
||||||
|
if account1 == account2:
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
with pytest.raises(ClientError) as cm:
|
with pytest.raises(ClientError) as cm:
|
||||||
ec2_usw1.accept_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id)
|
ec2_usw1.accept_vpc_peering_connection(
|
||||||
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
|
)
|
||||||
|
|
||||||
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
||||||
exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted in region ap-northeast-1"
|
exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted in region ap-northeast-1"
|
||||||
assert cm.value.response["Error"]["Message"] == exp_msg
|
assert cm.value.response["Error"]["Message"] == exp_msg
|
||||||
|
|
||||||
|
# Ensure accepting peering from requester account raises
|
||||||
@mock_ec2
|
# only applicable for cross-region inter-account peering.
|
||||||
def test_vpc_peering_connections_cross_region_reject_wrong_region():
|
if account1 != account2:
|
||||||
# create vpc in us-west-1 and ap-northeast-1
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
|
||||||
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
|
||||||
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
|
||||||
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
|
||||||
# create peering
|
|
||||||
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
|
||||||
VpcId=vpc_usw1.id, PeerVpcId=vpc_apn1.id, PeerRegion="ap-northeast-1"
|
|
||||||
)
|
|
||||||
# reject wrong peering from us-west-1 which will raise error
|
|
||||||
ec2_apn1 = boto3.client("ec2", region_name="ap-northeast-1")
|
|
||||||
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
with pytest.raises(ClientError) as cm:
|
with pytest.raises(ClientError) as cm:
|
||||||
ec2_usw1.reject_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_usw1.id)
|
ec2_usw1.accept_vpc_peering_connection(
|
||||||
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
||||||
|
exp_msg = f"User ({account1}) cannot accept peering {vpc_pcx_usw1.id}"
|
||||||
|
assert cm.value.response["Error"]["Message"] == exp_msg
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"account1,account2",
|
||||||
|
[
|
||||||
|
pytest.param("111111111111", "111111111111", id="within account"),
|
||||||
|
pytest.param("111111111111", "222222222222", id="across accounts"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
settings.TEST_SERVER_MODE, reason="Cannot set account ID in server mode"
|
||||||
|
)
|
||||||
|
def test_vpc_peering_connections_cross_region_reject_wrong_region(account1, account2):
|
||||||
|
# create vpc in us-west-1 and ap-northeast-1
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.resource("ec2", region_name="us-west-1")
|
||||||
|
vpc_usw1 = ec2_usw1.create_vpc(CidrBlock="10.90.0.0/16")
|
||||||
|
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account2}):
|
||||||
|
ec2_apn1 = boto3.resource("ec2", region_name="ap-northeast-1")
|
||||||
|
vpc_apn1 = ec2_apn1.create_vpc(CidrBlock="10.20.0.0/16")
|
||||||
|
|
||||||
|
# create peering
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
vpc_pcx_usw1 = ec2_usw1.create_vpc_peering_connection(
|
||||||
|
VpcId=vpc_usw1.id,
|
||||||
|
PeerVpcId=vpc_apn1.id,
|
||||||
|
PeerRegion="ap-northeast-1",
|
||||||
|
PeerOwnerId=account2,
|
||||||
|
)
|
||||||
|
|
||||||
|
# reject wrong peering from us-west-1 which will raise error.
|
||||||
|
# only applicable for cross-region intra-account peering.
|
||||||
|
if account1 == account2:
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
|
with pytest.raises(ClientError) as cm:
|
||||||
|
ec2_usw1.reject_vpc_peering_connection(
|
||||||
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
|
)
|
||||||
|
|
||||||
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
||||||
exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted or rejected in region ap-northeast-1"
|
exp_msg = f"Incorrect region (us-west-1) specified for this request. VPC peering connection {vpc_pcx_usw1.id} must be accepted or rejected in region ap-northeast-1"
|
||||||
assert cm.value.response["Error"]["Message"] == exp_msg
|
assert cm.value.response["Error"]["Message"] == exp_msg
|
||||||
|
|
||||||
|
# Ensure rejecting peering from requester account raises
|
||||||
|
# only applicable for cross-region inter-account peering.
|
||||||
|
if account1 != account2:
|
||||||
|
with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": account1}):
|
||||||
|
ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
|
||||||
|
with pytest.raises(ClientError) as cm:
|
||||||
|
ec2_usw1.reject_vpc_peering_connection(
|
||||||
|
VpcPeeringConnectionId=vpc_pcx_usw1.id
|
||||||
|
)
|
||||||
|
|
||||||
|
assert cm.value.response["Error"]["Code"] == "OperationNotPermitted"
|
||||||
|
exp_msg = f"User ({account1}) cannot reject peering {vpc_pcx_usw1.id}"
|
||||||
|
assert cm.value.response["Error"]["Message"] == exp_msg
|
||||||
|
|
||||||
|
|
||||||
def retrieve_all(client):
|
def retrieve_all(client):
|
||||||
resp = client.describe_vpc_peering_connections()
|
resp = client.describe_vpc_peering_connections()
|
||||||
|
Loading…
Reference in New Issue
Block a user