feature route53resolver: ip address associate/disassociate (#5254)
This commit is contained in:
parent
3abb737579
commit
ac07f03d9e
@ -292,6 +292,46 @@ class ResolverEndpoint(BaseModel): # pylint: disable=too-many-instance-attribut
|
||||
self.name = name
|
||||
self.modification_time = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
def associate_ip_address(self, ip_address):
|
||||
self.ip_addresses.append(ip_address)
|
||||
self.ip_address_count = len(self.ip_addresses)
|
||||
|
||||
eni_id = f"rni-{get_random_hex(17)}"
|
||||
self.subnets[ip_address["SubnetId"]][ip_address["Ip"]] = eni_id
|
||||
|
||||
eni_info = ec2_backends[self.region].create_network_interface(
|
||||
description=f"Route 53 Resolver: {self.id}:{eni_id}",
|
||||
group_ids=self.security_group_ids,
|
||||
interface_type="interface",
|
||||
private_ip_address=ip_address.get("Ip"),
|
||||
private_ip_addresses=[
|
||||
{"Primary": True, "PrivateIpAddress": ip_address.get("Ip")}
|
||||
],
|
||||
subnet=ip_address.get("SubnetId"),
|
||||
)
|
||||
self.eni_ids.append(eni_info.id)
|
||||
|
||||
def disassociate_ip_address(self, ip_address):
|
||||
if not ip_address.get("Ip") and ip_address.get("IpId"):
|
||||
for ip_addr, eni_id in self.subnets[ip_address.get("SubnetId")].items():
|
||||
if ip_address.get("IpId") == eni_id:
|
||||
ip_address["Ip"] = ip_addr
|
||||
if ip_address.get("Ip"):
|
||||
self.ip_addresses = list(
|
||||
filter(lambda i: i["Ip"] != ip_address.get("Ip"), self.ip_addresses)
|
||||
)
|
||||
|
||||
if len(self.subnets[ip_address["SubnetId"]]) == 1:
|
||||
self.subnets.pop(ip_address["SubnetId"])
|
||||
else:
|
||||
self.subnets[ip_address["SubnetId"]].pop(ip_address["Ip"])
|
||||
for eni_id in self.eni_ids:
|
||||
eni_info = ec2_backends[self.region].get_network_interface(eni_id)
|
||||
if eni_info.private_ip_address == ip_address.get("Ip"):
|
||||
ec2_backends[self.region].delete_network_interface(eni_id)
|
||||
self.eni_ids.remove(eni_id)
|
||||
self.ip_address_count = len(self.ip_addresses)
|
||||
|
||||
|
||||
class Route53ResolverBackend(BaseBackend):
|
||||
"""Implementation of Route53Resolver APIs."""
|
||||
@ -353,15 +393,17 @@ class Route53ResolverBackend(BaseBackend):
|
||||
return rule_association
|
||||
|
||||
@staticmethod
|
||||
def _verify_subnet_ips(region, ip_addresses):
|
||||
def _verify_subnet_ips(region, ip_addresses, initial=True):
|
||||
"""Perform additional checks on the IPAddresses.
|
||||
|
||||
NOTE: This does not include IPv6 addresses.
|
||||
"""
|
||||
if len(ip_addresses) < 2:
|
||||
raise InvalidRequestException(
|
||||
"Resolver endpoint needs to have at least 2 IP addresses"
|
||||
)
|
||||
# only initial endpoint creation requires atleast two ip addresses
|
||||
if initial:
|
||||
if len(ip_addresses) < 2:
|
||||
raise InvalidRequestException(
|
||||
"Resolver endpoint needs to have at least 2 IP addresses"
|
||||
)
|
||||
|
||||
subnets = defaultdict(set)
|
||||
for subnet_id, ip_addr in [(x["SubnetId"], x["Ip"]) for x in ip_addresses]:
|
||||
@ -836,5 +878,37 @@ class Route53ResolverBackend(BaseBackend):
|
||||
resolver_endpoint.update_name(name)
|
||||
return resolver_endpoint
|
||||
|
||||
def associate_resolver_endpoint_ip_address(
|
||||
self, region, resolver_endpoint_id, ip_address
|
||||
):
|
||||
"""associate resolver endpoint ip address."""
|
||||
self._validate_resolver_endpoint_id(resolver_endpoint_id)
|
||||
resolver_endpoint = self.resolver_endpoints[resolver_endpoint_id]
|
||||
|
||||
if not ip_address.get("Ip"):
|
||||
subnet_info = ec2_backends[region].get_all_subnets(
|
||||
subnet_ids=[ip_address.get("SubnetId")]
|
||||
)[0]
|
||||
ip_address["Ip"] = subnet_info.get_available_subnet_ip(self)
|
||||
self._verify_subnet_ips(region, [ip_address], False)
|
||||
|
||||
resolver_endpoint.associate_ip_address(ip_address)
|
||||
return resolver_endpoint
|
||||
|
||||
def disassociate_resolver_endpoint_ip_address(
|
||||
self, resolver_endpoint_id, ip_address
|
||||
):
|
||||
"""disassociate resolver endpoint ip address."""
|
||||
self._validate_resolver_endpoint_id(resolver_endpoint_id)
|
||||
resolver_endpoint = self.resolver_endpoints[resolver_endpoint_id]
|
||||
|
||||
if not (ip_address.get("Ip") or ip_address.get("IpId")):
|
||||
raise InvalidRequestException(
|
||||
"[RSLVR-00503] Need to specify either the IP ID or both subnet and IP address in order to remove IP address."
|
||||
)
|
||||
|
||||
resolver_endpoint.disassociate_ip_address(ip_address)
|
||||
return resolver_endpoint
|
||||
|
||||
|
||||
route53resolver_backends = BackendDict(Route53ResolverBackend, "route53resolver")
|
||||
|
@ -257,3 +257,27 @@ class Route53ResolverResponse(BaseResponse):
|
||||
resolver_endpoint_id=resolver_endpoint_id, name=name
|
||||
)
|
||||
return json.dumps({"ResolverEndpoint": resolver_endpoint.description()})
|
||||
|
||||
def associate_resolver_endpoint_ip_address(self):
|
||||
ip_address = self._get_param("IpAddress")
|
||||
resolver_endpoint_id = self._get_param("ResolverEndpointId")
|
||||
resolver_endpoint = (
|
||||
self.route53resolver_backend.associate_resolver_endpoint_ip_address(
|
||||
region=self.region,
|
||||
resolver_endpoint_id=resolver_endpoint_id,
|
||||
ip_address=ip_address,
|
||||
)
|
||||
)
|
||||
return json.dumps({"ResolverEndpoint": resolver_endpoint.description()})
|
||||
|
||||
def disassociate_resolver_endpoint_ip_address(self):
|
||||
ip_address = self._get_param("IpAddress")
|
||||
resolver_endpoint_id = self._get_param("ResolverEndpointId")
|
||||
|
||||
resolver_endpoint = (
|
||||
self.route53resolver_backend.disassociate_resolver_endpoint_ip_address(
|
||||
resolver_endpoint_id=resolver_endpoint_id,
|
||||
ip_address=ip_address,
|
||||
)
|
||||
)
|
||||
return json.dumps({"ResolverEndpoint": resolver_endpoint.description()})
|
||||
|
@ -189,7 +189,7 @@ route53:
|
||||
- TestAccRoute53HealthCheck_withSNI
|
||||
- TestAccRoute53HealthCheck_disabled
|
||||
- TestAccRoute53HealthCheck_disappears
|
||||
- TestAccRoute53ResolverEndpoint_basicInbound
|
||||
- TestAccRoute53ResolverEndpoint
|
||||
s3:
|
||||
- TestAccS3BucketPolicy
|
||||
- TestAccS3BucketPublicAccessBlock
|
||||
|
Loading…
Reference in New Issue
Block a user