moto/tests/test_ec2/test_route_tables.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1158 lines
41 KiB
Python
Raw Normal View History

from uuid import uuid4
import boto3
import pytest
from botocore.exceptions import ClientError
2024-01-07 12:03:33 +00:00
from moto import mock_aws, settings
from tests import EXAMPLE_AMI_ID
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_tables_defaults():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
assert len(all_route_tables) == 1
2021-09-25 11:13:07 +00:00
main_route_table = all_route_tables[0]
assert main_route_table["VpcId"] == vpc.id
2021-09-25 11:13:07 +00:00
routes = main_route_table["Routes"]
assert len(routes) == 1
2021-09-25 11:13:07 +00:00
local_route = routes[0]
assert local_route["GatewayId"] == "local"
assert local_route["State"] == "active"
assert local_route["DestinationCidrBlock"] == vpc.cidr_block
2021-09-25 11:13:07 +00:00
vpc.delete()
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
assert len(all_route_tables) == 0
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_tables_additional():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = vpc.create_route_table()
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
assert len(all_route_tables) == 2
assert all_route_tables[0]["VpcId"] == vpc.id
assert all_route_tables[1]["VpcId"] == vpc.id
2021-09-25 11:13:07 +00:00
all_route_table_ids = [r["RouteTableId"] for r in all_route_tables]
assert route_table.route_table_id in all_route_table_ids
2021-09-25 11:13:07 +00:00
routes = route_table.routes
assert len(routes) == 1
2021-09-25 11:13:07 +00:00
local_route = routes[0]
assert local_route.gateway_id == "local"
assert local_route.state == "active"
assert local_route.destination_cidr_block == vpc.cidr_block
2021-09-25 11:13:07 +00:00
with pytest.raises(ClientError) as ex:
client.delete_vpc(VpcId=vpc.id)
assert ex.value.response["Error"]["Code"] == "DependencyViolation"
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
2021-09-25 11:13:07 +00:00
client.delete_route_table(RouteTableId=route_table.route_table_id)
all_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"]
assert len(all_route_tables) == 1
2021-09-25 11:13:07 +00:00
with pytest.raises(ClientError) as ex:
client.delete_route_table(RouteTableId="rtb-1234abcd")
assert ex.value.response["Error"]["Code"] == "InvalidRouteTableID.NotFound"
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_tables_filters_standard():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table1 = ec2.create_route_table(VpcId=vpc1.id)
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table2 = ec2.create_route_table(VpcId=vpc2.id)
igw = ec2.create_internet_gateway()
route_table2.create_route(DestinationCidrBlock="10.0.0.4/24", GatewayId=igw.id)
2021-09-25 11:13:07 +00:00
all_route_tables = client.describe_route_tables()["RouteTables"]
2021-10-05 17:11:07 +00:00
all_ids = [rt["RouteTableId"] for rt in all_route_tables]
assert route_table1.id in all_ids
assert route_table2.id in all_ids
2021-09-25 11:13:07 +00:00
# Filter by main route table
main_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.main", "Values": ["true"]}]
)["RouteTables"]
main_route_table_ids = [
route_table["RouteTableId"] for route_table in main_route_tables
]
assert route_table1.id not in main_route_table_ids
assert route_table2.id not in main_route_table_ids
2021-09-25 11:13:07 +00:00
# Filter by VPC
vpc1_route_tables = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc1.id]}]
)["RouteTables"]
assert len(vpc1_route_tables) == 2
2021-09-25 11:13:07 +00:00
vpc1_route_table_ids = [
route_table["RouteTableId"] for route_table in vpc1_route_tables
]
assert route_table1.id in vpc1_route_table_ids
assert route_table2.id not in vpc1_route_table_ids
2021-09-25 11:13:07 +00:00
# Filter by VPC and main route table
vpc2_main_route_tables = client.describe_route_tables(
Filters=[
{"Name": "association.main", "Values": ["true"]},
{"Name": "vpc-id", "Values": [vpc2.id]},
]
)["RouteTables"]
assert len(vpc2_main_route_tables) == 1
2021-09-25 11:13:07 +00:00
vpc2_main_route_table_ids = [
route_table["RouteTableId"] for route_table in vpc2_main_route_tables
]
assert route_table1.id not in vpc2_main_route_table_ids
assert route_table2.id not in vpc2_main_route_table_ids
2021-09-25 11:13:07 +00:00
# Filter by route gateway id
resp = client.describe_route_tables(
Filters=[
{"Name": "route.gateway-id", "Values": [igw.id]},
]
)["RouteTables"]
assert any(
[route["GatewayId"] == igw.id for table in resp for route in table["Routes"]]
)
# Filter by route destination CIDR block
resp = client.describe_route_tables(
Filters=[
{"Name": "route.destination-cidr-block", "Values": ["10.0.0.4/24"]},
]
)["RouteTables"]
assert any([route_table["RouteTableId"] == route_table2.id for route_table in resp])
assert any(
[
route["DestinationCidrBlock"] == "10.0.0.4/24"
for table in resp
for route in table["Routes"]
]
)
2021-09-25 11:13:07 +00:00
# Unsupported filter
if not settings.TEST_SERVER_MODE:
# ServerMode will just throw a generic 500
filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}]
with pytest.raises(NotImplementedError):
client.describe_route_tables(Filters=filters)
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_tables_filters_associations():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet1 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
subnet2 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.1.0/24")
subnet3 = vpc.create_subnet(VpcId=vpc.id, CidrBlock="10.0.2.0/24")
route_table1 = ec2.create_route_table(VpcId=vpc.id)
route_table2 = ec2.create_route_table(VpcId=vpc.id)
association_id1 = client.associate_route_table(
RouteTableId=route_table1.id, SubnetId=subnet1.id
)["AssociationId"]
client.associate_route_table(RouteTableId=route_table1.id, SubnetId=subnet2.id)
client.associate_route_table(RouteTableId=route_table2.id, SubnetId=subnet3.id)
# Filter by association ID
association1_route_tables = client.describe_route_tables(
Filters=[
{
"Name": "association.route-table-association-id",
"Values": [association_id1],
}
]
)["RouteTables"]
assert len(association1_route_tables) == 1
assert association1_route_tables[0]["RouteTableId"] == route_table1.id
assert len(association1_route_tables[0]["Associations"]) == 2
2021-09-25 11:13:07 +00:00
# Filter by route table ID
route_table2_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.route-table-id", "Values": [route_table2.id]}]
)["RouteTables"]
assert len(route_table2_route_tables) == 1
assert route_table2_route_tables[0]["RouteTableId"] == route_table2.id
assert len(route_table2_route_tables[0]["Associations"]) == 1
2021-09-25 11:13:07 +00:00
# Filter by subnet ID
subnet_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.subnet-id", "Values": [subnet1.id]}]
)["RouteTables"]
assert len(subnet_route_tables) == 1
assert subnet_route_tables[0]["RouteTableId"] == route_table1.id
assert len(subnet_route_tables[0]["Associations"]) == 2
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_tables_filters_vpc_peering_connection():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
peer_vpc = ec2.create_vpc(CidrBlock="11.0.0.0/16")
vpc_pcx = ec2.create_vpc_peering_connection(VpcId=vpc.id, PeerVpcId=peer_vpc.id)
main_route_table.create_route(
DestinationCidrBlock=ROUTE_CIDR, VpcPeeringConnectionId=vpc_pcx.id
)
# Refresh route table
main_route_table.reload()
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 1
new_route = new_routes[0]
assert new_route.gateway_id is None
assert new_route.instance_id is None
assert new_route.vpc_peering_connection_id == vpc_pcx.id
assert new_route.state == "active"
assert new_route.destination_cidr_block == ROUTE_CIDR
# Filter by Peering Connection
route_tables = client.describe_route_tables(
Filters=[{"Name": "route.vpc-peering-connection-id", "Values": [vpc_pcx.id]}]
)["RouteTables"]
assert len(route_tables) == 1
route_table = route_tables[0]
assert route_table["RouteTableId"] == main_route_table_id
vpc_pcx_ids = [
route["VpcPeeringConnectionId"]
for route in route_table["Routes"]
if "VpcPeeringConnectionId" in route
]
all(vpc_pcx_id == vpc_pcx.id for vpc_pcx_id in vpc_pcx_ids)
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_table_associations():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
route_table = ec2.create_route_table(VpcId=vpc.id)
# Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
assert len(r["Associations"]) == 0
2021-09-25 11:13:07 +00:00
# Associate
association_id = client.associate_route_table(
RouteTableId=route_table.id, SubnetId=subnet.id
)["AssociationId"]
# Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
assert len(r["Associations"]) == 1
2021-09-25 11:13:07 +00:00
assert r["Associations"][0]["RouteTableAssociationId"] == association_id
assert r["Associations"][0]["Main"] is False
assert r["Associations"][0]["RouteTableId"] == route_table.id
assert r["Associations"][0]["SubnetId"] == subnet.id
2021-09-25 11:13:07 +00:00
# Associate is idempotent
association_id_idempotent = client.associate_route_table(
RouteTableId=route_table.id, SubnetId=subnet.id
)["AssociationId"]
assert association_id_idempotent == association_id
2021-09-25 11:13:07 +00:00
# Error: Attempt delete associated route table.
with pytest.raises(ClientError) as ex:
client.delete_route_table(RouteTableId=route_table.id)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "DependencyViolation"
2021-09-25 11:13:07 +00:00
# Disassociate
client.disassociate_route_table(AssociationId=association_id)
# Validate
2021-09-25 11:13:07 +00:00
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
assert len(r["Associations"]) == 0
2021-09-25 11:13:07 +00:00
# Error: Disassociate with invalid association ID
with pytest.raises(ClientError) as ex:
client.disassociate_route_table(AssociationId=association_id)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidAssociationID.NotFound"
2021-09-25 11:13:07 +00:00
# Error: Associate with invalid subnet ID
with pytest.raises(ClientError) as ex:
client.associate_route_table(
RouteTableId=route_table.id, SubnetId="subnet-1234abcd"
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidSubnetID.NotFound"
2021-09-25 11:13:07 +00:00
# Error: Associate with invalid route table ID
with pytest.raises(ClientError) as ex:
client.associate_route_table(RouteTableId="rtb-1234abcd", SubnetId=subnet.id)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidRouteTableID.NotFound"
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_table_replace_route_table_association():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
route_table1_id = ec2.create_route_table(VpcId=vpc.id).id
route_table2_id = ec2.create_route_table(VpcId=vpc.id).id
all_route_tables = client.describe_route_tables()["RouteTables"]
2021-10-05 17:11:07 +00:00
all_ids = [rt["RouteTableId"] for rt in all_route_tables]
assert route_table1_id in all_ids
assert route_table2_id in all_ids
2021-09-25 11:13:07 +00:00
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
assert len(route_table1["Associations"]) == 0
2021-09-25 11:13:07 +00:00
# Associate
association_id1 = client.associate_route_table(
RouteTableId=route_table1_id, SubnetId=subnet.id
)["AssociationId"]
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
route_table2 = client.describe_route_tables(RouteTableIds=[route_table2_id])[
"RouteTables"
][0]
# Validate
assert len(route_table1["Associations"]) == 1
assert len(route_table2["Associations"]) == 0
2021-09-25 11:13:07 +00:00
assert route_table1["Associations"][0]["RouteTableAssociationId"] == association_id1
assert route_table1["Associations"][0]["Main"] is False
assert route_table1["Associations"][0]["RouteTableId"] == route_table1_id
assert route_table1["Associations"][0]["SubnetId"] == subnet.id
2021-09-25 11:13:07 +00:00
# Replace Association
association_id2 = client.replace_route_table_association(
AssociationId=association_id1, RouteTableId=route_table2_id
)["NewAssociationId"]
# Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
"RouteTables"
][0]
route_table2 = client.describe_route_tables(RouteTableIds=[route_table2_id])[
"RouteTables"
][0]
# Validate
assert len(route_table1["Associations"]) == 0
assert len(route_table2["Associations"]) == 1
2021-09-25 11:13:07 +00:00
assert route_table2["Associations"][0]["RouteTableAssociationId"] == association_id2
assert route_table2["Associations"][0]["Main"] is False
assert route_table2["Associations"][0]["RouteTableId"] == route_table2_id
assert route_table2["Associations"][0]["SubnetId"] == subnet.id
2021-09-25 11:13:07 +00:00
# Replace Association is idempotent
association_id_idempotent = client.replace_route_table_association(
AssociationId=association_id2, RouteTableId=route_table2_id
)["NewAssociationId"]
assert association_id_idempotent == association_id2
2021-09-25 11:13:07 +00:00
# Error: Replace association with invalid association ID
with pytest.raises(ClientError) as ex:
client.replace_route_table_association(
AssociationId="rtbassoc-1234abcd", RouteTableId=route_table1_id
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidAssociationID.NotFound"
2021-09-25 11:13:07 +00:00
# Error: Replace association with invalid route table ID
with pytest.raises(ClientError) as ex:
client.replace_route_table_association(
AssociationId=association_id2, RouteTableId="rtb-1234abcd"
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidRouteTableID.NotFound"
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_table_replace_route_table_association_for_main():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
new_route_table_id = ec2.create_route_table(VpcId=vpc.id).id
# Get main route table details
main_route_table = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]
main_route_table_id = main_route_table["RouteTableId"]
main_route_table_association_id = main_route_table["Associations"][0][
"RouteTableAssociationId"
]
# Replace Association
new_association = client.replace_route_table_association(
AssociationId=main_route_table_association_id, RouteTableId=new_route_table_id
)
new_association_id = new_association["NewAssociationId"]
# Validate the format
assert new_association["AssociationState"]["State"] == "associated"
# Refresh
main_route_table = client.describe_route_tables(
RouteTableIds=[main_route_table_id]
)["RouteTables"][0]
new_route_table = client.describe_route_tables(RouteTableIds=[new_route_table_id])[
"RouteTables"
][0]
# Validate
assert len(main_route_table["Associations"]) == 0
assert len(new_route_table["Associations"]) == 1
assert (
new_route_table["Associations"][0]["RouteTableAssociationId"]
== new_association_id
)
assert new_route_table["Associations"][0]["Main"] is True
2024-01-07 12:03:33 +00:00
@mock_aws
def test_route_table_get_by_tag():
ec2 = boto3.resource("ec2", region_name="eu-central-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = ec2.create_route_table(VpcId=vpc.id)
2021-10-05 17:11:07 +00:00
tag_value = str(uuid4())
route_table.create_tags(Tags=[{"Key": "Name", "Value": tag_value}])
2021-10-05 17:11:07 +00:00
filters = [{"Name": "tag:Name", "Values": [tag_value]}]
route_tables = list(ec2.route_tables.filter(Filters=filters))
assert len(route_tables) == 1
assert route_tables[0].vpc_id == vpc.id
assert route_tables[0].id == route_table.id
assert len(route_tables[0].tags) == 1
assert route_tables[0].tags[0] == {"Key": "Name", "Value": tag_value}
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_additional():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[{"Name": "vpc-id", "Values": [vpc.id]}]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
assert len(main_route_table.routes) == 1
2021-09-25 11:13:07 +00:00
igw = ec2.create_internet_gateway()
ROUTE_CIDR = "10.0.0.4/24"
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
assert len(main_route_table.routes) == 2
2021-09-25 11:13:07 +00:00
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 1
2021-09-25 11:13:07 +00:00
new_route = new_routes[0]
assert new_route.gateway_id == igw.id
assert new_route.instance_id is None
assert new_route.state == "active"
assert new_route.destination_cidr_block == ROUTE_CIDR
2021-09-25 11:13:07 +00:00
client.delete_route(
RouteTableId=main_route_table.id, DestinationCidrBlock=ROUTE_CIDR
)
main_route_table.reload()
assert len(main_route_table.routes) == 1
2021-09-25 11:13:07 +00:00
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 0
2021-09-25 11:13:07 +00:00
with pytest.raises(ClientError) as ex:
client.delete_route(
RouteTableId=main_route_table.id, DestinationCidrBlock=ROUTE_CIDR
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidRoute.NotFound"
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_replace():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/24")
2021-09-25 11:13:07 +00:00
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
# Various route targets
igw = ec2.create_internet_gateway()
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
eni = ec2.create_network_interface(SubnetId=subnet.id)
2021-09-25 11:13:07 +00:00
# Create initial route
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
# Replace...
def get_target_route():
route_table = client.describe_route_tables(RouteTableIds=[main_route_table.id])[
"RouteTables"
][0]
routes = [
route
for route in route_table["Routes"]
if route["DestinationCidrBlock"] != vpc.cidr_block
]
assert len(routes) == 1
2021-09-25 11:13:07 +00:00
return routes[0]
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
InstanceId=instance.id,
)
target_route = get_target_route()
assert "GatewayId" not in target_route
assert target_route["InstanceId"] == instance.id
assert "NetworkInterfaceId" not in target_route
assert target_route["State"] == "active"
assert target_route["DestinationCidrBlock"] == ROUTE_CIDR
2021-09-25 11:13:07 +00:00
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
target_route = get_target_route()
assert target_route["GatewayId"] == igw.id
assert "InstanceId" not in target_route
assert "NetworkInterfaceId" not in target_route
assert target_route["State"] == "active"
assert target_route["DestinationCidrBlock"] == ROUTE_CIDR
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
NetworkInterfaceId=eni.id,
)
target_route = get_target_route()
assert "GatewayId" not in target_route
assert "InstanceId" not in target_route
assert target_route["NetworkInterfaceId"] == eni.id
assert target_route["State"] == "active"
assert target_route["DestinationCidrBlock"] == ROUTE_CIDR
2021-09-25 11:13:07 +00:00
with pytest.raises(ClientError) as ex:
client.replace_route(
RouteTableId="rtb-1234abcd",
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidRouteTableID.NotFound"
2021-09-25 11:13:07 +00:00
with pytest.raises(ClientError) as ex:
client.replace_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock="1.1.1.1/32",
NetworkInterfaceId=eni.id,
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
# This should be 'InvalidRoute.NotFound' in line with the delete_route()
# equivalent, but for some reason AWS returns InvalidParameterValue instead.
assert ex.value.response["Error"]["Code"] == "InvalidParameterValue"
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_already_exist():
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.0/23"
ROUTE_SUB_CIDR = "10.0.0.0/24"
ROUTE_NO_CONFLICT_CIDR = "10.0.2.0/24"
# Various route targets
igw = ec2.create_internet_gateway()
# Create initial route
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=igw.id)
main_route_table.create_route(
DestinationCidrBlock=ROUTE_NO_CONFLICT_CIDR, GatewayId=igw.id
)
# Create
with pytest.raises(ClientError) as ex:
client.create_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_CIDR,
GatewayId=igw.id,
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "RouteAlreadyExists"
# We can create a sub cidr
client.create_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock=ROUTE_SUB_CIDR,
GatewayId=igw.id,
)
# Or even a catch-all
client.create_route(
RouteTableId=main_route_table.id,
DestinationCidrBlock="0.0.0.0/0",
GatewayId=igw.id,
)
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_not_supported():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
main_route_table_id = client.describe_route_tables()["RouteTables"][0][
"RouteTableId"
]
ROUTE_CIDR = "10.0.0.4/24"
# Create
with pytest.raises(ClientError) as ex:
client.create_route(
RouteTableId=main_route_table_id,
DestinationCidrBlock=ROUTE_CIDR,
NetworkInterfaceId="eni-1234abcd",
)
assert ex.value.response["ResponseMetadata"]["HTTPStatusCode"] == 400
assert "RequestId" in ex.value.response["ResponseMetadata"]
assert ex.value.response["Error"]["Code"] == "InvalidNetworkInterfaceID.NotFound"
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_vpc_peering_connection():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
peer_vpc = ec2.create_vpc(CidrBlock="11.0.0.0/16")
vpc_pcx = ec2.create_vpc_peering_connection(VpcId=vpc.id, PeerVpcId=peer_vpc.id)
main_route_table.create_route(
DestinationCidrBlock=ROUTE_CIDR, VpcPeeringConnectionId=vpc_pcx.id
)
# Refresh route table
main_route_table.reload()
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 1
2021-09-25 11:13:07 +00:00
new_route = new_routes[0]
assert new_route.gateway_id is None
assert new_route.instance_id is None
assert new_route.vpc_peering_connection_id == vpc_pcx.id
assert new_route.state == "active"
assert new_route.destination_cidr_block == ROUTE_CIDR
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_routes_vpn_gateway():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
main_route_table_id = client.describe_route_tables(
Filters=[
{"Name": "vpc-id", "Values": [vpc.id]},
{"Name": "association.main", "Values": ["true"]},
]
)["RouteTables"][0]["RouteTableId"]
main_route_table = ec2.RouteTable(main_route_table_id)
ROUTE_CIDR = "10.0.0.4/24"
vpn_gw_id = client.create_vpn_gateway(Type="ipsec.1")["VpnGateway"]["VpnGatewayId"]
main_route_table.create_route(DestinationCidrBlock=ROUTE_CIDR, GatewayId=vpn_gw_id)
main_route_table.reload()
new_routes = [
route
for route in main_route_table.routes
if route.destination_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 1
2021-09-25 11:13:07 +00:00
new_route = new_routes[0]
assert new_route.gateway_id == vpn_gw_id
assert new_route.instance_id is None
assert new_route.vpc_peering_connection_id is None
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_network_acl_tagging():
2021-09-25 11:13:07 +00:00
client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = ec2.create_route_table(VpcId=vpc.id)
route_table.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
2021-10-05 17:11:07 +00:00
tag = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [route_table.id]}]
)["Tags"][0]
assert tag["ResourceType"] == "route-table"
assert tag["Key"] == "a key"
assert tag["Value"] == "some value"
2021-09-25 11:13:07 +00:00
all_route_tables = client.describe_route_tables()["RouteTables"]
test_route_table = next(
na for na in all_route_tables if na["RouteTableId"] == route_table.id
)
assert test_route_table["Tags"] == [{"Value": "some value", "Key": "a key"}]
2021-09-25 11:13:07 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_invalid_destination_cidr_block_parameter():
ec2 = boto3.resource("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc.reload()
assert vpc.is_default is False
route_table = ec2.create_route_table(VpcId=vpc.id)
route_table.reload()
internet_gateway = ec2.create_internet_gateway()
vpc.attach_internet_gateway(InternetGatewayId=internet_gateway.id)
internet_gateway.reload()
destination_cidr_block = "1000.1.0.0/20"
with pytest.raises(ClientError) as ex:
route_table.create_route(
DestinationCidrBlock=destination_cidr_block, GatewayId=internet_gateway.id
)
assert (
str(ex.value)
== f"An error occurred (InvalidParameterValue) when calling the CreateRoute operation: Value ({destination_cidr_block}) for parameter destinationCidrBlock is invalid. This is not a valid CIDR block."
2019-10-31 15:44:26 +00:00
)
route_table.create_route(
DestinationIpv6CidrBlock="2001:db8::/125", GatewayId=internet_gateway.id
)
new_routes = [
route
for route in route_table.routes
if route.destination_cidr_block != vpc.cidr_block
2021-08-11 20:23:04 +00:00
or route.destination_ipv6_cidr_block != vpc.cidr_block
]
assert len(new_routes) == 1
assert new_routes[0].route_table_id is not None
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_network_interface_id():
ec2 = boto3.resource("ec2", region_name="us-west-2")
ec2_client = boto3.client("ec2", region_name="us-west-2")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
)
route_table = ec2_client.create_route_table(VpcId=vpc.id)
route_table_id = route_table["RouteTable"]["RouteTableId"]
eni1 = ec2_client.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress="10.0.10.5"
)
route = ec2_client.create_route(
NetworkInterfaceId=eni1["NetworkInterface"]["NetworkInterfaceId"],
RouteTableId=route_table_id,
)
assert route["ResponseMetadata"]["HTTPStatusCode"] == 200
2024-01-07 12:03:33 +00:00
@mock_aws
def test_describe_route_tables_with_nat_gateway():
ec2 = boto3.client("ec2", region_name="us-west-1")
vpc_id = ec2.create_vpc(CidrBlock="192.168.0.0/23")["Vpc"]["VpcId"]
igw_id = ec2.create_internet_gateway()["InternetGateway"]["InternetGatewayId"]
ec2.attach_internet_gateway(VpcId=vpc_id, InternetGatewayId=igw_id)
az = ec2.describe_availability_zones()["AvailabilityZones"][0]["ZoneName"]
sn_id = ec2.create_subnet(
AvailabilityZone=az, CidrBlock="192.168.0.0/24", VpcId=vpc_id
)["Subnet"]["SubnetId"]
route_table_id = ec2.create_route_table(VpcId=vpc_id)["RouteTable"]["RouteTableId"]
ec2.associate_route_table(SubnetId=sn_id, RouteTableId=route_table_id)
alloc_id = ec2.allocate_address(Domain="vpc")["AllocationId"]
nat_gw_id = ec2.create_nat_gateway(SubnetId=sn_id, AllocationId=alloc_id)[
"NatGateway"
]["NatGatewayId"]
ec2.create_route(
DestinationCidrBlock="0.0.0.0/0",
NatGatewayId=nat_gw_id,
RouteTableId=route_table_id,
)
route_table = ec2.describe_route_tables(
Filters=[{"Name": "route-table-id", "Values": [route_table_id]}]
)["RouteTables"][0]
nat_gw_routes = [
route
for route in route_table["Routes"]
if route["DestinationCidrBlock"] == "0.0.0.0/0"
]
assert len(nat_gw_routes) == 1
assert nat_gw_routes[0]["DestinationCidrBlock"] == "0.0.0.0/0"
assert nat_gw_routes[0]["NatGatewayId"] == nat_gw_id
assert nat_gw_routes[0]["State"] == "active"
2020-04-28 18:58:19 +00:00
2024-01-07 12:03:33 +00:00
@mock_aws
2020-04-28 18:58:19 +00:00
def test_create_vpc_end_point():
ec2 = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
2020-04-29 15:29:25 +00:00
subnet = ec2.create_subnet(VpcId=vpc["Vpc"]["VpcId"], CidrBlock="10.0.0.0/24")
2020-04-28 18:58:19 +00:00
route_table = ec2.create_route_table(VpcId=vpc["Vpc"]["VpcId"])
2020-04-29 12:32:02 +00:00
# test without any end point type specified
2020-04-28 18:58:19 +00:00
vpc_end_point = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"],
ServiceName="com.amazonaws.us-east-1.s3",
2020-04-29 15:29:25 +00:00
RouteTableIds=[route_table["RouteTable"]["RouteTableId"]],
)
2020-04-28 18:58:19 +00:00
assert vpc_end_point["VpcEndpoint"]["ServiceName"] == "com.amazonaws.us-east-1.s3"
assert (
vpc_end_point["VpcEndpoint"]["RouteTableIds"][0]
== route_table["RouteTable"]["RouteTableId"]
2020-04-29 15:29:25 +00:00
)
assert vpc_end_point["VpcEndpoint"]["VpcId"] == vpc["Vpc"]["VpcId"]
assert len(vpc_end_point["VpcEndpoint"]["DnsEntries"]) == 0
2020-04-28 18:58:19 +00:00
2020-04-29 12:32:02 +00:00
# test with any end point type as gateway
vpc_end_point = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"],
ServiceName="com.amazonaws.us-east-1.s3",
RouteTableIds=[route_table["RouteTable"]["RouteTableId"]],
2020-04-29 15:29:25 +00:00
VpcEndpointType="gateway",
2020-04-29 12:32:02 +00:00
)
assert vpc_end_point["VpcEndpoint"]["ServiceName"] == "com.amazonaws.us-east-1.s3"
assert (
vpc_end_point["VpcEndpoint"]["RouteTableIds"][0]
== route_table["RouteTable"]["RouteTableId"]
2020-04-29 15:29:25 +00:00
)
assert vpc_end_point["VpcEndpoint"]["VpcId"] == vpc["Vpc"]["VpcId"]
assert len(vpc_end_point["VpcEndpoint"]["DnsEntries"]) == 0
2020-04-29 12:32:02 +00:00
# test with end point type as interface
2020-04-28 18:58:19 +00:00
vpc_end_point = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"],
ServiceName="com.amazonaws.us-east-1.s3",
SubnetIds=[subnet["Subnet"]["SubnetId"]],
2020-04-29 15:29:25 +00:00
VpcEndpointType="interface",
2020-04-28 18:58:19 +00:00
)
assert vpc_end_point["VpcEndpoint"]["ServiceName"] == "com.amazonaws.us-east-1.s3"
assert vpc_end_point["VpcEndpoint"]["SubnetIds"][0] == subnet["Subnet"]["SubnetId"]
assert vpc_end_point["VpcEndpoint"]["VpcId"] == vpc["Vpc"]["VpcId"]
assert len(vpc_end_point["VpcEndpoint"]["DnsEntries"]) > 0
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_tables_with_tags():
ec2 = boto3.resource("ec2", region_name="eu-central-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = ec2.create_route_table(
VpcId=vpc.id,
TagSpecifications=[
{
"ResourceType": "route-table",
"Tags": [{"Key": "test", "Value": "TestRouteTable"}],
}
],
)
assert len(route_table.tags) == 1
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_egress_only_igw():
ec2 = boto3.resource("ec2", region_name="eu-central-1")
ec2_client = boto3.client("ec2", region_name="eu-central-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
eigw = ec2_client.create_egress_only_internet_gateway(VpcId=vpc.id)
eigw_id = eigw["EgressOnlyInternetGateway"]["EgressOnlyInternetGatewayId"]
route_table = ec2.create_route_table(VpcId=vpc.id)
ec2_client.create_route(
RouteTableId=route_table.id,
EgressOnlyInternetGatewayId=eigw_id,
DestinationIpv6CidrBlock="::/0",
)
route_table.reload()
eigw_route = [
r
for r in route_table.routes_attribute
if r.get("DestinationIpv6CidrBlock") == "::/0"
][0]
assert eigw_route.get("EgressOnlyInternetGatewayId") == eigw_id
assert eigw_route.get("State") == "active"
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_unknown_egress_only_igw():
ec2 = boto3.resource("ec2", region_name="eu-central-1")
ec2_client = boto3.client("ec2", region_name="eu-central-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
2021-10-18 19:44:29 +00:00
ec2.create_subnet(
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
)
route_table = ec2.create_route_table(VpcId=vpc.id)
with pytest.raises(ClientError) as ex:
ec2_client.create_route(
RouteTableId=route_table.id, EgressOnlyInternetGatewayId="eoigw"
)
err = ex.value.response["Error"]
assert err["Code"] == "InvalidGatewayID.NotFound"
assert err["Message"] == "The eigw ID 'eoigw' does not exist"
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_vpc_endpoint():
# Setup
_, ec2_client, route_table, vpc = setup_vpc()
dest_cidr = "0.0.0.0/0"
vpc_end_point = ec2_client.create_vpc_endpoint(
VpcId=vpc.id,
ServiceName="com.amazonaws.vpce.eu-central-1.vpce-svc-084fa044c50cb1290",
RouteTableIds=[route_table.id],
VpcEndpointType="GatewayLoadBalancer",
)
vpce_id = vpc_end_point["VpcEndpoint"]["VpcEndpointId"]
# Execute
ec2_client.create_route(
DestinationCidrBlock=dest_cidr,
VpcEndpointId=vpce_id,
RouteTableId=route_table.id,
)
rt = ec2_client.describe_route_tables(RouteTableIds=[route_table.id])
new_route = rt["RouteTables"][-1]["Routes"][1]
# Verify
assert new_route["DestinationCidrBlock"] == dest_cidr
assert new_route["GatewayId"] == vpce_id
2024-01-07 12:03:33 +00:00
@mock_aws
def test_create_route_with_invalid_vpc_endpoint():
# Setup
_, ec2_client, route_table, vpc = setup_vpc()
dest_cidr = "0.0.0.0/0"
vpc_end_point = ec2_client.create_vpc_endpoint(
VpcId=vpc.id,
ServiceName="com.amazonaws.us-east-1.s3",
RouteTableIds=[route_table.id],
VpcEndpointType="Gateway",
)
vpce_id = vpc_end_point["VpcEndpoint"]["VpcEndpointId"]
# Execute
with pytest.raises(ClientError) as ex:
ec2_client.create_route(
DestinationCidrBlock=dest_cidr,
VpcEndpointId=vpce_id,
RouteTableId=route_table.id,
)
# Verify
err = ex.value.response["Error"]
assert err["Code"] == "RouteNotSupported"
assert (
err["Message"] == f"Route table contains unsupported route target: {vpce_id}. "
"VPC Endpoints of this type cannot be used as route targets."
)
2024-01-07 12:03:33 +00:00
@mock_aws
def test_associate_route_table_by_gateway():
ec2 = boto3.client("ec2", region_name="us-west-1")
vpc_id = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
route_table_id = ec2.create_route_table(VpcId=vpc_id)["RouteTable"]["RouteTableId"]
igw_id = ec2.create_internet_gateway()["InternetGateway"]["InternetGatewayId"]
assoc_id = ec2.associate_route_table(RouteTableId=route_table_id, GatewayId=igw_id)[
"AssociationId"
]
verify = ec2.describe_route_tables(
Filters=[
{"Name": "association.route-table-association-id", "Values": [assoc_id]}
]
)["RouteTables"]
assert len(verify[0]["Associations"]) == 1
assert verify[0]["Associations"][0]["Main"] is False
assert verify[0]["Associations"][0]["GatewayId"] == igw_id
assert verify[0]["Associations"][0]["RouteTableAssociationId"] == assoc_id
assert "SubnetId" not in verify[0]["Associations"][0]
2024-01-07 12:03:33 +00:00
@mock_aws
def test_associate_route_table_by_subnet():
ec2 = boto3.client("ec2", region_name="us-west-1")
vpc_id = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
route_table_id = ec2.create_route_table(VpcId=vpc_id)["RouteTable"]["RouteTableId"]
subnet_id = ec2.create_subnet(VpcId=vpc_id, CidrBlock="10.0.0.0/24")["Subnet"][
"SubnetId"
]
assoc_id = ec2.associate_route_table(
RouteTableId=route_table_id, SubnetId=subnet_id
)["AssociationId"]
verify = ec2.describe_route_tables(
Filters=[
{"Name": "association.route-table-association-id", "Values": [assoc_id]}
]
)["RouteTables"]
assert len(verify[0]["Associations"]) == 1
assert verify[0]["Associations"][0]["Main"] is False
assert verify[0]["Associations"][0]["SubnetId"] == subnet_id
assert verify[0]["Associations"][0]["RouteTableAssociationId"] == assoc_id
assert "GatewayId" not in verify[0]["Associations"][0]
def setup_vpc():
ec2_resource = boto3.resource("ec2", region_name="eu-central-1")
ec2_client = boto3.client("ec2", region_name="eu-central-1")
vpc = ec2_resource.create_vpc(CidrBlock="10.0.0.0/16")
ec2_resource.create_subnet(
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
)
route_table = ec2_resource.create_route_table(VpcId=vpc.id)
return ec2_resource, ec2_client, route_table, vpc