prompt: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Describe EC2 Vpc endpoints doesn't support vpc-endpoint-type filter.
  This happens on line 202
  ![image](https://user-images.githubusercontent.com/92550453/167168166-94b94167-5670-4d38-9577-ea2374cb674f.png)
  
  ![image](https://user-images.githubusercontent.com/92550453/167168009-be85eeea-44e0-4425-9ee0-f84798b4a1e7.png)
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### moto/ec2/models/vpcs.py
  import ipaddress
  import json
  import weakref
  from collections import defaultdict
  from operator import itemgetter
  
  from moto.core import get_account_id
  from moto.core.models import CloudFormationModel
  from .core import TaggedEC2Resource
  from ..exceptions import (
      CidrLimitExceeded,
      UnsupportedTenancy,
      DependencyViolationError,
      InvalidCIDRBlockParameterError,
      InvalidServiceName,
      InvalidFilter,
      InvalidNextToken,
      InvalidParameterValueError,
      InvalidVpcCidrBlockAssociationIdError,
      InvalidVPCIdError,
      InvalidVPCRangeError,
      OperationNotPermitted,
      InvalidVpcEndPointIdError,
  )
  from .availability_zones_and_regions import RegionsAndZonesBackend
  from ..utils import (
      random_ipv6_cidr,
      random_vpc_ep_id,
      random_private_ip,
      create_dns_entries,
      random_vpc_id,
      random_vpc_cidr_association_id,
      generic_filter,
      utc_date_and_time,
  )
  
  MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000
  DEFAULT_VPC_ENDPOINT_SERVICES = []
  
  
  class VPCEndPoint(TaggedEC2Resource, CloudFormationModel):
      def __init__(
          self,
          ec2_backend,
          endpoint_id,
          vpc_id,
          service_name,
          endpoint_type=None,
          policy_document=False,
          route_table_ids=None,
          subnet_ids=None,
          network_interface_ids=None,
          dns_entries=None,
          client_token=None,
          security_group_ids=None,
          tags=None,
          private_dns_enabled=None,
          destination_prefix_list_id=None,
      ):
          self.ec2_backend = ec2_backend
          self.id = endpoint_id
          self.vpc_id = vpc_id
          self.service_name = service_name
          self.endpoint_type = endpoint_type
          self.state = "available"
          self.policy_document = policy_document
          self.route_table_ids = route_table_ids
          self.network_interface_ids = network_interface_ids or []
          self.subnet_ids = subnet_ids
          self.client_token = client_token
          self.security_group_ids = security_group_ids
          self.private_dns_enabled = private_dns_enabled
          self.dns_entries = dns_entries
          self.add_tags(tags or {})
          self.destination_prefix_list_id = destination_prefix_list_id
  
          self.created_at = utc_date_and_time()
  
      @property
      def owner_id(self):
          return get_account_id()
  
      @property
      def physical_resource_id(self):
          return self.id
  
      @staticmethod
      def cloudformation_name_type():
          return None
  
      @staticmethod
      def cloudformation_type():
          return "AWS::EC2::VPCEndpoint"
  
      @classmethod
      def create_from_cloudformation_json(
          cls, resource_name, cloudformation_json, region_name, **kwargs
      ):
          from ..models import ec2_backends
  
          properties = cloudformation_json["Properties"]
  
          service_name = properties.get("ServiceName")
          subnet_ids = properties.get("SubnetIds")
          vpc_endpoint_type = properties.get("VpcEndpointType")
          vpc_id = properties.get("VpcId")
          policy_document = properties.get("PolicyDocument")
          private_dns_enabled = properties.get("PrivateDnsEnabled")
          route_table_ids = properties.get("RouteTableIds")
          security_group_ids = properties.get("SecurityGroupIds")
  
          ec2_backend = ec2_backends[region_name]
          vpc_endpoint = ec2_backend.create_vpc_endpoint(
              vpc_id=vpc_id,
              service_name=service_name,
              endpoint_type=vpc_endpoint_type,
              subnet_ids=subnet_ids,
              policy_document=policy_document,
              private_dns_enabled=private_dns_enabled,
              route_table_ids=route_table_ids,
              security_group_ids=security_group_ids,
          )
          return vpc_endpoint
  
  
  class VPC(TaggedEC2Resource, CloudFormationModel):
      def __init__(
          self,
          ec2_backend,
          vpc_id,
          cidr_block,
          is_default,
          instance_tenancy="default",
          amazon_provided_ipv6_cidr_block=False,
      ):
  
          self.ec2_backend = ec2_backend
          self.id = vpc_id
          self.cidr_block = cidr_block
          self.cidr_block_association_set = {}
          self.dhcp_options = None
          self.state = "available"
          self.instance_tenancy = instance_tenancy
          self.is_default = "true" if is_default else "false"
          self.enable_dns_support = "true"
          self.classic_link_enabled = "false"
          self.classic_link_dns_supported = "false"
          # This attribute is set to 'true' only for default VPCs
          # or VPCs created using the wizard of the VPC console
          self.enable_dns_hostnames = "true" if is_default else "false"
  
          self.associate_vpc_cidr_block(cidr_block)
          if amazon_provided_ipv6_cidr_block:
              self.associate_vpc_cidr_block(
                  cidr_block,
                  amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,
              )
  
      @property
      def owner_id(self):
          return get_account_id()
  
      @staticmethod
      def cloudformation_name_type():
          return None
  
      @staticmethod
      def cloudformation_type():
          # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
          return "AWS::EC2::VPC"
  
      @classmethod
      def create_from_cloudformation_json(
          cls, resource_name, cloudformation_json, region_name, **kwargs
      ):
          from ..models import ec2_backends
  
          properties = cloudformation_json["Properties"]
  
          ec2_backend = ec2_backends[region_name]
          vpc = ec2_backend.create_vpc(
              cidr_block=properties["CidrBlock"],
              instance_tenancy=properties.get("InstanceTenancy", "default"),
          )
          for tag in properties.get("Tags", []):
              tag_key = tag["Key"]
              tag_value = tag["Value"]
              vpc.add_tag(tag_key, tag_value)
  
          return vpc
  
      @property
      def physical_resource_id(self):
          return self.id
  
      def get_filter_value(self, filter_name):
          if filter_name in ("vpc-id", "vpcId"):
              return self.id
          elif filter_name in ("cidr", "cidr-block", "cidrBlock"):
              return self.cidr_block
          elif filter_name in (
              "cidr-block-association.cidr-block",
              "ipv6-cidr-block-association.ipv6-cidr-block",
          ):
              return [
                  c["cidr_block"]
                  for c in self.get_cidr_block_association_set(ipv6="ipv6" in filter_name)
              ]
          elif filter_name in (
              "cidr-block-association.association-id",
              "ipv6-cidr-block-association.association-id",
          ):
              return self.cidr_block_association_set.keys()
          elif filter_name in (
              "cidr-block-association.state",
              "ipv6-cidr-block-association.state",
          ):
              return [
                  c["cidr_block_state"]["state"]
                  for c in self.get_cidr_block_association_set(ipv6="ipv6" in filter_name)
              ]
          elif filter_name in ("instance_tenancy", "InstanceTenancy"):
              return self.instance_tenancy
          elif filter_name in ("is-default", "isDefault"):
              return self.is_default
          elif filter_name == "state":
              return self.state
          elif filter_name in ("dhcp-options-id", "dhcpOptionsId"):
              if not self.dhcp_options:
                  return None
              return self.dhcp_options.id
          else:
              return super().get_filter_value(filter_name, "DescribeVpcs")
  
      def modify_vpc_tenancy(self, tenancy):
          if tenancy != "default":
              raise UnsupportedTenancy(tenancy)
          self.instance_tenancy = tenancy
          return True
  
      def associate_vpc_cidr_block(
          self, cidr_block, amazon_provided_ipv6_cidr_block=False
      ):
          max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1
  
          for cidr in self.cidr_block_association_set.copy():
              if (
                  self.cidr_block_association_set.get(cidr)
                  .get("cidr_block_state")
                  .get("state")
                  == "disassociated"
              ):
                  self.cidr_block_association_set.pop(cidr)
          if (
              len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))
              >= max_associations
          ):
              raise CidrLimitExceeded(self.id, max_associations)
  
          association_id = random_vpc_cidr_association_id()
  
          association_set = {
              "association_id": association_id,
              "cidr_block_state": {"state": "associated", "StatusMessage": ""},
          }
  
          association_set["cidr_block"] = (
              random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block
          )
          self.cidr_block_association_set[association_id] = association_set
          return association_set
  
      def enable_vpc_classic_link(self):
          # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.
          # Doesn't check any route tables, maybe something for in the future?
          # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations
          network_address = ipaddress.ip_network(self.cidr_block).network_address
          if (
              network_address not in ipaddress.ip_network("10.0.0.0/8")
              or network_address in ipaddress.ip_network("10.0.0.0/16")
              or network_address in ipaddress.ip_network("10.1.0.0/16")
          ):
              self.classic_link_enabled = "true"
  
          return self.classic_link_enabled
  
      def disable_vpc_classic_link(self):
          self.classic_link_enabled = "false"
          return self.classic_link_enabled
  
      def enable_vpc_classic_link_dns_support(self):
          self.classic_link_dns_supported = "true"
          return self.classic_link_dns_supported
  
      def disable_vpc_classic_link_dns_support(self):
          self.classic_link_dns_supported = "false"
          return self.classic_link_dns_supported
  
      def disassociate_vpc_cidr_block(self, association_id):
          if self.cidr_block == self.cidr_block_association_set.get(
              association_id, {}
          ).get("cidr_block"):
              raise OperationNotPermitted(association_id)
  
          entry = response = self.cidr_block_association_set.get(association_id, {})
          if entry:
              response = json.loads(json.dumps(entry))
              response["vpc_id"] = self.id
              response["cidr_block_state"]["state"] = "disassociating"
              entry["cidr_block_state"]["state"] = "disassociated"
          return response
  
      def get_cidr_block_association_set(self, ipv6=False):
          return [
              c
              for c in self.cidr_block_association_set.values()
              if ("::/" if ipv6 else ".") in c.get("cidr_block")
          ]
  
  
  class VPCBackend(object):
      vpc_refs = defaultdict(set)
  
      def __init__(self):
          self.vpcs = {}
          self.vpc_end_points = {}
          self.vpc_refs[self.__class__].add(weakref.ref(self))
          super().__init__()
  
      def create_vpc(
          self,
          cidr_block,
          instance_tenancy="default",
          amazon_provided_ipv6_cidr_block=False,
          tags=None,
      ):
          vpc_id = random_vpc_id()
          try:
              vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
          except ValueError:
              raise InvalidCIDRBlockParameterError(cidr_block)
          if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:
              raise InvalidVPCRangeError(cidr_block)
          vpc = VPC(
              self,
              vpc_id,
              cidr_block,
              len(self.vpcs) == 0,
              instance_tenancy,
              amazon_provided_ipv6_cidr_block,
          )
  
          for tag in tags or []:
              tag_key = tag.get("Key")
              tag_value = tag.get("Value")
              vpc.add_tag(tag_key, tag_value)
  
          self.vpcs[vpc_id] = vpc
  
          # AWS creates a default main route table and security group.
          self.create_route_table(vpc_id, main=True)
  
          # AWS creates a default Network ACL
          self.create_network_acl(vpc_id, default=True)
  
          default = self.get_security_group_from_name("default", vpc_id=vpc_id)
          if not default:
              self.create_security_group(
                  "default", "default VPC security group", vpc_id=vpc_id, is_default=True
              )
  
          return vpc
  
      def get_vpc(self, vpc_id):
          if vpc_id not in self.vpcs:
              raise InvalidVPCIdError(vpc_id)
          return self.vpcs.get(vpc_id)
  
      def describe_vpcs(self, vpc_ids=None, filters=None):
          matches = self.vpcs.copy().values()
          if vpc_ids:
              matches = [vpc for vpc in matches if vpc.id in vpc_ids]
              if len(vpc_ids) > len(matches):
                  unknown_ids = set(vpc_ids) - set(matches)
                  raise InvalidVPCIdError(unknown_ids)
          if filters:
              matches = generic_filter(filters, matches)
          return matches
  
      def delete_vpc(self, vpc_id):
          # Do not delete if any VPN Gateway is attached
          vpn_gateways = self.describe_vpn_gateways(filters={"attachment.vpc-id": vpc_id})
          vpn_gateways = [
              item
              for item in vpn_gateways
              if item.attachments.get(vpc_id).state == "attached"
          ]
          if vpn_gateways:
              raise DependencyViolationError(
                  "The vpc {0} has dependencies and cannot be deleted.".format(vpc_id)
              )
  
          # Delete route table if only main route table remains.
          route_tables = self.describe_route_tables(filters={"vpc-id": vpc_id})
          if len(route_tables) > 1:
              raise DependencyViolationError(
                  "The vpc {0} has dependencies and cannot be deleted.".format(vpc_id)
              )
          for route_table in route_tables:
              self.delete_route_table(route_table.id)
  
          # Delete default security group if exists.
          default = self.get_security_group_by_name_or_id("default", vpc_id=vpc_id)
          if default:
              self.delete_security_group(group_id=default.id)
  
          # Now delete VPC.
          vpc = self.vpcs.pop(vpc_id, None)
          if not vpc:
              raise InvalidVPCIdError(vpc_id)
  
          if vpc.dhcp_options:
              vpc.dhcp_options.vpc = None
              self.delete_dhcp_options_set(vpc.dhcp_options.id)
              vpc.dhcp_options = None
          return vpc
  
      def describe_vpc_attribute(self, vpc_id, attr_name):
          vpc = self.get_vpc(vpc_id)
          if attr_name in ("enable_dns_support", "enable_dns_hostnames"):
              return getattr(vpc, attr_name)
          else:
              raise InvalidParameterValueError(attr_name)
  
      def modify_vpc_tenancy(self, vpc_id, tenancy):
          vpc = self.get_vpc(vpc_id)
          return vpc.modify_vpc_tenancy(tenancy)
  
      def enable_vpc_classic_link(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.enable_vpc_classic_link()
  
      def disable_vpc_classic_link(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.disable_vpc_classic_link()
  
      def enable_vpc_classic_link_dns_support(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.enable_vpc_classic_link_dns_support()
  
      def disable_vpc_classic_link_dns_support(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.disable_vpc_classic_link_dns_support()
  
      def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):
          vpc = self.get_vpc(vpc_id)
          if attr_name in ("enable_dns_support", "enable_dns_hostnames"):
              setattr(vpc, attr_name, attr_value)
          else:
              raise InvalidParameterValueError(attr_name)
  
      def disassociate_vpc_cidr_block(self, association_id):
          for vpc in self.vpcs.copy().values():
              response = vpc.disassociate_vpc_cidr_block(association_id)
              for route_table in self.route_tables.copy().values():
                  if route_table.vpc_id == response.get("vpc_id"):
                      if "::/" in response.get("cidr_block"):
                          self.delete_route(
                              route_table.id, None, response.get("cidr_block")
                          )
                      else:
                          self.delete_route(route_table.id, response.get("cidr_block"))
              if response:
                  return response
          raise InvalidVpcCidrBlockAssociationIdError(association_id)
  
      def associate_vpc_cidr_block(
          self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block
      ):
          vpc = self.get_vpc(vpc_id)
          association_set = vpc.associate_vpc_cidr_block(
              cidr_block, amazon_provided_ipv6_cidr_block
          )
          for route_table in self.route_tables.copy().values():
              if route_table.vpc_id == vpc_id:
                  if amazon_provided_ipv6_cidr_block:
                      self.create_route(
                          route_table.id,
                          None,
                          destination_ipv6_cidr_block=association_set["cidr_block"],
                          local=True,
                      )
                  else:
                      self.create_route(
                          route_table.id, association_set["cidr_block"], local=True
                      )
          return association_set
  
      def create_vpc_endpoint(
          self,
          vpc_id,
          service_name,
          endpoint_type=None,
          policy_document=False,
          route_table_ids=None,
          subnet_ids=None,
          network_interface_ids=None,
          dns_entries=None,
          client_token=None,
          security_group_ids=None,
          tags=None,
          private_dns_enabled=None,
      ):
  
          vpc_endpoint_id = random_vpc_ep_id()
  
          # validates if vpc is present or not.
          self.get_vpc(vpc_id)
          destination_prefix_list_id = None
  
          if endpoint_type and endpoint_type.lower() == "interface":
  
              network_interface_ids = []
              for subnet_id in subnet_ids or []:
                  self.get_subnet(subnet_id)
                  eni = self.create_network_interface(subnet_id, random_private_ip())
                  network_interface_ids.append(eni.id)
  
              dns_entries = create_dns_entries(service_name, vpc_endpoint_id)
  
          else:
              # considering gateway if type is not mentioned.
              for prefix_list in self.managed_prefix_lists.values():
                  if prefix_list.prefix_list_name == service_name:
                      destination_prefix_list_id = prefix_list.id
  
          if dns_entries:
              dns_entries = [dns_entries]
  
          vpc_end_point = VPCEndPoint(
              self,
              vpc_endpoint_id,
              vpc_id,
              service_name,
              endpoint_type,
              policy_document,
              route_table_ids,
              subnet_ids,
              network_interface_ids,
              dns_entries,
              client_token,
              security_group_ids,
              tags,
              private_dns_enabled,
              destination_prefix_list_id,
          )
  
          self.vpc_end_points[vpc_endpoint_id] = vpc_end_point
  
          if destination_prefix_list_id:
              for route_table_id in route_table_ids:
                  self.create_route(
                      route_table_id,
                      None,
                      gateway_id=vpc_endpoint_id,
                      destination_prefix_list_id=destination_prefix_list_id,
                  )
  
          return vpc_end_point
  
      def delete_vpc_endpoints(self, vpce_ids=None):
          for vpce_id in vpce_ids or []:
              vpc_endpoint = self.vpc_end_points.get(vpce_id, None)
              if vpc_endpoint:
                  if vpc_endpoint.endpoint_type.lower() == "interface":
                      for eni_id in vpc_endpoint.network_interface_ids:
                          self.enis.pop(eni_id, None)
                  else:
                      for route_table_id in vpc_endpoint.route_table_ids:
                          self.delete_route(
                              route_table_id, vpc_endpoint.destination_prefix_list_id
                          )
                  vpc_endpoint.state = "deleted"
          return True
  
      def describe_vpc_endpoints(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)
  
      @staticmethod
      def _collect_default_endpoint_services(region):
          """Return list of default services using list of backends."""
          if DEFAULT_VPC_ENDPOINT_SERVICES:
              return DEFAULT_VPC_ENDPOINT_SERVICES
  
          zones = [
              zone.name
              for zones in RegionsAndZonesBackend.zones.values()
              for zone in zones
              if zone.name.startswith(region)
          ]
  
          from moto import backends  # pylint: disable=import-outside-toplevel
  
          for _backends in backends.unique_backends():
              if region in _backends:
                  service = _backends[region].default_vpc_endpoint_service(region, zones)
                  if service:
                      DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
  
              if "global" in _backends:
                  service = _backends["global"].default_vpc_endpoint_service(
                      region, zones
                  )
                  if service:
                      DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
          return DEFAULT_VPC_ENDPOINT_SERVICES
  
      @staticmethod
      def _matches_service_by_tags(service, filter_item):
          """Return True if service tags are not filtered by their tags.
  
          Note that the API specifies a key of "Values" for a filter, but
          the botocore library returns "Value" instead.
          """
          # For convenience, collect the tags for this service.
          service_tag_keys = {x["Key"] for x in service["Tags"]}
          if not service_tag_keys:
              return False
  
          matched = True  # assume the best
          if filter_item["Name"] == "tag-key":
              # Filters=[{"Name":"tag-key", "Values":["Name"]}],
              # Any tag with this name, regardless of the tag value.
              if not service_tag_keys & set(filter_item["Value"]):
                  matched = False
  
          elif filter_item["Name"].startswith("tag:"):
              # Filters=[{"Name":"tag:Name", "Values":["my-load-balancer"]}],
              tag_name = filter_item["Name"].split(":")[1]
              if not service_tag_keys & {tag_name}:
                  matched = False
              else:
                  for tag in service["Tags"]:
                      if tag["Key"] == tag_name and tag["Value"] in filter_item["Value"]:
                          break
                  else:
                      matched = False
          return matched
  
      @staticmethod
      def _filter_endpoint_services(service_names_filters, filters, services):
          """Return filtered list of VPC endpoint services."""
          if not service_names_filters and not filters:
              return services
  
          # Verify the filters are valid.
          for filter_item in filters:
              if filter_item["Name"] not in [
                  "service-name",
                  "service-type",
                  "tag-key",
              ] and not filter_item["Name"].startswith("tag:"):
                  raise InvalidFilter(filter_item["Name"])
  
          # Apply both the service_names filter and the filters themselves.
          filtered_services = []
          for service in services:
              if (
                  service_names_filters
                  and service["ServiceName"] not in service_names_filters
              ):
                  continue
  
              # Note that the API specifies a key of "Values" for a filter, but
              # the botocore library returns "Value" instead.
              matched = True
              for filter_item in filters:
                  if filter_item["Name"] == "service-name":
                      if service["ServiceName"] not in filter_item["Value"]:
                          matched = False
  
                  elif filter_item["Name"] == "service-type":
                      service_types = {x["ServiceType"] for x in service["ServiceType"]}
                      if not service_types & set(filter_item["Value"]):
                          matched = False
  
                  elif filter_item["Name"] == "tag-key" or filter_item["Name"].startswith(
                      "tag:"
                  ):
                      if not VPCBackend._matches_service_by_tags(service, filter_item):
                          matched = False
  
                  # Exit early -- don't bother checking the remaining filters
                  # as a non-match was found.
                  if not matched:
                      break
  
              # Does the service have a matching service name or does it match
              # a filter?
              if matched:
                  filtered_services.append(service)
  
          return filtered_services
  
      def describe_vpc_endpoint_services(
          self, dry_run, service_names, filters, max_results, next_token, region
      ):  # pylint: disable=unused-argument,too-many-arguments
          """Return info on services to which you can create a VPC endpoint.
  
          Currently only the default endpoing services are returned.  When
          create_vpc_endpoint_service_configuration() is implemented, a
          list of those private endpoints would be kept and when this API
          is invoked, those private endpoints would be added to the list of
          default endpoint services.
  
          The DryRun parameter is ignored.
          """
          default_services = self._collect_default_endpoint_services(region)
          for service_name in service_names:
              if service_name not in [x["ServiceName"] for x in default_services]:
                  raise InvalidServiceName(service_name)
  
          # Apply filters specified in the service_names and filters arguments.
          filtered_services = sorted(
              self._filter_endpoint_services(service_names, filters, default_services),
              key=itemgetter("ServiceName"),
          )
  
          # Determine the start index into list of services based on the
          # next_token argument.
          start = 0
          vpce_ids = [x["ServiceId"] for x in filtered_services]
          if next_token:
              if next_token not in vpce_ids:
                  raise InvalidNextToken(next_token)
              start = vpce_ids.index(next_token)
  
          # Determine the stop index into the list of services based on the
          # max_results argument.
          if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:
              max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS
  
          # If necessary, set the value of the next_token.
          next_token = ""
          if len(filtered_services) > (start + max_results):
              service = filtered_services[start + max_results]
              next_token = service["ServiceId"]
  
          return {
              "servicesDetails": filtered_services[start : start + max_results],
              "serviceNames": [
                  x["ServiceName"] for x in filtered_services[start : start + max_results]
              ],
              "nextToken": next_token,
          }
  
      def get_vpc_end_point(self, vpc_end_point_id):
          vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)
          if not vpc_end_point:
              raise InvalidVpcEndPointIdError(vpc_end_point_id)
          return vpc_end_point
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
instance: {"FAIL_TO_PASS": ["tests/test_ec2/test_vpcs.py::test_describe_vpc_gateway_end_points"], "PASS_TO_PASS": ["tests/test_ec2/test_vpcs.py::test_create_vpc_with_invalid_cidr_block_parameter", "tests/test_ec2/test_vpcs.py::test_vpc_dedicated_tenancy", "tests/test_ec2/test_vpcs.py::test_vpc_state_available_filter", "tests/test_ec2/test_vpcs.py::test_disable_vpc_classic_link", "tests/test_ec2/test_vpcs.py::test_vpc_modify_enable_dns_hostnames", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_cidr_block", "tests/test_ec2/test_vpcs.py::test_vpc_modify_enable_dns_support", "tests/test_ec2/test_vpcs.py::test_disassociate_vpc_ipv4_cidr_block", "tests/test_ec2/test_vpcs.py::test_associate_vpc_ipv4_cidr_block", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_tag_key_subset", "tests/test_ec2/test_vpcs.py::test_describe_prefix_lists", "tests/test_ec2/test_vpcs.py::test_describe_vpc_interface_end_points", "tests/test_ec2/test_vpcs.py::test_enable_vpc_classic_link_dns_support", "tests/test_ec2/test_vpcs.py::test_ipv6_cidr_block_association_filters", "tests/test_ec2/test_vpcs.py::test_vpc_modify_tenancy_unknown", "tests/test_ec2/test_vpcs.py::test_enable_vpc_classic_link_failure", "tests/test_ec2/test_vpcs.py::test_create_vpc_with_invalid_cidr_range", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_id", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_disabled", "tests/test_ec2/test_vpcs.py::test_non_default_vpc", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_tag_value_subset", "tests/test_ec2/test_vpcs.py::test_vpc_defaults", "tests/test_ec2/test_vpcs.py::test_vpc_tagging", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_multiple", "tests/test_ec2/test_vpcs.py::test_describe_vpcs_dryrun", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_tag", "tests/test_ec2/test_vpcs.py::test_enable_vpc_classic_link", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_dns_support_multiple", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_dns_support_enabled", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_tag_key_superset", "tests/test_ec2/test_vpcs.py::test_multiple_vpcs_default_filter", "tests/test_ec2/test_vpcs.py::test_create_and_delete_vpc", "tests/test_ec2/test_vpcs.py::test_delete_vpc_end_points", "tests/test_ec2/test_vpcs.py::test_cidr_block_association_filters", "tests/test_ec2/test_vpcs.py::test_vpc_isdefault_filter", "tests/test_ec2/test_vpcs.py::test_vpc_associate_ipv6_cidr_block", "tests/test_ec2/test_vpcs.py::test_vpc_disassociate_ipv6_cidr_block", "tests/test_ec2/test_vpcs.py::test_default_vpc", "tests/test_ec2/test_vpcs.py::test_vpc_associate_dhcp_options", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_tag_value_superset", "tests/test_ec2/test_vpcs.py::test_disable_vpc_classic_link_dns_support", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_dns_support_disabled", "tests/test_ec2/test_vpcs.py::test_create_vpc_with_tags", "tests/test_ec2/test_vpcs.py::test_vpc_get_by_dhcp_options_id", "tests/test_ec2/test_vpcs.py::test_describe_classic_link_enabled"], "base_commit": "e911341e6ad1bfe7f3930f38c36b26b25cdb0f94", "created_at": "2022-05-08 20:29:13", "hints_text": "Thanks for raising this @kunalvudathu - marking it as an enhancement to add this filter.", "instance_id": "getmoto__moto-5110", "patch": "diff --git a/moto/ec2/models/vpcs.py b/moto/ec2/models/vpcs.py\n--- a/moto/ec2/models/vpcs.py\n+++ b/moto/ec2/models/vpcs.py\n@@ -76,6 +76,12 @@ def __init__(\n \n         self.created_at = utc_date_and_time()\n \n+    def get_filter_value(self, filter_name):\n+        if filter_name in (\"vpc-endpoint-type\", \"vpc_endpoint_type\"):\n+            return self.endpoint_type\n+        else:\n+            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n+\n     @property\n     def owner_id(self):\n         return ACCOUNT_ID\n", "problem_statement": "Describe EC2 Vpc endpoints doesn't support vpc-endpoint-type filter.\nThis happens on line 202\r\n![image](https://user-images.githubusercontent.com/92550453/167168166-94b94167-5670-4d38-9577-ea2374cb674f.png)\r\n\r\n![image](https://user-images.githubusercontent.com/92550453/167168009-be85eeea-44e0-4425-9ee0-f84798b4a1e7.png)\r\n\n", "repo": "getmoto/moto", "test_patch": "diff --git a/tests/test_ec2/test_vpcs.py b/tests/test_ec2/test_vpcs.py\n--- a/tests/test_ec2/test_vpcs.py\n+++ b/tests/test_ec2/test_vpcs.py\n@@ -947,7 +947,7 @@ def test_describe_vpc_gateway_end_points():\n         VpcId=vpc[\"VpcId\"],\n         ServiceName=\"com.amazonaws.us-east-1.s3\",\n         RouteTableIds=[route_table[\"RouteTableId\"]],\n-        VpcEndpointType=\"gateway\",\n+        VpcEndpointType=\"Gateway\",\n     )[\"VpcEndpoint\"]\n     our_id = vpc_end_point[\"VpcEndpointId\"]\n \n@@ -960,7 +960,7 @@ def test_describe_vpc_gateway_end_points():\n     our_endpoint[\"VpcId\"].should.equal(vpc[\"VpcId\"])\n     our_endpoint[\"RouteTableIds\"].should.equal([route_table[\"RouteTableId\"]])\n \n-    our_endpoint.should.have.key(\"VpcEndpointType\").equal(\"gateway\")\n+    our_endpoint.should.have.key(\"VpcEndpointType\").equal(\"Gateway\")\n     our_endpoint.should.have.key(\"ServiceName\").equal(\"com.amazonaws.us-east-1.s3\")\n     our_endpoint.should.have.key(\"State\").equal(\"available\")\n \n@@ -970,10 +970,15 @@ def test_describe_vpc_gateway_end_points():\n     endpoint_by_id[\"VpcEndpointId\"].should.equal(our_id)\n     endpoint_by_id[\"VpcId\"].should.equal(vpc[\"VpcId\"])\n     endpoint_by_id[\"RouteTableIds\"].should.equal([route_table[\"RouteTableId\"]])\n-    endpoint_by_id[\"VpcEndpointType\"].should.equal(\"gateway\")\n+    endpoint_by_id[\"VpcEndpointType\"].should.equal(\"Gateway\")\n     endpoint_by_id[\"ServiceName\"].should.equal(\"com.amazonaws.us-east-1.s3\")\n     endpoint_by_id[\"State\"].should.equal(\"available\")\n \n+    gateway_endpoints = ec2.describe_vpc_endpoints(\n+        Filters=[{\"Name\": \"vpc-endpoint-type\", \"Values\": [\"Gateway\"]}]\n+    )[\"VpcEndpoints\"]\n+    [e[\"VpcEndpointId\"] for e in gateway_endpoints].should.contain(our_id)\n+\n     with pytest.raises(ClientError) as ex:\n         ec2.describe_vpc_endpoints(VpcEndpointIds=[route_table[\"RouteTableId\"]])\n     err = ex.value.response[\"Error\"]\n", "version": "3.1"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"import ipaddress\nimport json\nimport weakref\nfrom collections import defaultdict\nfrom operator import itemgetter\n\nfrom moto.core import get_account_id\nfrom moto.core.models import CloudFormationModel\nfrom .core import TaggedEC2Resource\nfrom ..exceptions import (\n    CidrLimitExceeded,\n    UnsupportedTenancy,\n    DependencyViolationError,\n    InvalidCIDRBlockParameterError,\n    InvalidServiceName,\n    InvalidFilter,\n    InvalidNextToken,\n    InvalidParameterValueError,\n    InvalidVpcCidrBlockAssociationIdError,\n    InvalidVPCIdError,\n    InvalidVPCRangeError,\n    OperationNotPermitted,\n    InvalidVpcEndPointIdError,\n)\nfrom .availability_zones_and_regions import RegionsAndZonesBackend\nfrom ..utils import (\n    random_ipv6_cidr,\n    random_vpc_ep_id,\n    random_private_ip,\n    create_dns_entries,\n    random_vpc_id,\n    random_vpc_cidr_association_id,\n    generic_filter,\n    utc_date_and_time,\n)\n\nMAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000\nDEFAULT_VPC_ENDPOINT_SERVICES = []\n\n\nclass VPCEndPoint(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        endpoint_id,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n        destination_prefix_list_id=None,\n    ):\n        self.ec2_backend = ec2_backend\n        self.id = endpoint_id\n        self.vpc_id = vpc_id\n        self.service_name = service_name\n        self.endpoint_type = endpoint_type\n        self.state = \"available\"\n        self.policy_document = policy_document\n        self.route_table_ids = route_table_ids\n        self.network_interface_ids = network_interface_ids or []\n        self.subnet_ids = subnet_ids\n        self.client_token = client_token\n        self.security_group_ids = security_group_ids\n        self.private_dns_enabled = private_dns_enabled\n        self.dns_entries = dns_entries\n        self.add_tags(tags or {})\n        self.destination_prefix_list_id = destination_prefix_list_id\n\n        self.created_at = utc_date_and_time()\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        return \"AWS::EC2::VPCEndpoint\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        service_name = properties.get(\"ServiceName\")\n        subnet_ids = properties.get(\"SubnetIds\")\n        vpc_endpoint_type = properties.get(\"VpcEndpointType\")\n        vpc_id = properties.get(\"VpcId\")\n        policy_document = properties.get(\"PolicyDocument\")\n        private_dns_enabled = properties.get(\"PrivateDnsEnabled\")\n        route_table_ids = properties.get(\"RouteTableIds\")\n        security_group_ids = properties.get(\"SecurityGroupIds\")\n\n        ec2_backend = ec2_backends[region_name]\n        vpc_endpoint = ec2_backend.create_vpc_endpoint(\n            vpc_id=vpc_id,\n            service_name=service_name,\n            endpoint_type=vpc_endpoint_type,\n            subnet_ids=subnet_ids,\n            policy_document=policy_document,\n            private_dns_enabled=private_dns_enabled,\n            route_table_ids=route_table_ids,\n            security_group_ids=security_group_ids,\n        )\n        return vpc_endpoint\n\n\nclass VPC(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        vpc_id,\n        cidr_block,\n        is_default,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n    ):\n\n        self.ec2_backend = ec2_backend\n        self.id = vpc_id\n        self.cidr_block = cidr_block\n        self.cidr_block_association_set = {}\n        self.dhcp_options = None\n        self.state = \"available\"\n        self.instance_tenancy = instance_tenancy\n        self.is_default = \"true\" if is_default else \"false\"\n        self.enable_dns_support = \"true\"\n        self.classic_link_enabled = \"false\"\n        self.classic_link_dns_supported = \"false\"\n        # This attribute is set to 'true' only for default VPCs\n        # or VPCs created using the wizard of the VPC console\n        self.enable_dns_hostnames = \"true\" if is_default else \"false\"\n\n        self.associate_vpc_cidr_block(cidr_block)\n        if amazon_provided_ipv6_cidr_block:\n            self.associate_vpc_cidr_block(\n                cidr_block,\n                amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,\n            )\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html\n        return \"AWS::EC2::VPC\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        ec2_backend = ec2_backends[region_name]\n        vpc = ec2_backend.create_vpc(\n            cidr_block=properties[\"CidrBlock\"],\n            instance_tenancy=properties.get(\"InstanceTenancy\", \"default\"),\n        )\n        for tag in properties.get(\"Tags\", []):\n            tag_key = tag[\"Key\"]\n            tag_value = tag[\"Value\"]\n            vpc.add_tag(tag_key, tag_value)\n\n        return vpc\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    def get_filter_value(self, filter_name):\n        if filter_name in (\"vpc-id\", \"vpcId\"):\n            return self.id\n        elif filter_name in (\"cidr\", \"cidr-block\", \"cidrBlock\"):\n            return self.cidr_block\n        elif filter_name in (\n            \"cidr-block-association.cidr-block\",\n            \"ipv6-cidr-block-association.ipv6-cidr-block\",\n        ):\n            return [\n                c[\"cidr_block\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\n            \"cidr-block-association.association-id\",\n            \"ipv6-cidr-block-association.association-id\",\n        ):\n            return self.cidr_block_association_set.keys()\n        elif filter_name in (\n            \"cidr-block-association.state\",\n            \"ipv6-cidr-block-association.state\",\n        ):\n            return [\n                c[\"cidr_block_state\"][\"state\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\"instance_tenancy\", \"InstanceTenancy\"):\n            return self.instance_tenancy\n        elif filter_name in (\"is-default\", \"isDefault\"):\n            return self.is_default\n        elif filter_name == \"state\":\n            return self.state\n        elif filter_name in (\"dhcp-options-id\", \"dhcpOptionsId\"):\n            if not self.dhcp_options:\n                return None\n            return self.dhcp_options.id\n        else:\n            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n\n    def modify_vpc_tenancy(self, tenancy):\n        if tenancy != \"default\":\n            raise UnsupportedTenancy(tenancy)\n        self.instance_tenancy = tenancy\n        return True\n\n    def associate_vpc_cidr_block(\n        self, cidr_block, amazon_provided_ipv6_cidr_block=False\n    ):\n        max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1\n\n        for cidr in self.cidr_block_association_set.copy():\n            if (\n                self.cidr_block_association_set.get(cidr)\n                .get(\"cidr_block_state\")\n                .get(\"state\")\n                == \"disassociated\"\n            ):\n                self.cidr_block_association_set.pop(cidr)\n        if (\n            len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))\n            >= max_associations\n        ):\n            raise CidrLimitExceeded(self.id, max_associations)\n\n        association_id = random_vpc_cidr_association_id()\n\n        association_set = {\n            \"association_id\": association_id,\n            \"cidr_block_state\": {\"state\": \"associated\", \"StatusMessage\": \"\"},\n        }\n\n        association_set[\"cidr_block\"] = (\n            random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block\n        )\n        self.cidr_block_association_set[association_id] = association_set\n        return association_set\n\n    def enable_vpc_classic_link(self):\n        # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.\n        # Doesn't check any route tables, maybe something for in the future?\n        # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations\n        network_address = ipaddress.ip_network(self.cidr_block).network_address\n        if (\n            network_address not in ipaddress.ip_network(\"10.0.0.0/8\")\n            or network_address in ipaddress.ip_network(\"10.0.0.0/16\")\n            or network_address in ipaddress.ip_network(\"10.1.0.0/16\")\n        ):\n            self.classic_link_enabled = \"true\"\n\n        return self.classic_link_enabled\n\n    def disable_vpc_classic_link(self):\n        self.classic_link_enabled = \"false\"\n        return self.classic_link_enabled\n\n    def enable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"true\"\n        return self.classic_link_dns_supported\n\n    def disable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"false\"\n        return self.classic_link_dns_supported\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        if self.cidr_block == self.cidr_block_association_set.get(\n            association_id, {}\n        ).get(\"cidr_block\"):\n            raise OperationNotPermitted(association_id)\n\n        entry = response = self.cidr_block_association_set.get(association_id, {})\n        if entry:\n            response = json.loads(json.dumps(entry))\n            response[\"vpc_id\"] = self.id\n            response[\"cidr_block_state\"][\"state\"] = \"disassociating\"\n            entry[\"cidr_block_state\"][\"state\"] = \"disassociated\"\n        return response\n\n    def get_cidr_block_association_set(self, ipv6=False):\n        return [\n            c\n            for c in self.cidr_block_association_set.values()\n            if (\"::/\" if ipv6 else \".\") in c.get(\"cidr_block\")\n        ]\n\n\nclass VPCBackend(object):\n    vpc_refs = defaultdict(set)\n\n    def __init__(self):\n        self.vpcs = {}\n        self.vpc_end_points = {}\n        self.vpc_refs[self.__class__].add(weakref.ref(self))\n        super().__init__()\n\n    def create_vpc(\n        self,\n        cidr_block,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n        tags=None,\n    ):\n        vpc_id = random_vpc_id()\n        try:\n            vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)\n        except ValueError:\n            raise InvalidCIDRBlockParameterError(cidr_block)\n        if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:\n            raise InvalidVPCRangeError(cidr_block)\n        vpc = VPC(\n            self,\n            vpc_id,\n            cidr_block,\n            len(self.vpcs) == 0,\n            instance_tenancy,\n            amazon_provided_ipv6_cidr_block,\n        )\n\n        for tag in tags or []:\n            tag_key = tag.get(\"Key\")\n            tag_value = tag.get(\"Value\")\n            vpc.add_tag(tag_key, tag_value)\n\n        self.vpcs[vpc_id] = vpc\n\n        # AWS creates a default main route table and security group.\n        self.create_route_table(vpc_id, main=True)\n\n        # AWS creates a default Network ACL\n        self.create_network_acl(vpc_id, default=True)\n\n        default = self.get_security_group_from_name(\"default\", vpc_id=vpc_id)\n        if not default:\n            self.create_security_group(\n                \"default\", \"default VPC security group\", vpc_id=vpc_id, is_default=True\n            )\n\n        return vpc\n\n    def get_vpc(self, vpc_id):\n        if vpc_id not in self.vpcs:\n            raise InvalidVPCIdError(vpc_id)\n        return self.vpcs.get(vpc_id)\n\n    def describe_vpcs(self, vpc_ids=None, filters=None):\n        matches = self.vpcs.copy().values()\n        if vpc_ids:\n            matches = [vpc for vpc in matches if vpc.id in vpc_ids]\n            if len(vpc_ids) > len(matches):\n                unknown_ids = set(vpc_ids) - set(matches)\n                raise InvalidVPCIdError(unknown_ids)\n        if filters:\n            matches = generic_filter(filters, matches)\n        return matches\n\n    def delete_vpc(self, vpc_id):\n        # Do not delete if any VPN Gateway is attached\n        vpn_gateways = self.describe_vpn_gateways(filters={\"attachment.vpc-id\": vpc_id})\n        vpn_gateways = [\n            item\n            for item in vpn_gateways\n            if item.attachments.get(vpc_id).state == \"attached\"\n        ]\n        if vpn_gateways:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n\n        # Delete route table if only main route table remains.\n        route_tables = self.describe_route_tables(filters={\"vpc-id\": vpc_id})\n        if len(route_tables) > 1:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n        for route_table in route_tables:\n            self.delete_route_table(route_table.id)\n\n        # Delete default security group if exists.\n        default = self.get_security_group_by_name_or_id(\"default\", vpc_id=vpc_id)\n        if default:\n            self.delete_security_group(group_id=default.id)\n\n        # Now delete VPC.\n        vpc = self.vpcs.pop(vpc_id, None)\n        if not vpc:\n            raise InvalidVPCIdError(vpc_id)\n\n        if vpc.dhcp_options:\n            vpc.dhcp_options.vpc = None\n            self.delete_dhcp_options_set(vpc.dhcp_options.id)\n            vpc.dhcp_options = None\n        return vpc\n\n    def describe_vpc_attribute(self, vpc_id, attr_name):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            return getattr(vpc, attr_name)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def modify_vpc_tenancy(self, vpc_id, tenancy):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.modify_vpc_tenancy(tenancy)\n\n    def enable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link()\n\n    def disable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link()\n\n    def enable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link_dns_support()\n\n    def disable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link_dns_support()\n\n    def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            setattr(vpc, attr_name, attr_value)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        for vpc in self.vpcs.copy().values():\n            response = vpc.disassociate_vpc_cidr_block(association_id)\n            for route_table in self.route_tables.copy().values():\n                if route_table.vpc_id == response.get(\"vpc_id\"):\n                    if \"::/\" in response.get(\"cidr_block\"):\n                        self.delete_route(\n                            route_table.id, None, response.get(\"cidr_block\")\n                        )\n                    else:\n                        self.delete_route(route_table.id, response.get(\"cidr_block\"))\n            if response:\n                return response\n        raise InvalidVpcCidrBlockAssociationIdError(association_id)\n\n    def associate_vpc_cidr_block(\n        self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block\n    ):\n        vpc = self.get_vpc(vpc_id)\n        association_set = vpc.associate_vpc_cidr_block(\n            cidr_block, amazon_provided_ipv6_cidr_block\n        )\n        for route_table in self.route_tables.copy().values():\n            if route_table.vpc_id == vpc_id:\n                if amazon_provided_ipv6_cidr_block:\n                    self.create_route(\n                        route_table.id,\n                        None,\n                        destination_ipv6_cidr_block=association_set[\"cidr_block\"],\n                        local=True,\n                    )\n                else:\n                    self.create_route(\n                        route_table.id, association_set[\"cidr_block\"], local=True\n                    )\n        return association_set\n\n    def create_vpc_endpoint(\n        self,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n    ):\n\n        vpc_endpoint_id = random_vpc_ep_id()\n\n        # validates if vpc is present or not.\n        self.get_vpc(vpc_id)\n        destination_prefix_list_id = None\n\n        if endpoint_type and endpoint_type.lower() == \"interface\":\n\n            network_interface_ids = []\n            for subnet_id in subnet_ids or []:\n                self.get_subnet(subnet_id)\n                eni = self.create_network_interface(subnet_id, random_private_ip())\n                network_interface_ids.append(eni.id)\n\n            dns_entries = create_dns_entries(service_name, vpc_endpoint_id)\n\n        else:\n            # considering gateway if type is not mentioned.\n            for prefix_list in self.managed_prefix_lists.values():\n                if prefix_list.prefix_list_name == service_name:\n                    destination_prefix_list_id = prefix_list.id\n\n        if dns_entries:\n            dns_entries = [dns_entries]\n\n        vpc_end_point = VPCEndPoint(\n            self,\n            vpc_endpoint_id,\n            vpc_id,\n            service_name,\n            endpoint_type,\n            policy_document,\n            route_table_ids,\n            subnet_ids,\n            network_interface_ids,\n            dns_entries,\n            client_token,\n            security_group_ids,\n            tags,\n            private_dns_enabled,\n            destination_prefix_list_id,\n        )\n\n        self.vpc_end_points[vpc_endpoint_id] = vpc_end_point\n\n        if destination_prefix_list_id:\n            for route_table_id in route_table_ids:\n                self.create_route(\n                    route_table_id,\n                    None,\n                    gateway_id=vpc_endpoint_id,\n                    destination_prefix_list_id=destination_prefix_list_id,\n                )\n\n        return vpc_end_point\n\n    def delete_vpc_endpoints(self, vpce_ids=None):\n        for vpce_id in vpce_ids or []:\n            vpc_endpoint = self.vpc_end_points.get(vpce_id, None)\n            if vpc_endpoint:\n                if vpc_endpoint.endpoint_type.lower() == \"interface\":\n                    for eni_id in vpc_endpoint.network_interface_ids:\n                        self.enis.pop(eni_id, None)\n                else:\n                    for route_table_id in vpc_endpoint.route_table_ids:\n                        self.delete_route(\n                            route_table_id, vpc_endpoint.destination_prefix_list_id\n                        )\n                vpc_endpoint.state = \"deleted\"\n        return True\n\n    def describe_vpc_endpoints(self, vpc_end_point_ids, filters=None):\n        vpc_end_points = self.vpc_end_points.values()\n\n        if vpc_end_point_ids:\n            vpc_end_points = [\n                vpc_end_point\n                for vpc_end_point in vpc_end_points\n                if vpc_end_point.id in vpc_end_point_ids\n            ]\n            if len(vpc_end_points) != len(vpc_end_point_ids):\n                invalid_id = list(\n                    set(vpc_end_point_ids).difference(\n                        set([vpc_end_point.id for vpc_end_point in vpc_end_points])\n                    )\n                )[0]\n                raise InvalidVpcEndPointIdError(invalid_id)\n\n        return generic_filter(filters, vpc_end_points)\n\n    @staticmethod\n    def _collect_default_endpoint_services(region):\n        \"\"\"Return list of default services using list of backends.\"\"\"\n        if DEFAULT_VPC_ENDPOINT_SERVICES:\n            return DEFAULT_VPC_ENDPOINT_SERVICES\n\n        zones = [\n            zone.name\n            for zones in RegionsAndZonesBackend.zones.values()\n            for zone in zones\n            if zone.name.startswith(region)\n        ]\n\n        from moto import backends  # pylint: disable=import-outside-toplevel\n\n        for _backends in backends.unique_backends():\n            if region in _backends:\n                service = _backends[region].default_vpc_endpoint_service(region, zones)\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n\n            if \"global\" in _backends:\n                service = _backends[\"global\"].default_vpc_endpoint_service(\n                    region, zones\n                )\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n        return DEFAULT_VPC_ENDPOINT_SERVICES\n\n    @staticmethod\n    def _matches_service_by_tags(service, filter_item):\n        \"\"\"Return True if service tags are not filtered by their tags.\n\n        Note that the API specifies a key of \"Values\" for a filter, but\n        the botocore library returns \"Value\" instead.\n        \"\"\"\n        # For convenience, collect the tags for this service.\n        service_tag_keys = {x[\"Key\"] for x in service[\"Tags\"]}\n        if not service_tag_keys:\n            return False\n\n        matched = True  # assume the best\n        if filter_item[\"Name\"] == \"tag-key\":\n            # Filters=[{\"Name\":\"tag-key\", \"Values\":[\"Name\"]}],\n            # Any tag with this name, regardless of the tag value.\n            if not service_tag_keys & set(filter_item[\"Value\"]):\n                matched = False\n\n        elif filter_item[\"Name\"].startswith(\"tag:\"):\n            # Filters=[{\"Name\":\"tag:Name\", \"Values\":[\"my-load-balancer\"]}],\n            tag_name = filter_item[\"Name\"].split(\":\")[1]\n            if not service_tag_keys & {tag_name}:\n                matched = False\n            else:\n                for tag in service[\"Tags\"]:\n                    if tag[\"Key\"] == tag_name and tag[\"Value\"] in filter_item[\"Value\"]:\n                        break\n                else:\n                    matched = False\n        return matched\n\n    @staticmethod\n    def _filter_endpoint_services(service_names_filters, filters, services):\n        \"\"\"Return filtered list of VPC endpoint services.\"\"\"\n        if not service_names_filters and not filters:\n            return services\n\n        # Verify the filters are valid.\n        for filter_item in filters:\n            if filter_item[\"Name\"] not in [\n                \"service-name\",\n                \"service-type\",\n                \"tag-key\",\n            ] and not filter_item[\"Name\"].startswith(\"tag:\"):\n                raise InvalidFilter(filter_item[\"Name\"])\n\n        # Apply both the service_names filter and the filters themselves.\n        filtered_services = []\n        for service in services:\n            if (\n                service_names_filters\n                and service[\"ServiceName\"] not in service_names_filters\n            ):\n                continue\n\n            # Note that the API specifies a key of \"Values\" for a filter, but\n            # the botocore library returns \"Value\" instead.\n            matched = True\n            for filter_item in filters:\n                if filter_item[\"Name\"] == \"service-name\":\n                    if service[\"ServiceName\"] not in filter_item[\"Value\"]:\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"service-type\":\n                    service_types = {x[\"ServiceType\"] for x in service[\"ServiceType\"]}\n                    if not service_types & set(filter_item[\"Value\"]):\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"tag-key\" or filter_item[\"Name\"].startswith(\n                    \"tag:\"\n                ):\n                    if not VPCBackend._matches_service_by_tags(service, filter_item):\n                        matched = False\n\n                # Exit early -- don't bother checking the remaining filters\n                # as a non-match was found.\n                if not matched:\n                    break\n\n            # Does the service have a matching service name or does it match\n            # a filter?\n            if matched:\n                filtered_services.append(service)\n\n        return filtered_services\n\n    def describe_vpc_endpoint_services(\n        self, dry_run, service_names, filters, max_results, next_token, region\n    ):  # pylint: disable=unused-argument,too-many-arguments\n        \"\"\"Return info on services to which you can create a VPC endpoint.\n\n        Currently only the default endpoing services are returned.  When\n        create_vpc_endpoint_service_configuration() is implemented, a\n        list of those private endpoints would be kept and when this API\n        is invoked, those private endpoints would be added to the list of\n        default endpoint services.\n\n        The DryRun parameter is ignored.\n        \"\"\"\n        default_services = self._collect_default_endpoint_services(region)\n        for service_name in service_names:\n            if service_name not in [x[\"ServiceName\"] for x in default_services]:\n                raise InvalidServiceName(service_name)\n\n        # Apply filters specified in the service_names and filters arguments.\n        filtered_services = sorted(\n            self._filter_endpoint_services(service_names, filters, default_services),\n            key=itemgetter(\"ServiceName\"),\n        )\n\n        # Determine the start index into list of services based on the\n        # next_token argument.\n        start = 0\n        vpce_ids = [x[\"ServiceId\"] for x in filtered_services]\n        if next_token:\n            if next_token not in vpce_ids:\n                raise InvalidNextToken(next_token)\n            start = vpce_ids.index(next_token)\n\n        # Determine the stop index into the list of services based on the\n        # max_results argument.\n        if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:\n            max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS\n\n        # If necessary, set the value of the next_token.\n        next_token = \"\"\n        if len(filtered_services) > (start + max_results):\n            service = filtered_services[start + max_results]\n            next_token = service[\"ServiceId\"]\n\n        return {\n            \"servicesDetails\": filtered_services[start : start + max_results],\n            \"serviceNames\": [\n                x[\"ServiceName\"] for x in filtered_services[start : start + max_results]\n            ],\n            \"nextToken\": next_token,\n        }\n\n    def get_vpc_end_point(self, vpc_end_point_id):\n        vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)\n        if not vpc_end_point:\n            raise InvalidVpcEndPointIdError(vpc_end_point_id)\n        return vpc_end_point\n","new_file_content":"import ipaddress\nimport json\nimport weakref\nfrom collections import defaultdict\nfrom operator import itemgetter\n\nfrom moto.core import ACCOUNT_ID\nfrom moto.core.models import CloudFormationModel\nfrom .core import TaggedEC2Resource\nfrom ..exceptions import (\n    CidrLimitExceeded,\n    UnsupportedTenancy,\n    DependencyViolationError,\n    InvalidCIDRBlockParameterError,\n    InvalidServiceName,\n    InvalidFilter,\n    InvalidNextToken,\n    InvalidParameterValueError,\n    InvalidVpcCidrBlockAssociationIdError,\n    InvalidVPCIdError,\n    InvalidVPCRangeError,\n    OperationNotPermitted,\n    InvalidVpcEndPointIdError,\n)\nfrom .availability_zones_and_regions import RegionsAndZonesBackend\nfrom ..utils import (\n    random_ipv6_cidr,\n    random_vpc_ep_id,\n    random_private_ip,\n    create_dns_entries,\n    random_vpc_id,\n    random_vpc_cidr_association_id,\n    generic_filter,\n    utc_date_and_time,\n)\n\nMAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000\nDEFAULT_VPC_ENDPOINT_SERVICES = []\n\n\nclass VPCEndPoint(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        endpoint_id,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n        destination_prefix_list_id=None,\n    ):\n        self.ec2_backend = ec2_backend\n        self.id = endpoint_id\n        self.vpc_id = vpc_id\n        self.service_name = service_name\n        self.endpoint_type = endpoint_type\n        self.state = \"available\"\n        self.policy_document = policy_document\n        self.route_table_ids = route_table_ids\n        self.network_interface_ids = network_interface_ids or []\n        self.subnet_ids = subnet_ids\n        self.client_token = client_token\n        self.security_group_ids = security_group_ids\n        self.private_dns_enabled = private_dns_enabled\n        self.dns_entries = dns_entries\n        self.add_tags(tags or {})\n        self.destination_prefix_list_id = destination_prefix_list_id\n\n        self.created_at = utc_date_and_time()\n\n    def get_filter_value(self, filter_name):\n        if filter_name in (\"vpc-endpoint-type\", \"vpc_endpoint_type\"):\n            return self.endpoint_type\n        else:\n            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n\n    @property\n    def owner_id(self):\n        return ACCOUNT_ID\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        return \"AWS::EC2::VPCEndpoint\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        service_name = properties.get(\"ServiceName\")\n        subnet_ids = properties.get(\"SubnetIds\")\n        vpc_endpoint_type = properties.get(\"VpcEndpointType\")\n        vpc_id = properties.get(\"VpcId\")\n        policy_document = properties.get(\"PolicyDocument\")\n        private_dns_enabled = properties.get(\"PrivateDnsEnabled\")\n        route_table_ids = properties.get(\"RouteTableIds\")\n        security_group_ids = properties.get(\"SecurityGroupIds\")\n\n        ec2_backend = ec2_backends[region_name]\n        vpc_endpoint = ec2_backend.create_vpc_endpoint(\n            vpc_id=vpc_id,\n            service_name=service_name,\n            endpoint_type=vpc_endpoint_type,\n            subnet_ids=subnet_ids,\n            policy_document=policy_document,\n            private_dns_enabled=private_dns_enabled,\n            route_table_ids=route_table_ids,\n            security_group_ids=security_group_ids,\n        )\n        return vpc_endpoint\n\n\nclass VPC(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        vpc_id,\n        cidr_block,\n        is_default,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n    ):\n\n        self.ec2_backend = ec2_backend\n        self.id = vpc_id\n        self.cidr_block = cidr_block\n        self.cidr_block_association_set = {}\n        self.dhcp_options = None\n        self.state = \"available\"\n        self.instance_tenancy = instance_tenancy\n        self.is_default = \"true\" if is_default else \"false\"\n        self.enable_dns_support = \"true\"\n        self.classic_link_enabled = \"false\"\n        self.classic_link_dns_supported = \"false\"\n        # This attribute is set to 'true' only for default VPCs\n        # or VPCs created using the wizard of the VPC console\n        self.enable_dns_hostnames = \"true\" if is_default else \"false\"\n\n        self.associate_vpc_cidr_block(cidr_block)\n        if amazon_provided_ipv6_cidr_block:\n            self.associate_vpc_cidr_block(\n                cidr_block,\n                amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,\n            )\n\n    @property\n    def owner_id(self):\n        return ACCOUNT_ID\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html\n        return \"AWS::EC2::VPC\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        ec2_backend = ec2_backends[region_name]\n        vpc = ec2_backend.create_vpc(\n            cidr_block=properties[\"CidrBlock\"],\n            instance_tenancy=properties.get(\"InstanceTenancy\", \"default\"),\n        )\n        for tag in properties.get(\"Tags\", []):\n            tag_key = tag[\"Key\"]\n            tag_value = tag[\"Value\"]\n            vpc.add_tag(tag_key, tag_value)\n\n        return vpc\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    def get_filter_value(self, filter_name):\n        if filter_name in (\"vpc-id\", \"vpcId\"):\n            return self.id\n        elif filter_name in (\"cidr\", \"cidr-block\", \"cidrBlock\"):\n            return self.cidr_block\n        elif filter_name in (\n            \"cidr-block-association.cidr-block\",\n            \"ipv6-cidr-block-association.ipv6-cidr-block\",\n        ):\n            return [\n                c[\"cidr_block\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\n            \"cidr-block-association.association-id\",\n            \"ipv6-cidr-block-association.association-id\",\n        ):\n            return self.cidr_block_association_set.keys()\n        elif filter_name in (\n            \"cidr-block-association.state\",\n            \"ipv6-cidr-block-association.state\",\n        ):\n            return [\n                c[\"cidr_block_state\"][\"state\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\"instance_tenancy\", \"InstanceTenancy\"):\n            return self.instance_tenancy\n        elif filter_name in (\"is-default\", \"isDefault\"):\n            return self.is_default\n        elif filter_name == \"state\":\n            return self.state\n        elif filter_name in (\"dhcp-options-id\", \"dhcpOptionsId\"):\n            if not self.dhcp_options:\n                return None\n            return self.dhcp_options.id\n        else:\n            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n\n    def modify_vpc_tenancy(self, tenancy):\n        if tenancy != \"default\":\n            raise UnsupportedTenancy(tenancy)\n        self.instance_tenancy = tenancy\n        return True\n\n    def associate_vpc_cidr_block(\n        self, cidr_block, amazon_provided_ipv6_cidr_block=False\n    ):\n        max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1\n\n        for cidr in self.cidr_block_association_set.copy():\n            if (\n                self.cidr_block_association_set.get(cidr)\n                .get(\"cidr_block_state\")\n                .get(\"state\")\n                == \"disassociated\"\n            ):\n                self.cidr_block_association_set.pop(cidr)\n        if (\n            len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))\n            >= max_associations\n        ):\n            raise CidrLimitExceeded(self.id, max_associations)\n\n        association_id = random_vpc_cidr_association_id()\n\n        association_set = {\n            \"association_id\": association_id,\n            \"cidr_block_state\": {\"state\": \"associated\", \"StatusMessage\": \"\"},\n        }\n\n        association_set[\"cidr_block\"] = (\n            random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block\n        )\n        self.cidr_block_association_set[association_id] = association_set\n        return association_set\n\n    def enable_vpc_classic_link(self):\n        # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.\n        # Doesn't check any route tables, maybe something for in the future?\n        # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations\n        network_address = ipaddress.ip_network(self.cidr_block).network_address\n        if (\n            network_address not in ipaddress.ip_network(\"10.0.0.0/8\")\n            or network_address in ipaddress.ip_network(\"10.0.0.0/16\")\n            or network_address in ipaddress.ip_network(\"10.1.0.0/16\")\n        ):\n            self.classic_link_enabled = \"true\"\n\n        return self.classic_link_enabled\n\n    def disable_vpc_classic_link(self):\n        self.classic_link_enabled = \"false\"\n        return self.classic_link_enabled\n\n    def enable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"true\"\n        return self.classic_link_dns_supported\n\n    def disable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"false\"\n        return self.classic_link_dns_supported\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        if self.cidr_block == self.cidr_block_association_set.get(\n            association_id, {}\n        ).get(\"cidr_block\"):\n            raise OperationNotPermitted(association_id)\n\n        entry = response = self.cidr_block_association_set.get(association_id, {})\n        if entry:\n            response = json.loads(json.dumps(entry))\n            response[\"vpc_id\"] = self.id\n            response[\"cidr_block_state\"][\"state\"] = \"disassociating\"\n            entry[\"cidr_block_state\"][\"state\"] = \"disassociated\"\n        return response\n\n    def get_cidr_block_association_set(self, ipv6=False):\n        return [\n            c\n            for c in self.cidr_block_association_set.values()\n            if (\"::/\" if ipv6 else \".\") in c.get(\"cidr_block\")\n        ]\n\n\nclass VPCBackend(object):\n    vpc_refs = defaultdict(set)\n\n    def __init__(self):\n        self.vpcs = {}\n        self.vpc_end_points = {}\n        self.vpc_refs[self.__class__].add(weakref.ref(self))\n        super().__init__()\n\n    def create_vpc(\n        self,\n        cidr_block,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n        tags=None,\n    ):\n        vpc_id = random_vpc_id()\n        try:\n            vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)\n        except ValueError:\n            raise InvalidCIDRBlockParameterError(cidr_block)\n        if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:\n            raise InvalidVPCRangeError(cidr_block)\n        vpc = VPC(\n            self,\n            vpc_id,\n            cidr_block,\n            len(self.vpcs) == 0,\n            instance_tenancy,\n            amazon_provided_ipv6_cidr_block,\n        )\n\n        for tag in tags or []:\n            tag_key = tag.get(\"Key\")\n            tag_value = tag.get(\"Value\")\n            vpc.add_tag(tag_key, tag_value)\n\n        self.vpcs[vpc_id] = vpc\n\n        # AWS creates a default main route table and security group.\n        self.create_route_table(vpc_id, main=True)\n\n        # AWS creates a default Network ACL\n        self.create_network_acl(vpc_id, default=True)\n\n        default = self.get_security_group_from_name(\"default\", vpc_id=vpc_id)\n        if not default:\n            self.create_security_group(\n                \"default\", \"default VPC security group\", vpc_id=vpc_id, is_default=True\n            )\n\n        return vpc\n\n    def get_vpc(self, vpc_id):\n        if vpc_id not in self.vpcs:\n            raise InvalidVPCIdError(vpc_id)\n        return self.vpcs.get(vpc_id)\n\n    def describe_vpcs(self, vpc_ids=None, filters=None):\n        matches = self.vpcs.copy().values()\n        if vpc_ids:\n            matches = [vpc for vpc in matches if vpc.id in vpc_ids]\n            if len(vpc_ids) > len(matches):\n                unknown_ids = set(vpc_ids) - set(matches)\n                raise InvalidVPCIdError(unknown_ids)\n        if filters:\n            matches = generic_filter(filters, matches)\n        return matches\n\n    def delete_vpc(self, vpc_id):\n        # Do not delete if any VPN Gateway is attached\n        vpn_gateways = self.describe_vpn_gateways(filters={\"attachment.vpc-id\": vpc_id})\n        vpn_gateways = [\n            item\n            for item in vpn_gateways\n            if item.attachments.get(vpc_id).state == \"attached\"\n        ]\n        if vpn_gateways:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n\n        # Delete route table if only main route table remains.\n        route_tables = self.describe_route_tables(filters={\"vpc-id\": vpc_id})\n        if len(route_tables) > 1:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n        for route_table in route_tables:\n            self.delete_route_table(route_table.id)\n\n        # Delete default security group if exists.\n        default = self.get_security_group_by_name_or_id(\"default\", vpc_id=vpc_id)\n        if default:\n            self.delete_security_group(group_id=default.id)\n\n        # Now delete VPC.\n        vpc = self.vpcs.pop(vpc_id, None)\n        if not vpc:\n            raise InvalidVPCIdError(vpc_id)\n\n        if vpc.dhcp_options:\n            vpc.dhcp_options.vpc = None\n            self.delete_dhcp_options_set(vpc.dhcp_options.id)\n            vpc.dhcp_options = None\n        return vpc\n\n    def describe_vpc_attribute(self, vpc_id, attr_name):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            return getattr(vpc, attr_name)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def modify_vpc_tenancy(self, vpc_id, tenancy):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.modify_vpc_tenancy(tenancy)\n\n    def enable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link()\n\n    def disable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link()\n\n    def enable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link_dns_support()\n\n    def disable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link_dns_support()\n\n    def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            setattr(vpc, attr_name, attr_value)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        for vpc in self.vpcs.copy().values():\n            response = vpc.disassociate_vpc_cidr_block(association_id)\n            for route_table in self.route_tables.copy().values():\n                if route_table.vpc_id == response.get(\"vpc_id\"):\n                    if \"::/\" in response.get(\"cidr_block\"):\n                        self.delete_route(\n                            route_table.id, None, response.get(\"cidr_block\")\n                        )\n                    else:\n                        self.delete_route(route_table.id, response.get(\"cidr_block\"))\n            if response:\n                return response\n        raise InvalidVpcCidrBlockAssociationIdError(association_id)\n\n    def associate_vpc_cidr_block(\n        self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block\n    ):\n        vpc = self.get_vpc(vpc_id)\n        association_set = vpc.associate_vpc_cidr_block(\n            cidr_block, amazon_provided_ipv6_cidr_block\n        )\n        for route_table in self.route_tables.copy().values():\n            if route_table.vpc_id == vpc_id:\n                if amazon_provided_ipv6_cidr_block:\n                    self.create_route(\n                        route_table.id,\n                        None,\n                        destination_ipv6_cidr_block=association_set[\"cidr_block\"],\n                        local=True,\n                    )\n                else:\n                    self.create_route(\n                        route_table.id, association_set[\"cidr_block\"], local=True\n                    )\n        return association_set\n\n    def create_vpc_endpoint(\n        self,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n    ):\n\n        vpc_endpoint_id = random_vpc_ep_id()\n\n        # validates if vpc is present or not.\n        self.get_vpc(vpc_id)\n        destination_prefix_list_id = None\n\n        if endpoint_type and endpoint_type.lower() == \"interface\":\n\n            network_interface_ids = []\n            for subnet_id in subnet_ids or []:\n                self.get_subnet(subnet_id)\n                eni = self.create_network_interface(subnet_id, random_private_ip())\n                network_interface_ids.append(eni.id)\n\n            dns_entries = create_dns_entries(service_name, vpc_endpoint_id)\n\n        else:\n            # considering gateway if type is not mentioned.\n            for prefix_list in self.managed_prefix_lists.values():\n                if prefix_list.prefix_list_name == service_name:\n                    destination_prefix_list_id = prefix_list.id\n\n        if dns_entries:\n            dns_entries = [dns_entries]\n\n        vpc_end_point = VPCEndPoint(\n            self,\n            vpc_endpoint_id,\n            vpc_id,\n            service_name,\n            endpoint_type,\n            policy_document,\n            route_table_ids,\n            subnet_ids,\n            network_interface_ids,\n            dns_entries,\n            client_token,\n            security_group_ids,\n            tags,\n            private_dns_enabled,\n            destination_prefix_list_id,\n        )\n\n        self.vpc_end_points[vpc_endpoint_id] = vpc_end_point\n\n        if destination_prefix_list_id:\n            for route_table_id in route_table_ids:\n                self.create_route(\n                    route_table_id,\n                    None,\n                    gateway_id=vpc_endpoint_id,\n                    destination_prefix_list_id=destination_prefix_list_id,\n                )\n\n        return vpc_end_point\n\n    def delete_vpc_endpoints(self, vpce_ids=None):\n        for vpce_id in vpce_ids or []:\n            vpc_endpoint = self.vpc_end_points.get(vpce_id, None)\n            if vpc_endpoint:\n                if vpc_endpoint.endpoint_type.lower() == \"interface\":\n                    for eni_id in vpc_endpoint.network_interface_ids:\n                        self.enis.pop(eni_id, None)\n                else:\n                    for route_table_id in vpc_endpoint.route_table_ids:\n                        self.delete_route(\n                            route_table_id, vpc_endpoint.destination_prefix_list_id\n                        )\n                vpc_endpoint.state = \"deleted\"\n        return True\n\n    def describe_vpc_endpoints(self, vpc_end_point_ids, filters=None):\n        vpc_end_points = self.vpc_end_points.values()\n\n        if vpc_end_point_ids:\n            vpc_end_points = [\n                vpc_end_point\n                for vpc_end_point in vpc_end_points\n                if vpc_end_point.id in vpc_end_point_ids\n            ]\n            if len(vpc_end_points) != len(vpc_end_point_ids):\n                invalid_id = list(\n                    set(vpc_end_point_ids).difference(\n                        set([vpc_end_point.id for vpc_end_point in vpc_end_points])\n                    )\n                )[0]\n                raise InvalidVpcEndPointIdError(invalid_id)\n\n        return generic_filter(filters, vpc_end_points)\n\n    @staticmethod\n    def _collect_default_endpoint_services(region):\n        \"\"\"Return list of default services using list of backends.\"\"\"\n        if DEFAULT_VPC_ENDPOINT_SERVICES:\n            return DEFAULT_VPC_ENDPOINT_SERVICES\n\n        zones = [\n            zone.name\n            for zones in RegionsAndZonesBackend.zones.values()\n            for zone in zones\n            if zone.name.startswith(region)\n        ]\n\n        from moto import backends  # pylint: disable=import-outside-toplevel\n\n        for _backends in backends.unique_backends():\n            if region in _backends:\n                service = _backends[region].default_vpc_endpoint_service(region, zones)\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n\n            if \"global\" in _backends:\n                service = _backends[\"global\"].default_vpc_endpoint_service(\n                    region, zones\n                )\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n        return DEFAULT_VPC_ENDPOINT_SERVICES\n\n    @staticmethod\n    def _matches_service_by_tags(service, filter_item):\n        \"\"\"Return True if service tags are not filtered by their tags.\n\n        Note that the API specifies a key of \"Values\" for a filter, but\n        the botocore library returns \"Value\" instead.\n        \"\"\"\n        # For convenience, collect the tags for this service.\n        service_tag_keys = {x[\"Key\"] for x in service[\"Tags\"]}\n        if not service_tag_keys:\n            return False\n\n        matched = True  # assume the best\n        if filter_item[\"Name\"] == \"tag-key\":\n            # Filters=[{\"Name\":\"tag-key\", \"Values\":[\"Name\"]}],\n            # Any tag with this name, regardless of the tag value.\n            if not service_tag_keys & set(filter_item[\"Value\"]):\n                matched = False\n\n        elif filter_item[\"Name\"].startswith(\"tag:\"):\n            # Filters=[{\"Name\":\"tag:Name\", \"Values\":[\"my-load-balancer\"]}],\n            tag_name = filter_item[\"Name\"].split(\":\")[1]\n            if not service_tag_keys & {tag_name}:\n                matched = False\n            else:\n                for tag in service[\"Tags\"]:\n                    if tag[\"Key\"] == tag_name and tag[\"Value\"] in filter_item[\"Value\"]:\n                        break\n                else:\n                    matched = False\n        return matched\n\n    @staticmethod\n    def _filter_endpoint_services(service_names_filters, filters, services):\n        \"\"\"Return filtered list of VPC endpoint services.\"\"\"\n        if not service_names_filters and not filters:\n            return services\n\n        # Verify the filters are valid.\n        for filter_item in filters:\n            if filter_item[\"Name\"] not in [\n                \"service-name\",\n                \"service-type\",\n                \"tag-key\",\n            ] and not filter_item[\"Name\"].startswith(\"tag:\"):\n                raise InvalidFilter(filter_item[\"Name\"])\n\n        # Apply both the service_names filter and the filters themselves.\n        filtered_services = []\n        for service in services:\n            if (\n                service_names_filters\n                and service[\"ServiceName\"] not in service_names_filters\n            ):\n                continue\n\n            # Note that the API specifies a key of \"Values\" for a filter, but\n            # the botocore library returns \"Value\" instead.\n            matched = True\n            for filter_item in filters:\n                if filter_item[\"Name\"] == \"service-name\":\n                    if service[\"ServiceName\"] not in filter_item[\"Value\"]:\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"service-type\":\n                    service_types = {x[\"ServiceType\"] for x in service[\"ServiceType\"]}\n                    if not service_types & set(filter_item[\"Value\"]):\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"tag-key\" or filter_item[\"Name\"].startswith(\n                    \"tag:\"\n                ):\n                    if not VPCBackend._matches_service_by_tags(service, filter_item):\n                        matched = False\n\n                # Exit early -- don't bother checking the remaining filters\n                # as a non-match was found.\n                if not matched:\n                    break\n\n            # Does the service have a matching service name or does it match\n            # a filter?\n            if matched:\n                filtered_services.append(service)\n\n        return filtered_services\n\n    def describe_vpc_endpoint_services(\n        self, dry_run, service_names, filters, max_results, next_token, region\n    ):  # pylint: disable=unused-argument,too-many-arguments\n        \"\"\"Return info on services to which you can create a VPC endpoint.\n\n        Currently only the default endpoing services are returned.  When\n        create_vpc_endpoint_service_configuration() is implemented, a\n        list of those private endpoints would be kept and when this API\n        is invoked, those private endpoints would be added to the list of\n        default endpoint services.\n\n        The DryRun parameter is ignored.\n        \"\"\"\n        default_services = self._collect_default_endpoint_services(region)\n        for service_name in service_names:\n            if service_name not in [x[\"ServiceName\"] for x in default_services]:\n                raise InvalidServiceName(service_name)\n\n        # Apply filters specified in the service_names and filters arguments.\n        filtered_services = sorted(\n            self._filter_endpoint_services(service_names, filters, default_services),\n            key=itemgetter(\"ServiceName\"),\n        )\n\n        # Determine the start index into list of services based on the\n        # next_token argument.\n        start = 0\n        vpce_ids = [x[\"ServiceId\"] for x in filtered_services]\n        if next_token:\n            if next_token not in vpce_ids:\n                raise InvalidNextToken(next_token)\n            start = vpce_ids.index(next_token)\n\n        # Determine the stop index into the list of services based on the\n        # max_results argument.\n        if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:\n            max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS\n\n        # If necessary, set the value of the next_token.\n        next_token = \"\"\n        if len(filtered_services) > (start + max_results):\n            service = filtered_services[start + max_results]\n            next_token = service[\"ServiceId\"]\n\n        return {\n            \"servicesDetails\": filtered_services[start : start + max_results],\n            \"serviceNames\": [\n                x[\"ServiceName\"] for x in filtered_services[start : start + max_results]\n            ],\n            \"nextToken\": next_token,\n        }\n\n    def get_vpc_end_point(self, vpc_end_point_id):\n        vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)\n        if not vpc_end_point:\n            raise InvalidVpcEndPointIdError(vpc_end_point_id)\n        return vpc_end_point\n","header":{"file":{"path":"moto/ec2/models/vpcs.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/moto/ec2/models/vpcs.py"},"plus_file":{"path":"b/moto/ec2/models/vpcs.py"},"hunks":[{"descriptor":{"old_range":{"start":76,"length":6},"new_range":{"start":76,"length":12},"section":"def __init__("},"line_group":{"all_lines":[{"content":"","type":"context"},{"content":"        self.created_at = utc_date_and_time()","type":"context"},{"content":"","type":"context"},{"content":"    def get_filter_value(self, filter_name):","type":"added"},{"content":"        if filter_name in (\"vpc-endpoint-type\", \"vpc_endpoint_type\"):","type":"added"},{"content":"            return self.endpoint_type","type":"added"},{"content":"        else:","type":"added"},{"content":"            return super().get_filter_value(filter_name, \"DescribeVpcs\")","type":"added"},{"content":"","type":"added"},{"content":"    @property","type":"context"},{"content":"    def owner_id(self):","type":"context"},{"content":"        return ACCOUNT_ID","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"e911341e6ad1bfe7f3930f38c36b26b25cdb0f94","new_commit_hash":"bafa4a3daeee4419642b3c703bf3fe3758260f4a","commit_message":"Rework filter logic","commit_date":"2022-05-09T09:12:30Z","metadata":{}}
problem_statement: Describe EC2 Vpc endpoints doesn't support vpc-endpoint-type filter.
  This happens on line 202
  ![image](https://user-images.githubusercontent.com/92550453/167168166-94b94167-5670-4d38-9577-ea2374cb674f.png)
  
  ![image](https://user-images.githubusercontent.com/92550453/167168009-be85eeea-44e0-4425-9ee0-f84798b4a1e7.png)
  
  
patch: diff --git a/moto/ec2/models/vpcs.py b/moto/ec2/models/vpcs.py
  --- a/moto/ec2/models/vpcs.py
  +++ b/moto/ec2/models/vpcs.py
  @@ -76,6 +76,12 @@ def __init__(
   
           self.created_at = utc_date_and_time()
   
  +    def get_filter_value(self, filter_name):
  +        if filter_name in ("vpc-endpoint-type", "vpc_endpoint_type"):
  +            return self.endpoint_type
  +        else:
  +            return super().get_filter_value(filter_name, "DescribeVpcs")
  +
       @property
       def owner_id(self):
           return ACCOUNT_ID
   
  
file_context: {"moto/ec2/models/vpcs.py": "import ipaddress\nimport json\nimport weakref\nfrom collections import defaultdict\nfrom operator import itemgetter\n\nfrom moto.core import get_account_id\nfrom moto.core.models import CloudFormationModel\nfrom .core import TaggedEC2Resource\nfrom ..exceptions import (\n    CidrLimitExceeded,\n    UnsupportedTenancy,\n    DependencyViolationError,\n    InvalidCIDRBlockParameterError,\n    InvalidServiceName,\n    InvalidFilter,\n    InvalidNextToken,\n    InvalidParameterValueError,\n    InvalidVpcCidrBlockAssociationIdError,\n    InvalidVPCIdError,\n    InvalidVPCRangeError,\n    OperationNotPermitted,\n    InvalidVpcEndPointIdError,\n)\nfrom .availability_zones_and_regions import RegionsAndZonesBackend\nfrom ..utils import (\n    random_ipv6_cidr,\n    random_vpc_ep_id,\n    random_private_ip,\n    create_dns_entries,\n    random_vpc_id,\n    random_vpc_cidr_association_id,\n    generic_filter,\n    utc_date_and_time,\n)\n\nMAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000\nDEFAULT_VPC_ENDPOINT_SERVICES = []\n\n\nclass VPCEndPoint(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        endpoint_id,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n        destination_prefix_list_id=None,\n    ):\n        self.ec2_backend = ec2_backend\n        self.id = endpoint_id\n        self.vpc_id = vpc_id\n        self.service_name = service_name\n        self.endpoint_type = endpoint_type\n        self.state = \"available\"\n        self.policy_document = policy_document\n        self.route_table_ids = route_table_ids\n        self.network_interface_ids = network_interface_ids or []\n        self.subnet_ids = subnet_ids\n        self.client_token = client_token\n        self.security_group_ids = security_group_ids\n        self.private_dns_enabled = private_dns_enabled\n        self.dns_entries = dns_entries\n        self.add_tags(tags or {})\n        self.destination_prefix_list_id = destination_prefix_list_id\n\n        self.created_at = utc_date_and_time()\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        return \"AWS::EC2::VPCEndpoint\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        service_name = properties.get(\"ServiceName\")\n        subnet_ids = properties.get(\"SubnetIds\")\n        vpc_endpoint_type = properties.get(\"VpcEndpointType\")\n        vpc_id = properties.get(\"VpcId\")\n        policy_document = properties.get(\"PolicyDocument\")\n        private_dns_enabled = properties.get(\"PrivateDnsEnabled\")\n        route_table_ids = properties.get(\"RouteTableIds\")\n        security_group_ids = properties.get(\"SecurityGroupIds\")\n\n        ec2_backend = ec2_backends[region_name]\n        vpc_endpoint = ec2_backend.create_vpc_endpoint(\n            vpc_id=vpc_id,\n            service_name=service_name,\n            endpoint_type=vpc_endpoint_type,\n            subnet_ids=subnet_ids,\n            policy_document=policy_document,\n            private_dns_enabled=private_dns_enabled,\n            route_table_ids=route_table_ids,\n            security_group_ids=security_group_ids,\n        )\n        return vpc_endpoint\n\n\nclass VPC(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        vpc_id,\n        cidr_block,\n        is_default,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n    ):\n\n        self.ec2_backend = ec2_backend\n        self.id = vpc_id\n        self.cidr_block = cidr_block\n        self.cidr_block_association_set = {}\n        self.dhcp_options = None\n        self.state = \"available\"\n        self.instance_tenancy = instance_tenancy\n        self.is_default = \"true\" if is_default else \"false\"\n        self.enable_dns_support = \"true\"\n        self.classic_link_enabled = \"false\"\n        self.classic_link_dns_supported = \"false\"\n        # This attribute is set to 'true' only for default VPCs\n        # or VPCs created using the wizard of the VPC console\n        self.enable_dns_hostnames = \"true\" if is_default else \"false\"\n\n        self.associate_vpc_cidr_block(cidr_block)\n        if amazon_provided_ipv6_cidr_block:\n            self.associate_vpc_cidr_block(\n                cidr_block,\n                amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,\n            )\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html\n        return \"AWS::EC2::VPC\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        ec2_backend = ec2_backends[region_name]\n        vpc = ec2_backend.create_vpc(\n            cidr_block=properties[\"CidrBlock\"],\n            instance_tenancy=properties.get(\"InstanceTenancy\", \"default\"),\n        )\n        for tag in properties.get(\"Tags\", []):\n            tag_key = tag[\"Key\"]\n            tag_value = tag[\"Value\"]\n            vpc.add_tag(tag_key, tag_value)\n\n        return vpc\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    def get_filter_value(self, filter_name):\n        if filter_name in (\"vpc-id\", \"vpcId\"):\n            return self.id\n        elif filter_name in (\"cidr\", \"cidr-block\", \"cidrBlock\"):\n            return self.cidr_block\n        elif filter_name in (\n            \"cidr-block-association.cidr-block\",\n            \"ipv6-cidr-block-association.ipv6-cidr-block\",\n        ):\n            return [\n                c[\"cidr_block\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\n            \"cidr-block-association.association-id\",\n            \"ipv6-cidr-block-association.association-id\",\n        ):\n            return self.cidr_block_association_set.keys()\n        elif filter_name in (\n            \"cidr-block-association.state\",\n            \"ipv6-cidr-block-association.state\",\n        ):\n            return [\n                c[\"cidr_block_state\"][\"state\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\"instance_tenancy\", \"InstanceTenancy\"):\n            return self.instance_tenancy\n        elif filter_name in (\"is-default\", \"isDefault\"):\n            return self.is_default\n        elif filter_name == \"state\":\n            return self.state\n        elif filter_name in (\"dhcp-options-id\", \"dhcpOptionsId\"):\n            if not self.dhcp_options:\n                return None\n            return self.dhcp_options.id\n        else:\n            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n\n    def modify_vpc_tenancy(self, tenancy):\n        if tenancy != \"default\":\n            raise UnsupportedTenancy(tenancy)\n        self.instance_tenancy = tenancy\n        return True\n\n    def associate_vpc_cidr_block(\n        self, cidr_block, amazon_provided_ipv6_cidr_block=False\n    ):\n        max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1\n\n        for cidr in self.cidr_block_association_set.copy():\n            if (\n                self.cidr_block_association_set.get(cidr)\n                .get(\"cidr_block_state\")\n                .get(\"state\")\n                == \"disassociated\"\n            ):\n                self.cidr_block_association_set.pop(cidr)\n        if (\n            len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))\n            >= max_associations\n        ):\n            raise CidrLimitExceeded(self.id, max_associations)\n\n        association_id = random_vpc_cidr_association_id()\n\n        association_set = {\n            \"association_id\": association_id,\n            \"cidr_block_state\": {\"state\": \"associated\", \"StatusMessage\": \"\"},\n        }\n\n        association_set[\"cidr_block\"] = (\n            random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block\n        )\n        self.cidr_block_association_set[association_id] = association_set\n        return association_set\n\n    def enable_vpc_classic_link(self):\n        # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.\n        # Doesn't check any route tables, maybe something for in the future?\n        # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations\n        network_address = ipaddress.ip_network(self.cidr_block).network_address\n        if (\n            network_address not in ipaddress.ip_network(\"10.0.0.0/8\")\n            or network_address in ipaddress.ip_network(\"10.0.0.0/16\")\n            or network_address in ipaddress.ip_network(\"10.1.0.0/16\")\n        ):\n            self.classic_link_enabled = \"true\"\n\n        return self.classic_link_enabled\n\n    def disable_vpc_classic_link(self):\n        self.classic_link_enabled = \"false\"\n        return self.classic_link_enabled\n\n    def enable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"true\"\n        return self.classic_link_dns_supported\n\n    def disable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"false\"\n        return self.classic_link_dns_supported\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        if self.cidr_block == self.cidr_block_association_set.get(\n            association_id, {}\n        ).get(\"cidr_block\"):\n            raise OperationNotPermitted(association_id)\n\n        entry = response = self.cidr_block_association_set.get(association_id, {})\n        if entry:\n            response = json.loads(json.dumps(entry))\n            response[\"vpc_id\"] = self.id\n            response[\"cidr_block_state\"][\"state\"] = \"disassociating\"\n            entry[\"cidr_block_state\"][\"state\"] = \"disassociated\"\n        return response\n\n    def get_cidr_block_association_set(self, ipv6=False):\n        return [\n            c\n            for c in self.cidr_block_association_set.values()\n            if (\"::/\" if ipv6 else \".\") in c.get(\"cidr_block\")\n        ]\n\n\nclass VPCBackend(object):\n    vpc_refs = defaultdict(set)\n\n    def __init__(self):\n        self.vpcs = {}\n        self.vpc_end_points = {}\n        self.vpc_refs[self.__class__].add(weakref.ref(self))\n        super().__init__()\n\n    def create_vpc(\n        self,\n        cidr_block,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n        tags=None,\n    ):\n        vpc_id = random_vpc_id()\n        try:\n            vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)\n        except ValueError:\n            raise InvalidCIDRBlockParameterError(cidr_block)\n        if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:\n            raise InvalidVPCRangeError(cidr_block)\n        vpc = VPC(\n            self,\n            vpc_id,\n            cidr_block,\n            len(self.vpcs) == 0,\n            instance_tenancy,\n            amazon_provided_ipv6_cidr_block,\n        )\n\n        for tag in tags or []:\n            tag_key = tag.get(\"Key\")\n            tag_value = tag.get(\"Value\")\n            vpc.add_tag(tag_key, tag_value)\n\n        self.vpcs[vpc_id] = vpc\n\n        # AWS creates a default main route table and security group.\n        self.create_route_table(vpc_id, main=True)\n\n        # AWS creates a default Network ACL\n        self.create_network_acl(vpc_id, default=True)\n\n        default = self.get_security_group_from_name(\"default\", vpc_id=vpc_id)\n        if not default:\n            self.create_security_group(\n                \"default\", \"default VPC security group\", vpc_id=vpc_id, is_default=True\n            )\n\n        return vpc\n\n    def get_vpc(self, vpc_id):\n        if vpc_id not in self.vpcs:\n            raise InvalidVPCIdError(vpc_id)\n        return self.vpcs.get(vpc_id)\n\n    def describe_vpcs(self, vpc_ids=None, filters=None):\n        matches = self.vpcs.copy().values()\n        if vpc_ids:\n            matches = [vpc for vpc in matches if vpc.id in vpc_ids]\n            if len(vpc_ids) > len(matches):\n                unknown_ids = set(vpc_ids) - set(matches)\n                raise InvalidVPCIdError(unknown_ids)\n        if filters:\n            matches = generic_filter(filters, matches)\n        return matches\n\n    def delete_vpc(self, vpc_id):\n        # Do not delete if any VPN Gateway is attached\n        vpn_gateways = self.describe_vpn_gateways(filters={\"attachment.vpc-id\": vpc_id})\n        vpn_gateways = [\n            item\n            for item in vpn_gateways\n            if item.attachments.get(vpc_id).state == \"attached\"\n        ]\n        if vpn_gateways:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n\n        # Delete route table if only main route table remains.\n        route_tables = self.describe_route_tables(filters={\"vpc-id\": vpc_id})\n        if len(route_tables) > 1:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n        for route_table in route_tables:\n            self.delete_route_table(route_table.id)\n\n        # Delete default security group if exists.\n        default = self.get_security_group_by_name_or_id(\"default\", vpc_id=vpc_id)\n        if default:\n            self.delete_security_group(group_id=default.id)\n\n        # Now delete VPC.\n        vpc = self.vpcs.pop(vpc_id, None)\n        if not vpc:\n            raise InvalidVPCIdError(vpc_id)\n\n        if vpc.dhcp_options:\n            vpc.dhcp_options.vpc = None\n            self.delete_dhcp_options_set(vpc.dhcp_options.id)\n            vpc.dhcp_options = None\n        return vpc\n\n    def describe_vpc_attribute(self, vpc_id, attr_name):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            return getattr(vpc, attr_name)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def modify_vpc_tenancy(self, vpc_id, tenancy):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.modify_vpc_tenancy(tenancy)\n\n    def enable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link()\n\n    def disable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link()\n\n    def enable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link_dns_support()\n\n    def disable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link_dns_support()\n\n    def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            setattr(vpc, attr_name, attr_value)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        for vpc in self.vpcs.copy().values():\n            response = vpc.disassociate_vpc_cidr_block(association_id)\n            for route_table in self.route_tables.copy().values():\n                if route_table.vpc_id == response.get(\"vpc_id\"):\n                    if \"::/\" in response.get(\"cidr_block\"):\n                        self.delete_route(\n                            route_table.id, None, response.get(\"cidr_block\")\n                        )\n                    else:\n                        self.delete_route(route_table.id, response.get(\"cidr_block\"))\n            if response:\n                return response\n        raise InvalidVpcCidrBlockAssociationIdError(association_id)\n\n    def associate_vpc_cidr_block(\n        self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block\n    ):\n        vpc = self.get_vpc(vpc_id)\n        association_set = vpc.associate_vpc_cidr_block(\n            cidr_block, amazon_provided_ipv6_cidr_block\n        )\n        for route_table in self.route_tables.copy().values():\n            if route_table.vpc_id == vpc_id:\n                if amazon_provided_ipv6_cidr_block:\n                    self.create_route(\n                        route_table.id,\n                        None,\n                        destination_ipv6_cidr_block=association_set[\"cidr_block\"],\n                        local=True,\n                    )\n                else:\n                    self.create_route(\n                        route_table.id, association_set[\"cidr_block\"], local=True\n                    )\n        return association_set\n\n    def create_vpc_endpoint(\n        self,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n    ):\n\n        vpc_endpoint_id = random_vpc_ep_id()\n\n        # validates if vpc is present or not.\n        self.get_vpc(vpc_id)\n        destination_prefix_list_id = None\n\n        if endpoint_type and endpoint_type.lower() == \"interface\":\n\n            network_interface_ids = []\n            for subnet_id in subnet_ids or []:\n                self.get_subnet(subnet_id)\n                eni = self.create_network_interface(subnet_id, random_private_ip())\n                network_interface_ids.append(eni.id)\n\n            dns_entries = create_dns_entries(service_name, vpc_endpoint_id)\n\n        else:\n            # considering gateway if type is not mentioned.\n            for prefix_list in self.managed_prefix_lists.values():\n                if prefix_list.prefix_list_name == service_name:\n                    destination_prefix_list_id = prefix_list.id\n\n        if dns_entries:\n            dns_entries = [dns_entries]\n\n        vpc_end_point = VPCEndPoint(\n            self,\n            vpc_endpoint_id,\n            vpc_id,\n            service_name,\n            endpoint_type,\n            policy_document,\n            route_table_ids,\n            subnet_ids,\n            network_interface_ids,\n            dns_entries,\n            client_token,\n            security_group_ids,\n            tags,\n            private_dns_enabled,\n            destination_prefix_list_id,\n        )\n\n        self.vpc_end_points[vpc_endpoint_id] = vpc_end_point\n\n        if destination_prefix_list_id:\n            for route_table_id in route_table_ids:\n                self.create_route(\n                    route_table_id,\n                    None,\n                    gateway_id=vpc_endpoint_id,\n                    destination_prefix_list_id=destination_prefix_list_id,\n                )\n\n        return vpc_end_point\n\n    def delete_vpc_endpoints(self, vpce_ids=None):\n        for vpce_id in vpce_ids or []:\n            vpc_endpoint = self.vpc_end_points.get(vpce_id, None)\n            if vpc_endpoint:\n                if vpc_endpoint.endpoint_type.lower() == \"interface\":\n                    for eni_id in vpc_endpoint.network_interface_ids:\n                        self.enis.pop(eni_id, None)\n                else:\n                    for route_table_id in vpc_endpoint.route_table_ids:\n                        self.delete_route(\n                            route_table_id, vpc_endpoint.destination_prefix_list_id\n                        )\n                vpc_endpoint.state = \"deleted\"\n        return True\n\n    def describe_vpc_endpoints(self, vpc_end_point_ids, filters=None):\n        vpc_end_points = self.vpc_end_points.values()\n\n        if vpc_end_point_ids:\n            vpc_end_points = [\n                vpc_end_point\n                for vpc_end_point in vpc_end_points\n                if vpc_end_point.id in vpc_end_point_ids\n            ]\n            if len(vpc_end_points) != len(vpc_end_point_ids):\n                invalid_id = list(\n                    set(vpc_end_point_ids).difference(\n                        set([vpc_end_point.id for vpc_end_point in vpc_end_points])\n                    )\n                )[0]\n                raise InvalidVpcEndPointIdError(invalid_id)\n\n        return generic_filter(filters, vpc_end_points)\n\n    @staticmethod\n    def _collect_default_endpoint_services(region):\n        \"\"\"Return list of default services using list of backends.\"\"\"\n        if DEFAULT_VPC_ENDPOINT_SERVICES:\n            return DEFAULT_VPC_ENDPOINT_SERVICES\n\n        zones = [\n            zone.name\n            for zones in RegionsAndZonesBackend.zones.values()\n            for zone in zones\n            if zone.name.startswith(region)\n        ]\n\n        from moto import backends  # pylint: disable=import-outside-toplevel\n\n        for _backends in backends.unique_backends():\n            if region in _backends:\n                service = _backends[region].default_vpc_endpoint_service(region, zones)\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n\n            if \"global\" in _backends:\n                service = _backends[\"global\"].default_vpc_endpoint_service(\n                    region, zones\n                )\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n        return DEFAULT_VPC_ENDPOINT_SERVICES\n\n    @staticmethod\n    def _matches_service_by_tags(service, filter_item):\n        \"\"\"Return True if service tags are not filtered by their tags.\n\n        Note that the API specifies a key of \"Values\" for a filter, but\n        the botocore library returns \"Value\" instead.\n        \"\"\"\n        # For convenience, collect the tags for this service.\n        service_tag_keys = {x[\"Key\"] for x in service[\"Tags\"]}\n        if not service_tag_keys:\n            return False\n\n        matched = True  # assume the best\n        if filter_item[\"Name\"] == \"tag-key\":\n            # Filters=[{\"Name\":\"tag-key\", \"Values\":[\"Name\"]}],\n            # Any tag with this name, regardless of the tag value.\n            if not service_tag_keys & set(filter_item[\"Value\"]):\n                matched = False\n\n        elif filter_item[\"Name\"].startswith(\"tag:\"):\n            # Filters=[{\"Name\":\"tag:Name\", \"Values\":[\"my-load-balancer\"]}],\n            tag_name = filter_item[\"Name\"].split(\":\")[1]\n            if not service_tag_keys & {tag_name}:\n                matched = False\n            else:\n                for tag in service[\"Tags\"]:\n                    if tag[\"Key\"] == tag_name and tag[\"Value\"] in filter_item[\"Value\"]:\n                        break\n                else:\n                    matched = False\n        return matched\n\n    @staticmethod\n    def _filter_endpoint_services(service_names_filters, filters, services):\n        \"\"\"Return filtered list of VPC endpoint services.\"\"\"\n        if not service_names_filters and not filters:\n            return services\n\n        # Verify the filters are valid.\n        for filter_item in filters:\n            if filter_item[\"Name\"] not in [\n                \"service-name\",\n                \"service-type\",\n                \"tag-key\",\n            ] and not filter_item[\"Name\"].startswith(\"tag:\"):\n                raise InvalidFilter(filter_item[\"Name\"])\n\n        # Apply both the service_names filter and the filters themselves.\n        filtered_services = []\n        for service in services:\n            if (\n                service_names_filters\n                and service[\"ServiceName\"] not in service_names_filters\n            ):\n                continue\n\n            # Note that the API specifies a key of \"Values\" for a filter, but\n            # the botocore library returns \"Value\" instead.\n            matched = True\n            for filter_item in filters:\n                if filter_item[\"Name\"] == \"service-name\":\n                    if service[\"ServiceName\"] not in filter_item[\"Value\"]:\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"service-type\":\n                    service_types = {x[\"ServiceType\"] for x in service[\"ServiceType\"]}\n                    if not service_types & set(filter_item[\"Value\"]):\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"tag-key\" or filter_item[\"Name\"].startswith(\n                    \"tag:\"\n                ):\n                    if not VPCBackend._matches_service_by_tags(service, filter_item):\n                        matched = False\n\n                # Exit early -- don't bother checking the remaining filters\n                # as a non-match was found.\n                if not matched:\n                    break\n\n            # Does the service have a matching service name or does it match\n            # a filter?\n            if matched:\n                filtered_services.append(service)\n\n        return filtered_services\n\n    def describe_vpc_endpoint_services(\n        self, dry_run, service_names, filters, max_results, next_token, region\n    ):  # pylint: disable=unused-argument,too-many-arguments\n        \"\"\"Return info on services to which you can create a VPC endpoint.\n\n        Currently only the default endpoing services are returned.  When\n        create_vpc_endpoint_service_configuration() is implemented, a\n        list of those private endpoints would be kept and when this API\n        is invoked, those private endpoints would be added to the list of\n        default endpoint services.\n\n        The DryRun parameter is ignored.\n        \"\"\"\n        default_services = self._collect_default_endpoint_services(region)\n        for service_name in service_names:\n            if service_name not in [x[\"ServiceName\"] for x in default_services]:\n                raise InvalidServiceName(service_name)\n\n        # Apply filters specified in the service_names and filters arguments.\n        filtered_services = sorted(\n            self._filter_endpoint_services(service_names, filters, default_services),\n            key=itemgetter(\"ServiceName\"),\n        )\n\n        # Determine the start index into list of services based on the\n        # next_token argument.\n        start = 0\n        vpce_ids = [x[\"ServiceId\"] for x in filtered_services]\n        if next_token:\n            if next_token not in vpce_ids:\n                raise InvalidNextToken(next_token)\n            start = vpce_ids.index(next_token)\n\n        # Determine the stop index into the list of services based on the\n        # max_results argument.\n        if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:\n            max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS\n\n        # If necessary, set the value of the next_token.\n        next_token = \"\"\n        if len(filtered_services) > (start + max_results):\n            service = filtered_services[start + max_results]\n            next_token = service[\"ServiceId\"]\n\n        return {\n            \"servicesDetails\": filtered_services[start : start + max_results],\n            \"serviceNames\": [\n                x[\"ServiceName\"] for x in filtered_services[start : start + max_results]\n            ],\n            \"nextToken\": next_token,\n        }\n\n    def get_vpc_end_point(self, vpc_end_point_id):\n        vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)\n        if not vpc_end_point:\n            raise InvalidVpcEndPointIdError(vpc_end_point_id)\n        return vpc_end_point\n"}
filelevel_patches: {"moto/ec2/models/vpcs.py": "@@ -76,6 +76,12 @@ def __init__(\n \n         self.created_at = utc_date_and_time()\n \n+    def get_filter_value(self, filter_name):\n+        if filter_name in (\"vpc-endpoint-type\", \"vpc_endpoint_type\"):\n+            return self.endpoint_type\n+        else:\n+            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n+\n     @property\n     def owner_id(self):\n         return ACCOUNT_ID"}
messages.content: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Describe EC2 Vpc endpoints doesn't support vpc-endpoint-type filter.
  This happens on line 202
  ![image](https://user-images.githubusercontent.com/92550453/167168166-94b94167-5670-4d38-9577-ea2374cb674f.png)
  
  ![image](https://user-images.githubusercontent.com/92550453/167168009-be85eeea-44e0-4425-9ee0-f84798b4a1e7.png)
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### moto/ec2/models/vpcs.py
  import ipaddress
  import json
  import weakref
  from collections import defaultdict
  from operator import itemgetter
  
  from moto.core import get_account_id
  from moto.core.models import CloudFormationModel
  from .core import TaggedEC2Resource
  from ..exceptions import (
      CidrLimitExceeded,
      UnsupportedTenancy,
      DependencyViolationError,
      InvalidCIDRBlockParameterError,
      InvalidServiceName,
      InvalidFilter,
      InvalidNextToken,
      InvalidParameterValueError,
      InvalidVpcCidrBlockAssociationIdError,
      InvalidVPCIdError,
      InvalidVPCRangeError,
      OperationNotPermitted,
      InvalidVpcEndPointIdError,
  )
  from .availability_zones_and_regions import RegionsAndZonesBackend
  from ..utils import (
      random_ipv6_cidr,
      random_vpc_ep_id,
      random_private_ip,
      create_dns_entries,
      random_vpc_id,
      random_vpc_cidr_association_id,
      generic_filter,
      utc_date_and_time,
  )
  
  MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000
  DEFAULT_VPC_ENDPOINT_SERVICES = []
  
  
  class VPCEndPoint(TaggedEC2Resource, CloudFormationModel):
      def __init__(
          self,
          ec2_backend,
          endpoint_id,
          vpc_id,
          service_name,
          endpoint_type=None,
          policy_document=False,
          route_table_ids=None,
          subnet_ids=None,
          network_interface_ids=None,
          dns_entries=None,
          client_token=None,
          security_group_ids=None,
          tags=None,
          private_dns_enabled=None,
          destination_prefix_list_id=None,
      ):
          self.ec2_backend = ec2_backend
          self.id = endpoint_id
          self.vpc_id = vpc_id
          self.service_name = service_name
          self.endpoint_type = endpoint_type
          self.state = "available"
          self.policy_document = policy_document
          self.route_table_ids = route_table_ids
          self.network_interface_ids = network_interface_ids or []
          self.subnet_ids = subnet_ids
          self.client_token = client_token
          self.security_group_ids = security_group_ids
          self.private_dns_enabled = private_dns_enabled
          self.dns_entries = dns_entries
          self.add_tags(tags or {})
          self.destination_prefix_list_id = destination_prefix_list_id
  
          self.created_at = utc_date_and_time()
  
      @property
      def owner_id(self):
          return get_account_id()
  
      @property
      def physical_resource_id(self):
          return self.id
  
      @staticmethod
      def cloudformation_name_type():
          return None
  
      @staticmethod
      def cloudformation_type():
          return "AWS::EC2::VPCEndpoint"
  
      @classmethod
      def create_from_cloudformation_json(
          cls, resource_name, cloudformation_json, region_name, **kwargs
      ):
          from ..models import ec2_backends
  
          properties = cloudformation_json["Properties"]
  
          service_name = properties.get("ServiceName")
          subnet_ids = properties.get("SubnetIds")
          vpc_endpoint_type = properties.get("VpcEndpointType")
          vpc_id = properties.get("VpcId")
          policy_document = properties.get("PolicyDocument")
          private_dns_enabled = properties.get("PrivateDnsEnabled")
          route_table_ids = properties.get("RouteTableIds")
          security_group_ids = properties.get("SecurityGroupIds")
  
          ec2_backend = ec2_backends[region_name]
          vpc_endpoint = ec2_backend.create_vpc_endpoint(
              vpc_id=vpc_id,
              service_name=service_name,
              endpoint_type=vpc_endpoint_type,
              subnet_ids=subnet_ids,
              policy_document=policy_document,
              private_dns_enabled=private_dns_enabled,
              route_table_ids=route_table_ids,
              security_group_ids=security_group_ids,
          )
          return vpc_endpoint
  
  
  class VPC(TaggedEC2Resource, CloudFormationModel):
      def __init__(
          self,
          ec2_backend,
          vpc_id,
          cidr_block,
          is_default,
          instance_tenancy="default",
          amazon_provided_ipv6_cidr_block=False,
      ):
  
          self.ec2_backend = ec2_backend
          self.id = vpc_id
          self.cidr_block = cidr_block
          self.cidr_block_association_set = {}
          self.dhcp_options = None
          self.state = "available"
          self.instance_tenancy = instance_tenancy
          self.is_default = "true" if is_default else "false"
          self.enable_dns_support = "true"
          self.classic_link_enabled = "false"
          self.classic_link_dns_supported = "false"
          # This attribute is set to 'true' only for default VPCs
          # or VPCs created using the wizard of the VPC console
          self.enable_dns_hostnames = "true" if is_default else "false"
  
          self.associate_vpc_cidr_block(cidr_block)
          if amazon_provided_ipv6_cidr_block:
              self.associate_vpc_cidr_block(
                  cidr_block,
                  amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,
              )
  
      @property
      def owner_id(self):
          return get_account_id()
  
      @staticmethod
      def cloudformation_name_type():
          return None
  
      @staticmethod
      def cloudformation_type():
          # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
          return "AWS::EC2::VPC"
  
      @classmethod
      def create_from_cloudformation_json(
          cls, resource_name, cloudformation_json, region_name, **kwargs
      ):
          from ..models import ec2_backends
  
          properties = cloudformation_json["Properties"]
  
          ec2_backend = ec2_backends[region_name]
          vpc = ec2_backend.create_vpc(
              cidr_block=properties["CidrBlock"],
              instance_tenancy=properties.get("InstanceTenancy", "default"),
          )
          for tag in properties.get("Tags", []):
              tag_key = tag["Key"]
              tag_value = tag["Value"]
              vpc.add_tag(tag_key, tag_value)
  
          return vpc
  
      @property
      def physical_resource_id(self):
          return self.id
  
      def get_filter_value(self, filter_name):
          if filter_name in ("vpc-id", "vpcId"):
              return self.id
          elif filter_name in ("cidr", "cidr-block", "cidrBlock"):
              return self.cidr_block
          elif filter_name in (
              "cidr-block-association.cidr-block",
              "ipv6-cidr-block-association.ipv6-cidr-block",
          ):
              return [
                  c["cidr_block"]
                  for c in self.get_cidr_block_association_set(ipv6="ipv6" in filter_name)
              ]
          elif filter_name in (
              "cidr-block-association.association-id",
              "ipv6-cidr-block-association.association-id",
          ):
              return self.cidr_block_association_set.keys()
          elif filter_name in (
              "cidr-block-association.state",
              "ipv6-cidr-block-association.state",
          ):
              return [
                  c["cidr_block_state"]["state"]
                  for c in self.get_cidr_block_association_set(ipv6="ipv6" in filter_name)
              ]
          elif filter_name in ("instance_tenancy", "InstanceTenancy"):
              return self.instance_tenancy
          elif filter_name in ("is-default", "isDefault"):
              return self.is_default
          elif filter_name == "state":
              return self.state
          elif filter_name in ("dhcp-options-id", "dhcpOptionsId"):
              if not self.dhcp_options:
                  return None
              return self.dhcp_options.id
          else:
              return super().get_filter_value(filter_name, "DescribeVpcs")
  
      def modify_vpc_tenancy(self, tenancy):
          if tenancy != "default":
              raise UnsupportedTenancy(tenancy)
          self.instance_tenancy = tenancy
          return True
  
      def associate_vpc_cidr_block(
          self, cidr_block, amazon_provided_ipv6_cidr_block=False
      ):
          max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1
  
          for cidr in self.cidr_block_association_set.copy():
              if (
                  self.cidr_block_association_set.get(cidr)
                  .get("cidr_block_state")
                  .get("state")
                  == "disassociated"
              ):
                  self.cidr_block_association_set.pop(cidr)
          if (
              len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))
              >= max_associations
          ):
              raise CidrLimitExceeded(self.id, max_associations)
  
          association_id = random_vpc_cidr_association_id()
  
          association_set = {
              "association_id": association_id,
              "cidr_block_state": {"state": "associated", "StatusMessage": ""},
          }
  
          association_set["cidr_block"] = (
              random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block
          )
          self.cidr_block_association_set[association_id] = association_set
          return association_set
  
      def enable_vpc_classic_link(self):
          # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.
          # Doesn't check any route tables, maybe something for in the future?
          # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations
          network_address = ipaddress.ip_network(self.cidr_block).network_address
          if (
              network_address not in ipaddress.ip_network("10.0.0.0/8")
              or network_address in ipaddress.ip_network("10.0.0.0/16")
              or network_address in ipaddress.ip_network("10.1.0.0/16")
          ):
              self.classic_link_enabled = "true"
  
          return self.classic_link_enabled
  
      def disable_vpc_classic_link(self):
          self.classic_link_enabled = "false"
          return self.classic_link_enabled
  
      def enable_vpc_classic_link_dns_support(self):
          self.classic_link_dns_supported = "true"
          return self.classic_link_dns_supported
  
      def disable_vpc_classic_link_dns_support(self):
          self.classic_link_dns_supported = "false"
          return self.classic_link_dns_supported
  
      def disassociate_vpc_cidr_block(self, association_id):
          if self.cidr_block == self.cidr_block_association_set.get(
              association_id, {}
          ).get("cidr_block"):
              raise OperationNotPermitted(association_id)
  
          entry = response = self.cidr_block_association_set.get(association_id, {})
          if entry:
              response = json.loads(json.dumps(entry))
              response["vpc_id"] = self.id
              response["cidr_block_state"]["state"] = "disassociating"
              entry["cidr_block_state"]["state"] = "disassociated"
          return response
  
      def get_cidr_block_association_set(self, ipv6=False):
          return [
              c
              for c in self.cidr_block_association_set.values()
              if ("::/" if ipv6 else ".") in c.get("cidr_block")
          ]
  
  
  class VPCBackend(object):
      vpc_refs = defaultdict(set)
  
      def __init__(self):
          self.vpcs = {}
          self.vpc_end_points = {}
          self.vpc_refs[self.__class__].add(weakref.ref(self))
          super().__init__()
  
      def create_vpc(
          self,
          cidr_block,
          instance_tenancy="default",
          amazon_provided_ipv6_cidr_block=False,
          tags=None,
      ):
          vpc_id = random_vpc_id()
          try:
              vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)
          except ValueError:
              raise InvalidCIDRBlockParameterError(cidr_block)
          if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:
              raise InvalidVPCRangeError(cidr_block)
          vpc = VPC(
              self,
              vpc_id,
              cidr_block,
              len(self.vpcs) == 0,
              instance_tenancy,
              amazon_provided_ipv6_cidr_block,
          )
  
          for tag in tags or []:
              tag_key = tag.get("Key")
              tag_value = tag.get("Value")
              vpc.add_tag(tag_key, tag_value)
  
          self.vpcs[vpc_id] = vpc
  
          # AWS creates a default main route table and security group.
          self.create_route_table(vpc_id, main=True)
  
          # AWS creates a default Network ACL
          self.create_network_acl(vpc_id, default=True)
  
          default = self.get_security_group_from_name("default", vpc_id=vpc_id)
          if not default:
              self.create_security_group(
                  "default", "default VPC security group", vpc_id=vpc_id, is_default=True
              )
  
          return vpc
  
      def get_vpc(self, vpc_id):
          if vpc_id not in self.vpcs:
              raise InvalidVPCIdError(vpc_id)
          return self.vpcs.get(vpc_id)
  
      def describe_vpcs(self, vpc_ids=None, filters=None):
          matches = self.vpcs.copy().values()
          if vpc_ids:
              matches = [vpc for vpc in matches if vpc.id in vpc_ids]
              if len(vpc_ids) > len(matches):
                  unknown_ids = set(vpc_ids) - set(matches)
                  raise InvalidVPCIdError(unknown_ids)
          if filters:
              matches = generic_filter(filters, matches)
          return matches
  
      def delete_vpc(self, vpc_id):
          # Do not delete if any VPN Gateway is attached
          vpn_gateways = self.describe_vpn_gateways(filters={"attachment.vpc-id": vpc_id})
          vpn_gateways = [
              item
              for item in vpn_gateways
              if item.attachments.get(vpc_id).state == "attached"
          ]
          if vpn_gateways:
              raise DependencyViolationError(
                  "The vpc {0} has dependencies and cannot be deleted.".format(vpc_id)
              )
  
          # Delete route table if only main route table remains.
          route_tables = self.describe_route_tables(filters={"vpc-id": vpc_id})
          if len(route_tables) > 1:
              raise DependencyViolationError(
                  "The vpc {0} has dependencies and cannot be deleted.".format(vpc_id)
              )
          for route_table in route_tables:
              self.delete_route_table(route_table.id)
  
          # Delete default security group if exists.
          default = self.get_security_group_by_name_or_id("default", vpc_id=vpc_id)
          if default:
              self.delete_security_group(group_id=default.id)
  
          # Now delete VPC.
          vpc = self.vpcs.pop(vpc_id, None)
          if not vpc:
              raise InvalidVPCIdError(vpc_id)
  
          if vpc.dhcp_options:
              vpc.dhcp_options.vpc = None
              self.delete_dhcp_options_set(vpc.dhcp_options.id)
              vpc.dhcp_options = None
          return vpc
  
      def describe_vpc_attribute(self, vpc_id, attr_name):
          vpc = self.get_vpc(vpc_id)
          if attr_name in ("enable_dns_support", "enable_dns_hostnames"):
              return getattr(vpc, attr_name)
          else:
              raise InvalidParameterValueError(attr_name)
  
      def modify_vpc_tenancy(self, vpc_id, tenancy):
          vpc = self.get_vpc(vpc_id)
          return vpc.modify_vpc_tenancy(tenancy)
  
      def enable_vpc_classic_link(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.enable_vpc_classic_link()
  
      def disable_vpc_classic_link(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.disable_vpc_classic_link()
  
      def enable_vpc_classic_link_dns_support(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.enable_vpc_classic_link_dns_support()
  
      def disable_vpc_classic_link_dns_support(self, vpc_id):
          vpc = self.get_vpc(vpc_id)
          return vpc.disable_vpc_classic_link_dns_support()
  
      def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):
          vpc = self.get_vpc(vpc_id)
          if attr_name in ("enable_dns_support", "enable_dns_hostnames"):
              setattr(vpc, attr_name, attr_value)
          else:
              raise InvalidParameterValueError(attr_name)
  
      def disassociate_vpc_cidr_block(self, association_id):
          for vpc in self.vpcs.copy().values():
              response = vpc.disassociate_vpc_cidr_block(association_id)
              for route_table in self.route_tables.copy().values():
                  if route_table.vpc_id == response.get("vpc_id"):
                      if "::/" in response.get("cidr_block"):
                          self.delete_route(
                              route_table.id, None, response.get("cidr_block")
                          )
                      else:
                          self.delete_route(route_table.id, response.get("cidr_block"))
              if response:
                  return response
          raise InvalidVpcCidrBlockAssociationIdError(association_id)
  
      def associate_vpc_cidr_block(
          self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block
      ):
          vpc = self.get_vpc(vpc_id)
          association_set = vpc.associate_vpc_cidr_block(
              cidr_block, amazon_provided_ipv6_cidr_block
          )
          for route_table in self.route_tables.copy().values():
              if route_table.vpc_id == vpc_id:
                  if amazon_provided_ipv6_cidr_block:
                      self.create_route(
                          route_table.id,
                          None,
                          destination_ipv6_cidr_block=association_set["cidr_block"],
                          local=True,
                      )
                  else:
                      self.create_route(
                          route_table.id, association_set["cidr_block"], local=True
                      )
          return association_set
  
      def create_vpc_endpoint(
          self,
          vpc_id,
          service_name,
          endpoint_type=None,
          policy_document=False,
          route_table_ids=None,
          subnet_ids=None,
          network_interface_ids=None,
          dns_entries=None,
          client_token=None,
          security_group_ids=None,
          tags=None,
          private_dns_enabled=None,
      ):
  
          vpc_endpoint_id = random_vpc_ep_id()
  
          # validates if vpc is present or not.
          self.get_vpc(vpc_id)
          destination_prefix_list_id = None
  
          if endpoint_type and endpoint_type.lower() == "interface":
  
              network_interface_ids = []
              for subnet_id in subnet_ids or []:
                  self.get_subnet(subnet_id)
                  eni = self.create_network_interface(subnet_id, random_private_ip())
                  network_interface_ids.append(eni.id)
  
              dns_entries = create_dns_entries(service_name, vpc_endpoint_id)
  
          else:
              # considering gateway if type is not mentioned.
              for prefix_list in self.managed_prefix_lists.values():
                  if prefix_list.prefix_list_name == service_name:
                      destination_prefix_list_id = prefix_list.id
  
          if dns_entries:
              dns_entries = [dns_entries]
  
          vpc_end_point = VPCEndPoint(
              self,
              vpc_endpoint_id,
              vpc_id,
              service_name,
              endpoint_type,
              policy_document,
              route_table_ids,
              subnet_ids,
              network_interface_ids,
              dns_entries,
              client_token,
              security_group_ids,
              tags,
              private_dns_enabled,
              destination_prefix_list_id,
          )
  
          self.vpc_end_points[vpc_endpoint_id] = vpc_end_point
  
          if destination_prefix_list_id:
              for route_table_id in route_table_ids:
                  self.create_route(
                      route_table_id,
                      None,
                      gateway_id=vpc_endpoint_id,
                      destination_prefix_list_id=destination_prefix_list_id,
                  )
  
          return vpc_end_point
  
      def delete_vpc_endpoints(self, vpce_ids=None):
          for vpce_id in vpce_ids or []:
              vpc_endpoint = self.vpc_end_points.get(vpce_id, None)
              if vpc_endpoint:
                  if vpc_endpoint.endpoint_type.lower() == "interface":
                      for eni_id in vpc_endpoint.network_interface_ids:
                          self.enis.pop(eni_id, None)
                  else:
                      for route_table_id in vpc_endpoint.route_table_ids:
                          self.delete_route(
                              route_table_id, vpc_endpoint.destination_prefix_list_id
                          )
                  vpc_endpoint.state = "deleted"
          return True
  
      def describe_vpc_endpoints(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)
  
      @staticmethod
      def _collect_default_endpoint_services(region):
          """Return list of default services using list of backends."""
          if DEFAULT_VPC_ENDPOINT_SERVICES:
              return DEFAULT_VPC_ENDPOINT_SERVICES
  
          zones = [
              zone.name
              for zones in RegionsAndZonesBackend.zones.values()
              for zone in zones
              if zone.name.startswith(region)
          ]
  
          from moto import backends  # pylint: disable=import-outside-toplevel
  
          for _backends in backends.unique_backends():
              if region in _backends:
                  service = _backends[region].default_vpc_endpoint_service(region, zones)
                  if service:
                      DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
  
              if "global" in _backends:
                  service = _backends["global"].default_vpc_endpoint_service(
                      region, zones
                  )
                  if service:
                      DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)
          return DEFAULT_VPC_ENDPOINT_SERVICES
  
      @staticmethod
      def _matches_service_by_tags(service, filter_item):
          """Return True if service tags are not filtered by their tags.
  
          Note that the API specifies a key of "Values" for a filter, but
          the botocore library returns "Value" instead.
          """
          # For convenience, collect the tags for this service.
          service_tag_keys = {x["Key"] for x in service["Tags"]}
          if not service_tag_keys:
              return False
  
          matched = True  # assume the best
          if filter_item["Name"] == "tag-key":
              # Filters=[{"Name":"tag-key", "Values":["Name"]}],
              # Any tag with this name, regardless of the tag value.
              if not service_tag_keys & set(filter_item["Value"]):
                  matched = False
  
          elif filter_item["Name"].startswith("tag:"):
              # Filters=[{"Name":"tag:Name", "Values":["my-load-balancer"]}],
              tag_name = filter_item["Name"].split(":")[1]
              if not service_tag_keys & {tag_name}:
                  matched = False
              else:
                  for tag in service["Tags"]:
                      if tag["Key"] == tag_name and tag["Value"] in filter_item["Value"]:
                          break
                  else:
                      matched = False
          return matched
  
      @staticmethod
      def _filter_endpoint_services(service_names_filters, filters, services):
          """Return filtered list of VPC endpoint services."""
          if not service_names_filters and not filters:
              return services
  
          # Verify the filters are valid.
          for filter_item in filters:
              if filter_item["Name"] not in [
                  "service-name",
                  "service-type",
                  "tag-key",
              ] and not filter_item["Name"].startswith("tag:"):
                  raise InvalidFilter(filter_item["Name"])
  
          # Apply both the service_names filter and the filters themselves.
          filtered_services = []
          for service in services:
              if (
                  service_names_filters
                  and service["ServiceName"] not in service_names_filters
              ):
                  continue
  
              # Note that the API specifies a key of "Values" for a filter, but
              # the botocore library returns "Value" instead.
              matched = True
              for filter_item in filters:
                  if filter_item["Name"] == "service-name":
                      if service["ServiceName"] not in filter_item["Value"]:
                          matched = False
  
                  elif filter_item["Name"] == "service-type":
                      service_types = {x["ServiceType"] for x in service["ServiceType"]}
                      if not service_types & set(filter_item["Value"]):
                          matched = False
  
                  elif filter_item["Name"] == "tag-key" or filter_item["Name"].startswith(
                      "tag:"
                  ):
                      if not VPCBackend._matches_service_by_tags(service, filter_item):
                          matched = False
  
                  # Exit early -- don't bother checking the remaining filters
                  # as a non-match was found.
                  if not matched:
                      break
  
              # Does the service have a matching service name or does it match
              # a filter?
              if matched:
                  filtered_services.append(service)
  
          return filtered_services
  
      def describe_vpc_endpoint_services(
          self, dry_run, service_names, filters, max_results, next_token, region
      ):  # pylint: disable=unused-argument,too-many-arguments
          """Return info on services to which you can create a VPC endpoint.
  
          Currently only the default endpoing services are returned.  When
          create_vpc_endpoint_service_configuration() is implemented, a
          list of those private endpoints would be kept and when this API
          is invoked, those private endpoints would be added to the list of
          default endpoint services.
  
          The DryRun parameter is ignored.
          """
          default_services = self._collect_default_endpoint_services(region)
          for service_name in service_names:
              if service_name not in [x["ServiceName"] for x in default_services]:
                  raise InvalidServiceName(service_name)
  
          # Apply filters specified in the service_names and filters arguments.
          filtered_services = sorted(
              self._filter_endpoint_services(service_names, filters, default_services),
              key=itemgetter("ServiceName"),
          )
  
          # Determine the start index into list of services based on the
          # next_token argument.
          start = 0
          vpce_ids = [x["ServiceId"] for x in filtered_services]
          if next_token:
              if next_token not in vpce_ids:
                  raise InvalidNextToken(next_token)
              start = vpce_ids.index(next_token)
  
          # Determine the stop index into the list of services based on the
          # max_results argument.
          if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:
              max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS
  
          # If necessary, set the value of the next_token.
          next_token = ""
          if len(filtered_services) > (start + max_results):
              service = filtered_services[start + max_results]
              next_token = service["ServiceId"]
  
          return {
              "servicesDetails": filtered_services[start : start + max_results],
              "serviceNames": [
                  x["ServiceName"] for x in filtered_services[start : start + max_results]
              ],
              "nextToken": next_token,
          }
  
      def get_vpc_end_point(self, vpc_end_point_id):
          vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)
          if not vpc_end_point:
              raise InvalidVpcEndPointIdError(vpc_end_point_id)
          return vpc_end_point
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
messages.role: user
verification_info: {"file_context": {"moto/ec2/models/vpcs.py": "import ipaddress\nimport json\nimport weakref\nfrom collections import defaultdict\nfrom operator import itemgetter\n\nfrom moto.core import get_account_id\nfrom moto.core.models import CloudFormationModel\nfrom .core import TaggedEC2Resource\nfrom ..exceptions import (\n    CidrLimitExceeded,\n    UnsupportedTenancy,\n    DependencyViolationError,\n    InvalidCIDRBlockParameterError,\n    InvalidServiceName,\n    InvalidFilter,\n    InvalidNextToken,\n    InvalidParameterValueError,\n    InvalidVpcCidrBlockAssociationIdError,\n    InvalidVPCIdError,\n    InvalidVPCRangeError,\n    OperationNotPermitted,\n    InvalidVpcEndPointIdError,\n)\nfrom .availability_zones_and_regions import RegionsAndZonesBackend\nfrom ..utils import (\n    random_ipv6_cidr,\n    random_vpc_ep_id,\n    random_private_ip,\n    create_dns_entries,\n    random_vpc_id,\n    random_vpc_cidr_association_id,\n    generic_filter,\n    utc_date_and_time,\n)\n\nMAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS = 1000\nDEFAULT_VPC_ENDPOINT_SERVICES = []\n\n\nclass VPCEndPoint(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        endpoint_id,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n        destination_prefix_list_id=None,\n    ):\n        self.ec2_backend = ec2_backend\n        self.id = endpoint_id\n        self.vpc_id = vpc_id\n        self.service_name = service_name\n        self.endpoint_type = endpoint_type\n        self.state = \"available\"\n        self.policy_document = policy_document\n        self.route_table_ids = route_table_ids\n        self.network_interface_ids = network_interface_ids or []\n        self.subnet_ids = subnet_ids\n        self.client_token = client_token\n        self.security_group_ids = security_group_ids\n        self.private_dns_enabled = private_dns_enabled\n        self.dns_entries = dns_entries\n        self.add_tags(tags or {})\n        self.destination_prefix_list_id = destination_prefix_list_id\n\n        self.created_at = utc_date_and_time()\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        return \"AWS::EC2::VPCEndpoint\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        service_name = properties.get(\"ServiceName\")\n        subnet_ids = properties.get(\"SubnetIds\")\n        vpc_endpoint_type = properties.get(\"VpcEndpointType\")\n        vpc_id = properties.get(\"VpcId\")\n        policy_document = properties.get(\"PolicyDocument\")\n        private_dns_enabled = properties.get(\"PrivateDnsEnabled\")\n        route_table_ids = properties.get(\"RouteTableIds\")\n        security_group_ids = properties.get(\"SecurityGroupIds\")\n\n        ec2_backend = ec2_backends[region_name]\n        vpc_endpoint = ec2_backend.create_vpc_endpoint(\n            vpc_id=vpc_id,\n            service_name=service_name,\n            endpoint_type=vpc_endpoint_type,\n            subnet_ids=subnet_ids,\n            policy_document=policy_document,\n            private_dns_enabled=private_dns_enabled,\n            route_table_ids=route_table_ids,\n            security_group_ids=security_group_ids,\n        )\n        return vpc_endpoint\n\n\nclass VPC(TaggedEC2Resource, CloudFormationModel):\n    def __init__(\n        self,\n        ec2_backend,\n        vpc_id,\n        cidr_block,\n        is_default,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n    ):\n\n        self.ec2_backend = ec2_backend\n        self.id = vpc_id\n        self.cidr_block = cidr_block\n        self.cidr_block_association_set = {}\n        self.dhcp_options = None\n        self.state = \"available\"\n        self.instance_tenancy = instance_tenancy\n        self.is_default = \"true\" if is_default else \"false\"\n        self.enable_dns_support = \"true\"\n        self.classic_link_enabled = \"false\"\n        self.classic_link_dns_supported = \"false\"\n        # This attribute is set to 'true' only for default VPCs\n        # or VPCs created using the wizard of the VPC console\n        self.enable_dns_hostnames = \"true\" if is_default else \"false\"\n\n        self.associate_vpc_cidr_block(cidr_block)\n        if amazon_provided_ipv6_cidr_block:\n            self.associate_vpc_cidr_block(\n                cidr_block,\n                amazon_provided_ipv6_cidr_block=amazon_provided_ipv6_cidr_block,\n            )\n\n    @property\n    def owner_id(self):\n        return get_account_id()\n\n    @staticmethod\n    def cloudformation_name_type():\n        return None\n\n    @staticmethod\n    def cloudformation_type():\n        # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html\n        return \"AWS::EC2::VPC\"\n\n    @classmethod\n    def create_from_cloudformation_json(\n        cls, resource_name, cloudformation_json, region_name, **kwargs\n    ):\n        from ..models import ec2_backends\n\n        properties = cloudformation_json[\"Properties\"]\n\n        ec2_backend = ec2_backends[region_name]\n        vpc = ec2_backend.create_vpc(\n            cidr_block=properties[\"CidrBlock\"],\n            instance_tenancy=properties.get(\"InstanceTenancy\", \"default\"),\n        )\n        for tag in properties.get(\"Tags\", []):\n            tag_key = tag[\"Key\"]\n            tag_value = tag[\"Value\"]\n            vpc.add_tag(tag_key, tag_value)\n\n        return vpc\n\n    @property\n    def physical_resource_id(self):\n        return self.id\n\n    def get_filter_value(self, filter_name):\n        if filter_name in (\"vpc-id\", \"vpcId\"):\n            return self.id\n        elif filter_name in (\"cidr\", \"cidr-block\", \"cidrBlock\"):\n            return self.cidr_block\n        elif filter_name in (\n            \"cidr-block-association.cidr-block\",\n            \"ipv6-cidr-block-association.ipv6-cidr-block\",\n        ):\n            return [\n                c[\"cidr_block\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\n            \"cidr-block-association.association-id\",\n            \"ipv6-cidr-block-association.association-id\",\n        ):\n            return self.cidr_block_association_set.keys()\n        elif filter_name in (\n            \"cidr-block-association.state\",\n            \"ipv6-cidr-block-association.state\",\n        ):\n            return [\n                c[\"cidr_block_state\"][\"state\"]\n                for c in self.get_cidr_block_association_set(ipv6=\"ipv6\" in filter_name)\n            ]\n        elif filter_name in (\"instance_tenancy\", \"InstanceTenancy\"):\n            return self.instance_tenancy\n        elif filter_name in (\"is-default\", \"isDefault\"):\n            return self.is_default\n        elif filter_name == \"state\":\n            return self.state\n        elif filter_name in (\"dhcp-options-id\", \"dhcpOptionsId\"):\n            if not self.dhcp_options:\n                return None\n            return self.dhcp_options.id\n        else:\n            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n\n    def modify_vpc_tenancy(self, tenancy):\n        if tenancy != \"default\":\n            raise UnsupportedTenancy(tenancy)\n        self.instance_tenancy = tenancy\n        return True\n\n    def associate_vpc_cidr_block(\n        self, cidr_block, amazon_provided_ipv6_cidr_block=False\n    ):\n        max_associations = 5 if not amazon_provided_ipv6_cidr_block else 1\n\n        for cidr in self.cidr_block_association_set.copy():\n            if (\n                self.cidr_block_association_set.get(cidr)\n                .get(\"cidr_block_state\")\n                .get(\"state\")\n                == \"disassociated\"\n            ):\n                self.cidr_block_association_set.pop(cidr)\n        if (\n            len(self.get_cidr_block_association_set(amazon_provided_ipv6_cidr_block))\n            >= max_associations\n        ):\n            raise CidrLimitExceeded(self.id, max_associations)\n\n        association_id = random_vpc_cidr_association_id()\n\n        association_set = {\n            \"association_id\": association_id,\n            \"cidr_block_state\": {\"state\": \"associated\", \"StatusMessage\": \"\"},\n        }\n\n        association_set[\"cidr_block\"] = (\n            random_ipv6_cidr() if amazon_provided_ipv6_cidr_block else cidr_block\n        )\n        self.cidr_block_association_set[association_id] = association_set\n        return association_set\n\n    def enable_vpc_classic_link(self):\n        # Check if current cidr block doesn't fall within the 10.0.0.0/8 block, excluding 10.0.0.0/16 and 10.1.0.0/16.\n        # Doesn't check any route tables, maybe something for in the future?\n        # See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html#classiclink-limitations\n        network_address = ipaddress.ip_network(self.cidr_block).network_address\n        if (\n            network_address not in ipaddress.ip_network(\"10.0.0.0/8\")\n            or network_address in ipaddress.ip_network(\"10.0.0.0/16\")\n            or network_address in ipaddress.ip_network(\"10.1.0.0/16\")\n        ):\n            self.classic_link_enabled = \"true\"\n\n        return self.classic_link_enabled\n\n    def disable_vpc_classic_link(self):\n        self.classic_link_enabled = \"false\"\n        return self.classic_link_enabled\n\n    def enable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"true\"\n        return self.classic_link_dns_supported\n\n    def disable_vpc_classic_link_dns_support(self):\n        self.classic_link_dns_supported = \"false\"\n        return self.classic_link_dns_supported\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        if self.cidr_block == self.cidr_block_association_set.get(\n            association_id, {}\n        ).get(\"cidr_block\"):\n            raise OperationNotPermitted(association_id)\n\n        entry = response = self.cidr_block_association_set.get(association_id, {})\n        if entry:\n            response = json.loads(json.dumps(entry))\n            response[\"vpc_id\"] = self.id\n            response[\"cidr_block_state\"][\"state\"] = \"disassociating\"\n            entry[\"cidr_block_state\"][\"state\"] = \"disassociated\"\n        return response\n\n    def get_cidr_block_association_set(self, ipv6=False):\n        return [\n            c\n            for c in self.cidr_block_association_set.values()\n            if (\"::/\" if ipv6 else \".\") in c.get(\"cidr_block\")\n        ]\n\n\nclass VPCBackend(object):\n    vpc_refs = defaultdict(set)\n\n    def __init__(self):\n        self.vpcs = {}\n        self.vpc_end_points = {}\n        self.vpc_refs[self.__class__].add(weakref.ref(self))\n        super().__init__()\n\n    def create_vpc(\n        self,\n        cidr_block,\n        instance_tenancy=\"default\",\n        amazon_provided_ipv6_cidr_block=False,\n        tags=None,\n    ):\n        vpc_id = random_vpc_id()\n        try:\n            vpc_cidr_block = ipaddress.IPv4Network(str(cidr_block), strict=False)\n        except ValueError:\n            raise InvalidCIDRBlockParameterError(cidr_block)\n        if vpc_cidr_block.prefixlen < 16 or vpc_cidr_block.prefixlen > 28:\n            raise InvalidVPCRangeError(cidr_block)\n        vpc = VPC(\n            self,\n            vpc_id,\n            cidr_block,\n            len(self.vpcs) == 0,\n            instance_tenancy,\n            amazon_provided_ipv6_cidr_block,\n        )\n\n        for tag in tags or []:\n            tag_key = tag.get(\"Key\")\n            tag_value = tag.get(\"Value\")\n            vpc.add_tag(tag_key, tag_value)\n\n        self.vpcs[vpc_id] = vpc\n\n        # AWS creates a default main route table and security group.\n        self.create_route_table(vpc_id, main=True)\n\n        # AWS creates a default Network ACL\n        self.create_network_acl(vpc_id, default=True)\n\n        default = self.get_security_group_from_name(\"default\", vpc_id=vpc_id)\n        if not default:\n            self.create_security_group(\n                \"default\", \"default VPC security group\", vpc_id=vpc_id, is_default=True\n            )\n\n        return vpc\n\n    def get_vpc(self, vpc_id):\n        if vpc_id not in self.vpcs:\n            raise InvalidVPCIdError(vpc_id)\n        return self.vpcs.get(vpc_id)\n\n    def describe_vpcs(self, vpc_ids=None, filters=None):\n        matches = self.vpcs.copy().values()\n        if vpc_ids:\n            matches = [vpc for vpc in matches if vpc.id in vpc_ids]\n            if len(vpc_ids) > len(matches):\n                unknown_ids = set(vpc_ids) - set(matches)\n                raise InvalidVPCIdError(unknown_ids)\n        if filters:\n            matches = generic_filter(filters, matches)\n        return matches\n\n    def delete_vpc(self, vpc_id):\n        # Do not delete if any VPN Gateway is attached\n        vpn_gateways = self.describe_vpn_gateways(filters={\"attachment.vpc-id\": vpc_id})\n        vpn_gateways = [\n            item\n            for item in vpn_gateways\n            if item.attachments.get(vpc_id).state == \"attached\"\n        ]\n        if vpn_gateways:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n\n        # Delete route table if only main route table remains.\n        route_tables = self.describe_route_tables(filters={\"vpc-id\": vpc_id})\n        if len(route_tables) > 1:\n            raise DependencyViolationError(\n                \"The vpc {0} has dependencies and cannot be deleted.\".format(vpc_id)\n            )\n        for route_table in route_tables:\n            self.delete_route_table(route_table.id)\n\n        # Delete default security group if exists.\n        default = self.get_security_group_by_name_or_id(\"default\", vpc_id=vpc_id)\n        if default:\n            self.delete_security_group(group_id=default.id)\n\n        # Now delete VPC.\n        vpc = self.vpcs.pop(vpc_id, None)\n        if not vpc:\n            raise InvalidVPCIdError(vpc_id)\n\n        if vpc.dhcp_options:\n            vpc.dhcp_options.vpc = None\n            self.delete_dhcp_options_set(vpc.dhcp_options.id)\n            vpc.dhcp_options = None\n        return vpc\n\n    def describe_vpc_attribute(self, vpc_id, attr_name):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            return getattr(vpc, attr_name)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def modify_vpc_tenancy(self, vpc_id, tenancy):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.modify_vpc_tenancy(tenancy)\n\n    def enable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link()\n\n    def disable_vpc_classic_link(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link()\n\n    def enable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.enable_vpc_classic_link_dns_support()\n\n    def disable_vpc_classic_link_dns_support(self, vpc_id):\n        vpc = self.get_vpc(vpc_id)\n        return vpc.disable_vpc_classic_link_dns_support()\n\n    def modify_vpc_attribute(self, vpc_id, attr_name, attr_value):\n        vpc = self.get_vpc(vpc_id)\n        if attr_name in (\"enable_dns_support\", \"enable_dns_hostnames\"):\n            setattr(vpc, attr_name, attr_value)\n        else:\n            raise InvalidParameterValueError(attr_name)\n\n    def disassociate_vpc_cidr_block(self, association_id):\n        for vpc in self.vpcs.copy().values():\n            response = vpc.disassociate_vpc_cidr_block(association_id)\n            for route_table in self.route_tables.copy().values():\n                if route_table.vpc_id == response.get(\"vpc_id\"):\n                    if \"::/\" in response.get(\"cidr_block\"):\n                        self.delete_route(\n                            route_table.id, None, response.get(\"cidr_block\")\n                        )\n                    else:\n                        self.delete_route(route_table.id, response.get(\"cidr_block\"))\n            if response:\n                return response\n        raise InvalidVpcCidrBlockAssociationIdError(association_id)\n\n    def associate_vpc_cidr_block(\n        self, vpc_id, cidr_block, amazon_provided_ipv6_cidr_block\n    ):\n        vpc = self.get_vpc(vpc_id)\n        association_set = vpc.associate_vpc_cidr_block(\n            cidr_block, amazon_provided_ipv6_cidr_block\n        )\n        for route_table in self.route_tables.copy().values():\n            if route_table.vpc_id == vpc_id:\n                if amazon_provided_ipv6_cidr_block:\n                    self.create_route(\n                        route_table.id,\n                        None,\n                        destination_ipv6_cidr_block=association_set[\"cidr_block\"],\n                        local=True,\n                    )\n                else:\n                    self.create_route(\n                        route_table.id, association_set[\"cidr_block\"], local=True\n                    )\n        return association_set\n\n    def create_vpc_endpoint(\n        self,\n        vpc_id,\n        service_name,\n        endpoint_type=None,\n        policy_document=False,\n        route_table_ids=None,\n        subnet_ids=None,\n        network_interface_ids=None,\n        dns_entries=None,\n        client_token=None,\n        security_group_ids=None,\n        tags=None,\n        private_dns_enabled=None,\n    ):\n\n        vpc_endpoint_id = random_vpc_ep_id()\n\n        # validates if vpc is present or not.\n        self.get_vpc(vpc_id)\n        destination_prefix_list_id = None\n\n        if endpoint_type and endpoint_type.lower() == \"interface\":\n\n            network_interface_ids = []\n            for subnet_id in subnet_ids or []:\n                self.get_subnet(subnet_id)\n                eni = self.create_network_interface(subnet_id, random_private_ip())\n                network_interface_ids.append(eni.id)\n\n            dns_entries = create_dns_entries(service_name, vpc_endpoint_id)\n\n        else:\n            # considering gateway if type is not mentioned.\n            for prefix_list in self.managed_prefix_lists.values():\n                if prefix_list.prefix_list_name == service_name:\n                    destination_prefix_list_id = prefix_list.id\n\n        if dns_entries:\n            dns_entries = [dns_entries]\n\n        vpc_end_point = VPCEndPoint(\n            self,\n            vpc_endpoint_id,\n            vpc_id,\n            service_name,\n            endpoint_type,\n            policy_document,\n            route_table_ids,\n            subnet_ids,\n            network_interface_ids,\n            dns_entries,\n            client_token,\n            security_group_ids,\n            tags,\n            private_dns_enabled,\n            destination_prefix_list_id,\n        )\n\n        self.vpc_end_points[vpc_endpoint_id] = vpc_end_point\n\n        if destination_prefix_list_id:\n            for route_table_id in route_table_ids:\n                self.create_route(\n                    route_table_id,\n                    None,\n                    gateway_id=vpc_endpoint_id,\n                    destination_prefix_list_id=destination_prefix_list_id,\n                )\n\n        return vpc_end_point\n\n    def delete_vpc_endpoints(self, vpce_ids=None):\n        for vpce_id in vpce_ids or []:\n            vpc_endpoint = self.vpc_end_points.get(vpce_id, None)\n            if vpc_endpoint:\n                if vpc_endpoint.endpoint_type.lower() == \"interface\":\n                    for eni_id in vpc_endpoint.network_interface_ids:\n                        self.enis.pop(eni_id, None)\n                else:\n                    for route_table_id in vpc_endpoint.route_table_ids:\n                        self.delete_route(\n                            route_table_id, vpc_endpoint.destination_prefix_list_id\n                        )\n                vpc_endpoint.state = \"deleted\"\n        return True\n\n    def describe_vpc_endpoints(self, vpc_end_point_ids, filters=None):\n        vpc_end_points = self.vpc_end_points.values()\n\n        if vpc_end_point_ids:\n            vpc_end_points = [\n                vpc_end_point\n                for vpc_end_point in vpc_end_points\n                if vpc_end_point.id in vpc_end_point_ids\n            ]\n            if len(vpc_end_points) != len(vpc_end_point_ids):\n                invalid_id = list(\n                    set(vpc_end_point_ids).difference(\n                        set([vpc_end_point.id for vpc_end_point in vpc_end_points])\n                    )\n                )[0]\n                raise InvalidVpcEndPointIdError(invalid_id)\n\n        return generic_filter(filters, vpc_end_points)\n\n    @staticmethod\n    def _collect_default_endpoint_services(region):\n        \"\"\"Return list of default services using list of backends.\"\"\"\n        if DEFAULT_VPC_ENDPOINT_SERVICES:\n            return DEFAULT_VPC_ENDPOINT_SERVICES\n\n        zones = [\n            zone.name\n            for zones in RegionsAndZonesBackend.zones.values()\n            for zone in zones\n            if zone.name.startswith(region)\n        ]\n\n        from moto import backends  # pylint: disable=import-outside-toplevel\n\n        for _backends in backends.unique_backends():\n            if region in _backends:\n                service = _backends[region].default_vpc_endpoint_service(region, zones)\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n\n            if \"global\" in _backends:\n                service = _backends[\"global\"].default_vpc_endpoint_service(\n                    region, zones\n                )\n                if service:\n                    DEFAULT_VPC_ENDPOINT_SERVICES.extend(service)\n        return DEFAULT_VPC_ENDPOINT_SERVICES\n\n    @staticmethod\n    def _matches_service_by_tags(service, filter_item):\n        \"\"\"Return True if service tags are not filtered by their tags.\n\n        Note that the API specifies a key of \"Values\" for a filter, but\n        the botocore library returns \"Value\" instead.\n        \"\"\"\n        # For convenience, collect the tags for this service.\n        service_tag_keys = {x[\"Key\"] for x in service[\"Tags\"]}\n        if not service_tag_keys:\n            return False\n\n        matched = True  # assume the best\n        if filter_item[\"Name\"] == \"tag-key\":\n            # Filters=[{\"Name\":\"tag-key\", \"Values\":[\"Name\"]}],\n            # Any tag with this name, regardless of the tag value.\n            if not service_tag_keys & set(filter_item[\"Value\"]):\n                matched = False\n\n        elif filter_item[\"Name\"].startswith(\"tag:\"):\n            # Filters=[{\"Name\":\"tag:Name\", \"Values\":[\"my-load-balancer\"]}],\n            tag_name = filter_item[\"Name\"].split(\":\")[1]\n            if not service_tag_keys & {tag_name}:\n                matched = False\n            else:\n                for tag in service[\"Tags\"]:\n                    if tag[\"Key\"] == tag_name and tag[\"Value\"] in filter_item[\"Value\"]:\n                        break\n                else:\n                    matched = False\n        return matched\n\n    @staticmethod\n    def _filter_endpoint_services(service_names_filters, filters, services):\n        \"\"\"Return filtered list of VPC endpoint services.\"\"\"\n        if not service_names_filters and not filters:\n            return services\n\n        # Verify the filters are valid.\n        for filter_item in filters:\n            if filter_item[\"Name\"] not in [\n                \"service-name\",\n                \"service-type\",\n                \"tag-key\",\n            ] and not filter_item[\"Name\"].startswith(\"tag:\"):\n                raise InvalidFilter(filter_item[\"Name\"])\n\n        # Apply both the service_names filter and the filters themselves.\n        filtered_services = []\n        for service in services:\n            if (\n                service_names_filters\n                and service[\"ServiceName\"] not in service_names_filters\n            ):\n                continue\n\n            # Note that the API specifies a key of \"Values\" for a filter, but\n            # the botocore library returns \"Value\" instead.\n            matched = True\n            for filter_item in filters:\n                if filter_item[\"Name\"] == \"service-name\":\n                    if service[\"ServiceName\"] not in filter_item[\"Value\"]:\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"service-type\":\n                    service_types = {x[\"ServiceType\"] for x in service[\"ServiceType\"]}\n                    if not service_types & set(filter_item[\"Value\"]):\n                        matched = False\n\n                elif filter_item[\"Name\"] == \"tag-key\" or filter_item[\"Name\"].startswith(\n                    \"tag:\"\n                ):\n                    if not VPCBackend._matches_service_by_tags(service, filter_item):\n                        matched = False\n\n                # Exit early -- don't bother checking the remaining filters\n                # as a non-match was found.\n                if not matched:\n                    break\n\n            # Does the service have a matching service name or does it match\n            # a filter?\n            if matched:\n                filtered_services.append(service)\n\n        return filtered_services\n\n    def describe_vpc_endpoint_services(\n        self, dry_run, service_names, filters, max_results, next_token, region\n    ):  # pylint: disable=unused-argument,too-many-arguments\n        \"\"\"Return info on services to which you can create a VPC endpoint.\n\n        Currently only the default endpoing services are returned.  When\n        create_vpc_endpoint_service_configuration() is implemented, a\n        list of those private endpoints would be kept and when this API\n        is invoked, those private endpoints would be added to the list of\n        default endpoint services.\n\n        The DryRun parameter is ignored.\n        \"\"\"\n        default_services = self._collect_default_endpoint_services(region)\n        for service_name in service_names:\n            if service_name not in [x[\"ServiceName\"] for x in default_services]:\n                raise InvalidServiceName(service_name)\n\n        # Apply filters specified in the service_names and filters arguments.\n        filtered_services = sorted(\n            self._filter_endpoint_services(service_names, filters, default_services),\n            key=itemgetter(\"ServiceName\"),\n        )\n\n        # Determine the start index into list of services based on the\n        # next_token argument.\n        start = 0\n        vpce_ids = [x[\"ServiceId\"] for x in filtered_services]\n        if next_token:\n            if next_token not in vpce_ids:\n                raise InvalidNextToken(next_token)\n            start = vpce_ids.index(next_token)\n\n        # Determine the stop index into the list of services based on the\n        # max_results argument.\n        if not max_results or max_results > MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS:\n            max_results = MAX_NUMBER_OF_ENDPOINT_SERVICES_RESULTS\n\n        # If necessary, set the value of the next_token.\n        next_token = \"\"\n        if len(filtered_services) > (start + max_results):\n            service = filtered_services[start + max_results]\n            next_token = service[\"ServiceId\"]\n\n        return {\n            \"servicesDetails\": filtered_services[start : start + max_results],\n            \"serviceNames\": [\n                x[\"ServiceName\"] for x in filtered_services[start : start + max_results]\n            ],\n            \"nextToken\": next_token,\n        }\n\n    def get_vpc_end_point(self, vpc_end_point_id):\n        vpc_end_point = self.vpc_end_points.get(vpc_end_point_id)\n        if not vpc_end_point:\n            raise InvalidVpcEndPointIdError(vpc_end_point_id)\n        return vpc_end_point\n"}, "filelevel_patches": {"moto/ec2/models/vpcs.py": "@@ -76,6 +76,12 @@ def __init__(\n \n         self.created_at = utc_date_and_time()\n \n+    def get_filter_value(self, filter_name):\n+        if filter_name in (\"vpc-endpoint-type\", \"vpc_endpoint_type\"):\n+            return self.endpoint_type\n+        else:\n+            return super().get_filter_value(filter_name, \"DescribeVpcs\")\n+\n     @property\n     def owner_id(self):\n         return ACCOUNT_ID"}}