EC2 - VpcEndpointServiceConfiguration (#4815)
This commit is contained in:
parent
f554ad3997
commit
2fd6f34060
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -268,6 +268,8 @@ jobs:
|
||||
cd ..
|
||||
- name: "Create report"
|
||||
run: |
|
||||
ls -la
|
||||
cp server_output.log moto-terraform-tests/build/server_output.log
|
||||
cd moto-terraform-tests
|
||||
bin/create-report
|
||||
bin/create-report-cli
|
||||
|
@ -1280,7 +1280,7 @@
|
||||
|
||||
## ec2
|
||||
<details>
|
||||
<summary>34% implemented</summary>
|
||||
<summary>35% implemented</summary>
|
||||
|
||||
- [ ] accept_reserved_instances_exchange_quote
|
||||
- [ ] accept_transit_gateway_multicast_domain_associations
|
||||
@ -1394,7 +1394,7 @@
|
||||
- [X] create_vpc
|
||||
- [X] create_vpc_endpoint
|
||||
- [ ] create_vpc_endpoint_connection_notification
|
||||
- [ ] create_vpc_endpoint_service_configuration
|
||||
- [X] create_vpc_endpoint_service_configuration
|
||||
- [X] create_vpc_peering_connection
|
||||
- [X] create_vpn_connection
|
||||
- [ ] create_vpn_connection_route
|
||||
@ -1455,7 +1455,7 @@
|
||||
- [X] delete_volume
|
||||
- [X] delete_vpc
|
||||
- [ ] delete_vpc_endpoint_connection_notifications
|
||||
- [ ] delete_vpc_endpoint_service_configurations
|
||||
- [X] delete_vpc_endpoint_service_configurations
|
||||
- [X] delete_vpc_endpoints
|
||||
- [X] delete_vpc_peering_connection
|
||||
- [X] delete_vpn_connection
|
||||
@ -1593,8 +1593,8 @@
|
||||
- [ ] describe_vpc_classic_link_dns_support
|
||||
- [ ] describe_vpc_endpoint_connection_notifications
|
||||
- [ ] describe_vpc_endpoint_connections
|
||||
- [ ] describe_vpc_endpoint_service_configurations
|
||||
- [ ] describe_vpc_endpoint_service_permissions
|
||||
- [X] describe_vpc_endpoint_service_configurations
|
||||
- [X] describe_vpc_endpoint_service_permissions
|
||||
- [X] describe_vpc_endpoint_services
|
||||
- [X] describe_vpc_endpoints
|
||||
- [X] describe_vpc_peering_connections
|
||||
@ -1728,9 +1728,9 @@
|
||||
- [X] modify_vpc_attribute
|
||||
- [ ] modify_vpc_endpoint
|
||||
- [ ] modify_vpc_endpoint_connection_notification
|
||||
- [ ] modify_vpc_endpoint_service_configuration
|
||||
- [X] modify_vpc_endpoint_service_configuration
|
||||
- [ ] modify_vpc_endpoint_service_payer_responsibility
|
||||
- [ ] modify_vpc_endpoint_service_permissions
|
||||
- [X] modify_vpc_endpoint_service_permissions
|
||||
- [X] modify_vpc_peering_connection_options
|
||||
- [X] modify_vpc_tenancy
|
||||
- [ ] modify_vpn_connection
|
||||
|
@ -1,6 +1,7 @@
|
||||
include README.md LICENSE AUTHORS.md
|
||||
include requirements.txt requirements-dev.txt tox.ini
|
||||
include moto/config/resources/aws_managed_rules.json
|
||||
include moto/ec2/_models/*.py
|
||||
include moto/ec2/resources/instance_types.json
|
||||
include moto/ec2/resources/instance_type_offerings/*/*.json
|
||||
include moto/ec2/resources/amis.json
|
||||
|
@ -141,7 +141,7 @@ ec2
|
||||
- [X] create_vpc
|
||||
- [X] create_vpc_endpoint
|
||||
- [ ] create_vpc_endpoint_connection_notification
|
||||
- [ ] create_vpc_endpoint_service_configuration
|
||||
- [X] create_vpc_endpoint_service_configuration
|
||||
- [X] create_vpc_peering_connection
|
||||
- [X] create_vpn_connection
|
||||
- [ ] create_vpn_connection_route
|
||||
@ -202,7 +202,7 @@ ec2
|
||||
- [X] delete_volume
|
||||
- [X] delete_vpc
|
||||
- [ ] delete_vpc_endpoint_connection_notifications
|
||||
- [ ] delete_vpc_endpoint_service_configurations
|
||||
- [X] delete_vpc_endpoint_service_configurations
|
||||
- [X] delete_vpc_endpoints
|
||||
- [X] delete_vpc_peering_connection
|
||||
- [X] delete_vpn_connection
|
||||
@ -344,8 +344,16 @@ ec2
|
||||
- [ ] describe_vpc_classic_link_dns_support
|
||||
- [ ] describe_vpc_endpoint_connection_notifications
|
||||
- [ ] describe_vpc_endpoint_connections
|
||||
- [ ] describe_vpc_endpoint_service_configurations
|
||||
- [ ] describe_vpc_endpoint_service_permissions
|
||||
- [X] describe_vpc_endpoint_service_configurations
|
||||
|
||||
The Filters, MaxResults, NextToken parameters are not yet implemented
|
||||
|
||||
|
||||
- [X] describe_vpc_endpoint_service_permissions
|
||||
|
||||
The Filters, MaxResults, NextToken parameters are not yet implemented
|
||||
|
||||
|
||||
- [X] describe_vpc_endpoint_services
|
||||
Return info on services to which you can create a VPC endpoint.
|
||||
|
||||
@ -490,9 +498,13 @@ ec2
|
||||
- [X] modify_vpc_attribute
|
||||
- [ ] modify_vpc_endpoint
|
||||
- [ ] modify_vpc_endpoint_connection_notification
|
||||
- [ ] modify_vpc_endpoint_service_configuration
|
||||
- [X] modify_vpc_endpoint_service_configuration
|
||||
|
||||
The following parameters are not yet implemented: RemovePrivateDnsName, AddNetworkLoadBalancerArns, RemoveNetworkLoadBalancerArns, AddGatewayLoadBalancerArns, RemoveGatewayLoadBalancerArns
|
||||
|
||||
|
||||
- [ ] modify_vpc_endpoint_service_payer_responsibility
|
||||
- [ ] modify_vpc_endpoint_service_permissions
|
||||
- [X] modify_vpc_endpoint_service_permissions
|
||||
- [X] modify_vpc_peering_connection_options
|
||||
- [X] modify_vpc_tenancy
|
||||
- [ ] modify_vpn_connection
|
||||
|
39
moto/ec2/_models/core.py
Normal file
39
moto/ec2/_models/core.py
Normal file
@ -0,0 +1,39 @@
|
||||
from moto.core.models import BaseModel
|
||||
|
||||
from ..exceptions import FilterNotImplementedError
|
||||
|
||||
|
||||
class TaggedEC2Resource(BaseModel):
|
||||
def get_tags(self, *args, **kwargs):
|
||||
tags = []
|
||||
if self.id:
|
||||
tags = self.ec2_backend.describe_tags(filters={"resource-id": [self.id]})
|
||||
return tags
|
||||
|
||||
def add_tag(self, key, value):
|
||||
self.ec2_backend.create_tags([self.id], {key: value})
|
||||
|
||||
def add_tags(self, tag_map):
|
||||
for key, value in tag_map.items():
|
||||
self.ec2_backend.create_tags([self.id], {key: value})
|
||||
|
||||
def get_filter_value(self, filter_name, method_name=None):
|
||||
tags = self.get_tags()
|
||||
|
||||
if filter_name.startswith("tag:"):
|
||||
tagname = filter_name.replace("tag:", "", 1)
|
||||
for tag in tags:
|
||||
if tag["key"] == tagname:
|
||||
return tag["value"]
|
||||
|
||||
return None
|
||||
elif filter_name == "tag-key":
|
||||
return [tag["key"] for tag in tags]
|
||||
elif filter_name == "tag-value":
|
||||
return [tag["value"] for tag in tags]
|
||||
|
||||
value = getattr(self, filter_name.lower().replace("-", "_"), None)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
raise FilterNotImplementedError(filter_name, method_name)
|
132
moto/ec2/_models/vpc_service_configuration.py
Normal file
132
moto/ec2/_models/vpc_service_configuration.py
Normal file
@ -0,0 +1,132 @@
|
||||
from moto.core.models import CloudFormationModel
|
||||
from moto.core.utils import get_random_hex
|
||||
from .core import TaggedEC2Resource
|
||||
from ..exceptions import UnknownVpcEndpointService
|
||||
|
||||
|
||||
class VPCServiceConfiguration(TaggedEC2Resource, CloudFormationModel):
|
||||
def __init__(
|
||||
self, load_balancers, region, acceptance_required, private_dns_name, ec2_backend
|
||||
):
|
||||
self.id = f"vpce-svc-{get_random_hex(length=8)}"
|
||||
self.service_name = f"com.amazonaws.vpce.{region}.{self.id}"
|
||||
self.service_state = "Available"
|
||||
|
||||
self.availability_zones = []
|
||||
for lb in load_balancers:
|
||||
for subnet in lb.subnets:
|
||||
self.availability_zones.append(subnet.availability_zone)
|
||||
|
||||
self.gateway_load_balancer_arns = []
|
||||
self.network_load_balancer_arns = []
|
||||
for lb in load_balancers:
|
||||
if lb.loadbalancer_type == "network":
|
||||
self.service_type = "Interface"
|
||||
self.network_load_balancer_arns.append(lb.arn)
|
||||
else:
|
||||
self.service_type = "Gateway"
|
||||
self.gateway_load_balancer_arns.append(lb.arn)
|
||||
|
||||
self.acceptance_required = acceptance_required
|
||||
self.manages_vpc_endpoints = False
|
||||
self.private_dns_name = private_dns_name
|
||||
self.endpoint_dns_name = f"{self.id}.{region}.vpce.amazonaws.com"
|
||||
|
||||
self.principals = []
|
||||
self.ec2_backend = ec2_backend
|
||||
|
||||
|
||||
class VPCServiceConfigurationBackend(object):
|
||||
def __init__(self):
|
||||
self.configurations = {}
|
||||
super().__init__()
|
||||
|
||||
@property
|
||||
def elbv2_backend(self):
|
||||
from moto.elbv2.models import elbv2_backends
|
||||
|
||||
return elbv2_backends[self.region_name]
|
||||
|
||||
def get_vpc_endpoint_service(self, resource_id):
|
||||
return self.configurations.get(resource_id)
|
||||
|
||||
def create_vpc_endpoint_service_configuration(
|
||||
self, lb_arns, acceptance_required, private_dns_name, tags
|
||||
):
|
||||
lbs = self.elbv2_backend.describe_load_balancers(arns=lb_arns, names=None)
|
||||
config = VPCServiceConfiguration(
|
||||
load_balancers=lbs,
|
||||
region=self.region_name,
|
||||
acceptance_required=acceptance_required,
|
||||
private_dns_name=private_dns_name,
|
||||
ec2_backend=self,
|
||||
)
|
||||
for tag in tags or []:
|
||||
tag_key = tag.get("Key")
|
||||
tag_value = tag.get("Value")
|
||||
config.add_tag(tag_key, tag_value)
|
||||
|
||||
self.configurations[config.id] = config
|
||||
return config
|
||||
|
||||
def describe_vpc_endpoint_service_configurations(self, service_ids):
|
||||
"""
|
||||
The Filters, MaxResults, NextToken parameters are not yet implemented
|
||||
"""
|
||||
if service_ids:
|
||||
found_configs = []
|
||||
for service_id in service_ids:
|
||||
if service_id in self.configurations:
|
||||
found_configs.append(self.configurations[service_id])
|
||||
else:
|
||||
raise UnknownVpcEndpointService(service_id)
|
||||
return found_configs
|
||||
return self.configurations.values()
|
||||
|
||||
def delete_vpc_endpoint_service_configurations(self, service_ids):
|
||||
missing = [s for s in service_ids if s not in self.configurations]
|
||||
for s in service_ids:
|
||||
self.configurations.pop(s, None)
|
||||
return missing
|
||||
|
||||
def describe_vpc_endpoint_service_permissions(self, service_id):
|
||||
"""
|
||||
The Filters, MaxResults, NextToken parameters are not yet implemented
|
||||
"""
|
||||
config = self.describe_vpc_endpoint_service_configurations([service_id])[0]
|
||||
return config.principals
|
||||
|
||||
def modify_vpc_endpoint_service_permissions(
|
||||
self, service_id, add_principals, remove_principals
|
||||
):
|
||||
config = self.describe_vpc_endpoint_service_configurations([service_id])[0]
|
||||
config.principals += add_principals
|
||||
config.principals = [p for p in config.principals if p not in remove_principals]
|
||||
config.principals = list(set(config.principals))
|
||||
|
||||
def modify_vpc_endpoint_service_configuration(
|
||||
self,
|
||||
service_id,
|
||||
acceptance_required,
|
||||
private_dns_name,
|
||||
add_network_lbs,
|
||||
remove_network_lbs,
|
||||
add_gateway_lbs,
|
||||
remove_gateway_lbs,
|
||||
):
|
||||
"""
|
||||
The following parameters are not yet implemented: RemovePrivateDnsName
|
||||
"""
|
||||
config = self.describe_vpc_endpoint_service_configurations([service_id])[0]
|
||||
if private_dns_name is not None:
|
||||
config.private_dns_name = private_dns_name
|
||||
if acceptance_required is not None:
|
||||
config.acceptance_required = str(acceptance_required).lower() == "true"
|
||||
for lb in add_network_lbs:
|
||||
config.network_load_balancer_arns.append(lb)
|
||||
for lb in remove_network_lbs:
|
||||
config.network_load_balancer_arns.remove(lb)
|
||||
for lb in add_gateway_lbs:
|
||||
config.gateway_load_balancer_arns.append(lb)
|
||||
for lb in remove_gateway_lbs:
|
||||
config.gateway_load_balancer_arns.remove(lb)
|
@ -734,3 +734,19 @@ class InvalidCarrierGatewayID(EC2ClientError):
|
||||
"InvalidCarrierGatewayID.NotFound",
|
||||
"The CarrierGateway ID '{0}' does not exist".format(carrier_gateway_id),
|
||||
)
|
||||
|
||||
|
||||
class NoLoadBalancersProvided(EC2ClientError):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
"InvalidParameter",
|
||||
"exactly one of network_load_balancer_arn or gateway_load_balancer_arn is a required member",
|
||||
)
|
||||
|
||||
|
||||
class UnknownVpcEndpointService(EC2ClientError):
|
||||
def __init__(self, service_id):
|
||||
super().__init__(
|
||||
"InvalidVpcEndpointServiceId.NotFound",
|
||||
f"The VpcEndpointService Id '{service_id}' does not exist",
|
||||
)
|
||||
|
@ -17,7 +17,7 @@ from boto3 import Session
|
||||
|
||||
from moto.core import ACCOUNT_ID
|
||||
from moto.core import BaseBackend
|
||||
from moto.core.models import Model, BaseModel, CloudFormationModel
|
||||
from moto.core.models import Model, CloudFormationModel
|
||||
from moto.core.utils import (
|
||||
iso_8601_datetime_with_milliseconds,
|
||||
camelcase_to_underscores,
|
||||
@ -121,6 +121,8 @@ from .exceptions import (
|
||||
InvalidGatewayIDError,
|
||||
InvalidCarrierGatewayID,
|
||||
)
|
||||
from ._models.core import TaggedEC2Resource
|
||||
from ._models.vpc_service_configuration import VPCServiceConfigurationBackend
|
||||
from .utils import (
|
||||
EC2_RESOURCE_TO_PREFIX,
|
||||
EC2_PREFIX_TO_RESOURCE,
|
||||
@ -239,42 +241,6 @@ class StateReason(object):
|
||||
self.code = code
|
||||
|
||||
|
||||
class TaggedEC2Resource(BaseModel):
|
||||
def get_tags(self, *args, **kwargs):
|
||||
tags = []
|
||||
if self.id:
|
||||
tags = self.ec2_backend.describe_tags(filters={"resource-id": [self.id]})
|
||||
return tags
|
||||
|
||||
def add_tag(self, key, value):
|
||||
self.ec2_backend.create_tags([self.id], {key: value})
|
||||
|
||||
def add_tags(self, tag_map):
|
||||
for key, value in tag_map.items():
|
||||
self.ec2_backend.create_tags([self.id], {key: value})
|
||||
|
||||
def get_filter_value(self, filter_name, method_name=None):
|
||||
tags = self.get_tags()
|
||||
|
||||
if filter_name.startswith("tag:"):
|
||||
tagname = filter_name.replace("tag:", "", 1)
|
||||
for tag in tags:
|
||||
if tag["key"] == tagname:
|
||||
return tag["value"]
|
||||
|
||||
return None
|
||||
elif filter_name == "tag-key":
|
||||
return [tag["key"] for tag in tags]
|
||||
elif filter_name == "tag-value":
|
||||
return [tag["value"] for tag in tags]
|
||||
|
||||
value = getattr(self, filter_name.lower().replace("-", "_"), None)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
raise FilterNotImplementedError(filter_name, method_name)
|
||||
|
||||
|
||||
class NetworkInterface(TaggedEC2Resource, CloudFormationModel):
|
||||
def __init__(
|
||||
self,
|
||||
@ -503,6 +469,8 @@ class NetworkInterface(TaggedEC2Resource, CloudFormationModel):
|
||||
return self.description
|
||||
elif filter_name == "attachment.instance-id":
|
||||
return self.instance.id if self.instance else None
|
||||
elif filter_name == "attachment.instance-owner-id":
|
||||
return self.owner_id
|
||||
else:
|
||||
return super().get_filter_value(filter_name, "DescribeNetworkInterfaces")
|
||||
|
||||
@ -1509,27 +1477,6 @@ class SettingsBackend(object):
|
||||
class TagBackend(object):
|
||||
VALID_TAG_FILTERS = ["key", "resource-id", "resource-type", "value"]
|
||||
|
||||
VALID_TAG_RESOURCE_FILTER_TYPES = [
|
||||
"customer-gateway",
|
||||
"dhcp-options",
|
||||
"image",
|
||||
"instance",
|
||||
"internet-gateway",
|
||||
"network-acl",
|
||||
"network-interface",
|
||||
"reserved-instances",
|
||||
"route-table",
|
||||
"security-group",
|
||||
"snapshot",
|
||||
"spot-instances-request",
|
||||
"subnet",
|
||||
"volume",
|
||||
"vpc",
|
||||
"vpc-flow-log",
|
||||
"vpc-peering-connection" "vpn-connection",
|
||||
"vpn-gateway",
|
||||
]
|
||||
|
||||
def __init__(self):
|
||||
self.tags = defaultdict(dict)
|
||||
super().__init__()
|
||||
@ -8667,6 +8614,7 @@ class EC2Backend(
|
||||
FlowLogsBackend,
|
||||
NetworkInterfaceBackend,
|
||||
VPNConnectionBackend,
|
||||
VPCServiceConfigurationBackend,
|
||||
VPCPeeringConnectionBackend,
|
||||
RouteTableBackend,
|
||||
RouteBackend,
|
||||
@ -8781,6 +8729,8 @@ class EC2Backend(
|
||||
self.get_volume(volume_id=resource_id)
|
||||
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["vpc"]:
|
||||
self.get_vpc(vpc_id=resource_id)
|
||||
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["vpc-endpoint-service"]:
|
||||
self.get_vpc_endpoint_service(resource_id)
|
||||
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["vpc-peering-connection"]:
|
||||
self.get_vpc_peering_connection(vpc_pcx_id=resource_id)
|
||||
elif resource_prefix == EC2_RESOURCE_TO_PREFIX["vpn-connection"]:
|
||||
|
@ -30,6 +30,7 @@ from .virtual_private_gateways import VirtualPrivateGateways
|
||||
from .vm_export import VMExport
|
||||
from .vm_import import VMImport
|
||||
from .vpcs import VPCs
|
||||
from .vpc_service_configuration import VPCEndpointServiceConfiguration
|
||||
from .vpc_peering_connections import VPCPeeringConnections
|
||||
from .vpn_connections import VPNConnections
|
||||
from .windows import Windows
|
||||
@ -74,6 +75,7 @@ class EC2Response(
|
||||
VMExport,
|
||||
VMImport,
|
||||
VPCs,
|
||||
VPCEndpointServiceConfiguration,
|
||||
VPCPeeringConnections,
|
||||
VPNConnections,
|
||||
Windows,
|
||||
|
223
moto/ec2/responses/vpc_service_configuration.py
Normal file
223
moto/ec2/responses/vpc_service_configuration.py
Normal file
@ -0,0 +1,223 @@
|
||||
from moto.core.responses import BaseResponse
|
||||
|
||||
from ..exceptions import NoLoadBalancersProvided
|
||||
|
||||
|
||||
class VPCEndpointServiceConfiguration(BaseResponse):
|
||||
def create_vpc_endpoint_service_configuration(self):
|
||||
gateway_lbs = self._get_multi_param("GatewayLoadBalancerArn")
|
||||
network_lbs = self._get_multi_param("NetworkLoadBalancerArn")
|
||||
if not gateway_lbs and not network_lbs:
|
||||
raise NoLoadBalancersProvided
|
||||
|
||||
tags = self._get_multi_param("TagSpecification")
|
||||
if tags:
|
||||
tags = tags[0].get("Tag")
|
||||
acceptance_required = (
|
||||
str(self._get_param("AcceptanceRequired", "true")).lower() == "true"
|
||||
)
|
||||
private_dns_name = self._get_param("PrivateDnsName")
|
||||
|
||||
config = self.ec2_backend.create_vpc_endpoint_service_configuration(
|
||||
gateway_lbs or network_lbs,
|
||||
acceptance_required=acceptance_required,
|
||||
private_dns_name=private_dns_name,
|
||||
tags=tags,
|
||||
)
|
||||
template = self.response_template(CREATE_VPC_ENDPOINT_SERVICE_CONFIGURATION)
|
||||
return template.render(config=config)
|
||||
|
||||
def describe_vpc_endpoint_service_configurations(self):
|
||||
service_ids = self._get_multi_param("ServiceId")
|
||||
|
||||
configs = self.ec2_backend.describe_vpc_endpoint_service_configurations(
|
||||
service_ids
|
||||
)
|
||||
|
||||
template = self.response_template(DESCRIBE_VPC_ENDPOINT_SERVICE_CONFIGURATION)
|
||||
return template.render(configs=configs)
|
||||
|
||||
def delete_vpc_endpoint_service_configurations(self):
|
||||
service_ids = self._get_multi_param("ServiceId")
|
||||
missing_configs = self.ec2_backend.delete_vpc_endpoint_service_configurations(
|
||||
service_ids
|
||||
)
|
||||
|
||||
template = self.response_template(DELETE_VPC_ENDPOINT_SERVICE_CONFIGURATION)
|
||||
return template.render(missing=missing_configs)
|
||||
|
||||
def describe_vpc_endpoint_service_permissions(self):
|
||||
service_id = self._get_param("ServiceId")
|
||||
|
||||
principals = self.ec2_backend.describe_vpc_endpoint_service_permissions(
|
||||
service_id
|
||||
)
|
||||
|
||||
template = self.response_template(DESCRIBE_VPC_ENDPOINT_SERVICE_PERMISSIONS)
|
||||
return template.render(principals=principals)
|
||||
|
||||
def modify_vpc_endpoint_service_configuration(self):
|
||||
service_id = self._get_param("ServiceId")
|
||||
private_dns_name = self._get_param("PrivateDnsName")
|
||||
acceptance_required = self._get_param("AcceptanceRequired")
|
||||
add_network_lbs = self._get_multi_param("AddNetworkLoadBalancerArn")
|
||||
remove_network_lbs = self._get_multi_param("RemoveNetworkLoadBalancerArn")
|
||||
add_gateway_lbs = self._get_multi_param("AddGatewayLoadBalancerArn")
|
||||
remove_gateway_lbs = self._get_multi_param("RemoveGatewayLoadBalancerArn")
|
||||
|
||||
self.ec2_backend.modify_vpc_endpoint_service_configuration(
|
||||
service_id,
|
||||
acceptance_required=acceptance_required,
|
||||
private_dns_name=private_dns_name,
|
||||
add_network_lbs=add_network_lbs,
|
||||
remove_network_lbs=remove_network_lbs,
|
||||
add_gateway_lbs=add_gateway_lbs,
|
||||
remove_gateway_lbs=remove_gateway_lbs,
|
||||
)
|
||||
|
||||
return MODIFY_VPC_ENDPOINT_SERVICE_CONFIGURATION
|
||||
|
||||
def modify_vpc_endpoint_service_permissions(self):
|
||||
service_id = self._get_param("ServiceId")
|
||||
add_principals = self._get_multi_param("AddAllowedPrincipals")
|
||||
remove_principals = self._get_multi_param("RemoveAllowedPrincipals")
|
||||
|
||||
self.ec2_backend.modify_vpc_endpoint_service_permissions(
|
||||
service_id, add_principals, remove_principals
|
||||
)
|
||||
|
||||
return MODIFY_VPC_ENDPOINT_SERVICE_PERMISSIONS
|
||||
|
||||
|
||||
CREATE_VPC_ENDPOINT_SERVICE_CONFIGURATION = """
|
||||
<CreateVpcEndpointServiceConfigurationResult xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
<requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
|
||||
<serviceConfiguration>
|
||||
<serviceType>
|
||||
<item><serviceType>{{ config.service_type }}</serviceType></item>
|
||||
</serviceType>
|
||||
<serviceId>{{ config.id }}</serviceId>
|
||||
<serviceName>{{ config.service_name }}</serviceName>
|
||||
<serviceState>{{ config.service_state }}</serviceState>
|
||||
<availabilityZoneSet>
|
||||
{% for zone in config.availability_zones %}<item>{{ zone }}</item>{% endfor %}
|
||||
</availabilityZoneSet>
|
||||
<acceptanceRequired>{{ 'true' if config.acceptance_required else 'false' }}</acceptanceRequired>
|
||||
<managesVpcEndpoints>{{ 'true' if config.manages_vpc_endpoints else 'false' }}</managesVpcEndpoints>
|
||||
{%- if config.network_load_balancer_arns %}
|
||||
<networkLoadBalancerArnSet>
|
||||
{% for lb in config.network_load_balancer_arns %}<item>{{ lb }}</item>{% endfor %}
|
||||
</networkLoadBalancerArnSet>
|
||||
{% endif -%}
|
||||
{%- if config.gateway_load_balancer_arns %}
|
||||
<gatewayLoadBalancerArnSet>
|
||||
{% for lb in config.gateway_load_balancer_arns %}<item>{{ lb }}</item>{% endfor %}
|
||||
</gatewayLoadBalancerArnSet>
|
||||
{% endif -%}
|
||||
<baseEndpointDnsNameSet><item>{{ config.endpoint_dns_name }}</item></baseEndpointDnsNameSet>
|
||||
<privateDnsName>{{ config.private_dns_name }}</privateDnsName>
|
||||
<privateDnsNameConfiguration>
|
||||
{% if config.private_dns_name %}
|
||||
<state>verified</state>
|
||||
<type>TXT</type>
|
||||
<value>val</value>
|
||||
<name>n</name>
|
||||
{% endif %}
|
||||
</privateDnsNameConfiguration>
|
||||
</serviceConfiguration>
|
||||
</CreateVpcEndpointServiceConfigurationResult>
|
||||
"""
|
||||
|
||||
|
||||
DESCRIBE_VPC_ENDPOINT_SERVICE_CONFIGURATION = """
|
||||
<DescribeVpcEndpointServiceConfigurationsResult>
|
||||
<serviceConfigurationSet>
|
||||
{% for config in configs %}
|
||||
<item>
|
||||
<serviceType>
|
||||
<item><serviceType>{{ config.service_type }}</serviceType></item>
|
||||
</serviceType>
|
||||
<serviceId>{{ config.id }}</serviceId>
|
||||
<serviceName>{{ config.service_name }}</serviceName>
|
||||
<serviceState>{{ config.service_state }}</serviceState>
|
||||
<availabilityZoneSet>
|
||||
{% for zone in config.availability_zones %}<item>{{ zone }}</item>{% endfor %}
|
||||
</availabilityZoneSet>
|
||||
<acceptanceRequired>{{ 'true' if config.acceptance_required else 'false' }}</acceptanceRequired>
|
||||
<managesVpcEndpoints>{{ 'true' if config.manages_vpc_endpoints else 'false' }}</managesVpcEndpoints>
|
||||
{%- if config.network_load_balancer_arns %}
|
||||
<networkLoadBalancerArnSet>
|
||||
{% for lb in config.network_load_balancer_arns %}<item>{{ lb }}</item>{% endfor %}
|
||||
</networkLoadBalancerArnSet>
|
||||
{% endif -%}
|
||||
{%- if config.gateway_load_balancer_arns %}
|
||||
<gatewayLoadBalancerArnSet>
|
||||
{% for lb in config.gateway_load_balancer_arns %}<item>{{ lb }}</item>{% endfor %}
|
||||
</gatewayLoadBalancerArnSet>
|
||||
{% endif -%}
|
||||
<baseEndpointDnsNameSet><item>{{ config.endpoint_dns_name }}</item></baseEndpointDnsNameSet>
|
||||
<privateDnsName>{{ config.private_dns_name }}</privateDnsName>
|
||||
<privateDnsNameConfiguration>
|
||||
{% if config.private_dns_name %}
|
||||
<state>verified</state>
|
||||
<type>TXT</type>
|
||||
<value>val</value>
|
||||
<name>n</name>
|
||||
{% endif %}
|
||||
</privateDnsNameConfiguration>
|
||||
<tagSet>
|
||||
{% for tag in config.get_tags() %}
|
||||
<item>
|
||||
<key>{{ tag.key }}</key>
|
||||
<value>{{ tag.value }}</value>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</tagSet>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</serviceConfigurationSet>
|
||||
</DescribeVpcEndpointServiceConfigurationsResult>
|
||||
"""
|
||||
|
||||
|
||||
DELETE_VPC_ENDPOINT_SERVICE_CONFIGURATION = """
|
||||
<DeleteVpcEndpointServiceConfigurationsResult>
|
||||
<unsuccessful>
|
||||
{% for m in missing %}
|
||||
<item>
|
||||
<error>
|
||||
<code>InvalidVpcEndpointService.NotFound</code>
|
||||
<message>The VpcEndpointService Id '{{ m }}' does not exist</message>
|
||||
</error>
|
||||
<resourceId>{{ m }}</resourceId>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</unsuccessful>
|
||||
</DeleteVpcEndpointServiceConfigurationsResult>
|
||||
"""
|
||||
|
||||
|
||||
DESCRIBE_VPC_ENDPOINT_SERVICE_PERMISSIONS = """
|
||||
<DescribeVpcEndpointServicePermissionsResult>
|
||||
<allowedPrincipals>
|
||||
{% for principal in principals %}
|
||||
<item>
|
||||
<principal>{{ principal }}</principal>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</allowedPrincipals>
|
||||
</DescribeVpcEndpointServicePermissionsResult>
|
||||
"""
|
||||
|
||||
MODIFY_VPC_ENDPOINT_SERVICE_PERMISSIONS = """
|
||||
<ModifyVpcEndpointServicePermissionsResult>
|
||||
<return>true</return>
|
||||
</ModifyVpcEndpointServicePermissionsResult>
|
||||
"""
|
||||
|
||||
|
||||
MODIFY_VPC_ENDPOINT_SERVICE_CONFIGURATION = """
|
||||
<ModifyVpcEndpointServiceConfigurationResult>
|
||||
<return>true</return>
|
||||
</ModifyVpcEndpointServiceConfigurationResult>
|
||||
"""
|
@ -43,6 +43,7 @@ EC2_RESOURCE_TO_PREFIX = {
|
||||
"volume": "vol",
|
||||
"vpc": "vpc",
|
||||
"vpc-endpoint": "vpce",
|
||||
"vpc-endpoint-service": "vpce-svc",
|
||||
"managed-prefix-list": "pl",
|
||||
"vpc-cidr-association-id": "vpc-cidr-assoc",
|
||||
"vpc-elastic-ip": "eipalloc",
|
||||
@ -626,6 +627,8 @@ def get_prefix(resource_id):
|
||||
if resource_id_prefix == EC2_RESOURCE_TO_PREFIX["network-interface"]:
|
||||
if after.startswith("attach"):
|
||||
resource_id_prefix = EC2_RESOURCE_TO_PREFIX["network-interface-attachment"]
|
||||
if resource_id.startswith(EC2_RESOURCE_TO_PREFIX["vpc-endpoint-service"]):
|
||||
resource_id_prefix = EC2_RESOURCE_TO_PREFIX["vpc-endpoint-service"]
|
||||
if resource_id_prefix not in EC2_RESOURCE_TO_PREFIX.values():
|
||||
uuid4hex = re.compile(r"[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}\Z", re.I)
|
||||
if uuid4hex.match(resource_id) is not None:
|
||||
|
@ -4,7 +4,7 @@ from jinja2 import Template
|
||||
from botocore.exceptions import ParamValidationError
|
||||
from collections import OrderedDict
|
||||
from moto.core.exceptions import RESTError
|
||||
from moto.core import BaseBackend, BaseModel, CloudFormationModel
|
||||
from moto.core import ACCOUNT_ID, BaseBackend, BaseModel, CloudFormationModel
|
||||
from moto.core.utils import (
|
||||
iso_8601_datetime_with_milliseconds,
|
||||
get_random_hex,
|
||||
@ -428,6 +428,7 @@ class FakeLoadBalancer(CloudFormationModel):
|
||||
"access_logs.s3.prefix",
|
||||
"deletion_protection.enabled",
|
||||
"idle_timeout.timeout_seconds",
|
||||
"load_balancing.cross_zone.enabled",
|
||||
"routing.http2.enabled",
|
||||
"routing.http.drop_invalid_header_fields.enabled",
|
||||
}
|
||||
@ -618,7 +619,7 @@ class ELBv2Backend(BaseBackend):
|
||||
|
||||
vpc_id = subnets[0].vpc_id
|
||||
arn = make_arn_for_load_balancer(
|
||||
account_id=1, name=name, region_name=self.region_name
|
||||
account_id=ACCOUNT_ID, name=name, region_name=self.region_name
|
||||
)
|
||||
dns_name = "%s-1.%s.elb.amazonaws.com" % (name, self.region_name)
|
||||
|
||||
@ -944,7 +945,7 @@ Member must satisfy regular expression pattern: {}".format(
|
||||
)
|
||||
|
||||
arn = make_arn_for_target_group(
|
||||
account_id=1, name=name, region_name=self.region_name
|
||||
account_id=ACCOUNT_ID, name=name, region_name=self.region_name
|
||||
)
|
||||
target_group = FakeTargetGroup(name, arn, **kwargs)
|
||||
self.target_groups[target_group.arn] = target_group
|
||||
|
@ -133,3 +133,4 @@ TestAccAWSDataSourceIAMRole
|
||||
TestAccAWSDataSourceIAMUser
|
||||
TestAccAWSIAMAccountAlias
|
||||
TestAccAWSIAMOpenIDConnectProvider
|
||||
TestAccAWSVpcEndpointService
|
||||
|
@ -6,6 +6,7 @@ from botocore.exceptions import ClientError
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from moto import mock_ec2, settings
|
||||
from moto.core import ACCOUNT_ID
|
||||
from moto.ec2.utils import random_private_ip
|
||||
from tests import EXAMPLE_AMI_ID
|
||||
from uuid import uuid4
|
||||
@ -488,6 +489,38 @@ def test_elastic_network_interfaces_get_by_attachment_instance_id():
|
||||
enis.get("NetworkInterfaces").should.have.length_of(0)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def test_elastic_network_interfaces_get_by_attachment_instance_owner_id():
|
||||
ec2_resource = boto3.resource("ec2", region_name="us-west-2")
|
||||
ec2_client = boto3.client("ec2", region_name="us-west-2")
|
||||
|
||||
vpc = ec2_resource.create_vpc(CidrBlock="10.0.0.0/16")
|
||||
subnet = ec2_resource.create_subnet(
|
||||
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
|
||||
)
|
||||
|
||||
security_group1 = ec2_resource.create_security_group(
|
||||
GroupName=str(uuid4()), Description="desc"
|
||||
)
|
||||
|
||||
create_instances_result = ec2_resource.create_instances(
|
||||
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1
|
||||
)
|
||||
instance = create_instances_result[0]
|
||||
|
||||
eni1 = ec2_resource.create_network_interface(
|
||||
SubnetId=subnet.id, Groups=[security_group1.id]
|
||||
)
|
||||
ec2_client.attach_network_interface(
|
||||
NetworkInterfaceId=eni1.id, InstanceId=instance.id, DeviceIndex=1
|
||||
)
|
||||
|
||||
filters = [{"Name": "attachment.instance-owner-id", "Values": [ACCOUNT_ID]}]
|
||||
enis = ec2_client.describe_network_interfaces(Filters=filters)["NetworkInterfaces"]
|
||||
eni_ids = [eni["NetworkInterfaceId"] for eni in enis]
|
||||
eni_ids.should.contain(eni1.id)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def test_elastic_network_interfaces_describe_network_interfaces_with_filter():
|
||||
ec2 = boto3.resource("ec2", region_name="us-west-2")
|
||||
|
397
tests/test_ec2/test_vpc_service_configuration.py
Normal file
397
tests/test_ec2/test_vpc_service_configuration.py
Normal file
@ -0,0 +1,397 @@
|
||||
import boto3
|
||||
import pytest
|
||||
import sure # noqa # pylint: disable=unused-import
|
||||
|
||||
from botocore.exceptions import ClientError
|
||||
from moto import mock_ec2, mock_elbv2
|
||||
from moto.core.utils import get_random_hex
|
||||
|
||||
# See our Development Tips on writing tests for hints on how to write good tests:
|
||||
# http://docs.getmoto.org/en/latest/docs/contributing/development_tips/tests.html
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def test_create_vpc_endpoint_service_configuration_without_params():
|
||||
client = boto3.client("ec2", region_name="us-west-2")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
client.create_vpc_endpoint_service_configuration()
|
||||
err = exc.value.response["Error"]
|
||||
|
||||
err["Code"].should.equal("InvalidParameter")
|
||||
err["Message"].should.equal(
|
||||
"exactly one of network_load_balancer_arn or gateway_load_balancer_arn is a required member"
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_create_vpc_endpoint_service_configuration_with_network_load_balancer():
|
||||
region_name = "eu-west-3"
|
||||
client = boto3.client("ec2", region_name=region_name)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region_name, lb_type="network", zone="eu-west-3b"
|
||||
)
|
||||
|
||||
resp = client.create_vpc_endpoint_service_configuration(
|
||||
NetworkLoadBalancerArns=[lb_arn]
|
||||
)
|
||||
resp.should.have.key("ServiceConfiguration")
|
||||
config = resp["ServiceConfiguration"]
|
||||
|
||||
config.should.have.key("ServiceType").equals([{"ServiceType": "Interface"}])
|
||||
config.should.have.key("ServiceId").match("^vpce-svc-")
|
||||
config.should.have.key("ServiceName").equals(
|
||||
f"com.amazonaws.vpce.eu-west-3.{config['ServiceId']}"
|
||||
)
|
||||
config.should.have.key("ServiceState").equals("Available")
|
||||
config.should.have.key("AvailabilityZones").equals(["eu-west-3b"])
|
||||
config.should.have.key("AcceptanceRequired").equals(True)
|
||||
config.should.have.key("ManagesVpcEndpoints").equals(False)
|
||||
config.should.have.key("NetworkLoadBalancerArns").equals([lb_arn])
|
||||
config.should.have.key("BaseEndpointDnsNames").equals(
|
||||
[f"{config['ServiceId']}.eu-west-3.vpce.amazonaws.com"]
|
||||
)
|
||||
config.should.have.key("PrivateDnsNameConfiguration").equals({})
|
||||
|
||||
config.shouldnt.have.key("GatewayLoadBalancerArns")
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_create_vpc_endpoint_service_configuration_with_gateway_load_balancer():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
resp = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)
|
||||
resp.should.have.key("ServiceConfiguration")
|
||||
config = resp["ServiceConfiguration"]
|
||||
|
||||
config.should.have.key("ServiceType").equals([{"ServiceType": "Gateway"}])
|
||||
config.should.have.key("ServiceId").match("^vpce-svc-")
|
||||
config.should.have.key("ServiceName").equals(
|
||||
f"com.amazonaws.vpce.us-east-2.{config['ServiceId']}"
|
||||
)
|
||||
config.should.have.key("ServiceState").equals("Available")
|
||||
config.should.have.key("AvailabilityZones").equals(["us-east-1c"])
|
||||
config.should.have.key("AcceptanceRequired").equals(True)
|
||||
config.should.have.key("ManagesVpcEndpoints").equals(False)
|
||||
config.should.have.key("GatewayLoadBalancerArns").equals([lb_arn])
|
||||
config.should.have.key("BaseEndpointDnsNames").equals(
|
||||
[f"{config['ServiceId']}.us-east-2.vpce.amazonaws.com"]
|
||||
)
|
||||
config.should.have.key("PrivateDnsNameConfiguration").equals({})
|
||||
|
||||
config.shouldnt.have.key("NetworkLoadBalancerArns")
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_create_vpc_endpoint_service_configuration_with_options():
|
||||
client = boto3.client("ec2", region_name="us-east-2")
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name="us-east-2", lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
resp = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn],
|
||||
AcceptanceRequired=False,
|
||||
PrivateDnsName="example.com",
|
||||
)
|
||||
resp.should.have.key("ServiceConfiguration")
|
||||
config = resp["ServiceConfiguration"]
|
||||
|
||||
config.should.have.key("AcceptanceRequired").equals(False)
|
||||
config.should.have.key("PrivateDnsName").equals("example.com")
|
||||
config.should.have.key("PrivateDnsNameConfiguration").equals(
|
||||
{"Name": "n", "State": "verified", "Type": "TXT", "Value": "val"}
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_describe_vpc_endpoint_service_configurations():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
config1 = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
config2 = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_configurations()
|
||||
resp.should.have.key("ServiceConfigurations")
|
||||
service_ids = [s["ServiceId"] for s in resp["ServiceConfigurations"]]
|
||||
service_ids.should.contain(config1)
|
||||
service_ids.should.contain(config2)
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_configurations(ServiceIds=[config2])
|
||||
|
||||
resp.should.have.key("ServiceConfigurations").length_of(1)
|
||||
result = resp["ServiceConfigurations"][0]
|
||||
|
||||
result.should.have.key("ServiceId").equals(config2)
|
||||
result.should.have.key("ServiceName")
|
||||
result.should.have.key("ServiceState")
|
||||
result.should.have.key("GatewayLoadBalancerArns").equals([lb_arn])
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
@pytest.mark.parametrize(
|
||||
"tags",
|
||||
[
|
||||
[{"Key": "k1", "Value": "v1"}],
|
||||
[{"Key": "k1", "Value": "v1"}, {"Key": "k2", "Value": "v2"}],
|
||||
],
|
||||
)
|
||||
def test_describe_vpc_endpoint_service_configurations_with_tags(tags):
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn],
|
||||
TagSpecifications=[{"ResourceType": "vpc-endpoint-service", "Tags": tags}],
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_configurations(ServiceIds=[service_id])
|
||||
|
||||
resp.should.have.key("ServiceConfigurations").length_of(1)
|
||||
result = resp["ServiceConfigurations"][0]
|
||||
result.should.have.key("Tags").length_of(len(tags))
|
||||
for tag in tags:
|
||||
result["Tags"].should.contain(tag)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_describe_vpc_endpoint_service_configurations_and_add_tags():
|
||||
tags = [{"Key": "k1", "Value": "v1"}]
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
client.create_tags(Resources=[service_id], Tags=tags)
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_configurations(ServiceIds=[service_id])
|
||||
|
||||
resp.should.have.key("ServiceConfigurations").length_of(1)
|
||||
result = resp["ServiceConfigurations"][0]
|
||||
result.should.have.key("Tags").length_of(len(tags))
|
||||
for tag in tags:
|
||||
result["Tags"].should.contain(tag)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def test_describe_vpc_endpoint_service_configurations_unknown():
|
||||
client = boto3.client("ec2", region_name="eu-west-3")
|
||||
|
||||
with pytest.raises(ClientError) as exc:
|
||||
# Will always fail if at least one ServiceId is unknown
|
||||
client.describe_vpc_endpoint_service_configurations(
|
||||
ServiceIds=["vpce-svc-unknown"]
|
||||
)
|
||||
err = exc.value.response["Error"]
|
||||
|
||||
err["Code"].should.equal("InvalidVpcEndpointServiceId.NotFound")
|
||||
err["Message"].should.equal(
|
||||
"The VpcEndpointService Id 'vpce-svc-unknown' does not exist"
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_delete_vpc_endpoint_service_configurations():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
resp = client.delete_vpc_endpoint_service_configurations(ServiceIds=[service_id])
|
||||
resp.should.have.key("Unsuccessful").equals([])
|
||||
|
||||
|
||||
@mock_ec2
|
||||
def test_delete_vpc_endpoint_service_configurations_already_deleted():
|
||||
client = boto3.client("ec2", region_name="eu-west-3")
|
||||
|
||||
resp = client.delete_vpc_endpoint_service_configurations(
|
||||
ServiceIds=["vpce-svc-03cf101d15c3bff53"]
|
||||
)
|
||||
resp.should.have.key("Unsuccessful").length_of(1)
|
||||
|
||||
u = resp["Unsuccessful"][0]
|
||||
u.should.have.key("ResourceId").equals("vpce-svc-03cf101d15c3bff53")
|
||||
u.should.have.key("Error")
|
||||
|
||||
u["Error"].should.have.key("Code").equals("InvalidVpcEndpointService.NotFound")
|
||||
u["Error"].should.have.key("Message").equals(
|
||||
"The VpcEndpointService Id 'vpce-svc-03cf101d15c3bff53' does not exist"
|
||||
)
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_describe_vpc_endpoint_service_permissions():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_permissions(ServiceId=service_id)
|
||||
resp.should.have.key("AllowedPrincipals").equals([])
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_modify_vpc_endpoint_service_permissions():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
client.modify_vpc_endpoint_service_permissions(
|
||||
ServiceId=service_id, AddAllowedPrincipals=["prin1", "cipal2"]
|
||||
)
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_permissions(ServiceId=service_id)
|
||||
resp.should.have.key("AllowedPrincipals").length_of(2)
|
||||
resp["AllowedPrincipals"].should.contain({"Principal": "prin1"})
|
||||
resp["AllowedPrincipals"].should.contain({"Principal": "cipal2"})
|
||||
|
||||
client.modify_vpc_endpoint_service_permissions(
|
||||
ServiceId=service_id, RemoveAllowedPrincipals=["prin1"]
|
||||
)
|
||||
|
||||
resp = client.describe_vpc_endpoint_service_permissions(ServiceId=service_id)
|
||||
resp.should.have.key("AllowedPrincipals").length_of(1)
|
||||
resp["AllowedPrincipals"].should.contain({"Principal": "cipal2"})
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_modify_vpc_endpoint_service_configuration():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
client.modify_vpc_endpoint_service_configuration(
|
||||
ServiceId=service_id, PrivateDnsName="dnsname", AcceptanceRequired=False
|
||||
)
|
||||
|
||||
config = client.describe_vpc_endpoint_service_configurations(
|
||||
ServiceIds=[service_id]
|
||||
)["ServiceConfigurations"][0]
|
||||
|
||||
config.should.have.key("AcceptanceRequired").equals(False)
|
||||
config.should.have.key("PrivateDnsName").equals("dnsname")
|
||||
|
||||
|
||||
@mock_ec2
|
||||
@mock_elbv2
|
||||
def test_modify_vpc_endpoint_service_configuration_with_new_loadbalancers():
|
||||
region = "us-east-2"
|
||||
client = boto3.client("ec2", region_name=region)
|
||||
|
||||
lb_arn = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
lb_arn2 = create_load_balancer(
|
||||
region_name=region, lb_type="gateway", zone="us-east-1c"
|
||||
)
|
||||
lb_arn3 = create_load_balancer(
|
||||
region_name=region, lb_type="network", zone="us-east-1c"
|
||||
)
|
||||
|
||||
service_id = client.create_vpc_endpoint_service_configuration(
|
||||
GatewayLoadBalancerArns=[lb_arn]
|
||||
)["ServiceConfiguration"]["ServiceId"]
|
||||
|
||||
client.modify_vpc_endpoint_service_configuration(
|
||||
ServiceId=service_id,
|
||||
AddNetworkLoadBalancerArns=[lb_arn3],
|
||||
AddGatewayLoadBalancerArns=[lb_arn2],
|
||||
)
|
||||
|
||||
config = client.describe_vpc_endpoint_service_configurations(
|
||||
ServiceIds=[service_id]
|
||||
)["ServiceConfigurations"][0]
|
||||
config["GatewayLoadBalancerArns"].should.equal([lb_arn, lb_arn2])
|
||||
config["NetworkLoadBalancerArns"].should.equal([lb_arn3])
|
||||
|
||||
client.modify_vpc_endpoint_service_configuration(
|
||||
ServiceId=service_id,
|
||||
RemoveNetworkLoadBalancerArns=[lb_arn3],
|
||||
RemoveGatewayLoadBalancerArns=[lb_arn],
|
||||
)
|
||||
|
||||
config = client.describe_vpc_endpoint_service_configurations(
|
||||
ServiceIds=[service_id]
|
||||
)["ServiceConfigurations"][0]
|
||||
config["GatewayLoadBalancerArns"].should.equal([lb_arn2])
|
||||
config.shouldnt.have.key("NetworkLoadBalancerArns")
|
||||
|
||||
|
||||
def create_load_balancer(region_name, zone, lb_type):
|
||||
ec2 = boto3.resource("ec2", region_name=region_name)
|
||||
elbv2 = boto3.client("elbv2", region_name=region_name)
|
||||
|
||||
vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default")
|
||||
subnet = ec2.create_subnet(
|
||||
VpcId=vpc.id, CidrBlock="172.28.7.192/26", AvailabilityZone=zone
|
||||
)
|
||||
lb_name = f"lb_vpce-{get_random_hex(length=10)}"
|
||||
response = elbv2.create_load_balancer(
|
||||
Name=lb_name, Subnets=[subnet.id], Scheme="internal", Type=lb_type
|
||||
)
|
||||
return response["LoadBalancers"][0]["LoadBalancerArn"]
|
@ -19,7 +19,7 @@ def test_create_load_balancer():
|
||||
lb = response.get("LoadBalancers")[0]
|
||||
lb.get("DNSName").should.equal("my-lb-1.us-east-1.elb.amazonaws.com")
|
||||
lb.get("LoadBalancerArn").should.equal(
|
||||
"arn:aws:elasticloadbalancing:us-east-1:1:loadbalancer/my-lb/50dc6c495c0c9188"
|
||||
f"arn:aws:elasticloadbalancing:us-east-1:{ACCOUNT_ID}:loadbalancer/my-lb/50dc6c495c0c9188"
|
||||
)
|
||||
lb.get("SecurityGroups").should.equal([security_group.id])
|
||||
lb.get("AvailabilityZones").should.equal(
|
||||
@ -1224,6 +1224,25 @@ def test_modify_load_balancer_attributes_routing_http2_enabled():
|
||||
routing_http2_enabled["Value"].should.equal("false")
|
||||
|
||||
|
||||
@mock_elbv2
|
||||
@mock_ec2
|
||||
def test_modify_load_balancer_attributes_crosszone_enabled():
|
||||
response, _, _, _, _, client = create_load_balancer()
|
||||
arn = response["LoadBalancers"][0]["LoadBalancerArn"]
|
||||
|
||||
client.modify_load_balancer_attributes(
|
||||
LoadBalancerArn=arn,
|
||||
Attributes=[
|
||||
{"Key": "load_balancing.cross_zone.enabled", "Value": "false"},
|
||||
{"Key": "deletion_protection.enabled", "Value": "false"},
|
||||
],
|
||||
)
|
||||
|
||||
attrs = client.describe_load_balancer_attributes(LoadBalancerArn=arn)["Attributes"]
|
||||
attrs.should.contain({"Key": "deletion_protection.enabled", "Value": "false"})
|
||||
attrs.should.contain({"Key": "load_balancing.cross_zone.enabled", "Value": "false"})
|
||||
|
||||
|
||||
@mock_elbv2
|
||||
@mock_ec2
|
||||
def test_modify_load_balancer_attributes_routing_http_drop_invalid_header_fields_enabled():
|
||||
|
@ -153,7 +153,7 @@ def test_create_target_group_and_listeners():
|
||||
e.value.operation_name.should.equal("DeleteTargetGroup")
|
||||
e.value.args.should.equal(
|
||||
(
|
||||
"An error occurred (ResourceInUse) when calling the DeleteTargetGroup operation: The target group 'arn:aws:elasticloadbalancing:us-east-1:1:targetgroup/a-target/50dc6c495c0c9188' is currently in use by a listener or a rule",
|
||||
f"An error occurred (ResourceInUse) when calling the DeleteTargetGroup operation: The target group 'arn:aws:elasticloadbalancing:us-east-1:{ACCOUNT_ID}:targetgroup/a-target/50dc6c495c0c9188' is currently in use by a listener or a rule",
|
||||
)
|
||||
) # NOQA
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user