diff --git a/moto/ec2/exceptions.py b/moto/ec2/exceptions.py index 022a19c67..f17bcbaa1 100644 --- a/moto/ec2/exceptions.py +++ b/moto/ec2/exceptions.py @@ -607,3 +607,11 @@ class InvalidAssociationIDIamProfileAssociationError(EC2ClientError): "InvalidAssociationID.NotFound", "An invalid association-id of '{0}' was given".format(association_id), ) + + +class InvalidVpcEndPointIdError(EC2ClientError): + def __init__(self, vpc_end_point_id): + super(InvalidVpcEndPointIdError, self).__init__( + "InvalidVpcEndPointId.NotFound", + "The VpcEndPoint ID '{0}' does not exist".format(vpc_end_point_id), + ) diff --git a/moto/ec2/models.py b/moto/ec2/models.py index e3e55cad7..633968d2d 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -108,6 +108,7 @@ from .exceptions import ( InvalidParameterDependency, IncorrectStateIamProfileAssociationError, InvalidAssociationIDIamProfileAssociationError, + InvalidVpcEndPointIdError, ) from .utils import ( EC2_RESOURCE_TO_PREFIX, @@ -3222,6 +3223,25 @@ class VPCBackend(object): return vpc_end_point + def get_vpc_end_point(self, vpc_end_point_ids, filters=None): + vpc_end_points = self.vpc_end_points.values() + + if vpc_end_point_ids: + vpc_end_points = [ + vpc_end_point + for vpc_end_point in vpc_end_points + if vpc_end_point.id in vpc_end_point_ids + ] + if len(vpc_end_points) != len(vpc_end_point_ids): + invalid_id = list( + set(vpc_end_point_ids).difference( + set([vpc_end_point.id for vpc_end_point in vpc_end_points]) + ) + )[0] + raise InvalidVpcEndPointIdError(invalid_id) + + return generic_filter(filters, vpc_end_points) + def get_vpc_end_point_services(self): vpc_end_point_services = self.vpc_end_points.values() diff --git a/moto/ec2/responses/vpcs.py b/moto/ec2/responses/vpcs.py index de4bb3feb..c5ccca63b 100644 --- a/moto/ec2/responses/vpcs.py +++ b/moto/ec2/responses/vpcs.py @@ -198,9 +198,18 @@ class VPCs(BaseResponse): def describe_vpc_endpoint_services(self): vpc_end_point_services = self.ec2_backend.get_vpc_end_point_services() - template = self.response_template(DESCRIBE_VPC_ENDPOINT_RESPONSE) + template = self.response_template(DESCRIBE_VPC_ENDPOINT_SERVICES_RESPONSE) return template.render(vpc_end_points=vpc_end_point_services) + def describe_vpc_endpoints(self): + vpc_end_points_ids = self._get_multi_param("VpcEndpointId") + filters = filters_from_querystring(self.querystring) + vpc_end_points = self.ec2_backend.get_vpc_end_point( + vpc_end_point_ids=vpc_end_points_ids, filters=filters + ) + template = self.response_template(DESCRIBE_VPC_ENDPOINT_RESPONSE) + return template.render(vpc_end_points=vpc_end_points) + CREATE_VPC_RESPONSE = """ @@ -460,7 +469,7 @@ CREATE_VPC_END_POINT = """ +DESCRIBE_VPC_ENDPOINT_SERVICES_RESPONSE = """ 19a9ff46-7df6-49b8-9726-3df27527089d {% for serviceName in vpc_end_points.services %} @@ -491,3 +500,69 @@ DESCRIBE_VPC_ENDPOINT_RESPONSE = """ + 19a9ff46-7df6-49b8-9726-3df27527089d + + {% for vpc_end_point in vpc_end_points %} + + {% if vpc_end_point.policy_document %} + {{ vpc_end_point.policy_document }} + {% endif %} + available + {{ vpc_end_point.private_dns_enabled }} + {{ vpc_end_point.service_name }} + {{ vpc_end_point.vpc_id }} + {{ vpc_end_point.id }} + {{ vpc_end_point.type }} + {% if vpc_end_point.subnet_ids %} + + {% for subnet_id in vpc_end_point.subnet_ids %} + {{ subnet_id }} + {% endfor %} + + {% endif %} + {% if vpc_end_point.route_table_ids %} + + {% for route_table_id in vpc_end_point.route_table_ids %} + {{ route_table_id }} + {% endfor %} + + {% endif %} + {% if vpc_end_point.network_interface_ids %} + + {% for network_interface_id in vpc_end_point.network_interface_ids %} + {{ network_interface_id }} + {% endfor %} + + {% endif %} + {% if vpc_end_point.dns_entries %} + + {% for dns_entry in vpc_end_point.dns_entries %} + {{ dns_entry }} + {% endfor %} + + {% endif %} + {% if vpc_end_point.groups %} + + {% for group in vpc_end_point.groups %} + {{ group }} + {% endfor %} + + {% endif %} + {% if vpc_end_point.tag_specifications %} + + {% for tag in vpc_end_point.tag_specifications %} + + {{ tag.key }} + {{ tag.value }} + + {% endfor %} + + {% endif %} + 123456789012 + {{ vpc_end_point.created_at }} + + {% endfor %} + +""" diff --git a/tests/test_ec2/test_vpcs.py b/tests/test_ec2/test_vpcs.py index 5344098ba..fe9278ec2 100644 --- a/tests/test_ec2/test_vpcs.py +++ b/tests/test_ec2/test_vpcs.py @@ -8,7 +8,8 @@ from botocore.exceptions import ClientError import boto3 import boto from boto.exception import EC2ResponseError -import sure # noqa + +# import sure # noqa from moto import mock_ec2, mock_ec2_deprecated @@ -868,3 +869,50 @@ def test_describe_vpc_end_point_services(): "us-west-1a", "us-west-1b", ] + + +@mock_ec2 +def test_describe_vpc_end_points(): + ec2 = boto3.client("ec2", region_name="us-west-1") + vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") + + route_table = ec2.create_route_table(VpcId=vpc["Vpc"]["VpcId"]) + vpc_end_point = ec2.create_vpc_endpoint( + VpcId=vpc["Vpc"]["VpcId"], + ServiceName="com.amazonaws.us-east-1.s3", + RouteTableIds=[route_table["RouteTable"]["RouteTableId"]], + VpcEndpointType="gateway", + ) + + vpc_endpoints = ec2.describe_vpc_endpoints() + assert vpc_endpoints.get("VpcEndpoints")[0].get( + "VpcEndpointId" + ) == vpc_end_point.get("VpcEndpoint").get("VpcEndpointId") + assert vpc_endpoints.get("VpcEndpoints")[0].get("VpcId") == vpc["Vpc"]["VpcId"] + assert vpc_endpoints.get("VpcEndpoints")[0].get("RouteTableIds") == [ + route_table.get("RouteTable").get("RouteTableId") + ] + assert "VpcEndpointType" in vpc_endpoints.get("VpcEndpoints")[0] + assert "ServiceName" in vpc_endpoints.get("VpcEndpoints")[0] + assert "State" in vpc_endpoints.get("VpcEndpoints")[0] + + vpc_endpoints = ec2.describe_vpc_endpoints( + VpcEndpointIds=[vpc_end_point.get("VpcEndpoint").get("VpcEndpointId")] + ) + assert vpc_endpoints.get("VpcEndpoints")[0].get( + "VpcEndpointId" + ) == vpc_end_point.get("VpcEndpoint").get("VpcEndpointId") + assert vpc_endpoints.get("VpcEndpoints")[0].get("VpcId") == vpc["Vpc"]["VpcId"] + assert vpc_endpoints.get("VpcEndpoints")[0].get("RouteTableIds") == [ + route_table.get("RouteTable").get("RouteTableId") + ] + assert "VpcEndpointType" in vpc_endpoints.get("VpcEndpoints")[0] + assert "ServiceName" in vpc_endpoints.get("VpcEndpoints")[0] + assert "State" in vpc_endpoints.get("VpcEndpoints")[0] + + try: + ec2.describe_vpc_endpoints( + VpcEndpointIds=[route_table.get("RouteTable").get("RouteTableId")] + ) + except ClientError as err: + assert err.response["Error"]["Code"] == "InvalidVpcEndPointId.NotFound"