Parallelize tests - Part 1 (#4368)

This commit is contained in:
Bert Blommers 2021-10-05 17:11:07 +00:00 committed by GitHub
parent e9a4100324
commit 8526013e61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 2872 additions and 1752 deletions

View File

@ -143,7 +143,7 @@ jobs:
pip install "coverage<=4.5.4" pip install "coverage<=4.5.4"
- name: Test with pytest - name: Test with pytest
run: | run: |
make test-coverage make test-only
- name: "Upload coverage to Codecov" - name: "Upload coverage to Codecov"
if: ${{ github.repository == 'spulec/moto'}} if: ${{ github.repository == 'spulec/moto'}}
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v1
@ -192,13 +192,28 @@ jobs:
env: env:
TEST_SERVER_MODE: ${{ true }} TEST_SERVER_MODE: ${{ true }}
run: | run: |
make test-coverage make test-only
- name: "Upload coverage to Codecov" - name: "Upload coverage to Codecov"
if: ${{ github.repository == 'spulec/moto'}} if: ${{ github.repository == 'spulec/moto'}}
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v1
with: with:
fail_ci_if_error: false fail_ci_if_error: false
flags: servertests flags: servertests
- name: "Stop MotoServer"
if: always()
run: |
mkdir serverlogs
pwd
ls -la
cp server_output.log serverlogs/server_output.log
docker stop motoserver
- name: Archive TF logs
if: always()
uses: actions/upload-artifact@v2
with:
name: motoserver-${{ matrix.python-version }}
path: |
serverlogs/*
test_responses: test_responses:
name: Test Responses==0.12.0 name: Test Responses==0.12.0
@ -283,11 +298,14 @@ jobs:
# So we simply split the list of tests, and ask our CI for separate VM's to run them in parallel # So we simply split the list of tests, and ask our CI for separate VM's to run them in parallel
- name: Get list of tests - name: Get list of tests
run: | run: |
split -n l/3 tests/terraform-tests.success.txt tf-split- cd moto-terraform-tests
bin/list-tests -i ../tests/terraform-tests.success.txt -e ../tests/terraform-tests.failures.txt > tftestlist.txt
split -n l/3 tftestlist.txt tf-split-
cd ..
- name: Run Terraform Tests - name: Run Terraform Tests
run: | run: |
cd moto-terraform-tests cd moto-terraform-tests
AWS_DEFAULT_REGION=us-east-1 AWS_ALTERNATE_REGION=eu-west-1 bin/run-tests -t -i ../tf-split-${{ matrix.part }} -e ../tests/terraform-tests.failures.txt AWS_DEFAULT_REGION=us-east-1 AWS_ALTERNATE_REGION=eu-west-1 bin/run-tests -t -i tf-split-${{ matrix.part }} -e ../tests/terraform-tests.failures.txt
cd .. cd ..
- name: "Create report" - name: "Create report"
run: | run: |

View File

@ -54,6 +54,10 @@ TEST_SERVER_MODE=true pytest -sv tests/test_service/..
import warnings import warnings
warnings.warn("The Filters-parameter is not yet implemented for client.method()") warnings.warn("The Filters-parameter is not yet implemented for client.method()")
``` ```
- To speed up our CI, the ServerMode tests for the `awslambda`, `batch`, `ec2` and `sqs` services will run in parallel.
This means the following:
- Make sure you use unique names for functions/queues/etc
- Calls to `describe_reservations()`/`list_queues()`/etc might return unexpected results
# Missing features # Missing features

View File

@ -3,9 +3,12 @@ SHELL := /bin/bash
ifeq ($(TEST_SERVER_MODE), true) ifeq ($(TEST_SERVER_MODE), true)
# exclude test_kinesisvideoarchivedmedia # exclude test_kinesisvideoarchivedmedia
# because testing with moto_server is difficult with data-endpoint # because testing with moto_server is difficult with data-endpoint
TEST_EXCLUDE := -k 'not test_kinesisvideoarchivedmedia' TEST_EXCLUDE := -k 'not (test_kinesisvideoarchivedmedia or test_awslambda or test_batch or test_ec2 or test_sqs)'
# Parallel tests will be run separate
PARALLEL_TESTS := ./tests/test_awslambda ./tests/test_batch ./tests/test_ec2 ./tests/test_sqs
else else
TEST_EXCLUDE := TEST_EXCLUDE :=
PARALLEL_TESTS := ./tests/test_core
endif endif
init: init:
@ -21,14 +24,10 @@ format:
black moto/ tests/ black moto/ tests/
test-only: test-only:
rm -f .coverage
rm -rf cover
pytest -sv ./tests/ $(TEST_EXCLUDE)
test-coverage:
rm -f .coverage rm -f .coverage
rm -rf cover rm -rf cover
pytest -sv --cov=moto --cov-report xml ./tests/ $(TEST_EXCLUDE) pytest -sv --cov=moto --cov-report xml ./tests/ $(TEST_EXCLUDE)
MOTO_CALL_RESET_API=false pytest -n 4 $(PARALLEL_TESTS)
test: lint test-only test: lint test-only
@ -38,22 +37,6 @@ test_server:
aws_managed_policies: aws_managed_policies:
scripts/update_managed_policies.py scripts/update_managed_policies.py
upload_pypi_artifact:
python setup.py sdist bdist_wheel
twine upload dist/*
push_dockerhub_image:
docker build -t motoserver/moto . --tag moto:`python setup.py --version`
docker push motoserver/moto
tag_github_release:
git tag `python setup.py --version`
git push origin `python setup.py --version`
publish: upload_pypi_artifact \
tag_github_release \
push_dockerhub_image
implementation_coverage: implementation_coverage:
./scripts/implementation_coverage.py ./scripts/implementation_coverage.py
git commit IMPLEMENTATION_COVERAGE.md -m "Updating implementation coverage" || true git commit IMPLEMENTATION_COVERAGE.md -m "Updating implementation coverage" || true

View File

@ -481,9 +481,11 @@ MockAWS = BotocoreEventMockAWS
class ServerModeMockAWS(BaseMockAWS): class ServerModeMockAWS(BaseMockAWS):
def reset(self): def reset(self):
import requests call_reset_api = os.environ.get("MOTO_CALL_RESET_API")
if not call_reset_api or call_reset_api.lower() != "false":
import requests
requests.post("http://localhost:5000/moto-api/reset") requests.post("http://localhost:5000/moto-api/reset")
def enable_patching(self): def enable_patching(self):
if self.__class__.nested_count == 1: if self.__class__.nested_count == 1:

View File

@ -358,7 +358,9 @@ class NetworkInterface(TaggedEC2Resource, CloudFormationModel):
def association(self): def association(self):
association = {} association = {}
if self.public_ip: if self.public_ip:
eips = self.ec2_backend.address_by_ip([self.public_ip]) eips = self.ec2_backend.address_by_ip(
[self.public_ip], fail_if_not_found=False
)
eip = eips[0] if len(eips) > 0 else None eip = eips[0] if len(eips) > 0 else None
if eip: if eip:
association["allocationId"] = eip.allocation_id or None association["allocationId"] = eip.allocation_id or None
@ -538,7 +540,7 @@ class NetworkInterfaceBackend(object):
eni.source_dest_check = source_dest_check eni.source_dest_check = source_dest_check
def get_all_network_interfaces(self, eni_ids=None, filters=None): def get_all_network_interfaces(self, eni_ids=None, filters=None):
enis = self.enis.values() enis = self.enis.copy().values()
if eni_ids: if eni_ids:
enis = [eni for eni in enis if eni.id in eni_ids] enis = [eni for eni in enis if eni.id in eni_ids]
@ -1234,7 +1236,7 @@ class InstanceBackend(object):
def all_reservations(self, filters=None): def all_reservations(self, filters=None):
reservations = [ reservations = [
copy.copy(reservation) for reservation in self.reservations.values() copy.copy(reservation) for reservation in self.reservations.copy().values()
] ]
if filters is not None: if filters is not None:
reservations = filter_reservations(reservations, filters) reservations = filter_reservations(reservations, filters)
@ -1441,7 +1443,7 @@ class TagBackend(object):
value_filters.append( value_filters.append(
re.compile(simple_aws_filter_to_re(value)) re.compile(simple_aws_filter_to_re(value))
) )
for resource_id, tags in self.tags.items(): for resource_id, tags in self.tags.copy().items():
for key, value in tags.items(): for key, value in tags.items():
add_result = False add_result = False
if filters is None: if filters is None:
@ -1486,9 +1488,9 @@ class TagBackend(object):
"resource_id": resource_id, "resource_id": resource_id,
"key": key, "key": key,
"value": value, "value": value,
"resource_type": EC2_PREFIX_TO_RESOURCE[ "resource_type": EC2_PREFIX_TO_RESOURCE.get(
get_prefix(resource_id) get_prefix(resource_id), ""
], ),
} }
results.append(result) results.append(result)
return results return results
@ -1677,7 +1679,7 @@ class AmiBackend(object):
def describe_images( def describe_images(
self, ami_ids=(), filters=None, exec_users=None, owners=None, context=None self, ami_ids=(), filters=None, exec_users=None, owners=None, context=None
): ):
images = self.amis.values() images = self.amis.copy().values()
if len(ami_ids): if len(ami_ids):
# boto3 seems to default to just searching based on ami ids if that parameter is passed # boto3 seems to default to just searching based on ami ids if that parameter is passed
@ -2536,7 +2538,8 @@ class SecurityGroupBackend(object):
return group return group
def describe_security_groups(self, group_ids=None, groupnames=None, filters=None): def describe_security_groups(self, group_ids=None, groupnames=None, filters=None):
matches = itertools.chain(*[x.values() for x in self.groups.values()]) all_groups = self.groups.copy()
matches = itertools.chain(*[x.copy().values() for x in all_groups.values()])
if group_ids: if group_ids:
matches = [grp for grp in matches if grp.id in group_ids] matches = [grp for grp in matches if grp.id in group_ids]
if len(group_ids) > len(matches): if len(group_ids) > len(matches):
@ -2578,7 +2581,7 @@ class SecurityGroupBackend(object):
def get_security_group_from_id(self, group_id): def get_security_group_from_id(self, group_id):
# 2 levels of chaining necessary since it's a complex structure # 2 levels of chaining necessary since it's a complex structure
all_groups = itertools.chain.from_iterable( all_groups = itertools.chain.from_iterable(
[x.values() for x in self.groups.values()] [x.copy().values() for x in self.groups.copy().values()]
) )
for group in all_groups: for group in all_groups:
if group.id == group_id: if group.id == group_id:
@ -3273,7 +3276,7 @@ class Volume(TaggedEC2Resource, CloudFormationModel):
elif filter_name == "encrypted": elif filter_name == "encrypted":
return str(self.encrypted).lower() return str(self.encrypted).lower()
elif filter_name == "availability-zone": elif filter_name == "availability-zone":
return self.zone.name return self.zone.name if self.zone else None
else: else:
return super().get_filter_value(filter_name, "DescribeVolumes") return super().get_filter_value(filter_name, "DescribeVolumes")
@ -3347,7 +3350,7 @@ class EBSBackend(object):
return volume return volume
def describe_volumes(self, volume_ids=None, filters=None): def describe_volumes(self, volume_ids=None, filters=None):
matches = self.volumes.values() matches = self.volumes.copy().values()
if volume_ids: if volume_ids:
matches = [vol for vol in matches if vol.id in volume_ids] matches = [vol for vol in matches if vol.id in volume_ids]
if len(volume_ids) > len(matches): if len(volume_ids) > len(matches):
@ -3422,7 +3425,7 @@ class EBSBackend(object):
return snapshot return snapshot
def describe_snapshots(self, snapshot_ids=None, filters=None): def describe_snapshots(self, snapshot_ids=None, filters=None):
matches = self.snapshots.values() matches = self.snapshots.copy().values()
if snapshot_ids: if snapshot_ids:
matches = [snap for snap in matches if snap.id in snapshot_ids] matches = [snap for snap in matches if snap.id in snapshot_ids]
if len(snapshot_ids) > len(matches): if len(snapshot_ids) > len(matches):
@ -3776,7 +3779,7 @@ class VPCBackend(object):
return match_vpc return match_vpc
def describe_vpcs(self, vpc_ids=None, filters=None): def describe_vpcs(self, vpc_ids=None, filters=None):
matches = self.vpcs.values() matches = self.vpcs.copy().values()
if vpc_ids: if vpc_ids:
matches = [vpc for vpc in matches if vpc.id in vpc_ids] matches = [vpc for vpc in matches if vpc.id in vpc_ids]
if len(vpc_ids) > len(matches): if len(vpc_ids) > len(matches):
@ -3859,9 +3862,9 @@ class VPCBackend(object):
raise InvalidParameterValueError(attr_name) raise InvalidParameterValueError(attr_name)
def disassociate_vpc_cidr_block(self, association_id): def disassociate_vpc_cidr_block(self, association_id):
for vpc in self.vpcs.values(): for vpc in self.vpcs.copy().values():
response = vpc.disassociate_vpc_cidr_block(association_id) response = vpc.disassociate_vpc_cidr_block(association_id)
for route_table in self.route_tables.values(): for route_table in self.route_tables.copy().values():
if route_table.vpc_id == response.get("vpc_id"): if route_table.vpc_id == response.get("vpc_id"):
if "::/" in response.get("cidr_block"): if "::/" in response.get("cidr_block"):
self.delete_route( self.delete_route(
@ -4277,9 +4280,10 @@ class VPCPeeringConnectionBackend(object):
return vpc_pcx return vpc_pcx
def describe_vpc_peering_connections(self, vpc_peering_ids=None): def describe_vpc_peering_connections(self, vpc_peering_ids=None):
all_pcxs = self.vpc_pcxs.copy().values()
if vpc_peering_ids: if vpc_peering_ids:
return [pcx for pcx in self.vpc_pcxs.values() if pcx.id in vpc_peering_ids] return [pcx for pcx in all_pcxs if pcx.id in vpc_peering_ids]
return self.vpc_pcxs.values() return all_pcxs
def get_vpc_peering_connection(self, vpc_pcx_id): def get_vpc_peering_connection(self, vpc_pcx_id):
if vpc_pcx_id not in self.vpc_pcxs: if vpc_pcx_id not in self.vpc_pcxs:
@ -4346,9 +4350,7 @@ class Subnet(TaggedEC2Resource, CloudFormationModel):
self.vpc_id = vpc_id self.vpc_id = vpc_id
self.cidr_block = cidr_block self.cidr_block = cidr_block
self.cidr = ipaddress.IPv4Network(str(self.cidr_block), strict=False) self.cidr = ipaddress.IPv4Network(str(self.cidr_block), strict=False)
self._available_ip_addresses = ( self._available_ip_addresses = self.cidr.num_addresses - 5
ipaddress.IPv4Network(str(self.cidr_block)).num_addresses - 5
)
self._availability_zone = availability_zone self._availability_zone = availability_zone
self.default_for_az = default_for_az self.default_for_az = default_for_az
self.map_public_ip_on_launch = map_public_ip_on_launch self.map_public_ip_on_launch = map_public_ip_on_launch
@ -5111,7 +5113,7 @@ class RouteTableBackend(object):
return route_table return route_table
def describe_route_tables(self, route_table_ids=None, filters=None): def describe_route_tables(self, route_table_ids=None, filters=None):
route_tables = self.route_tables.values() route_tables = self.route_tables.copy().values()
if route_table_ids: if route_table_ids:
route_tables = [ route_tables = [
@ -5380,7 +5382,7 @@ class ManagedPrefixListBackend(object):
return managed_prefix_list return managed_prefix_list
def describe_managed_prefix_lists(self, prefix_list_ids=None, filters=None): def describe_managed_prefix_lists(self, prefix_list_ids=None, filters=None):
managed_prefix_lists = list(self.managed_prefix_lists.values()) managed_prefix_lists = list(self.managed_prefix_lists.copy().values())
attr_pairs = ( attr_pairs = (
("owner-id", "owner_id"), ("owner-id", "owner_id"),
("prefix-list-id", "id"), ("prefix-list-id", "id"),
@ -6036,8 +6038,11 @@ class SpotRequestBackend(object, metaclass=Model):
return requests return requests
@Model.prop("SpotInstanceRequest") @Model.prop("SpotInstanceRequest")
def describe_spot_instance_requests(self, filters=None): def describe_spot_instance_requests(self, filters=None, spot_instance_ids=[]):
requests = self.spot_instance_requests.values() requests = self.spot_instance_requests.copy().values()
if spot_instance_ids:
requests = [i for i in requests if i.id in spot_instance_ids]
return generic_filter(filters, requests) return generic_filter(filters, requests)
@ -6447,12 +6452,18 @@ class ElasticAddress(TaggedEC2Resource, CloudFormationModel):
return self.association_id return self.association_id
elif filter_name == "domain": elif filter_name == "domain":
return self.domain return self.domain
elif filter_name == "instance-id" and self.instance: elif filter_name == "instance-id":
return self.instance.id if self.instance:
elif filter_name == "network-interface-id" and self.eni: return self.instance.id
return self.eni.id return None
elif filter_name == "private-ip-address" and self.eni: elif filter_name == "network-interface-id":
return self.eni.private_ip_address if self.eni:
return self.eni.id
return None
elif filter_name == "private-ip-address":
if self.eni:
return self.eni.private_ip_address
return None
elif filter_name == "public-ip": elif filter_name == "public-ip":
return self.public_ip return self.public_ip
elif filter_name == "network-interface-owner-id": elif filter_name == "network-interface-owner-id":
@ -6477,11 +6488,13 @@ class ElasticAddressBackend(object):
self.addresses.append(address) self.addresses.append(address)
return address return address
def address_by_ip(self, ips): def address_by_ip(self, ips, fail_if_not_found=True):
eips = [address for address in self.addresses if address.public_ip in ips] eips = [
address for address in self.addresses.copy() if address.public_ip in ips
]
# TODO: Trim error message down to specific invalid address. # TODO: Trim error message down to specific invalid address.
if not eips or len(ips) > len(eips): if (not eips or len(ips) > len(eips)) and fail_if_not_found:
raise InvalidAddressError(ips) raise InvalidAddressError(ips)
return eips return eips
@ -6548,7 +6561,7 @@ class ElasticAddressBackend(object):
raise ResourceAlreadyAssociatedError(eip.public_ip) raise ResourceAlreadyAssociatedError(eip.public_ip)
def describe_addresses(self, allocation_ids=None, public_ips=None, filters=None): def describe_addresses(self, allocation_ids=None, public_ips=None, filters=None):
matches = self.addresses matches = self.addresses.copy()
if allocation_ids: if allocation_ids:
matches = [addr for addr in matches if addr.allocation_id in allocation_ids] matches = [addr for addr in matches if addr.allocation_id in allocation_ids]
if len(allocation_ids) > len(matches): if len(allocation_ids) > len(matches):
@ -6557,7 +6570,7 @@ class ElasticAddressBackend(object):
if public_ips: if public_ips:
matches = [addr for addr in matches if addr.public_ip in public_ips] matches = [addr for addr in matches if addr.public_ip in public_ips]
if len(public_ips) > len(matches): if len(public_ips) > len(matches):
unknown_ips = set(allocation_ids) - set(matches) unknown_ips = set(public_ips) - set(matches)
raise InvalidAddressError(unknown_ips) raise InvalidAddressError(unknown_ips)
if filters: if filters:
matches = generic_filter(filters, matches) matches = generic_filter(filters, matches)
@ -6690,7 +6703,7 @@ class DHCPOptionsSetBackend(object):
options_sets.append(self.dhcp_options_sets[option_id]) options_sets.append(self.dhcp_options_sets[option_id])
else: else:
raise InvalidDHCPOptionsIdError(option_id) raise InvalidDHCPOptionsIdError(option_id)
return options_sets or self.dhcp_options_sets.values() return options_sets or self.dhcp_options_sets.copy().values()
def delete_dhcp_options_set(self, options_id): def delete_dhcp_options_set(self, options_id):
if not (options_id and options_id.startswith("dopt-")): if not (options_id and options_id.startswith("dopt-")):
@ -6988,7 +7001,7 @@ class NetworkAclBackend(object):
) )
def describe_network_acls(self, network_acl_ids=None, filters=None): def describe_network_acls(self, network_acl_ids=None, filters=None):
network_acls = self.network_acls.values() network_acls = self.network_acls.copy().values()
if network_acl_ids: if network_acl_ids:
network_acls = [ network_acls = [
@ -7199,8 +7212,13 @@ class CustomerGatewayBackend(object):
self.customer_gateways[customer_gateway_id] = customer_gateway self.customer_gateways[customer_gateway_id] = customer_gateway
return customer_gateway return customer_gateway
def get_all_customer_gateways(self, filters=None): def get_all_customer_gateways(self, filters=None, customer_gateway_ids=None):
customer_gateways = self.customer_gateways.values() customer_gateways = self.customer_gateways.copy().values()
if customer_gateway_ids:
customer_gateways = [
cg for cg in customer_gateways if cg.id in customer_gateway_ids
]
if filters is not None: if filters is not None:
if filters.get("customer-gateway-id") is not None: if filters.get("customer-gateway-id") is not None:
customer_gateways = [ customer_gateways = [
@ -7324,8 +7342,13 @@ class TransitGatewayBackend(object):
self.transit_gateways[transit_gateway.id] = transit_gateway self.transit_gateways[transit_gateway.id] = transit_gateway
return transit_gateway return transit_gateway
def describe_transit_gateways(self, filters): def describe_transit_gateways(self, filters, transit_gateway_ids):
transit_gateways = list(self.transit_gateways.values()) transit_gateways = list(self.transit_gateways.copy().values())
if transit_gateway_ids:
transit_gateways = [
item for item in transit_gateways if item.id in transit_gateway_ids
]
attr_pairs = ( attr_pairs = (
("transit-gateway-id", "id"), ("transit-gateway-id", "id"),

View File

@ -27,7 +27,10 @@ class CustomerGateways(BaseResponse):
def describe_customer_gateways(self): def describe_customer_gateways(self):
filters = filters_from_querystring(self.querystring) filters = filters_from_querystring(self.querystring)
customer_gateways = self.ec2_backend.get_all_customer_gateways(filters) customer_gateway_ids = self._get_multi_param("CustomerGatewayId")
customer_gateways = self.ec2_backend.get_all_customer_gateways(
filters, customer_gateway_ids
)
template = self.response_template(DESCRIBE_CUSTOMER_GATEWAYS_RESPONSE) template = self.response_template(DESCRIBE_CUSTOMER_GATEWAYS_RESPONSE)
return template.render(customer_gateways=customer_gateways) return template.render(customer_gateways=customer_gateways)

View File

@ -29,8 +29,11 @@ class SpotInstances(BaseResponse):
) )
def describe_spot_instance_requests(self): def describe_spot_instance_requests(self):
spot_instance_ids = self._get_multi_param("SpotInstanceRequestId")
filters = filters_from_querystring(self.querystring) filters = filters_from_querystring(self.querystring)
requests = self.ec2_backend.describe_spot_instance_requests(filters=filters) requests = self.ec2_backend.describe_spot_instance_requests(
filters=filters, spot_instance_ids=spot_instance_ids
)
template = self.response_template(DESCRIBE_SPOT_INSTANCES_TEMPLATE) template = self.response_template(DESCRIBE_SPOT_INSTANCES_TEMPLATE)
return template.render(requests=requests) return template.render(requests=requests)

View File

@ -256,11 +256,13 @@ DESCRIBE_TRANSIT_GATEWAY_VPC_ATTACHMENTS = """<DescribeTransitGatewayVpcAttachme
{% for transit_gateway_vpc_attachment in transit_gateway_vpc_attachments %} {% for transit_gateway_vpc_attachment in transit_gateway_vpc_attachments %}
<item> <item>
<creationTime>2021-07-18T08:57:21.000Z</creationTime> <creationTime>2021-07-18T08:57:21.000Z</creationTime>
{% if transit_gateway_vpc_attachment.options %}
<options> <options>
<applianceModeSupport>{{ transit_gateway_vpc_attachment.options.ApplianceModeSupport }}</applianceModeSupport> <applianceModeSupport>{{ transit_gateway_vpc_attachment.options.ApplianceModeSupport }}</applianceModeSupport>
<dnsSupport>{{ transit_gateway_vpc_attachment.options.DnsSupport }}</dnsSupport> <dnsSupport>{{ transit_gateway_vpc_attachment.options.DnsSupport }}</dnsSupport>
<ipv6Support>{{ transit_gateway_vpc_attachment.options.Ipv6Support }}</ipv6Support> <ipv6Support>{{ transit_gateway_vpc_attachment.options.Ipv6Support }}</ipv6Support>
</options> </options>
{% endif %}
<state>{{ transit_gateway_vpc_attachment.state }}</state> <state>{{ transit_gateway_vpc_attachment.state }}</state>
<subnetIds> <subnetIds>
{% for id in transit_gateway_vpc_attachment.subnet_ids %} {% for id in transit_gateway_vpc_attachment.subnet_ids %}
@ -423,17 +425,23 @@ DESCRIBE_TRANSIT_GATEWAY_PEERING_ATTACHMENTS = """<DescribeTransitGatewayPeering
<item> <item>
<createTime>{{ transit_gateway_peering_attachment.create_time }}</createTime> <createTime>{{ transit_gateway_peering_attachment.create_time }}</createTime>
<state>{{ transit_gateway_peering_attachment.state }}</state> <state>{{ transit_gateway_peering_attachment.state }}</state>
{% if transit_gateway_peering_attachment.accepter_tgw_info %}
<accepterTgwInfo> <accepterTgwInfo>
<ownerId>{{ transit_gateway_peering_attachment.accepter_tgw_info.ownerId or '' }}</ownerId> <ownerId>{{ transit_gateway_peering_attachment.accepter_tgw_info.ownerId or '' }}</ownerId>
<region>{{ transit_gateway_peering_attachment.accepter_tgw_info.region or '' }}</region> <region>{{ transit_gateway_peering_attachment.accepter_tgw_info.region or '' }}</region>
<transitGatewayId>{{ transit_gateway_peering_attachment.accepter_tgw_info.transitGatewayId or '' }}</transitGatewayId> <transitGatewayId>{{ transit_gateway_peering_attachment.accepter_tgw_info.transitGatewayId or '' }}</transitGatewayId>
</accepterTgwInfo> </accepterTgwInfo>
{% endif %}
{% if transit_gateway_peering_attachment.requester_tgw_info %}
<requesterTgwInfo> <requesterTgwInfo>
<ownerId>{{ transit_gateway_peering_attachment.requester_tgw_info.ownerId or '' }}</ownerId> <ownerId>{{ transit_gateway_peering_attachment.requester_tgw_info.ownerId or '' }}</ownerId>
<region>{{ transit_gateway_peering_attachment.requester_tgw_info.region or '' }}</region> <region>{{ transit_gateway_peering_attachment.requester_tgw_info.region or '' }}</region>
<transitGatewayId>{{ transit_gateway_peering_attachment.requester_tgw_info.transitGatewayId or '' }}</transitGatewayId> <transitGatewayId>{{ transit_gateway_peering_attachment.requester_tgw_info.transitGatewayId or '' }}</transitGatewayId>
</requesterTgwInfo> </requesterTgwInfo>
{% endif %}
{% if transit_gateway_peering_attachment.status %}
<status>{{ transit_gateway_peering_attachment.status.code }}</status> <status>{{ transit_gateway_peering_attachment.status.code }}</status>
{% endif %}
<tagSet> <tagSet>
{% for tag in transit_gateway_peering_attachment.get_tags() %} {% for tag in transit_gateway_peering_attachment.get_tags() %}
<item> <item>

View File

@ -39,8 +39,11 @@ class TransitGateways(BaseResponse):
return template.render(transit_gateway=transit_gateway) return template.render(transit_gateway=transit_gateway)
def describe_transit_gateways(self): def describe_transit_gateways(self):
transit_gateway_ids = self._get_multi_param("TransitGatewayIds")
filters = filters_from_querystring(self.querystring) filters = filters_from_querystring(self.querystring)
transit_gateways = self.ec2_backend.describe_transit_gateways(filters) transit_gateways = self.ec2_backend.describe_transit_gateways(
filters, transit_gateway_ids
)
template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_RESPONSE) template = self.response_template(DESCRIBE_TRANSIT_GATEWAY_RESPONSE)
return template.render(transit_gateways=transit_gateways) return template.render(transit_gateways=transit_gateways)

View File

@ -826,7 +826,7 @@ DESCRIBE_PREFIX_LIST = """<DescribePrefixListsResponse xmlns="http://ec2.amazona
<requestId>8a2ec0e2-6918-4270-ae45-58e61971e97d</requestId> <requestId>8a2ec0e2-6918-4270-ae45-58e61971e97d</requestId>
<prefixListSet> <prefixListSet>
{% for pl in managed_pls %} {% for pl in managed_pls %}
{% if pl.prefix_list_name.startswith("com.amazonaws.") %} {% if pl.prefix_list_name and pl.prefix_list_name.startswith("com.amazonaws.") %}
<item> <item>
<cidrSet> <cidrSet>
{% for entry in pl.entries.1 %} {% for entry in pl.entries.1 %}

View File

@ -402,6 +402,9 @@ class Queue(CloudFormationModel):
tags = properties.pop("Tags", []) tags = properties.pop("Tags", [])
tags_dict = tags_from_cloudformation_tags_list(tags) tags_dict = tags_from_cloudformation_tags_list(tags)
# Could be passed as an integer - just treat it as a string
resource_name = str(resource_name)
sqs_backend = sqs_backends[region_name] sqs_backend = sqs_backends[region_name]
return sqs_backend.create_queue( return sqs_backend.create_queue(
name=resource_name, tags=tags_dict, region=region_name, **properties name=resource_name, tags=tags_dict, region=region_name, **properties

View File

@ -1,5 +1,6 @@
pytest pytest
pytest-cov pytest-cov
pytest-xdist
sure sure
freezegun freezegun
pylint pylint

View File

@ -1,4 +1,5 @@
import boto3 import boto3
from uuid import uuid4
DEFAULT_REGION = "eu-central-1" DEFAULT_REGION = "eu-central-1"
@ -27,17 +28,18 @@ def _setup(ec2_client, iam_client):
) )
subnet_id = resp["Subnet"]["SubnetId"] subnet_id = resp["Subnet"]["SubnetId"]
resp = ec2_client.create_security_group( resp = ec2_client.create_security_group(
Description="test_sg_desc", GroupName="test_sg", VpcId=vpc_id Description="test_sg_desc", GroupName=str(uuid4())[0:6], VpcId=vpc_id
) )
sg_id = resp["GroupId"] sg_id = resp["GroupId"]
role_name = f"{str(uuid4())[0:6]}"
resp = iam_client.create_role( resp = iam_client.create_role(
RoleName="TestRole", AssumeRolePolicyDocument="some_policy" RoleName=role_name, AssumeRolePolicyDocument="some_policy"
) )
iam_arn = resp["Role"]["Arn"] iam_arn = resp["Role"]["Arn"]
iam_client.create_instance_profile(InstanceProfileName="TestRole") iam_client.create_instance_profile(InstanceProfileName=role_name)
iam_client.add_role_to_instance_profile( iam_client.add_role_to_instance_profile(
InstanceProfileName="TestRole", RoleName="TestRole" InstanceProfileName=role_name, RoleName=role_name
) )
return vpc_id, subnet_id, sg_id, iam_arn return vpc_id, subnet_id, sg_id, iam_arn

View File

@ -1,20 +1,16 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import time
import datetime
import boto3 import boto3
from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
from moto import ( from moto import (
mock_batch, mock_batch,
mock_iam, mock_iam,
mock_ec2, mock_ec2,
mock_ecs, mock_ecs,
mock_logs,
mock_cloudformation, mock_cloudformation,
) )
import functools
import json import json
from uuid import uuid4
DEFAULT_REGION = "eu-central-1" DEFAULT_REGION = "eu-central-1"
@ -42,17 +38,18 @@ def _setup(ec2_client, iam_client):
) )
subnet_id = resp["Subnet"]["SubnetId"] subnet_id = resp["Subnet"]["SubnetId"]
resp = ec2_client.create_security_group( resp = ec2_client.create_security_group(
Description="test_sg_desc", GroupName="test_sg", VpcId=vpc_id Description="test_sg_desc", GroupName=str(uuid4())[0:6], VpcId=vpc_id
) )
sg_id = resp["GroupId"] sg_id = resp["GroupId"]
role_name = str(uuid4())[0:6]
resp = iam_client.create_role( resp = iam_client.create_role(
RoleName="TestRole", AssumeRolePolicyDocument="some_policy" RoleName=role_name, AssumeRolePolicyDocument="some_policy"
) )
iam_arn = resp["Role"]["Arn"] iam_arn = resp["Role"]["Arn"]
iam_client.create_instance_profile(InstanceProfileName="TestRole") iam_client.create_instance_profile(InstanceProfileName=role_name)
iam_client.add_role_to_instance_profile( iam_client.add_role_to_instance_profile(
InstanceProfileName="TestRole", RoleName="TestRole" InstanceProfileName=role_name, RoleName=role_name
) )
return vpc_id, subnet_id, sg_id, iam_arn return vpc_id, subnet_id, sg_id, iam_arn
@ -91,7 +88,8 @@ def test_create_env_cf():
cf_json = json.dumps(create_environment_template) cf_json = json.dumps(create_environment_template)
cf_conn = boto3.client("cloudformation", DEFAULT_REGION) cf_conn = boto3.client("cloudformation", DEFAULT_REGION)
stack_id = cf_conn.create_stack(StackName="test_stack", TemplateBody=cf_json)[ stack_name = str(uuid4())[0:6]
stack_id = cf_conn.create_stack(StackName=stack_name, TemplateBody=cf_json)[
"StackId" "StackId"
] ]
@ -105,7 +103,7 @@ def test_create_env_cf():
"arn:aws:batch:" "arn:aws:batch:"
) )
stack_resources["StackResourceSummaries"][0]["PhysicalResourceId"].should.contain( stack_resources["StackResourceSummaries"][0]["PhysicalResourceId"].should.contain(
"test_stack" stack_name
) )
@ -154,7 +152,8 @@ def test_create_job_queue_cf():
cf_json = json.dumps(create_environment_template) cf_json = json.dumps(create_environment_template)
cf_conn = boto3.client("cloudformation", DEFAULT_REGION) cf_conn = boto3.client("cloudformation", DEFAULT_REGION)
stack_id = cf_conn.create_stack(StackName="test_stack", TemplateBody=cf_json)[ stack_name = str(uuid4())[0:6]
stack_id = cf_conn.create_stack(StackName=stack_name, TemplateBody=cf_json)[
"StackId" "StackId"
] ]
@ -171,7 +170,7 @@ def test_create_job_queue_cf():
job_queue_resource["ResourceStatus"].should.equal("CREATE_COMPLETE") job_queue_resource["ResourceStatus"].should.equal("CREATE_COMPLETE")
# Spot checks on the ARN # Spot checks on the ARN
job_queue_resource["PhysicalResourceId"].startswith("arn:aws:batch:") job_queue_resource["PhysicalResourceId"].startswith("arn:aws:batch:")
job_queue_resource["PhysicalResourceId"].should.contain("test_stack") job_queue_resource["PhysicalResourceId"].should.contain(stack_name)
job_queue_resource["PhysicalResourceId"].should.contain("job-queue/") job_queue_resource["PhysicalResourceId"].should.contain("job-queue/")
@ -243,7 +242,8 @@ def test_create_job_def_cf():
cf_json = json.dumps(create_environment_template) cf_json = json.dumps(create_environment_template)
cf_conn = boto3.client("cloudformation", DEFAULT_REGION) cf_conn = boto3.client("cloudformation", DEFAULT_REGION)
stack_id = cf_conn.create_stack(StackName="test_stack", TemplateBody=cf_json)[ stack_name = str(uuid4())[0:6]
stack_id = cf_conn.create_stack(StackName=stack_name, TemplateBody=cf_json)[
"StackId" "StackId"
] ]
@ -260,7 +260,7 @@ def test_create_job_def_cf():
job_def_resource["ResourceStatus"].should.equal("CREATE_COMPLETE") job_def_resource["ResourceStatus"].should.equal("CREATE_COMPLETE")
# Spot checks on the ARN # Spot checks on the ARN
job_def_resource["PhysicalResourceId"].startswith("arn:aws:batch:") job_def_resource["PhysicalResourceId"].startswith("arn:aws:batch:")
job_def_resource["PhysicalResourceId"].should.contain("test_stack-JobDef") job_def_resource["PhysicalResourceId"].should.contain(f"{stack_name}-JobDef")
job_def_resource["PhysicalResourceId"].should.contain("job-definition/") job_def_resource["PhysicalResourceId"].should.contain("job-definition/")
# Test the linux parameter device host path # Test the linux parameter device host path

View File

@ -2,7 +2,8 @@ from __future__ import unicode_literals
from . import _get_clients, _setup from . import _get_clients, _setup
import sure # noqa import sure # noqa
from moto import mock_batch, mock_iam, mock_ec2, mock_ecs, mock_logs from moto import mock_batch, mock_iam, mock_ec2, mock_ecs, settings
from uuid import uuid4
# Yes, yes it talks to all the things # Yes, yes it talks to all the things
@ -14,7 +15,7 @@ def test_create_managed_compute_environment():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="MANAGED", type="MANAGED",
@ -39,15 +40,20 @@ def test_create_managed_compute_environment():
resp.should.contain("computeEnvironmentArn") resp.should.contain("computeEnvironmentArn")
resp["computeEnvironmentName"].should.equal(compute_name) resp["computeEnvironmentName"].should.equal(compute_name)
our_env = batch_client.describe_compute_environments(
computeEnvironments=[compute_name]
)["computeEnvironments"][0]
# Given a t2.medium is 2 vcpu and t2.small is 1, therefore 2 mediums and 1 small should be created # Given a t2.medium is 2 vcpu and t2.small is 1, therefore 2 mediums and 1 small should be created
resp = ec2_client.describe_instances() if not settings.TEST_SERVER_MODE:
resp.should.contain("Reservations") # Can't verify this in ServerMode, as other tests may have created instances
len(resp["Reservations"]).should.equal(3) resp = ec2_client.describe_instances()
resp.should.contain("Reservations")
len(resp["Reservations"]).should.equal(3)
# Should have created 1 ECS cluster # Should have created 1 ECS cluster
resp = ecs_client.list_clusters() all_clusters = ecs_client.list_clusters()["clusterArns"]
resp.should.contain("clusterArns") all_clusters.should.contain(our_env["ecsClusterArn"])
len(resp["clusterArns"]).should.equal(1)
@mock_ec2 @mock_ec2
@ -58,7 +64,7 @@ def test_create_unmanaged_compute_environment():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -68,15 +74,21 @@ def test_create_unmanaged_compute_environment():
resp.should.contain("computeEnvironmentArn") resp.should.contain("computeEnvironmentArn")
resp["computeEnvironmentName"].should.equal(compute_name) resp["computeEnvironmentName"].should.equal(compute_name)
our_env = batch_client.describe_compute_environments(
computeEnvironments=[compute_name]
)["computeEnvironments"][0]
our_env.should.have.key("ecsClusterArn")
# Its unmanaged so no instances should be created # Its unmanaged so no instances should be created
resp = ec2_client.describe_instances() if not settings.TEST_SERVER_MODE:
resp.should.contain("Reservations") # Can't verify this in ServerMode, as other tests may have created instances
len(resp["Reservations"]).should.equal(0) resp = ec2_client.describe_instances()
resp.should.contain("Reservations")
len(resp["Reservations"]).should.equal(0)
# Should have created 1 ECS cluster # Should have created 1 ECS cluster
resp = ecs_client.list_clusters() all_clusters = ecs_client.list_clusters()["clusterArns"]
resp.should.contain("clusterArns") all_clusters.should.contain(our_env["ecsClusterArn"])
len(resp["clusterArns"]).should.equal(1)
# TODO create 1000s of tests to test complex option combinations of create environment # TODO create 1000s of tests to test complex option combinations of create environment
@ -90,7 +102,10 @@ def test_describe_compute_environment():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
compute_arn = (
f"arn:aws:batch:eu-central-1:123456789012:compute-environment/{compute_name}"
)
batch_client.create_compute_environment( batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -98,9 +113,14 @@ def test_describe_compute_environment():
serviceRole=iam_arn, serviceRole=iam_arn,
) )
resp = batch_client.describe_compute_environments() all_envs = batch_client.describe_compute_environments()["computeEnvironments"]
len(resp["computeEnvironments"]).should.equal(1) our_envs = [e for e in all_envs if e["computeEnvironmentName"] == compute_name]
resp["computeEnvironments"][0]["computeEnvironmentName"].should.equal(compute_name) our_envs.should.have.length_of(1)
our_envs[0]["computeEnvironmentName"].should.equal(compute_name)
our_envs[0]["computeEnvironmentArn"].should.equal(compute_arn)
our_envs[0].should.have.key("ecsClusterArn")
our_envs[0].should.have.key("state").equal("ENABLED")
our_envs[0].should.have.key("status").equal("VALID")
# Test filtering # Test filtering
resp = batch_client.describe_compute_environments(computeEnvironments=["test1"]) resp = batch_client.describe_compute_environments(computeEnvironments=["test1"])
@ -115,7 +135,7 @@ def test_delete_unmanaged_compute_environment():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
batch_client.create_compute_environment( batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -123,13 +143,18 @@ def test_delete_unmanaged_compute_environment():
serviceRole=iam_arn, serviceRole=iam_arn,
) )
our_env = batch_client.describe_compute_environments(
computeEnvironments=[compute_name]
)["computeEnvironments"][0]
batch_client.delete_compute_environment(computeEnvironment=compute_name) batch_client.delete_compute_environment(computeEnvironment=compute_name)
resp = batch_client.describe_compute_environments() all_envs = batch_client.describe_compute_environments()["computeEnvironments"]
len(resp["computeEnvironments"]).should.equal(0) all_names = [e["computeEnvironmentName"] for e in all_envs]
all_names.shouldnt.contain(compute_name)
resp = ecs_client.list_clusters() all_clusters = ecs_client.list_clusters()["clusterArns"]
len(resp.get("clusterArns", [])).should.equal(0) all_clusters.shouldnt.contain(our_env["ecsClusterArn"])
@mock_ec2 @mock_ec2
@ -140,7 +165,7 @@ def test_delete_managed_compute_environment():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
batch_client.create_compute_environment( batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="MANAGED", type="MANAGED",
@ -163,19 +188,26 @@ def test_delete_managed_compute_environment():
serviceRole=iam_arn, serviceRole=iam_arn,
) )
our_env = batch_client.describe_compute_environments(
computeEnvironments=[compute_name]
)["computeEnvironments"][0]
batch_client.delete_compute_environment(computeEnvironment=compute_name) batch_client.delete_compute_environment(computeEnvironment=compute_name)
resp = batch_client.describe_compute_environments() all_envs = batch_client.describe_compute_environments()["computeEnvironments"]
len(resp["computeEnvironments"]).should.equal(0) all_names = [e["computeEnvironmentName"] for e in all_envs]
all_names.shouldnt.contain(compute_name)
resp = ec2_client.describe_instances() if not settings.TEST_SERVER_MODE:
resp.should.contain("Reservations") # Too many instances to know which one is ours in ServerMode
len(resp["Reservations"]).should.equal(3) resp = ec2_client.describe_instances()
for reservation in resp["Reservations"]: resp.should.contain("Reservations")
reservation["Instances"][0]["State"]["Name"].should.equal("terminated") len(resp["Reservations"]).should.equal(3)
for reservation in resp["Reservations"]:
reservation["Instances"][0]["State"]["Name"].should.equal("terminated")
resp = ecs_client.list_clusters() all_clusters = ecs_client.list_clusters()["clusterArns"]
len(resp.get("clusterArns", [])).should.equal(0) all_clusters.shouldnt.contain(our_env["ecsClusterArn"])
@mock_ec2 @mock_ec2
@ -186,7 +218,7 @@ def test_update_unmanaged_compute_environment_state():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
batch_client.create_compute_environment( batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -198,6 +230,7 @@ def test_update_unmanaged_compute_environment_state():
computeEnvironment=compute_name, state="DISABLED" computeEnvironment=compute_name, state="DISABLED"
) )
resp = batch_client.describe_compute_environments() all_envs = batch_client.describe_compute_environments()["computeEnvironments"]
len(resp["computeEnvironments"]).should.equal(1) our_envs = [e for e in all_envs if e["computeEnvironmentName"] == compute_name]
resp["computeEnvironments"][0]["state"].should.equal("DISABLED") our_envs.should.have.length_of(1)
our_envs[0]["state"].should.equal("DISABLED")

View File

@ -4,6 +4,7 @@ from botocore.exceptions import ClientError
import pytest import pytest
import sure # noqa import sure # noqa
from moto import mock_batch, mock_iam, mock_ec2, mock_ecs from moto import mock_batch, mock_iam, mock_ec2, mock_ecs
from uuid import uuid4
@mock_ec2 @mock_ec2
@ -14,7 +15,7 @@ def test_create_job_queue():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -23,8 +24,9 @@ def test_create_job_queue():
) )
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
jq_name = str(uuid4())[0:6]
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=jq_name,
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
@ -33,9 +35,10 @@ def test_create_job_queue():
resp.should.contain("jobQueueName") resp.should.contain("jobQueueName")
queue_arn = resp["jobQueueArn"] queue_arn = resp["jobQueueArn"]
resp = batch_client.describe_job_queues() all_queues = batch_client.describe_job_queues()["jobQueues"]
resp.should.have.key("jobQueues").being.length_of(1) our_queues = [q for q in all_queues if q["jobQueueName"] == jq_name]
resp["jobQueues"][0]["jobQueueArn"].should.equal(queue_arn) our_queues.should.have.length_of(1)
our_queues[0]["jobQueueArn"].should.equal(queue_arn)
@mock_ec2 @mock_ec2
@ -57,7 +60,7 @@ def test_create_job_queue_twice():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -66,15 +69,16 @@ def test_create_job_queue_twice():
) )
compute_env_arn = resp["computeEnvironmentArn"] compute_env_arn = resp["computeEnvironmentArn"]
jq_name = str(uuid4())[0:6]
batch_client.create_job_queue( batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=jq_name,
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": compute_env_arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": compute_env_arn}],
) )
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
batch_client.create_job_queue( batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=jq_name,
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[ computeEnvironmentOrder=[
@ -84,7 +88,7 @@ def test_create_job_queue_twice():
err = ex.value.response["Error"] err = ex.value.response["Error"]
err["Code"].should.equal("ClientException") err["Code"].should.equal("ClientException")
err["Message"].should.equal("Job queue test_job_queue already exists") err["Message"].should.equal(f"Job queue {jq_name} already exists")
@mock_ec2 @mock_ec2
@ -96,7 +100,7 @@ def test_create_job_queue_incorrect_state():
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
batch_client.create_job_queue( batch_client.create_job_queue(
jobQueueName="test_job_queue2", jobQueueName=str(uuid4()),
state="JUNK", state="JUNK",
priority=123, priority=123,
computeEnvironmentOrder=[], computeEnvironmentOrder=[],
@ -115,7 +119,7 @@ def test_create_job_queue_without_compute_environment():
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
batch_client.create_job_queue( batch_client.create_job_queue(
jobQueueName="test_job_queue3", jobQueueName=str(uuid4()),
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[], computeEnvironmentOrder=[],
@ -133,7 +137,7 @@ def test_job_queue_bad_arn():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -144,7 +148,7 @@ def test_job_queue_bad_arn():
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
batch_client.create_job_queue( batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=str(uuid4()),
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[ computeEnvironmentOrder=[
@ -164,7 +168,7 @@ def test_update_job_queue():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -173,8 +177,9 @@ def test_update_job_queue():
) )
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
jq_name = str(uuid4())
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=jq_name,
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
@ -183,15 +188,16 @@ def test_update_job_queue():
batch_client.update_job_queue(jobQueue=queue_arn, priority=5) batch_client.update_job_queue(jobQueue=queue_arn, priority=5)
resp = batch_client.describe_job_queues() all_queues = batch_client.describe_job_queues()["jobQueues"]
resp.should.have.key("jobQueues").being.length_of(1) our_queues = [q for q in all_queues if q["jobQueueName"] == jq_name]
resp["jobQueues"][0]["priority"].should.equal(5) our_queues[0]["priority"].should.equal(5)
batch_client.update_job_queue(jobQueue="test_job_queue", priority=5) batch_client.update_job_queue(jobQueue=jq_name, priority=15)
resp = batch_client.describe_job_queues() all_queues = batch_client.describe_job_queues()["jobQueues"]
resp.should.have.key("jobQueues").being.length_of(1) our_queues = [q for q in all_queues if q["jobQueueName"] == jq_name]
resp["jobQueues"][0]["priority"].should.equal(5) our_queues.should.have.length_of(1)
our_queues[0]["priority"].should.equal(15)
@mock_ec2 @mock_ec2
@ -202,7 +208,7 @@ def test_delete_job_queue():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -211,8 +217,9 @@ def test_delete_job_queue():
) )
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
jq_name = str(uuid4())
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=jq_name,
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
@ -221,5 +228,5 @@ def test_delete_job_queue():
batch_client.delete_job_queue(jobQueue=queue_arn) batch_client.delete_job_queue(jobQueue=queue_arn)
resp = batch_client.describe_job_queues() all_queues = batch_client.describe_job_queues()["jobQueues"]
resp.should.have.key("jobQueues").being.length_of(0) [q["jobQueueName"] for q in all_queues].shouldnt.contain(jq_name)

View File

@ -5,6 +5,7 @@ import sure # noqa
from moto import mock_batch, mock_iam, mock_ec2, mock_ecs, mock_logs from moto import mock_batch, mock_iam, mock_ec2, mock_ecs, mock_logs
import pytest import pytest
import time import time
from uuid import uuid4
@mock_logs @mock_logs
@ -16,7 +17,7 @@ def test_submit_job_by_name():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -26,14 +27,14 @@ def test_submit_job_by_name():
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=str(uuid4()),
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
) )
queue_arn = resp["jobQueueArn"] queue_arn = resp["jobQueueArn"]
job_definition_name = "sleep10" job_definition_name = f"sleep10_{str(uuid4())[0:6]}"
batch_client.register_job_definition( batch_client.register_job_definition(
jobDefinitionName=job_definition_name, jobDefinitionName=job_definition_name,
@ -95,12 +96,12 @@ def test_submit_job():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
job_def_name = "sayhellotomylittlefriend" job_def_name = str(uuid4())[0:6]
commands = ["echo", "hello"] commands = ["echo", "hello"]
job_def_arn, queue_arn = prepare_job(batch_client, commands, iam_arn, job_def_name) job_def_arn, queue_arn = prepare_job(batch_client, commands, iam_arn, job_def_name)
resp = batch_client.submit_job( resp = batch_client.submit_job(
jobName="test1", jobQueue=queue_arn, jobDefinition=job_def_arn jobName=str(uuid4())[0:6], jobQueue=queue_arn, jobDefinition=job_def_arn
) )
job_id = resp["jobId"] job_id = resp["jobId"]
@ -163,7 +164,7 @@ def test_terminate_job():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
job_def_name = "echo-sleep-echo" job_def_name = f"echo-sleep-echo-{str(uuid4())[0:6]}"
commands = ["sh", "-c", "echo start && sleep 30 && echo stop"] commands = ["sh", "-c", "echo start && sleep 30 && echo stop"]
job_def_arn, queue_arn = prepare_job(batch_client, commands, iam_arn, job_def_name) job_def_arn, queue_arn = prepare_job(batch_client, commands, iam_arn, job_def_name)
@ -183,11 +184,7 @@ def test_terminate_job():
resp["jobs"][0]["status"].should.equal("FAILED") resp["jobs"][0]["status"].should.equal("FAILED")
resp["jobs"][0]["statusReason"].should.equal("test_terminate") resp["jobs"][0]["statusReason"].should.equal("test_terminate")
resp = logs_client.describe_log_streams( ls_name = f"{job_def_name}/default/{job_id}"
logGroupName="/aws/batch/job", logStreamNamePrefix=job_def_name
)
resp["logStreams"].should.have.length_of(1)
ls_name = resp["logStreams"][0]["logStreamName"]
resp = logs_client.get_log_events( resp = logs_client.get_log_events(
logGroupName="/aws/batch/job", logStreamName=ls_name logGroupName="/aws/batch/job", logStreamName=ls_name
@ -365,16 +362,40 @@ def test_dependencies():
else: else:
raise RuntimeError("Batch job timed out") raise RuntimeError("Batch job timed out")
resp = logs_client.describe_log_streams(logGroupName="/aws/batch/job") log_stream_name = "/aws/batch/job"
len(resp["logStreams"]).should.equal(3) all_streams = retrieve_all_streams(log_stream_name, logs_client)
for log_stream in resp["logStreams"]:
nr_logstreams_found = 0
expected_logstream_names = [
f"dependencytest/default/{_id}" for _id in [job_id1, job_id2, job_id3]
]
for log_stream in all_streams:
ls_name = log_stream["logStreamName"] ls_name = log_stream["logStreamName"]
if ls_name not in expected_logstream_names:
continue
resp = logs_client.get_log_events( resp = logs_client.get_log_events(
logGroupName="/aws/batch/job", logStreamName=ls_name logGroupName=log_stream_name, logStreamName=ls_name
) )
[event["message"] for event in resp["events"]].should.equal(["hello"]) [event["message"] for event in resp["events"]].should.equal(["hello"])
nr_logstreams_found = nr_logstreams_found + 1
nr_logstreams_found.should.equal(3)
def retrieve_all_streams(log_stream_name, logs_client):
resp = logs_client.describe_log_streams(logGroupName=log_stream_name)
all_streams = resp["logStreams"]
token = resp.get("nextToken")
while token:
resp = logs_client.describe_log_streams(
logGroupName=log_stream_name, nextToken=token
)
all_streams.extend(resp["logStreams"])
token = resp.get("nextToken")
return all_streams
@mock_logs @mock_logs
@mock_ec2 @mock_ec2
@ -385,7 +406,7 @@ def test_failed_dependencies():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())[0:6]
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -395,7 +416,7 @@ def test_failed_dependencies():
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=str(uuid4())[0:6],
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
@ -485,7 +506,7 @@ def test_container_overrides():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client) vpc_id, subnet_id, sg_id, iam_arn = _setup(ec2_client, iam_client)
compute_name = "test_compute_env" compute_name = str(uuid4())[0:6]
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -495,14 +516,14 @@ def test_container_overrides():
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=str(uuid4())[0:6],
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],
) )
queue_arn = resp["jobQueueArn"] queue_arn = resp["jobQueueArn"]
job_definition_name = "sleep10" job_definition_name = f"sleep10_{str(uuid4())[0:6]}"
# Set up Job Definition # Set up Job Definition
# We will then override the container properties in the actual job # We will then override the container properties in the actual job
@ -600,7 +621,7 @@ def test_container_overrides():
def prepare_job(batch_client, commands, iam_arn, job_def_name): def prepare_job(batch_client, commands, iam_arn, job_def_name):
compute_name = "test_compute_env" compute_name = str(uuid4())[0:6]
resp = batch_client.create_compute_environment( resp = batch_client.create_compute_environment(
computeEnvironmentName=compute_name, computeEnvironmentName=compute_name,
type="UNMANAGED", type="UNMANAGED",
@ -610,7 +631,7 @@ def prepare_job(batch_client, commands, iam_arn, job_def_name):
arn = resp["computeEnvironmentArn"] arn = resp["computeEnvironmentArn"]
resp = batch_client.create_job_queue( resp = batch_client.create_job_queue(
jobQueueName="test_job_queue", jobQueueName=str(uuid4())[0:6],
state="ENABLED", state="ENABLED",
priority=123, priority=123,
computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}], computeEnvironmentOrder=[{"order": 123, "computeEnvironment": arn}],

View File

@ -2,6 +2,7 @@ from . import _get_clients, _setup
import random import random
import sure # noqa import sure # noqa
from moto import mock_batch, mock_iam, mock_ec2, mock_ecs from moto import mock_batch, mock_iam, mock_ec2, mock_ecs
from uuid import uuid4
@mock_ec2 @mock_ec2
@ -51,10 +52,11 @@ def test_reregister_task_definition():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
_setup(ec2_client, iam_client) _setup(ec2_client, iam_client)
resp1 = register_job_def(batch_client) job_def_name = str(uuid4())[0:6]
resp1 = register_job_def(batch_client, definition_name=job_def_name)
resp1.should.contain("jobDefinitionArn") resp1.should.contain("jobDefinitionArn")
resp1.should.contain("jobDefinitionName") resp1.should.have.key("jobDefinitionName").equals(job_def_name)
resp1.should.contain("revision") resp1.should.contain("revision")
assert resp1["jobDefinitionArn"].endswith( assert resp1["jobDefinitionArn"].endswith(
@ -62,18 +64,18 @@ def test_reregister_task_definition():
) )
resp1["revision"].should.equal(1) resp1["revision"].should.equal(1)
resp2 = register_job_def(batch_client) resp2 = register_job_def(batch_client, definition_name=job_def_name)
resp2["revision"].should.equal(2) resp2["revision"].should.equal(2)
resp2["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"]) resp2["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"])
resp3 = register_job_def(batch_client) resp3 = register_job_def(batch_client, definition_name=job_def_name)
resp3["revision"].should.equal(3) resp3["revision"].should.equal(3)
resp3["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"]) resp3["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"])
resp3["jobDefinitionArn"].should_not.equal(resp2["jobDefinitionArn"]) resp3["jobDefinitionArn"].should_not.equal(resp2["jobDefinitionArn"])
resp4 = register_job_def(batch_client) resp4 = register_job_def(batch_client, definition_name=job_def_name)
resp4["revision"].should.equal(4) resp4["revision"].should.equal(4)
resp4["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"]) resp4["jobDefinitionArn"].should_not.equal(resp1["jobDefinitionArn"])
@ -89,12 +91,13 @@ def test_delete_task_definition():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
_setup(ec2_client, iam_client) _setup(ec2_client, iam_client)
resp = register_job_def(batch_client) resp = register_job_def(batch_client, definition_name=str(uuid4()))
name = resp["jobDefinitionName"]
batch_client.deregister_job_definition(jobDefinition=resp["jobDefinitionArn"]) batch_client.deregister_job_definition(jobDefinition=resp["jobDefinitionArn"])
resp = batch_client.describe_job_definitions() all_defs = batch_client.describe_job_definitions()["jobDefinitions"]
len(resp["jobDefinitions"]).should.equal(0) [jobdef["jobDefinitionName"] for jobdef in all_defs].shouldnt.contain(name)
@mock_ec2 @mock_ec2
@ -105,14 +108,13 @@ def test_delete_task_definition_by_name():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
_setup(ec2_client, iam_client) _setup(ec2_client, iam_client)
resp = register_job_def(batch_client) resp = register_job_def(batch_client, definition_name=str(uuid4()))
name = resp["jobDefinitionName"]
batch_client.deregister_job_definition( batch_client.deregister_job_definition(jobDefinition=f"{name}:{resp['revision']}")
jobDefinition=f"{resp['jobDefinitionName']}:{resp['revision']}"
)
resp = batch_client.describe_job_definitions() all_defs = batch_client.describe_job_definitions()["jobDefinitions"]
len(resp["jobDefinitions"]).should.equal(0) [jobdef["jobDefinitionName"] for jobdef in all_defs].shouldnt.contain(name)
@mock_ec2 @mock_ec2
@ -123,22 +125,30 @@ def test_describe_task_definition():
ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients() ec2_client, iam_client, ecs_client, logs_client, batch_client = _get_clients()
_setup(ec2_client, iam_client) _setup(ec2_client, iam_client)
register_job_def(batch_client, definition_name="sleep10") sleep_def_name = f"sleep10_{str(uuid4())[0:6]}"
register_job_def(batch_client, definition_name="sleep10") other_name = str(uuid4())[0:6]
register_job_def(batch_client, definition_name="test1") tagged_name = str(uuid4())[0:6]
register_job_def_with_tags(batch_client, definition_name="tagged_def") register_job_def(batch_client, definition_name=sleep_def_name)
register_job_def(batch_client, definition_name=sleep_def_name)
register_job_def(batch_client, definition_name=other_name)
register_job_def_with_tags(batch_client, definition_name=tagged_name)
resp = batch_client.describe_job_definitions(jobDefinitionName="sleep10") resp = batch_client.describe_job_definitions(jobDefinitionName=sleep_def_name)
len(resp["jobDefinitions"]).should.equal(2) len(resp["jobDefinitions"]).should.equal(2)
resp = batch_client.describe_job_definitions() job_defs = batch_client.describe_job_definitions()["jobDefinitions"]
len(resp["jobDefinitions"]).should.equal(4) all_names = [jd["jobDefinitionName"] for jd in job_defs]
all_names.should.contain(sleep_def_name)
all_names.should.contain(other_name)
all_names.should.contain(tagged_name)
resp = batch_client.describe_job_definitions(jobDefinitions=["sleep10", "test1"]) resp = batch_client.describe_job_definitions(
jobDefinitions=[sleep_def_name, other_name]
)
len(resp["jobDefinitions"]).should.equal(3) len(resp["jobDefinitions"]).should.equal(3)
resp["jobDefinitions"][0]["tags"].should.equal({}) resp["jobDefinitions"][0]["tags"].should.equal({})
resp = batch_client.describe_job_definitions(jobDefinitionName="tagged_def") resp = batch_client.describe_job_definitions(jobDefinitionName=tagged_name)
resp["jobDefinitions"][0]["tags"].should.equal( resp["jobDefinitions"][0]["tags"].should.equal(
{"foo": "123", "bar": "456",} {"foo": "123", "bar": "456",}
) )

View File

@ -7,13 +7,15 @@ from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import pytest import pytest
import random
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from moto.ec2.models import AMIS, OWNER_ID from moto.ec2.models import AMIS, OWNER_ID
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_PARAVIRTUAL, EXAMPLE_AMI_WINDOWS from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_PARAVIRTUAL
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
from uuid import uuid4
# Has boto3 equivalent # Has boto3 equivalent
@ -95,16 +97,31 @@ def test_ami_create_and_delete():
cm.value.request_id.should_not.be.none cm.value.request_id.should_not.be.none
@mock_ec2
def test_snapshots_for_initial_amis():
ec2 = boto3.client("ec2", region_name="us-east-1")
snapshots = ec2.describe_snapshots()["Snapshots"]
snapshot_descs = [s["Description"] for s in snapshots]
initial_ami_count = len(AMIS)
assert (
len(snapshots) >= initial_ami_count
), "Should have at least as many snapshots as AMIs"
for ami in AMIS:
ami_id = ami["ami_id"]
expected_description = f"Auto-created snapshot for AMI {ami_id}"
snapshot_descs.should.contain(expected_description)
@mock_ec2 @mock_ec2
def test_ami_create_and_delete_boto3(): def test_ami_create_and_delete_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
initial_ami_count = len(AMIS)
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count)
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0] instance = reservation["Instances"][0]
instance_id = instance["InstanceId"]
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
ec2.create_image( ec2.create_image(
@ -118,15 +135,14 @@ def test_ami_create_and_delete_boto3():
) )
image_id = ec2.create_image( image_id = ec2.create_image(
InstanceId=instance["InstanceId"], InstanceId=instance_id, Name="test-ami", Description="this is a test ami",
Name="test-ami",
Description="this is a test ami",
)["ImageId"] )["ImageId"]
all_images = ec2.describe_images()["Images"] all_images = ec2.describe_images()["Images"]
set([i["ImageId"] for i in all_images]).should.contain(image_id) set([i["ImageId"] for i in all_images]).should.contain(image_id)
retrieved_image = [i for i in all_images if i["ImageId"] == image_id][0] retrieved_image = [i for i in all_images if i["ImageId"] == image_id][0]
created_snapshot_id = retrieved_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"]
retrieved_image.should.have.key("ImageId").equal(image_id) retrieved_image.should.have.key("ImageId").equal(image_id)
retrieved_image.should.have.key("VirtualizationType").equal( retrieved_image.should.have.key("VirtualizationType").equal(
@ -136,14 +152,18 @@ def test_ami_create_and_delete_boto3():
retrieved_image.should.have.key("KernelId").equal(instance["KernelId"]) retrieved_image.should.have.key("KernelId").equal(instance["KernelId"])
retrieved_image.should.have.key("Platform").equal(instance["Platform"]) retrieved_image.should.have.key("Platform").equal(instance["Platform"])
retrieved_image.should.have.key("CreationDate") retrieved_image.should.have.key("CreationDate")
ec2.terminate_instances(InstanceIds=[instance["InstanceId"]]) ec2.terminate_instances(InstanceIds=[instance_id])
# Ensure we're no longer creating a volume # Ensure we're no longer creating a volume
ec2.describe_volumes()["Volumes"].should.have.length_of(0) volumes_for_instance = [
v
for v in ec2.describe_volumes()["Volumes"]
if "Attachment" in v and v["Attachment"][0]["InstanceId"] == instance_id
]
volumes_for_instance.should.have.length_of(0)
# Validate auto-created snapshot # Validate auto-created snapshot
snapshots = ec2.describe_snapshots()["Snapshots"] snapshots = ec2.describe_snapshots()["Snapshots"]
snapshots.should.have.length_of(initial_ami_count + 1)
retrieved_image_snapshot_id = retrieved_image["BlockDeviceMappings"][0]["Ebs"][ retrieved_image_snapshot_id = retrieved_image["BlockDeviceMappings"][0]["Ebs"][
"SnapshotId" "SnapshotId"
@ -269,13 +289,9 @@ def test_ami_copy():
@mock_ec2 @mock_ec2
def test_ami_copy_boto3(): def test_ami_copy_boto3_dryrun():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
initial_ami_count = len(AMIS)
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count)
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0] instance = reservation["Instances"][0]
@ -284,7 +300,6 @@ def test_ami_copy_boto3():
Name="test-ami", Name="test-ami",
Description="this is a test ami", Description="this is a test ami",
)["ImageId"] )["ImageId"]
ec2.terminate_instances(InstanceIds=[instance["InstanceId"]])
source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0] source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0]
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -302,6 +317,22 @@ def test_ami_copy_boto3():
"An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set"
) )
@mock_ec2
def test_ami_copy_boto3():
ec2 = boto3.client("ec2", region_name="us-west-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
source_image_id = ec2.create_image(
InstanceId=instance["InstanceId"],
Name="test-ami",
Description="this is a test ami",
)["ImageId"]
ec2.terminate_instances(InstanceIds=[instance["InstanceId"]])
source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0]
copy_image_ref = ec2.copy_image( copy_image_ref = ec2.copy_image(
SourceRegion="us-west-1", SourceRegion="us-west-1",
SourceImageId=source_image["ImageId"], SourceImageId=source_image["ImageId"],
@ -319,15 +350,22 @@ def test_ami_copy_boto3():
copy_image["KernelId"].should.equal(source_image["KernelId"]) copy_image["KernelId"].should.equal(source_image["KernelId"])
copy_image["Platform"].should.equal(source_image["Platform"]) copy_image["Platform"].should.equal(source_image["Platform"])
# Ensure we're no longer creating a volume
ec2.describe_volumes()["Volumes"].should.have.length_of(0)
# Validate auto-created snapshot # Validate auto-created snapshot
ec2.describe_snapshots()["Snapshots"].should.have.length_of(initial_ami_count + 2) source_image_snapshot_id = source_image["BlockDeviceMappings"][0]["Ebs"][
"SnapshotId"
]
copied_image_snapshot_id = copy_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"]
copy_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"].shouldnt.equal( snapshot_ids = [s["SnapshotId"] for s in ec2.describe_snapshots()["Snapshots"]]
source_image["BlockDeviceMappings"][0]["Ebs"]["SnapshotId"] snapshot_ids.should.contain(source_image_snapshot_id)
) snapshot_ids.should.contain(copied_image_snapshot_id)
copied_image_snapshot_id.shouldnt.equal(source_image_snapshot_id)
@mock_ec2
def test_ami_copy_nonexistent_source_id():
ec2 = boto3.client("ec2", region_name="us-west-1")
# Copy from non-existent source ID. # Copy from non-existent source ID.
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -341,6 +379,21 @@ def test_ami_copy_boto3():
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound") ex.value.response["Error"]["Code"].should.equal("InvalidAMIID.NotFound")
@mock_ec2
def test_ami_copy_nonexisting_source_region():
ec2 = boto3.client("ec2", region_name="us-west-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0]
source_image_id = ec2.create_image(
InstanceId=instance["InstanceId"],
Name="test-ami",
Description="this is a test ami",
)["ImageId"]
source_image = ec2.describe_images(ImageIds=[source_image_id])["Images"][0]
# Copy from non-existent source region. # Copy from non-existent source region.
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
ec2.copy_image( ec2.copy_image(
@ -366,16 +419,21 @@ def test_copy_image_changes_owner_id():
check_resp = conn.describe_images(ImageIds=[source_ami_id]) check_resp = conn.describe_images(ImageIds=[source_ami_id])
check_resp["Images"][0]["OwnerId"].should_not.equal(OWNER_ID) check_resp["Images"][0]["OwnerId"].should_not.equal(OWNER_ID)
new_image_name = str(uuid4())[0:6]
copy_resp = conn.copy_image( copy_resp = conn.copy_image(
SourceImageId=source_ami_id, SourceImageId=source_ami_id,
Name="new-image", Name=new_image_name,
Description="a copy of an image", Description="a copy of an image",
SourceRegion="us-east-1", SourceRegion="us-east-1",
) )
describe_resp = conn.describe_images(Owners=["self"]) describe_resp = conn.describe_images(
describe_resp["Images"][0]["OwnerId"].should.equal(OWNER_ID) Owners=["self"], Filters=[{"Name": "name", "Values": [new_image_name]}]
describe_resp["Images"][0]["ImageId"].should.equal(copy_resp["ImageId"]) )["Images"]
describe_resp.should.have.length_of(1)
describe_resp[0]["OwnerId"].should.equal(OWNER_ID)
describe_resp[0]["ImageId"].should.equal(copy_resp["ImageId"])
# Has boto3 equivalent # Has boto3 equivalent
@ -510,20 +568,16 @@ def test_ami_uses_account_id_if_valid_access_key_is_supplied_boto3():
# The boto-equivalent required an access_key to be passed in, but Moto will always mock this in boto3 # The boto-equivalent required an access_key to be passed in, but Moto will always mock this in boto3
# So the only thing we're testing here, really.. is whether OwnerId is equal to ACCOUNT_ID? # So the only thing we're testing here, really.. is whether OwnerId is equal to ACCOUNT_ID?
# TODO: Maybe patch account_id with multiple values, and verify it always matches with OwnerId # TODO: Maybe patch account_id with multiple values, and verify it always matches with OwnerId
# TODO: And probably remove the modify_instance_attribute, as it looks like it was a unnecessary copy-paste
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservation = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instance = reservation["Instances"][0] instance = reservation["Instances"][0]
ec2.modify_instance_attribute(
InstanceId=instance["InstanceId"], Kernel={"Value": "test-kernel"}
)
image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[ image_id = ec2.create_image(InstanceId=instance["InstanceId"], Name="test-ami")[
"ImageId" "ImageId"
] ]
images = ec2.describe_images(Owners=["self"])["Images"] images = ec2.describe_images(Owners=["self"])["Images"]
[(ami["ImageId"], ami["OwnerId"]) for ami in images].should.equal( [(ami["ImageId"], ami["OwnerId"]) for ami in images].should.contain(
[(image_id, ACCOUNT_ID)] (image_id, ACCOUNT_ID)
) )
@ -591,14 +645,18 @@ def test_ami_filters():
@mock_ec2 @mock_ec2
def test_ami_filters_boto3(): def test_ami_filters_boto3():
image_name_A = f"test-ami-{str(uuid4())[0:6]}"
kernel_value_A = f"k-{str(uuid4())[0:6]}"
kernel_value_B = f"k-{str(uuid4())[0:6]}"
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceA = reservationA["Instances"][0] instanceA = reservationA["Instances"][0]
ec2.modify_instance_attribute( ec2.modify_instance_attribute(
InstanceId=instanceA["InstanceId"], Kernel={"Value": "k-1234abcd"} InstanceId=instanceA["InstanceId"], Kernel={"Value": kernel_value_A}
) )
imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name="test-ami-A")[ imageA_id = ec2.create_image(InstanceId=instanceA["InstanceId"], Name=image_name_A)[
"ImageId" "ImageId"
] ]
imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id) imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id)
@ -608,7 +666,7 @@ def test_ami_filters_boto3():
) )
instanceB = reservationB["Instances"][0] instanceB = reservationB["Instances"][0]
ec2.modify_instance_attribute( ec2.modify_instance_attribute(
InstanceId=instanceB["InstanceId"], Kernel={"Value": "k-abcd1234"} InstanceId=instanceB["InstanceId"], Kernel={"Value": kernel_value_B}
) )
imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[ imageB_id = ec2.create_image(InstanceId=instanceB["InstanceId"], Name="test-ami-B")[
"ImageId" "ImageId"
@ -620,10 +678,12 @@ def test_ami_filters_boto3():
Filters=[{"Name": "architecture", "Values": ["x86_64"]}] Filters=[{"Name": "architecture", "Values": ["x86_64"]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_architecture].should.contain(imageB_id) [ami["ImageId"] for ami in amis_by_architecture].should.contain(imageB_id)
amis_by_architecture.should.have.length_of(40) assert (
len(amis_by_architecture) >= 40
), "Should have at least 40 AMI's of type x86_64"
amis_by_kernel = ec2.describe_images( amis_by_kernel = ec2.describe_images(
Filters=[{"Name": "kernel-id", "Values": ["k-abcd1234"]}] Filters=[{"Name": "kernel-id", "Values": [kernel_value_B]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_kernel].should.equal([imageB.id]) [ami["ImageId"] for ami in amis_by_kernel].should.equal([imageB.id])
@ -631,13 +691,13 @@ def test_ami_filters_boto3():
Filters=[{"Name": "virtualization-type", "Values": ["paravirtual"]}] Filters=[{"Name": "virtualization-type", "Values": ["paravirtual"]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_virtualization].should.contain(imageB.id) [ami["ImageId"] for ami in amis_by_virtualization].should.contain(imageB.id)
amis_by_virtualization.should.have.length_of(3) assert len(amis_by_virtualization) >= 3, "Should have at least 3 paravirtual AMI's"
amis_by_platform = ec2.describe_images( amis_by_platform = ec2.describe_images(
Filters=[{"Name": "platform", "Values": ["windows"]}] Filters=[{"Name": "platform", "Values": ["windows"]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_platform].should.contain(imageA_id) [ami["ImageId"] for ami in amis_by_platform].should.contain(imageA_id)
amis_by_platform.should.have.length_of(25) assert len(amis_by_platform) >= 25, "Should have at least 25 Windows images"
amis_by_id = ec2.describe_images( amis_by_id = ec2.describe_images(
Filters=[{"Name": "image-id", "Values": [imageA_id]}] Filters=[{"Name": "image-id", "Values": [imageA_id]}]
@ -650,7 +710,7 @@ def test_ami_filters_boto3():
ami_ids_by_state = [ami["ImageId"] for ami in amis_by_state] ami_ids_by_state = [ami["ImageId"] for ami in amis_by_state]
ami_ids_by_state.should.contain(imageA_id) ami_ids_by_state.should.contain(imageA_id)
ami_ids_by_state.should.contain(imageB.id) ami_ids_by_state.should.contain(imageB.id)
amis_by_state.should.have.length_of(40) assert len(amis_by_state) >= 40, "Should have at least 40 images available"
amis_by_name = ec2.describe_images( amis_by_name = ec2.describe_images(
Filters=[{"Name": "name", "Values": [imageA.name]}] Filters=[{"Name": "name", "Values": [imageA.name]}]
@ -660,13 +720,13 @@ def test_ami_filters_boto3():
amis_by_public = ec2.describe_images( amis_by_public = ec2.describe_images(
Filters=[{"Name": "is-public", "Values": ["true"]}] Filters=[{"Name": "is-public", "Values": ["true"]}]
)["Images"] )["Images"]
amis_by_public.should.have.length_of(38) assert len(amis_by_public) >= 38, "Should have at least 38 public images"
amis_by_nonpublic = ec2.describe_images( amis_by_nonpublic = ec2.describe_images(
Filters=[{"Name": "is-public", "Values": ["false"]}] Filters=[{"Name": "is-public", "Values": ["false"]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_nonpublic].should.contain(imageA.id) [ami["ImageId"] for ami in amis_by_nonpublic].should.contain(imageA.id)
amis_by_nonpublic.should.have.length_of(2) assert len(amis_by_nonpublic) >= 2, "Should have at least 2 non-public images"
# Has boto3 equivalent # Has boto3 equivalent
@ -695,6 +755,8 @@ def test_ami_filtering_via_tag():
@mock_ec2 @mock_ec2
def test_ami_filtering_via_tag_boto3(): def test_ami_filtering_via_tag_boto3():
tag_value = f"value {str(uuid4())}"
other_value = f"value {str(uuid4())}"
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservationA = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceA = reservationA["Instances"][0] instanceA = reservationA["Instances"][0]
@ -703,7 +765,7 @@ def test_ami_filtering_via_tag_boto3():
"ImageId" "ImageId"
] ]
imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id) imageA = boto3.resource("ec2", region_name="us-east-1").Image(imageA_id)
imageA.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) imageA.create_tags(Tags=[{"Key": "a key", "Value": tag_value}])
reservationB = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) reservationB = ec2.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
instanceB = reservationB["Instances"][0] instanceB = reservationB["Instances"][0]
@ -711,15 +773,15 @@ def test_ami_filtering_via_tag_boto3():
"ImageId" "ImageId"
] ]
imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id) imageB = boto3.resource("ec2", region_name="us-east-1").Image(imageB_id)
imageB.create_tags(Tags=[{"Key": "another key", "Value": "some other value"}]) imageB.create_tags(Tags=[{"Key": "another key", "Value": other_value}])
amis_by_tagA = ec2.describe_images( amis_by_tagA = ec2.describe_images(
Filters=[{"Name": "tag:a key", "Values": ["some value"]}] Filters=[{"Name": "tag:a key", "Values": [tag_value]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_tagA].should.equal([imageA_id]) [ami["ImageId"] for ami in amis_by_tagA].should.equal([imageA_id])
amis_by_tagB = ec2.describe_images( amis_by_tagB = ec2.describe_images(
Filters=[{"Name": "tag:another key", "Values": ["some other value"]}] Filters=[{"Name": "tag:another key", "Values": [other_value]}]
)["Images"] )["Images"]
[ami["ImageId"] for ami in amis_by_tagB].should.equal([imageB_id]) [ami["ImageId"] for ami in amis_by_tagB].should.equal([imageB_id])
@ -993,8 +1055,8 @@ def test_ami_attribute_user_permissions_boto3():
] ]
permissions.should.equal([]) permissions.should.equal([])
USER1 = "123456789011" USER1 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
USER2 = "123456789022" USER2 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
ADD_USERS_ARGS = { ADD_USERS_ARGS = {
"ImageId": image.id, "ImageId": image.id,
@ -1067,7 +1129,7 @@ def test_ami_describe_executable_users():
instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"] instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"]
image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"] image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"]
USER1 = "123456789011" USER1 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
ADD_USER_ARGS = { ADD_USER_ARGS = {
"ImageId": image_id, "ImageId": image_id,
@ -1100,8 +1162,8 @@ def test_ami_describe_executable_users_negative():
instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"] instance_id = response["Reservations"][0]["Instances"][0]["InstanceId"]
image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"] image_id = conn.create_image(InstanceId=instance_id, Name="TestImage")["ImageId"]
USER1 = "123456789011" USER1 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
USER2 = "113355789012" USER2 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
ADD_USER_ARGS = { ADD_USER_ARGS = {
"ImageId": image_id, "ImageId": image_id,
@ -1136,7 +1198,7 @@ def test_ami_describe_executable_users_and_filter():
"ImageId" "ImageId"
] ]
USER1 = "123456789011" USER1 = "".join(["{}".format(random.randint(0, 9)) for _ in range(0, 12)])
ADD_USER_ARGS = { ADD_USER_ARGS = {
"ImageId": image_id, "ImageId": image_id,
@ -1504,16 +1566,19 @@ def test_ami_filter_wildcard():
ec2_resource = boto3.resource("ec2", region_name="us-west-1") ec2_resource = boto3.resource("ec2", region_name="us-west-1")
ec2_client = boto3.client("ec2", region_name="us-west-1") ec2_client = boto3.client("ec2", region_name="us-west-1")
image_name = str(uuid4())[0:6]
instance = ec2_resource.create_instances( instance = ec2_resource.create_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1 ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1
)[0] )[0]
instance.create_image(Name="test-image") instance.create_image(Name=image_name)
# create an image with the same owner but will not match the filter # create an image with the same owner but will not match the filter
instance.create_image(Name="not-matching-image") instance.create_image(Name=str(uuid4())[0:6])
my_images = ec2_client.describe_images( my_images = ec2_client.describe_images(
Owners=[ACCOUNT_ID], Filters=[{"Name": "name", "Values": ["test*"]}] Owners=[ACCOUNT_ID],
Filters=[{"Name": "name", "Values": [f"{image_name[0:4]}*"]}],
)["Images"] )["Images"]
my_images.should.have.length_of(1) my_images.should.have.length_of(1)
@ -1541,17 +1606,21 @@ def test_ami_filter_by_self():
ec2_resource = boto3.resource("ec2", region_name="us-west-1") ec2_resource = boto3.resource("ec2", region_name="us-west-1")
ec2_client = boto3.client("ec2", region_name="us-west-1") ec2_client = boto3.client("ec2", region_name="us-west-1")
my_images = ec2_client.describe_images(Owners=["self"])["Images"] unique_name = str(uuid4())[0:6]
my_images.should.have.length_of(0)
images = ec2_client.describe_images(Owners=["self"])["Images"]
image_names = [i["Name"] for i in images]
image_names.shouldnt.contain(unique_name)
# Create a new image # Create a new image
instance = ec2_resource.create_instances( instance = ec2_resource.create_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1 ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1
)[0] )[0]
instance.create_image(Name="test-image") instance.create_image(Name=unique_name)
my_images = ec2_client.describe_images(Owners=["self"])["Images"] images = ec2_client.describe_images(Owners=["self"])["Images"]
my_images.should.have.length_of(1) image_names = [i["Name"] for i in images]
image_names.should.contain(unique_name)
@mock_ec2 @mock_ec2
@ -1654,9 +1723,11 @@ def test_ami_filter_by_empty_tag():
) )
fake_images.append(image) fake_images.append(image)
# Add release tags to some of the images in the middle # Add release tags to some of the images in the middle
release_version = str(uuid4())[0:6]
for image in fake_images[3:6]: for image in fake_images[3:6]:
ec2.create_tags( ec2.create_tags(
Resources=[image["ImageId"]], Tags=[{"Key": "RELEASE", "Value": ""}] Resources=[image["ImageId"]],
Tags=[{"Key": "RELEASE", "Value": release_version}],
) )
images_filter = [ images_filter = [
{ {
@ -1664,7 +1735,7 @@ def test_ami_filter_by_empty_tag():
"Values": ["Deep Learning Base AMI (Amazon Linux 2) Version 31.0"], "Values": ["Deep Learning Base AMI (Amazon Linux 2) Version 31.0"],
}, },
{"Name": "tag:OS_Version", "Values": ["AWS Linux 2"]}, {"Name": "tag:OS_Version", "Values": ["AWS Linux 2"]},
{"Name": "tag:RELEASE", "Values": [""]}, {"Name": "tag:RELEASE", "Values": [release_version]},
] ]
assert len(client.describe_images(Filters=images_filter)["Images"]) == 3 assert len(client.describe_images(Filters=images_filter)["Images"]) == 3

View File

@ -2,12 +2,15 @@ import boto3
import sure # noqa import sure # noqa
import pytest import pytest
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2 from moto import mock_ec2, settings
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from unittest import SkipTest
@mock_ec2 @mock_ec2
def test_describe_carrier_gateways_none(): def test_describe_carrier_gateways_none():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
ec2.describe_carrier_gateways()["CarrierGateways"].should.equal([]) ec2.describe_carrier_gateways()["CarrierGateways"].should.equal([])
@ -20,7 +23,11 @@ def test_describe_carrier_gateways_multiple():
cg1 = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"] cg1 = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"]
cg2 = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"] cg2 = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"]
client.describe_carrier_gateways()["CarrierGateways"].should.have.length_of(2) gateways = client.describe_carrier_gateways()["CarrierGateways"]
gateway_ids = [g["CarrierGatewayId"] for g in gateways]
gateway_ids.should.contain(cg1["CarrierGatewayId"])
gateway_ids.should.contain(cg2["CarrierGatewayId"])
find_one = client.describe_carrier_gateways( find_one = client.describe_carrier_gateways(
CarrierGatewayIds=[cg1["CarrierGatewayId"]] CarrierGatewayIds=[cg1["CarrierGatewayId"]]
@ -86,4 +93,7 @@ def test_delete_carrier_gateways():
cg = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"] cg = client.create_carrier_gateway(VpcId=vpc.id)["CarrierGateway"]
client.delete_carrier_gateway(CarrierGatewayId=cg["CarrierGatewayId"]) client.delete_carrier_gateway(CarrierGatewayId=cg["CarrierGatewayId"])
client.describe_carrier_gateways()["CarrierGateways"].should.equal([]) gateways = client.describe_carrier_gateways()["CarrierGateways"]
gateway_ids = [g["CarrierGatewayId"] for g in gateways]
gateway_ids.shouldnt.contain(cg["CarrierGatewayId"])

View File

@ -48,9 +48,25 @@ def test_describe_customer_gateways_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
customer_gateway = create_customer_gateway(ec2) customer_gateway = create_customer_gateway(ec2)
cg_id = customer_gateway["CustomerGatewayId"]
cgws = ec2.describe_customer_gateways()["CustomerGateways"] cgws = ec2.describe_customer_gateways()["CustomerGateways"]
cgws.should.have.length_of(1) cg_ids = [cg["CustomerGatewayId"] for cg in cgws]
cgws[0]["CustomerGatewayId"].should.match(customer_gateway["CustomerGatewayId"]) cg_ids.should.contain(cg_id)
cgw = ec2.describe_customer_gateways(CustomerGatewayIds=[cg_id])[
"CustomerGateways"
][0]
cgw.should.have.key("BgpAsn")
cgw.should.have.key("CustomerGatewayId").equal(cg_id)
cgw.should.have.key("IpAddress")
cgw.should.have.key("State").equal("available")
cgw.should.have.key("Type").equal("ipsec.1")
all_cgws = ec2.describe_customer_gateways()["CustomerGateways"]
assert (
len(all_cgws) >= 1
), "Should have at least the one CustomerGateway we just created"
# Has boto3 equivalent # Has boto3 equivalent
@ -73,12 +89,19 @@ def test_delete_customer_gateways_boto3():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
customer_gateway = create_customer_gateway(ec2) customer_gateway = create_customer_gateway(ec2)
cg_id = customer_gateway["CustomerGatewayId"]
cgws = ec2.describe_customer_gateways()["CustomerGateways"] cgws = ec2.describe_customer_gateways(CustomerGatewayIds=[cg_id])[
"CustomerGateways"
]
cgws.should.have.length_of(1) cgws.should.have.length_of(1)
cgws[0].should.have.key("State").equal("available")
ec2.delete_customer_gateway(CustomerGatewayId=customer_gateway["CustomerGatewayId"]) ec2.delete_customer_gateway(CustomerGatewayId=customer_gateway["CustomerGatewayId"])
cgws = ec2.describe_customer_gateways()["CustomerGateways"]
cgws = ec2.describe_customer_gateways(CustomerGatewayIds=[cg_id])[
"CustomerGateways"
]
cgws.should.have.length_of(1) cgws.should.have.length_of(1)
cgws[0].should.have.key("State").equal("deleted") cgws[0].should.have.key("State").equal("deleted")

View File

@ -8,6 +8,8 @@ from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
import random
import uuid
from moto import mock_ec2, mock_ec2_deprecated, settings from moto import mock_ec2, mock_ec2_deprecated, settings
from unittest import SkipTest from unittest import SkipTest
@ -269,9 +271,6 @@ def test_describe_dhcp_options_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
all_options = client.describe_dhcp_options()["DhcpOptions"]
all_options.should.have.length_of(0)
dhcp_options = ec2.create_dhcp_options( dhcp_options = ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[
{"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]}, {"Key": "domain-name", "Values": [SAMPLE_DOMAIN_NAME]},
@ -284,9 +283,12 @@ def test_describe_dhcp_options_boto3():
all_options.should.have.length_of(1) all_options.should.have.length_of(1)
all_options = client.describe_dhcp_options()["DhcpOptions"] all_options = client.describe_dhcp_options()["DhcpOptions"]
all_options.should.have.length_of(1) assert len(all_options) >= 1, "Should have recently created DHCP option"
all_options[0]["DhcpOptionsId"].should.equal(dhcp_options.id) recently_created = [
config = all_options[0]["DhcpConfigurations"] o for o in all_options if o["DhcpOptionsId"] == dhcp_options.id
][0]
recently_created["DhcpOptionsId"].should.equal(dhcp_options.id)
config = recently_created["DhcpConfigurations"]
config.should.have.length_of(2) config.should.have.length_of(2)
config.should.contain( config.should.contain(
{ {
@ -445,17 +447,22 @@ def test_dhcp_tagging_boto3():
] ]
) )
dhcp_option.create_tags(Tags=[{"Key": "a tag", "Value": "some value"}]) tag_value = str(uuid.uuid4())
dhcp_option.create_tags(Tags=[{"Key": "a tag", "Value": tag_value}])
tag = client.describe_tags()["Tags"][0] tag = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [dhcp_option.id]}]
)["Tags"][0]
tag.should.have.key("ResourceId").equal(dhcp_option.id) tag.should.have.key("ResourceId").equal(dhcp_option.id)
tag.should.have.key("ResourceType").equal("dhcp-options") tag.should.have.key("ResourceType").equal("dhcp-options")
tag.should.have.key("Key").equal("a tag") tag.should.have.key("Key").equal("a tag")
tag.should.have.key("Value").equal("some value") tag.should.have.key("Value").equal(tag_value)
# Refresh the DHCP options # Refresh the DHCP options
dhcp_option = client.describe_dhcp_options()["DhcpOptions"][0] dhcp_option = client.describe_dhcp_options(DhcpOptionsIds=[dhcp_option.id])[
dhcp_option["Tags"].should.equal([{"Key": "a tag", "Value": "some value"}]) "DhcpOptions"
][0]
dhcp_option["Tags"].should.equal([{"Key": "a tag", "Value": tag_value}])
# Has boto3 equivalent # Has boto3 equivalent
@ -500,16 +507,19 @@ def test_dhcp_options_get_by_tag_boto3():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
dhcp_tag_value = str(uuid.uuid4())
dhcp1 = ec2.create_dhcp_options( dhcp1 = ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]}, {"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.10.2"]}, {"Key": "domain-name-servers", "Values": ["10.0.10.2"]},
] ]
) )
dhcp1_tag_name = str(uuid.uuid4())
dhcp1.create_tags( dhcp1.create_tags(
Tags=[ Tags=[
{"Key": "Name", "Value": "TestDhcpOptions1"}, {"Key": "Name", "Value": dhcp1_tag_name},
{"Key": "test-tag", "Value": "test-value"}, {"Key": "test-tag", "Value": dhcp_tag_value},
] ]
) )
@ -519,17 +529,18 @@ def test_dhcp_options_get_by_tag_boto3():
{"Key": "domain-name-servers", "Values": ["10.0.20.2"]}, {"Key": "domain-name-servers", "Values": ["10.0.20.2"]},
] ]
) )
dhcp2_tag_name = str(uuid.uuid4())
dhcp2.create_tags( dhcp2.create_tags(
Tags=[ Tags=[
{"Key": "Name", "Value": "TestDhcpOptions2"}, {"Key": "Name", "Value": dhcp2_tag_name},
{"Key": "test-tag", "Value": "test-value"}, {"Key": "test-tag", "Value": dhcp_tag_value},
] ]
) )
dhcp_options_sets = client.describe_dhcp_options( dhcp_options_sets = client.describe_dhcp_options(
Filters=[ Filters=[
{"Name": "tag:Name", "Values": ["TestDhcpOptions1"]}, {"Name": "tag:Name", "Values": [dhcp1_tag_name]},
{"Name": "tag:test-tag", "Values": ["test-value"]}, {"Name": "tag:test-tag", "Values": [dhcp_tag_value]},
] ]
)["DhcpOptions"] )["DhcpOptions"]
@ -542,13 +553,13 @@ def test_dhcp_options_get_by_tag_boto3():
) )
tags = dhcp_options_sets[0]["Tags"] tags = dhcp_options_sets[0]["Tags"]
tags.should.have.length_of(2) tags.should.have.length_of(2)
tags.should.contain({"Key": "Name", "Value": "TestDhcpOptions1"}) tags.should.contain({"Key": "Name", "Value": dhcp1_tag_name})
tags.should.contain({"Key": "test-tag", "Value": "test-value"}) tags.should.contain({"Key": "test-tag", "Value": dhcp_tag_value})
dhcp_options_sets = client.describe_dhcp_options( dhcp_options_sets = client.describe_dhcp_options(
Filters=[ Filters=[
{"Name": "tag:Name", "Values": ["TestDhcpOptions2"]}, {"Name": "tag:Name", "Values": [dhcp2_tag_name]},
{"Name": "tag:test-tag", "Values": ["test-value"]}, {"Name": "tag:test-tag", "Values": [dhcp_tag_value]},
] ]
)["DhcpOptions"] )["DhcpOptions"]
@ -561,11 +572,11 @@ def test_dhcp_options_get_by_tag_boto3():
) )
tags = dhcp_options_sets[0]["Tags"] tags = dhcp_options_sets[0]["Tags"]
tags.should.have.length_of(2) tags.should.have.length_of(2)
tags.should.contain({"Key": "Name", "Value": "TestDhcpOptions2"}) tags.should.contain({"Key": "Name", "Value": dhcp2_tag_name})
tags.should.contain({"Key": "test-tag", "Value": "test-value"}) tags.should.contain({"Key": "test-tag", "Value": dhcp_tag_value})
dhcp_options_sets = client.describe_dhcp_options( dhcp_options_sets = client.describe_dhcp_options(
Filters=[{"Name": "tag:test-tag", "Values": ["test-value"]}] Filters=[{"Name": "tag:test-tag", "Values": [dhcp_tag_value]}]
)["DhcpOptions"] )["DhcpOptions"]
dhcp_options_sets.should.have.length_of(2) dhcp_options_sets.should.have.length_of(2)
@ -625,8 +636,10 @@ def test_dhcp_options_get_by_id_boto3():
dhcp1.create_tags(Tags=[{"Key": "Name", "Value": "TestDhcpOptions2"}]) dhcp1.create_tags(Tags=[{"Key": "Name", "Value": "TestDhcpOptions2"}])
dhcp1.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}]) dhcp1.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}])
d = client.describe_dhcp_options()["DhcpOptions"] options = client.describe_dhcp_options()["DhcpOptions"]
d.should.have.length_of(2) d_ids = [d["DhcpOptionsId"] for d in options]
d_ids.should.contain(dhcp1.id)
d_ids.should.contain(dhcp2.id)
d = client.describe_dhcp_options( d = client.describe_dhcp_options(
Filters=[{"Name": "dhcp-options-id", "Values": [dhcp1.id]}] Filters=[{"Name": "dhcp-options-id", "Values": [dhcp1.id]}]
@ -647,28 +660,32 @@ def test_dhcp_options_get_by_id_boto3():
def test_dhcp_options_get_by_value_filter(): def test_dhcp_options_get_by_value_filter():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
random_server_1 = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
random_server_2 = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
random_server_3 = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]}, {"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.10.2"]}, {"Key": "domain-name-servers", "Values": [random_server_1]},
] ]
) )
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]}, {"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.20.2"]}, {"Key": "domain-name-servers", "Values": [random_server_2]},
] ]
) )
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[
{"Key": "domain-name", "Values": ["example.com"]}, {"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.30.2"]}, {"Key": "domain-name-servers", "Values": [random_server_3]},
] ]
) )
filters = [{"Name": "value", "Values": ["10.0.10.2"]}] filters = [{"Name": "value", "Values": [random_server_2]}]
dhcp_options_sets = list(ec2.dhcp_options_sets.filter(Filters=filters)) dhcp_options_sets = list(ec2.dhcp_options_sets.filter(Filters=filters))
dhcp_options_sets.should.have.length_of(1) dhcp_options_sets.should.have.length_of(1)
@ -677,30 +694,36 @@ def test_dhcp_options_get_by_value_filter():
def test_dhcp_options_get_by_key_filter(): def test_dhcp_options_get_by_key_filter():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
random_domain_name = str(uuid.uuid4())[0:6]
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[{"Key": "domain-name", "Values": [random_domain_name]},]
{"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.10.2"]},
]
) )
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[{"Key": "domain-name", "Values": ["example.com"]},]
{"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.20.2"]},
]
) )
ec2.create_dhcp_options( ec2.create_dhcp_options(
DhcpConfigurations=[ DhcpConfigurations=[{"Key": "domain-name", "Values": [random_domain_name]},]
{"Key": "domain-name", "Values": ["example.com"]},
{"Key": "domain-name-servers", "Values": ["10.0.30.2"]},
]
) )
filters = [{"Name": "key", "Values": ["domain-name"]}] filters = [{"Name": "key", "Values": ["domain-name"]}]
dhcp_options_sets = list(ec2.dhcp_options_sets.filter(Filters=filters)) dhcp_options_sets = list(ec2.dhcp_options_sets.filter(Filters=filters))
dhcp_options_sets.should.have.length_of(3) assert (
len(dhcp_options_sets) >= 3
), "Should have at least 3 DHCP options just created"
configs = []
for d in dhcp_options_sets:
configs.extend(d.dhcp_configurations)
servers = []
for config in configs:
if config["Key"] == "domain-name":
servers.extend(config["Values"])
servers.should.contain({"Value": random_domain_name})
servers.should.contain({"Value": "example.com"})
# Has boto3 equivalent # Has boto3 equivalent

View File

@ -7,6 +7,7 @@ from tests.test_cloudformation.fixtures import single_instance_with_ebs_volume
from tests.test_cloudformation.fixtures import vpc_eip from tests.test_cloudformation.fixtures import vpc_eip
from tests.test_cloudformation.fixtures import vpc_eni from tests.test_cloudformation.fixtures import vpc_eni
from tests.test_cloudformation.fixtures import vpc_single_instance_in_subnet from tests.test_cloudformation.fixtures import vpc_single_instance_in_subnet
from uuid import uuid4
import boto import boto
import boto.ec2 import boto.ec2
import boto.cloudformation import boto.cloudformation
@ -31,67 +32,59 @@ template_vpc = {
def test_vpc_single_instance_in_subnet(): def test_vpc_single_instance_in_subnet():
template_json = json.dumps(vpc_single_instance_in_subnet.template) template_json = json.dumps(vpc_single_instance_in_subnet.template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
stack_name = str(uuid4())[0:6]
cf.create_stack( cf.create_stack(
StackName="test_stack", StackName=stack_name,
TemplateBody=template_json, TemplateBody=template_json,
Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "my_key"}], Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "my_key"}],
) )
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.describe_vpcs(Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/16"]}])[ stack = cf.describe_stacks(StackName=stack_name)["Stacks"][0]
"Vpcs"
][0] resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
vpc_id = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::EC2::VPC"
][0]["PhysicalResourceId"]
vpc = ec2.describe_vpcs(VpcIds=[vpc_id])["Vpcs"][0]
vpc["CidrBlock"].should.equal("10.0.0.0/16") vpc["CidrBlock"].should.equal("10.0.0.0/16")
vpc["Tags"].should.contain({"Key": "Application", "Value": stack["StackId"]})
ec2.describe_internet_gateways()["InternetGateways"].should.have.length_of(1)
subnet = ec2.describe_subnets(
Filters=[{"Name": "vpcId", "Values": [vpc["VpcId"]]}]
)["Subnets"][0]
subnet["VpcId"].should.equal(vpc["VpcId"])
ec2 = boto3.client("ec2", region_name="us-west-1")
reservation = ec2.describe_instances()["Reservations"][0]
instance = reservation["Instances"][0]
instance["Tags"].should.contain({"Key": "Foo", "Value": "Bar"})
# Check that the EIP is attached the the EC2 instance
eip = ec2.describe_addresses()["Addresses"][0]
eip["Domain"].should.equal("vpc")
eip["InstanceId"].should.equal(instance["InstanceId"])
security_group = ec2.describe_security_groups( security_group = ec2.describe_security_groups(
Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}] Filters=[{"Name": "vpc-id", "Values": [vpc["VpcId"]]}]
)["SecurityGroups"][0] )["SecurityGroups"][0]
security_group["VpcId"].should.equal(vpc["VpcId"]) security_group["VpcId"].should.equal(vpc["VpcId"])
stack = cf.describe_stacks(StackName="test_stack")["Stacks"][0] subnet_id = [
vpc["Tags"].should.contain({"Key": "Application", "Value": stack["StackId"]})
resources = cf.list_stack_resources(StackName="test_stack")[
"StackResourceSummaries"
]
vpc_resource = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::EC2::VPC"
][0]
vpc_resource["PhysicalResourceId"].should.equal(vpc["VpcId"])
subnet_resource = [
resource resource
for resource in resources for resource in resources
if resource["ResourceType"] == "AWS::EC2::Subnet" if resource["ResourceType"] == "AWS::EC2::Subnet"
][0] ][0]["PhysicalResourceId"]
subnet_resource["PhysicalResourceId"].should.equal(subnet["SubnetId"])
eip_resource = [ subnet = ec2.describe_subnets(SubnetIds=[subnet_id])["Subnets"][0]
subnet["VpcId"].should.equal(vpc["VpcId"])
instance_id = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::EC2::Instance"
][0]["PhysicalResourceId"]
res = ec2.describe_instances(InstanceIds=[instance_id])["Reservations"][0]
instance = res["Instances"][0]
instance["Tags"].should.contain({"Key": "Foo", "Value": "Bar"})
eip_id = [
resource resource
for resource in resources for resource in resources
if resource["ResourceType"] == "AWS::EC2::EIP" if resource["ResourceType"] == "AWS::EC2::EIP"
][0] ][0]["PhysicalResourceId"]
eip_resource["PhysicalResourceId"].should.equal(eip["PublicIp"]) eip = ec2.describe_addresses(PublicIps=[eip_id])["Addresses"][0]
eip["Domain"].should.equal("vpc")
eip["InstanceId"].should.equal(instance["InstanceId"])
@mock_cloudformation @mock_cloudformation
@ -99,11 +92,13 @@ def test_vpc_single_instance_in_subnet():
def test_delete_stack_with_resource_missing_delete_attr(): def test_delete_stack_with_resource_missing_delete_attr():
cf = boto3.client("cloudformation", region_name="us-east-1") cf = boto3.client("cloudformation", region_name="us-east-1")
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
name = "test_stack" name = str(uuid4())[0:6]
cf.create_stack(StackName=name, TemplateBody=json.dumps(template_vpc)) cf.create_stack(StackName=name, TemplateBody=json.dumps(template_vpc))
cf.describe_stacks(StackName=name)["Stacks"].should.have.length_of(1) cf.describe_stacks(StackName=name)["Stacks"].should.have.length_of(1)
ec2.describe_vpcs()["Vpcs"].should.have.length_of(2)
resources = cf.list_stack_resources(StackName=name)["StackResourceSummaries"]
vpc_id = resources[0]["PhysicalResourceId"]
cf.delete_stack( cf.delete_stack(
StackName=name StackName=name
@ -112,10 +107,10 @@ def test_delete_stack_with_resource_missing_delete_attr():
cf.describe_stacks(StackName=name) cf.describe_stacks(StackName=name)
err = exc.value.response["Error"] err = exc.value.response["Error"]
err.should.have.key("Code").equals("ValidationError") err.should.have.key("Code").equals("ValidationError")
err.should.have.key("Message").equals("Stack with id test_stack does not exist") err.should.have.key("Message").equals(f"Stack with id {name} does not exist")
# We still have two VPCs, as the VPC-object does not have a delete-method yet # We still have our VPC, as the VPC-object does not have a delete-method yet
ec2.describe_vpcs()["Vpcs"].should.have.length_of(2) ec2.describe_vpcs(VpcIds=[vpc_id])["Vpcs"].should.have.length_of(1)
# Has boto3 equivalent # Has boto3 equivalent
@ -149,26 +144,26 @@ def test_elastic_network_interfaces_cloudformation_boto3():
template = vpc_eni.template template = vpc_eni.template
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=template_json)
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
eni = ec2.describe_network_interfaces()["NetworkInterfaces"][0] all_enis = ec2.describe_network_interfaces()["NetworkInterfaces"]
eni["PrivateIpAddresses"].should.have.length_of(1) all_eni_ids = [eni["NetworkInterfaceId"] for eni in all_enis]
private_ip_address = eni["PrivateIpAddresses"][0]["PrivateIpAddress"] all_ips = [eni["PrivateIpAddresses"][0]["PrivateIpAddress"] for eni in all_enis]
resources = cf.list_stack_resources(StackName="test_stack")[ resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
"StackResourceSummaries"
]
cfn_eni = [ cfn_eni = [
resource resource
for resource in resources for resource in resources
if resource["ResourceType"] == "AWS::EC2::NetworkInterface" if resource["ResourceType"] == "AWS::EC2::NetworkInterface"
][0] ][0]
cfn_eni["PhysicalResourceId"].should.equal(eni["NetworkInterfaceId"]) all_eni_ids.should.contain(cfn_eni["PhysicalResourceId"])
outputs = cf.describe_stacks(StackName="test_stack")["Stacks"][0]["Outputs"] outputs = cf.describe_stacks(StackName=stack_name)["Stacks"][0]["Outputs"]
outputs.should.contain( received_ip = [
{"OutputKey": "ENIIpAddress", "OutputValue": private_ip_address} o["OutputValue"] for o in outputs if o["OutputKey"] == "ENIIpAddress"
) ][0]
all_ips.should.contain(received_ip)
@mock_ec2 @mock_ec2
@ -177,6 +172,7 @@ def test_volume_size_through_cloudformation():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
cf = boto3.client("cloudformation", region_name="us-east-1") cf = boto3.client("cloudformation", region_name="us-east-1")
tag_value = str(uuid4())
volume_template = { volume_template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
@ -191,23 +187,26 @@ def test_volume_size_through_cloudformation():
], ],
"Tags": [ "Tags": [
{"Key": "foo", "Value": "bar"}, {"Key": "foo", "Value": "bar"},
{"Key": "blah", "Value": "baz"}, {"Key": "blah", "Value": tag_value},
], ],
}, },
} }
}, },
} }
template_json = json.dumps(volume_template) template_json = json.dumps(volume_template)
cf.create_stack(StackName="test_stack", TemplateBody=template_json)
resource = cf.list_stack_resources(StackName="test_stack")[ stack_name = str(uuid4())[0:6]
"StackResourceSummaries" cf.create_stack(StackName=stack_name, TemplateBody=template_json)
][0]
resource = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"][
0
]
resource.should.have.key("LogicalResourceId").being.equal("testInstance") resource.should.have.key("LogicalResourceId").being.equal("testInstance")
resource.should.have.key("PhysicalResourceId").shouldnt.be.none resource.should.have.key("PhysicalResourceId").shouldnt.be.none
resource.should.have.key("ResourceType").being.equal("AWS::EC2::Instance") resource.should.have.key("ResourceType").being.equal("AWS::EC2::Instance")
instances = ec2.describe_instances(InstanceIds=[resource["PhysicalResourceId"]]) instances = ec2.describe_instances(InstanceIds=[resource["PhysicalResourceId"]])
volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][ volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][
"Ebs" "Ebs"
] ]
@ -275,11 +274,13 @@ def test_subnet_tags_through_cloudformation_boto3():
} }
template_json = json.dumps(subnet_template) template_json = json.dumps(subnet_template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=template_json)
resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
subnet_id = resources[0]["PhysicalResourceId"]
subnet = ec2.describe_subnets( subnet = ec2.describe_subnets(SubnetIds=[subnet_id])["Subnets"][0]
Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/24"]}] subnet["CidrBlock"].should.equal("10.0.0.0/24")
)["Subnets"][0]
subnet["Tags"].should.contain({"Key": "foo", "Value": "bar"}) subnet["Tags"].should.contain({"Key": "foo", "Value": "bar"})
subnet["Tags"].should.contain({"Key": "blah", "Value": "baz"}) subnet["Tags"].should.contain({"Key": "blah", "Value": "baz"})
@ -289,16 +290,30 @@ def test_subnet_tags_through_cloudformation_boto3():
def test_single_instance_with_ebs_volume(): def test_single_instance_with_ebs_volume():
template_json = json.dumps(single_instance_with_ebs_volume.template) template_json = json.dumps(single_instance_with_ebs_volume.template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
stack_name = str(uuid4())[0:6]
cf.create_stack( cf.create_stack(
StackName="test_stack", StackName=stack_name,
TemplateBody=template_json, TemplateBody=template_json,
Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "key_name"}], Parameters=[{"ParameterKey": "KeyName", "ParameterValue": "key_name"}],
) )
resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
instance_id = [
r["PhysicalResourceId"]
for r in resources
if r["ResourceType"] == "AWS::EC2::Instance"
][0]
volume_id = [
r["PhysicalResourceId"]
for r in resources
if r["ResourceType"] == "AWS::EC2::Volume"
][0]
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] ec2_instance = ec2.describe_instances(InstanceIds=[instance_id])["Reservations"][0][
"Instances"
][0]
volumes = ec2.describe_volumes()["Volumes"] volumes = ec2.describe_volumes(VolumeIds=[volume_id])["Volumes"]
# Grab the mounted drive # Grab the mounted drive
volume = [ volume = [
volume for volume in volumes if volume["Attachments"][0]["Device"] == "/dev/sdh" volume for volume in volumes if volume["Attachments"][0]["Device"] == "/dev/sdh"
@ -306,35 +321,24 @@ def test_single_instance_with_ebs_volume():
volume["State"].should.equal("in-use") volume["State"].should.equal("in-use")
volume["Attachments"][0]["InstanceId"].should.equal(ec2_instance["InstanceId"]) volume["Attachments"][0]["InstanceId"].should.equal(ec2_instance["InstanceId"])
resources = cf.list_stack_resources(StackName="test_stack")[
"StackResourceSummaries"
]
ebs_volumes = [
resource
for resource in resources
if resource["ResourceType"] == "AWS::EC2::Volume"
]
ebs_volumes[0]["PhysicalResourceId"].should.equal(volume["VolumeId"])
@mock_ec2 @mock_ec2
@mock_cloudformation @mock_cloudformation
def test_classic_eip(): def test_classic_eip():
template_json = json.dumps(ec2_classic_eip.template) template_json = json.dumps(ec2_classic_eip.template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=template_json)
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
eip = ec2.describe_addresses()["Addresses"][0] all_ips = [eip["PublicIp"] for eip in ec2.describe_addresses()["Addresses"]]
resources = cf.list_stack_resources(StackName="test_stack")[ resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
"StackResourceSummaries"
]
cfn_eip = [ cfn_eip = [
resource resource
for resource in resources for resource in resources
if resource["ResourceType"] == "AWS::EC2::EIP" if resource["ResourceType"] == "AWS::EC2::EIP"
][0] ][0]
cfn_eip["PhysicalResourceId"].should.equal(eip["PublicIp"]) all_ips.should.contain(cfn_eip["PhysicalResourceId"])
@mock_ec2 @mock_ec2
@ -342,19 +346,19 @@ def test_classic_eip():
def test_vpc_eip(): def test_vpc_eip():
template_json = json.dumps(vpc_eip.template) template_json = json.dumps(vpc_eip.template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
ec2 = boto3.client("ec2", region_name="us-west-1") cf.create_stack(StackName=stack_name, TemplateBody=template_json)
eip = ec2.describe_addresses()["Addresses"][0]
resources = cf.list_stack_resources(StackName="test_stack")[ ec2 = boto3.client("ec2", region_name="us-west-1")
"StackResourceSummaries" all_ips = [eip["PublicIp"] for eip in ec2.describe_addresses()["Addresses"]]
]
resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
cfn_eip = [ cfn_eip = [
resource resource
for resource in resources for resource in resources
if resource["ResourceType"] == "AWS::EC2::EIP" if resource["ResourceType"] == "AWS::EC2::EIP"
][0] ][0]
cfn_eip["PhysicalResourceId"].should.equal(eip["PublicIp"]) all_ips.should.contain(cfn_eip["PhysicalResourceId"])
@mock_cloudformation @mock_cloudformation
@ -385,12 +389,15 @@ def test_vpc_gateway_attachment_creation_should_attach_itself_to_vpc():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=template_json)
resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
vpc_id = resources[1]["PhysicalResourceId"]
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.describe_vpcs(Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/16"]}])[ vpc = ec2.describe_vpcs(VpcIds=[vpc_id])["Vpcs"][0]
"Vpcs" vpc["CidrBlock"].should.equal("10.0.0.0/16")
][0]
igws = ec2.describe_internet_gateways( igws = ec2.describe_internet_gateways(
Filters=[{"Name": "attachment.vpc-id", "Values": [vpc["VpcId"]]}] Filters=[{"Name": "attachment.vpc-id", "Values": [vpc["VpcId"]]}]
@ -417,17 +424,22 @@ def test_vpc_peering_creation():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=template_json)
resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
our_vpx_id = resources[0]["PhysicalResourceId"]
peering_connections = ec2_client.describe_vpc_peering_connections()[ peering_connections = ec2_client.describe_vpc_peering_connections(
"VpcPeeringConnections" VpcPeeringConnectionIds=[our_vpx_id]
] )["VpcPeeringConnections"]
peering_connections.should.have.length_of(1) peering_connections.should.have.length_of(1)
@mock_cloudformation @mock_cloudformation
@mock_ec2 @mock_ec2
def test_multiple_security_group_ingress_separate_from_security_group_by_id(): def test_multiple_security_group_ingress_separate_from_security_group_by_id():
sg1 = str(uuid4())[0:6]
sg2 = str(uuid4())[0:6]
template = { template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
@ -435,14 +447,14 @@ def test_multiple_security_group_ingress_separate_from_security_group_by_id():
"Type": "AWS::EC2::SecurityGroup", "Type": "AWS::EC2::SecurityGroup",
"Properties": { "Properties": {
"GroupDescription": "test security group", "GroupDescription": "test security group",
"Tags": [{"Key": "sg-name", "Value": "sg1"}], "Tags": [{"Key": "sg-name", "Value": sg1}],
}, },
}, },
"test-security-group2": { "test-security-group2": {
"Type": "AWS::EC2::SecurityGroup", "Type": "AWS::EC2::SecurityGroup",
"Properties": { "Properties": {
"GroupDescription": "test security group", "GroupDescription": "test security group",
"Tags": [{"Key": "sg-name", "Value": "sg2"}], "Tags": [{"Key": "sg-name", "Value": sg2}],
}, },
}, },
"test-sg-ingress": { "test-sg-ingress": {
@ -460,11 +472,11 @@ def test_multiple_security_group_ingress_separate_from_security_group_by_id():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) cf.create_stack(StackName=str(uuid4())[0:6], TemplateBody=template_json)
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
security_group1 = get_secgroup_by_tag(ec2, "sg1") security_group1 = get_secgroup_by_tag(ec2, sg1)
security_group2 = get_secgroup_by_tag(ec2, "sg2") security_group2 = get_secgroup_by_tag(ec2, sg2)
security_group1["IpPermissions"].should.have.length_of(1) security_group1["IpPermissions"].should.have.length_of(1)
security_group1["IpPermissions"][0]["UserIdGroupPairs"].should.have.length_of(1) security_group1["IpPermissions"][0]["UserIdGroupPairs"].should.have.length_of(1)
@ -480,10 +492,10 @@ def test_multiple_security_group_ingress_separate_from_security_group_by_id():
@mock_ec2 @mock_ec2
def test_security_group_ingress_separate_from_security_group_by_id(): def test_security_group_ingress_separate_from_security_group_by_id():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
ec2.create_security_group( sg_name = str(uuid4())
GroupName="test-security-group1", Description="test security group" ec2.create_security_group(GroupName=sg_name, Description="test security group")
)
sg_2 = str(uuid4())[0:6]
template = { template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
@ -491,13 +503,13 @@ def test_security_group_ingress_separate_from_security_group_by_id():
"Type": "AWS::EC2::SecurityGroup", "Type": "AWS::EC2::SecurityGroup",
"Properties": { "Properties": {
"GroupDescription": "test security group", "GroupDescription": "test security group",
"Tags": [{"Key": "sg-name", "Value": "sg2"}], "Tags": [{"Key": "sg-name", "Value": sg_2}],
}, },
}, },
"test-sg-ingress": { "test-sg-ingress": {
"Type": "AWS::EC2::SecurityGroupIngress", "Type": "AWS::EC2::SecurityGroupIngress",
"Properties": { "Properties": {
"GroupName": "test-security-group1", "GroupName": sg_name,
"IpProtocol": "tcp", "IpProtocol": "tcp",
"FromPort": "80", "FromPort": "80",
"ToPort": "8080", "ToPort": "8080",
@ -509,11 +521,11 @@ def test_security_group_ingress_separate_from_security_group_by_id():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) cf.create_stack(StackName=str(uuid4())[0:6], TemplateBody=template_json)
security_group1 = ec2.describe_security_groups(GroupNames=["test-security-group1"])[ security_group1 = ec2.describe_security_groups(GroupNames=[sg_name])[
"SecurityGroups" "SecurityGroups"
][0] ][0]
security_group2 = get_secgroup_by_tag(ec2, "sg2") security_group2 = get_secgroup_by_tag(ec2, sg_2)
security_group1["IpPermissions"].should.have.length_of(1) security_group1["IpPermissions"].should.have.length_of(1)
security_group1["IpPermissions"][0]["UserIdGroupPairs"].should.have.length_of(1) security_group1["IpPermissions"][0]["UserIdGroupPairs"].should.have.length_of(1)
@ -567,7 +579,7 @@ def test_security_group_ingress_separate_from_security_group_by_id_using_vpc():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) cf.create_stack(StackName=str(uuid4())[0:6], TemplateBody=template_json)
security_group1 = get_secgroup_by_tag(ec2_client, "sg1") security_group1 = get_secgroup_by_tag(ec2_client, "sg1")
security_group2 = get_secgroup_by_tag(ec2_client, "sg2") security_group2 = get_secgroup_by_tag(ec2_client, "sg2")
@ -589,6 +601,7 @@ def test_security_group_with_update():
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc2 = ec2.create_vpc(CidrBlock="10.1.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.1.0.0/16")
sg = str(uuid4())[0:6]
template = { template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
@ -597,7 +610,7 @@ def test_security_group_with_update():
"Properties": { "Properties": {
"GroupDescription": "test security group", "GroupDescription": "test security group",
"VpcId": vpc1.id, "VpcId": vpc1.id,
"Tags": [{"Key": "sg-name", "Value": "sg"}], "Tags": [{"Key": "sg-name", "Value": sg}],
}, },
} }
}, },
@ -605,14 +618,15 @@ def test_security_group_with_update():
template_json = json.dumps(template) template_json = json.dumps(template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
security_group = get_secgroup_by_tag(ec2_client, "sg") cf.create_stack(StackName=stack_name, TemplateBody=template_json)
security_group = get_secgroup_by_tag(ec2_client, sg)
security_group["VpcId"].should.equal(vpc1.id) security_group["VpcId"].should.equal(vpc1.id)
template["Resources"]["test-security-group"]["Properties"]["VpcId"] = vpc2.id template["Resources"]["test-security-group"]["Properties"]["VpcId"] = vpc2.id
template_json = json.dumps(template) template_json = json.dumps(template)
cf.update_stack(StackName="test_stack", TemplateBody=template_json) cf.update_stack(StackName=stack_name, TemplateBody=template_json)
security_group = get_secgroup_by_tag(ec2_client, "sg") security_group = get_secgroup_by_tag(ec2_client, sg)
security_group["VpcId"].should.equal(vpc2.id) security_group["VpcId"].should.equal(vpc2.id)
@ -638,10 +652,12 @@ def test_subnets_should_be_created_with_availability_zone():
} }
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
template_json = json.dumps(subnet_template) template_json = json.dumps(subnet_template)
cf.create_stack(StackName="test_stack", TemplateBody=template_json) stack_name = str(uuid4())[0:6]
subnet = ec2_client.describe_subnets( cf.create_stack(StackName=stack_name, TemplateBody=template_json)
Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/24"]}] resources = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"]
)["Subnets"][0] subnet_id = resources[0]["PhysicalResourceId"]
subnet = ec2_client.describe_subnets(SubnetIds=[subnet_id])["Subnets"][0]
subnet["CidrBlock"].should.equal("10.0.0.0/24")
subnet["AvailabilityZone"].should.equal("us-west-1b") subnet["AvailabilityZone"].should.equal("us-west-1b")

View File

@ -33,9 +33,14 @@ def test_run_instance_with_encrypted_ebs():
} }
], ],
} }
ec2.run_instances(**kwargs) instance = ec2.run_instances(**kwargs)
instance_id = instance["Instances"][0]["InstanceId"]
instances = ec2.describe_instances().get("Reservations")[0].get("Instances") instances = (
ec2.describe_instances(InstanceIds=[instance_id])
.get("Reservations")[0]
.get("Instances")
)
volume = instances[0]["BlockDeviceMappings"][0]["Ebs"] volume = instances[0]["BlockDeviceMappings"][0]["Ebs"]
volumes = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]]) volumes = ec2.describe_volumes(VolumeIds=[volume["VolumeId"]])

View File

@ -48,7 +48,7 @@ def test_describe_all():
gateways = client.describe_egress_only_internet_gateways()[ gateways = client.describe_egress_only_internet_gateways()[
"EgressOnlyInternetGateways" "EgressOnlyInternetGateways"
] ]
gateways.should.have.length_of(2) assert len(gateways) >= 2, "Should have two recently created gateways"
gateways.should.contain(gw1) gateways.should.contain(gw1)
gateways.should.contain(gw2) gateways.should.contain(gw2)
@ -90,12 +90,12 @@ def test_create_and_delete():
] ]
gw1_id = gw1["EgressOnlyInternetGatewayId"] gw1_id = gw1["EgressOnlyInternetGatewayId"]
client.describe_egress_only_internet_gateways()[ client.describe_egress_only_internet_gateways(
"EgressOnlyInternetGateways" EgressOnlyInternetGatewayIds=[gw1_id]
].should.have.length_of(1) )["EgressOnlyInternetGateways"].should.have.length_of(1)
client.delete_egress_only_internet_gateway(EgressOnlyInternetGatewayId=gw1_id) client.delete_egress_only_internet_gateway(EgressOnlyInternetGatewayId=gw1_id)
client.describe_egress_only_internet_gateways()[ client.describe_egress_only_internet_gateways(
"EgressOnlyInternetGateways" EgressOnlyInternetGatewayIds=[gw1_id]
].should.have.length_of(0) )["EgressOnlyInternetGateways"].should.have.length_of(0)

View File

@ -13,6 +13,7 @@ from moto.ec2 import ec2_backends
from moto.ec2.models import OWNER_ID from moto.ec2.models import OWNER_ID
from moto.kms import mock_kms from moto.kms import mock_kms
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from uuid import uuid4
# Has boto3 equivalent # Has boto3 equivalent
@ -391,9 +392,9 @@ def test_volume_filters_boto3():
Size=25, AvailabilityZone="us-east-1a", SnapshotId=snapshot.id Size=25, AvailabilityZone="us-east-1a", SnapshotId=snapshot.id
) )
ec2.create_tags( tag_key1 = str(uuid4())[0:6]
Resources=[volume1.id], Tags=[{"Key": "testkey1", "Value": "testvalue1"}] tag_val1 = str(uuid4())
) ec2.create_tags(Resources=[volume1.id], Tags=[{"Key": tag_key1, "Value": tag_val1}])
ec2.create_tags( ec2.create_tags(
Resources=[volume2.id], Tags=[{"Key": "testkey2", "Value": "testvalue2"}] Resources=[volume2.id], Tags=[{"Key": "testkey2", "Value": "testvalue2"}]
) )
@ -411,30 +412,84 @@ def test_volume_filters_boto3():
][0] ][0]
block_volume = block_mapping["Ebs"]["VolumeId"] block_volume = block_mapping["Ebs"]["VolumeId"]
def verify_filter(name, value, expected=None): def verify_filter(name, value, expected=None, not_expected=None):
multiple_results = not_expected is not None
expected = expected or block_volume expected = expected or block_volume
expected = expected if type(expected) == list else [expected] expected = expected if type(expected) == list else [expected]
volumes = client.describe_volumes(Filters=[{"Name": name, "Values": [value]}])[ volumes = client.describe_volumes(Filters=[{"Name": name, "Values": [value]}])[
"Volumes" "Volumes"
] ]
set([vol["VolumeId"] for vol in volumes]).should.equal(set(expected)) actual = [vol["VolumeId"] for vol in volumes]
if multiple_results:
for e in expected:
actual.should.contain(e)
for e in not_expected:
actual.shouldnt.contain(e)
else:
set(actual).should.equal(set(expected))
# We should probably make this less strict, i.e. figure out which formats AWS expects/approves of # We should probably make this less strict, i.e. figure out which formats AWS expects/approves of
attach_time = block_mapping["Ebs"]["AttachTime"].strftime("%Y-%m-%dT%H:%M:%S.000Z") attach_time = block_mapping["Ebs"]["AttachTime"].strftime("%Y-%m-%dT%H:%M:%S.000Z")
verify_filter("attachment.attach-time", attach_time) verify_filter(
verify_filter("attachment.device", "/dev/sda1") "attachment.attach-time",
attach_time,
not_expected=[volume1.id, volume2.id, volume3.id, volume4.id],
)
verify_filter(
"attachment.device",
"/dev/sda1",
not_expected=[volume1.id, volume2.id, volume3.id, volume4.id],
)
verify_filter("attachment.instance-id", instance.id) verify_filter("attachment.instance-id", instance.id)
verify_filter("attachment.status", "attached") verify_filter(
verify_filter("size", str(volume2.size), expected=volume2.id) "attachment.status",
verify_filter("snapshot-id", snapshot.id, expected=volume4.id) "attached",
verify_filter("status", "in-use") not_expected=[volume1.id, volume2.id, volume3.id, volume4.id],
verify_filter("volume-id", volume1.id, expected=volume1.id) )
verify_filter("tag-key", "testkey1", expected=volume1.id) verify_filter(
verify_filter("tag-value", "testvalue1", expected=volume1.id) "size",
verify_filter("tag:testkey1", "testvalue1", expected=volume1.id) str(volume2.size),
verify_filter("encrypted", "false", expected=[block_volume, volume2.id]) expected=volume2.id,
verify_filter("encrypted", "true", expected=[volume1.id, volume3.id, volume4.id]) not_expected=[volume1.id, volume3.id, volume4.id],
verify_filter("availability-zone", "us-east-1b", expected=volume2.id) )
verify_filter(
"snapshot-id",
snapshot.id,
expected=volume4.id,
not_expected=[volume1.id, volume2.id, volume3.id],
)
verify_filter(
"status",
"in-use",
not_expected=[volume1.id, volume2.id, volume3.id, volume4.id],
)
verify_filter(
"volume-id",
volume1.id,
expected=volume1.id,
not_expected=[volume2.id, volume3.id, volume4.id],
)
verify_filter("tag-key", tag_key1, expected=volume1.id)
verify_filter("tag-value", tag_val1, expected=volume1.id)
verify_filter(f"tag:{tag_key1}", tag_val1, expected=volume1.id)
verify_filter(
"encrypted",
"false",
expected=[block_volume, volume2.id],
not_expected=[volume1.id, volume3.id, volume4.id],
)
verify_filter(
"encrypted",
"true",
expected=[volume1.id, volume3.id, volume4.id],
not_expected=[block_volume, volume2.id],
)
verify_filter(
"availability-zone",
"us-east-1b",
expected=volume2.id,
not_expected=[volume1.id, volume3.id, volume4.id],
)
# #
create_time = volume4.create_time.strftime("%Y-%m-%dT%H:%M:%S.000Z") create_time = volume4.create_time.strftime("%Y-%m-%dT%H:%M:%S.000Z")
volumes_by_attach_device = client.describe_volumes( volumes_by_attach_device = client.describe_volumes(
@ -634,10 +689,12 @@ def test_create_snapshot_boto3():
num_snapshots = len(client.describe_snapshots()["Snapshots"]) num_snapshots = len(client.describe_snapshots()["Snapshots"])
snapshot = volume.create_snapshot() snapshot = volume.create_snapshot()
client.describe_snapshots()["Snapshots"].should.have.length_of(num_snapshots + 1) current_snapshots = client.describe_snapshots()["Snapshots"]
[s["SnapshotId"] for s in current_snapshots].should.contain(snapshot.id)
snapshot.delete() snapshot.delete()
client.describe_snapshots()["Snapshots"].should.have.length_of(num_snapshots) current_snapshots = client.describe_snapshots()["Snapshots"]
[s["SnapshotId"] for s in current_snapshots].shouldnt.contain(snapshot.id)
# Deleting something that was already deleted should throw an error # Deleting something that was already deleted should throw an error
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -814,36 +871,53 @@ def test_snapshot_filters_boto3():
volume1 = ec2.create_volume(Size=20, AvailabilityZone="us-east-1a", Encrypted=False) volume1 = ec2.create_volume(Size=20, AvailabilityZone="us-east-1a", Encrypted=False)
volume2 = ec2.create_volume(Size=25, AvailabilityZone="us-east-1a", Encrypted=True) volume2 = ec2.create_volume(Size=25, AvailabilityZone="us-east-1a", Encrypted=True)
snapshot1 = volume1.create_snapshot(Description="testsnapshot1") snapshot1_desc = str(uuid4())
snapshot1 = volume1.create_snapshot(Description=snapshot1_desc)
snapshot2 = volume1.create_snapshot(Description="testsnapshot2") snapshot2 = volume1.create_snapshot(Description="testsnapshot2")
snapshot3 = volume2.create_snapshot(Description="testsnapshot3") snapshot3 = volume2.create_snapshot(Description="testsnapshot3")
key_name_1 = str(uuid4())[0:6]
key_value_1 = str(uuid4())[0:6]
key_name_2 = str(uuid4())[0:6]
key_value_2 = str(uuid4())[0:6]
ec2.create_tags( ec2.create_tags(
Resources=[snapshot1.id], Tags=[{"Key": "testkey1", "Value": "testvalue1"}] Resources=[snapshot1.id], Tags=[{"Key": key_name_1, "Value": key_value_1}]
) )
ec2.create_tags( ec2.create_tags(
Resources=[snapshot2.id], Tags=[{"Key": "testkey2", "Value": "testvalue2"}] Resources=[snapshot2.id], Tags=[{"Key": key_name_2, "Value": key_value_2}]
) )
def verify_filter(name, value, expected): def verify_filter(name, value, expected, others=False):
expected = expected if type(expected) == list else [expected] expected = expected if type(expected) == list else [expected]
snapshots = client.describe_snapshots( snapshots = client.describe_snapshots(
Filters=[{"Name": name, "Values": [value]}] Filters=[{"Name": name, "Values": [value]}]
)["Snapshots"] )["Snapshots"]
set([s["SnapshotId"] for s in snapshots]).should.equal(set(expected)) if others:
actual = set([s["SnapshotId"] for s in snapshots])
for e in expected:
actual.should.contain(e)
else:
set([s["SnapshotId"] for s in snapshots]).should.equal(set(expected))
verify_filter("description", "testsnapshot1", expected=snapshot1.id) verify_filter("description", snapshot1_desc, expected=snapshot1.id)
verify_filter("snapshot-id", snapshot1.id, expected=snapshot1.id) verify_filter("snapshot-id", snapshot1.id, expected=snapshot1.id)
verify_filter("volume-id", volume1.id, expected=[snapshot1.id, snapshot2.id]) verify_filter("volume-id", volume1.id, expected=[snapshot1.id, snapshot2.id])
verify_filter( verify_filter(
"volume-size", str(volume1.size), expected=[snapshot1.id, snapshot2.id] "volume-size",
str(volume1.size),
expected=[snapshot1.id, snapshot2.id],
others=True,
) )
verify_filter("tag-key", "testkey1", expected=snapshot1.id) verify_filter("tag-key", key_name_1, expected=snapshot1.id)
verify_filter("tag-value", "testvalue1", expected=snapshot1.id) verify_filter("tag-value", key_value_1, expected=snapshot1.id)
verify_filter("tag:testkey2", "testvalue2", expected=snapshot2.id) verify_filter(f"tag:{key_name_2}", key_value_2, expected=snapshot2.id)
verify_filter("encrypted", "true", expected=snapshot3.id) verify_filter("encrypted", "true", expected=snapshot3.id, others=True)
verify_filter( verify_filter(
"owner-id", OWNER_ID, expected=[snapshot1.id, snapshot2.id, snapshot3.id] "owner-id",
OWNER_ID,
expected=[snapshot1.id, snapshot2.id, snapshot3.id],
others=True,
) )
# #
# We should probably make this less strict, i.e. figure out which formats AWS expects/approves of # We should probably make this less strict, i.e. figure out which formats AWS expects/approves of
@ -1427,10 +1501,7 @@ def test_create_unencrypted_volume_with_kms_key_fails():
@mock_ec2 @mock_ec2
def test_create_encrypted_volume_without_kms_key_should_use_default_key(): def test_create_encrypted_volume_without_kms_key_should_use_default_key():
kms = boto3.client("kms", region_name="us-east-1") kms = boto3.client("kms", region_name="us-east-1")
# Default master key for EBS does not exist until needed.
with pytest.raises(ClientError) as ex:
kms.describe_key(KeyId="alias/aws/ebs")
ex.value.response["Error"]["Code"].should.equal("NotFoundException")
# Creating an encrypted volume should create (and use) the default key. # Creating an encrypted volume should create (and use) the default key.
resource = boto3.resource("ec2", region_name="us-east-1") resource = boto3.resource("ec2", region_name="us-east-1")
volume = resource.create_volume( volume = resource.create_volume(

View File

@ -6,6 +6,7 @@ import boto
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from uuid import uuid4
import sure # noqa import sure # noqa
@ -65,7 +66,9 @@ def test_eip_allocate_classic_boto3():
standard.should.have.key("PublicIp") standard.should.have.key("PublicIp")
standard.should.have.key("Domain").equal("standard") standard.should.have.key("Domain").equal("standard")
standard = ec2.ClassicAddress(standard["PublicIp"]) public_ip = standard["PublicIp"]
standard = ec2.ClassicAddress(public_ip)
standard.load() standard.load()
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -77,7 +80,9 @@ def test_eip_allocate_classic_boto3():
) )
standard.release() standard.release()
client.describe_addresses()["Addresses"].should.be.empty
all_addresses = client.describe_addresses()["Addresses"]
[a["PublicIp"] for a in all_addresses].shouldnt.contain(public_ip)
# Has boto3 equivalent # Has boto3 equivalent
@ -119,12 +124,20 @@ def test_eip_allocate_vpc_boto3():
vpc.should.have.key("AllocationId") vpc.should.have.key("AllocationId")
vpc.should.have.key("Domain").equal("vpc") vpc.should.have.key("Domain").equal("vpc")
client.describe_addresses()["Addresses"].should.have.length_of(1) allocation_id = vpc["AllocationId"]
vpc = ec2.VpcAddress(vpc["AllocationId"]) all_addresses = client.describe_addresses()["Addresses"]
[a["AllocationId"] for a in all_addresses if "AllocationId" in a].should.contain(
allocation_id
)
vpc = ec2.VpcAddress(allocation_id)
vpc.release() vpc.release()
client.describe_addresses()["Addresses"].should.be.empty all_addresses = client.describe_addresses()["Addresses"]
[a["AllocationId"] for a in all_addresses if "AllocationId" in a].shouldnt.contain(
allocation_id
)
@mock_ec2 @mock_ec2
@ -264,7 +277,12 @@ def test_eip_associate_classic_boto3():
eip.reload() eip.reload()
eip.instance_id.should.be.equal("") eip.instance_id.should.be.equal("")
eip.release() eip.release()
client.describe_addresses()["Addresses"].should.be.empty
with pytest.raises(ClientError) as ex:
client.describe_addresses(PublicIps=[eip.public_ip])
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidAddress.NotFound")
err["Message"].should.equal("Address '{'" + eip.public_ip + "'}' not found.")
instance.terminate() instance.terminate()
@ -835,7 +853,9 @@ def test_eip_describe_boto3():
# Release all IPs # Release all IPs
for eip in eips: for eip in eips:
eip.release() eip.release()
client.describe_addresses()["Addresses"].should.have.length_of(0) all_addresses = client.describe_addresses()["Addresses"]
[a["PublicIp"] for a in all_addresses].shouldnt.contain(eips[0].public_ip)
[a["PublicIp"] for a in all_addresses].shouldnt.contain(eips[1].public_ip)
# Has boto3 equivalent # Has boto3 equivalent
@ -908,16 +928,21 @@ def test_eip_filters():
inst3.public_ip_address.should.equal(addresses[0].public_ip) inst3.public_ip_address.should.equal(addresses[0].public_ip)
# Param search by Filter # Param search by Filter
def check_vpc_filter_valid(filter_name, filter_values): def check_vpc_filter_valid(filter_name, filter_values, all_values=True):
addresses = list( addresses = list(
service.vpc_addresses.filter( service.vpc_addresses.filter(
Filters=[{"Name": filter_name, "Values": filter_values}] Filters=[{"Name": filter_name, "Values": filter_values}]
) )
) )
len(addresses).should.equal(2) if all_values:
ips = [addr.public_ip for addr in addresses] len(addresses).should.equal(2)
set(ips).should.equal(set([eip1.public_ip, eip2.public_ip])) ips = [addr.public_ip for addr in addresses]
ips.should.contain(inst1.public_ip_address) set(ips).should.equal(set([eip1.public_ip, eip2.public_ip]))
ips.should.contain(inst1.public_ip_address)
else:
ips = [addr.public_ip for addr in addresses]
ips.should.contain(eip1.public_ip)
ips.should.contain(eip2.public_ip)
def check_vpc_filter_invalid(filter_name): def check_vpc_filter_invalid(filter_name):
addresses = list( addresses = list(
@ -927,8 +952,8 @@ def test_eip_filters():
) )
len(addresses).should.equal(0) len(addresses).should.equal(0)
def check_vpc_filter(filter_name, filter_values): def check_vpc_filter(filter_name, filter_values, all_values=True):
check_vpc_filter_valid(filter_name, filter_values) check_vpc_filter_valid(filter_name, filter_values, all_values)
check_vpc_filter_invalid(filter_name) check_vpc_filter_invalid(filter_name)
check_vpc_filter("allocation-id", [eip1.allocation_id, eip2.allocation_id]) check_vpc_filter("allocation-id", [eip1.allocation_id, eip2.allocation_id])
@ -947,6 +972,7 @@ def test_eip_filters():
inst1.network_interfaces_attribute[0].get("PrivateIpAddress"), inst1.network_interfaces_attribute[0].get("PrivateIpAddress"),
inst2.network_interfaces_attribute[0].get("PrivateIpAddress"), inst2.network_interfaces_attribute[0].get("PrivateIpAddress"),
], ],
all_values=False, # Other ENI's may have the same ip address
) )
check_vpc_filter("public-ip", [inst1.public_ip_address, inst2.public_ip_address]) check_vpc_filter("public-ip", [inst1.public_ip_address, inst2.public_ip_address])
@ -954,7 +980,10 @@ def test_eip_filters():
addresses = list( addresses = list(
service.vpc_addresses.filter(Filters=[{"Name": "domain", "Values": ["vpc"]}]) service.vpc_addresses.filter(Filters=[{"Name": "domain", "Values": ["vpc"]}])
) )
len(addresses).should.equal(3) public_ips = [a.public_ip for a in addresses]
public_ips.should.contain(eip1.public_ip)
public_ips.should.contain(eip1.public_ip)
public_ips.should.contain(inst1.public_ip_address)
@mock_ec2 @mock_ec2
@ -963,17 +992,19 @@ def test_eip_tags():
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
# Allocate one address without tags # Allocate one address without tags
client.allocate_address(Domain="vpc") no_tags = client.allocate_address(Domain="vpc")
# Allocate one address and add tags # Allocate one address and add tags
alloc_tags = client.allocate_address(Domain="vpc") alloc_tags = client.allocate_address(Domain="vpc")
managed_by = str(uuid4())
with_tags = client.create_tags( with_tags = client.create_tags(
Resources=[alloc_tags["AllocationId"]], Resources=[alloc_tags["AllocationId"]],
Tags=[{"Key": "ManagedBy", "Value": "MyCode"}], Tags=[{"Key": "ManagedBy", "Value": managed_by}],
) )
addresses_with_tags = client.describe_addresses( addresses_with_tags = client.describe_addresses(
Filters=[ Filters=[
{"Name": "domain", "Values": ["vpc"]}, {"Name": "domain", "Values": ["vpc"]},
{"Name": "tag:ManagedBy", "Values": ["MyCode"]}, {"Name": "tag:ManagedBy", "Values": [managed_by]},
] ]
) )
len(addresses_with_tags["Addresses"]).should.equal(1) len(addresses_with_tags["Addresses"]).should.equal(1)
@ -981,7 +1012,7 @@ def test_eip_tags():
service.vpc_addresses.filter( service.vpc_addresses.filter(
Filters=[ Filters=[
{"Name": "domain", "Values": ["vpc"]}, {"Name": "domain", "Values": ["vpc"]},
{"Name": "tag:ManagedBy", "Values": ["MyCode"]}, {"Name": "tag:ManagedBy", "Values": [managed_by]},
] ]
) )
) )
@ -998,8 +1029,10 @@ def test_eip_tags():
addresses = list( addresses = list(
service.vpc_addresses.filter(Filters=[{"Name": "domain", "Values": ["vpc"]}]) service.vpc_addresses.filter(Filters=[{"Name": "domain", "Values": ["vpc"]}])
) )
# Expected total is 2, one with and one without tags # Expected at least 2, one with and one without tags
len(addresses).should.equal(2) assert len(addresses) >= 2, "Should find our two created addresses"
[a.allocation_id for a in addresses].should.contain(no_tags["AllocationId"])
[a.allocation_id for a in addresses].should.contain(alloc_tags["AllocationId"])
@mock_ec2 @mock_ec2
@ -1011,7 +1044,10 @@ def test_describe_addresses_tags():
Resources=[alloc_tags["AllocationId"]], Resources=[alloc_tags["AllocationId"]],
Tags=[{"Key": "ManagedBy", "Value": "MyCode"}], Tags=[{"Key": "ManagedBy", "Value": "MyCode"}],
) )
addresses_with_tags = client.describe_addresses()
addresses_with_tags = client.describe_addresses(
AllocationIds=[alloc_tags["AllocationId"]]
)
assert addresses_with_tags.get("Addresses")[0].get("Tags") == [ assert addresses_with_tags.get("Addresses")[0].get("Tags") == [
{"Key": "ManagedBy", "Value": "MyCode"} {"Key": "ManagedBy", "Value": "MyCode"}
] ]

View File

@ -1,6 +1,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import pytest import pytest
import random
import boto3 import boto3
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
@ -11,6 +12,7 @@ import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated, settings from moto import mock_ec2, mock_ec2_deprecated, settings
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
from uuid import uuid4
# Has boto3 equivalent # Has boto3 equivalent
@ -75,9 +77,11 @@ def test_elastic_network_interfaces_boto3():
eni_id = ec2.create_network_interface(SubnetId=subnet.id).id eni_id = ec2.create_network_interface(SubnetId=subnet.id).id
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] my_enis = client.describe_network_interfaces(NetworkInterfaceIds=[eni_id])[
all_enis.should.have.length_of(1) "NetworkInterfaces"
eni = all_enis[0] ]
my_enis.should.have.length_of(1)
eni = my_enis[0]
eni["Groups"].should.have.length_of(0) eni["Groups"].should.have.length_of(0)
eni["PrivateIpAddresses"].should.have.length_of(1) eni["PrivateIpAddresses"].should.have.length_of(1)
eni["PrivateIpAddresses"][0]["PrivateIpAddress"].startswith("10.").should.be.true eni["PrivateIpAddresses"][0]["PrivateIpAddress"].startswith("10.").should.be.true
@ -93,7 +97,15 @@ def test_elastic_network_interfaces_boto3():
client.delete_network_interface(NetworkInterfaceId=eni_id) client.delete_network_interface(NetworkInterfaceId=eni_id)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(0) [eni["NetworkInterfaceId"] for eni in all_enis].shouldnt.contain(eni_id)
with pytest.raises(ClientError) as ex:
client.describe_network_interfaces(NetworkInterfaceIds=[eni_id])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal(
"InvalidNetworkInterfaceID.NotFound"
)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_network_interface(NetworkInterfaceId=eni_id) client.delete_network_interface(NetworkInterfaceId=eni_id)
@ -155,12 +167,16 @@ def test_elastic_network_interfaces_with_private_ip_boto3():
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
private_ip = "54.0.0.1" private_ip = "54.0.0.1"
ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress=private_ip) eni = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress=private_ip)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1) [eni["NetworkInterfaceId"] for eni in all_enis].should.contain(eni.id)
eni = all_enis[0] my_enis = client.describe_network_interfaces(NetworkInterfaceIds=[eni.id])[
"NetworkInterfaces"
]
eni = my_enis[0]
eni["Groups"].should.have.length_of(0) eni["Groups"].should.have.length_of(0)
eni["PrivateIpAddresses"].should.have.length_of(1) eni["PrivateIpAddresses"].should.have.length_of(1)
@ -201,16 +217,16 @@ def test_elastic_network_interfaces_with_groups_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a") sec_group1 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a") sec_group2 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id]) my_eni = subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id])
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1) [eni["NetworkInterfaceId"] for eni in all_enis].should.contain(my_eni.id)
eni = all_enis[0] my_eni = [eni for eni in all_enis if eni["NetworkInterfaceId"] == my_eni.id][0]
eni["Groups"].should.have.length_of(2) my_eni["Groups"].should.have.length_of(2)
set([group["GroupId"] for group in eni["Groups"]]).should.equal( set([group["GroupId"] for group in my_eni["Groups"]]).should.equal(
set([sec_group1.id, sec_group2.id]) set([sec_group1.id, sec_group2.id])
) )
@ -267,16 +283,16 @@ def test_elastic_network_interfaces_modify_attribute_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a") sec_group1 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a") sec_group2 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
eni_id = subnet.create_network_interface(Groups=[sec_group1.id]).id eni_id = subnet.create_network_interface(Groups=[sec_group1.id]).id
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] my_eni = client.describe_network_interfaces(NetworkInterfaceIds=[eni_id])[
all_enis.should.have.length_of(1) "NetworkInterfaces"
][0]
eni = all_enis[0] my_eni["Groups"].should.have.length_of(1)
eni["Groups"].should.have.length_of(1) my_eni["Groups"][0]["GroupId"].should.equal(sec_group1.id)
eni["Groups"][0]["GroupId"].should.equal(sec_group1.id)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.modify_network_interface_attribute( client.modify_network_interface_attribute(
@ -292,12 +308,11 @@ def test_elastic_network_interfaces_modify_attribute_boto3():
NetworkInterfaceId=eni_id, Groups=[sec_group2.id] NetworkInterfaceId=eni_id, Groups=[sec_group2.id]
) )
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] my_eni = client.describe_network_interfaces(NetworkInterfaceIds=[eni_id])[
all_enis.should.have.length_of(1) "NetworkInterfaces"
][0]
eni = all_enis[0] my_eni["Groups"].should.have.length_of(1)
eni["Groups"].should.have.length_of(1) my_eni["Groups"][0]["GroupId"].should.equal(sec_group2.id)
eni["Groups"][0]["GroupId"].should.equal(sec_group2.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -370,15 +385,17 @@ def test_elastic_network_interfaces_filtering_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
sec_group1 = ec2.create_security_group(GroupName="group #1", Description="n/a") sec_group1 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
sec_group2 = ec2.create_security_group(GroupName="group #2", Description="n/a") sec_group2 = ec2.create_security_group(GroupName=str(uuid4()), Description="n/a")
eni1 = subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id]) eni1 = subnet.create_network_interface(Groups=[sec_group1.id, sec_group2.id])
eni2 = subnet.create_network_interface(Groups=[sec_group1.id]) eni2 = subnet.create_network_interface(Groups=[sec_group1.id])
eni3 = subnet.create_network_interface(Description="test description") eni3 = subnet.create_network_interface(Description=str(uuid4()))
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(3) [eni["NetworkInterfaceId"] for eni in all_enis].should.contain(eni1.id)
[eni["NetworkInterfaceId"] for eni in all_enis].should.contain(eni2.id)
[eni["NetworkInterfaceId"] for eni in all_enis].should.contain(eni3.id)
# Filter by NetworkInterfaceId # Filter by NetworkInterfaceId
enis_by_id = client.describe_network_interfaces(NetworkInterfaceIds=[eni1.id])[ enis_by_id = client.describe_network_interfaces(NetworkInterfaceIds=[eni1.id])[
@ -453,13 +470,14 @@ def test_elastic_network_interfaces_get_by_tag_name():
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
) )
eni1.create_tags(Tags=[{"Key": "Name", "Value": "eni1"}]) tag_value = str(uuid4())
eni1.create_tags(Tags=[{"Key": "Name", "Value": tag_value}])
# The status of the new interface should be 'available' # The status of the new interface should be 'available'
waiter = ec2_client.get_waiter("network_interface_available") waiter = ec2_client.get_waiter("network_interface_available")
waiter.wait(NetworkInterfaceIds=[eni1.id]) waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{"Name": "tag:Name", "Values": ["eni1"]}] filters = [{"Name": "tag:Name", "Values": [tag_value]}]
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1) enis.should.have.length_of(1)
@ -496,32 +514,33 @@ def test_elastic_network_interfaces_get_by_availability_zone():
filters = [{"Name": "availability-zone", "Values": ["us-west-2a"]}] filters = [{"Name": "availability-zone", "Values": ["us-west-2a"]}]
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1) [eni.id for eni in enis].should.contain(eni1.id)
[eni.id for eni in enis].shouldnt.contain(eni2.id)
filters = [{"Name": "availability-zone", "Values": ["us-west-2c"]}] filters = [{"Name": "availability-zone", "Values": ["us-west-2c"]}]
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0) [eni.id for eni in enis].shouldnt.contain(eni1.id)
[eni.id for eni in enis].shouldnt.contain(eni2.id)
@mock_ec2 @mock_ec2
def test_elastic_network_interfaces_get_by_private_ip(): def test_elastic_network_interfaces_get_by_private_ip():
ec2 = boto3.resource("ec2", region_name="us-west-2") ec2 = boto3.resource("ec2", region_name="us-west-2")
ec2_client = boto3.client("ec2", region_name="us-west-2") ec2_client = boto3.client("ec2", region_name="us-west-2")
random_ip = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet( subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a" VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
) )
eni1 = ec2.create_network_interface( eni1 = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress=random_ip)
SubnetId=subnet.id, PrivateIpAddress="10.0.10.5"
)
# The status of the new interface should be 'available' # The status of the new interface should be 'available'
waiter = ec2_client.get_waiter("network_interface_available") waiter = ec2_client.get_waiter("network_interface_available")
waiter.wait(NetworkInterfaceIds=[eni1.id]) waiter.wait(NetworkInterfaceIds=[eni1.id])
filters = [{"Name": "private-ip-address", "Values": ["10.0.10.5"]}] filters = [{"Name": "private-ip-address", "Values": [random_ip]}]
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1) enis.should.have.length_of(1)
@ -529,7 +548,7 @@ def test_elastic_network_interfaces_get_by_private_ip():
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(0) enis.should.have.length_of(0)
filters = [{"Name": "addresses.private-ip-address", "Values": ["10.0.10.5"]}] filters = [{"Name": "addresses.private-ip-address", "Values": [random_ip]}]
enis = list(ec2.network_interfaces.filter(Filters=filters)) enis = list(ec2.network_interfaces.filter(Filters=filters))
enis.should.have.length_of(1) enis.should.have.length_of(1)
@ -602,8 +621,9 @@ def test_elastic_network_interfaces_get_by_description():
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a" VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
) )
desc = str(uuid4())
eni1 = ec2.create_network_interface( eni1 = ec2.create_network_interface(
SubnetId=subnet.id, PrivateIpAddress="10.0.10.5", Description="test interface" SubnetId=subnet.id, PrivateIpAddress="10.0.10.5", Description=desc
) )
# The status of the new interface should be 'available' # The status of the new interface should be 'available'
@ -624,18 +644,20 @@ def test_elastic_network_interfaces_describe_network_interfaces_with_filter():
ec2 = boto3.resource("ec2", region_name="us-west-2") ec2 = boto3.resource("ec2", region_name="us-west-2")
ec2_client = boto3.client("ec2", region_name="us-west-2") ec2_client = boto3.client("ec2", region_name="us-west-2")
random_ip = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet( subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a" VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
) )
sg = ec2_client.create_security_group(Description="test", GroupName="test_sg") sg = ec2_client.create_security_group(Description="test", GroupName=str(uuid4()))
sg_id = sg["GroupId"] sg_id = sg["GroupId"]
eni1 = ec2.create_network_interface( eni1 = ec2.create_network_interface(
SubnetId=subnet.id, SubnetId=subnet.id,
PrivateIpAddress="10.0.10.5", PrivateIpAddress=random_ip,
Description="test interface", Description=str(uuid4()),
Groups=[sg_id], Groups=[sg_id],
) )
@ -740,6 +762,9 @@ def test_elastic_network_interfaces_filter_by_tag():
VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a" VpcId=vpc.id, CidrBlock="10.0.0.0/24", AvailabilityZone="us-west-2a"
) )
dev_env = f"dev-{str(uuid4())[0:4]}"
prod_env = f"prod-{str(uuid4())[0:4]}"
eni_dev = ec2.create_network_interface( eni_dev = ec2.create_network_interface(
SubnetId=subnet.id, SubnetId=subnet.id,
PrivateIpAddress="10.0.10.5", PrivateIpAddress="10.0.10.5",
@ -747,7 +772,7 @@ def test_elastic_network_interfaces_filter_by_tag():
TagSpecifications=[ TagSpecifications=[
{ {
"ResourceType": "network-interface", "ResourceType": "network-interface",
"Tags": [{"Key": "environment", "Value": "dev"}], "Tags": [{"Key": "environment", "Value": dev_env}],
}, },
], ],
) )
@ -759,7 +784,7 @@ def test_elastic_network_interfaces_filter_by_tag():
TagSpecifications=[ TagSpecifications=[
{ {
"ResourceType": "network-interface", "ResourceType": "network-interface",
"Tags": [{"Key": "environment", "Value": "prod"}], "Tags": [{"Key": "environment", "Value": prod_env}],
}, },
], ],
) )
@ -774,19 +799,19 @@ def test_elastic_network_interfaces_filter_by_tag():
resp["NetworkInterfaces"].should.have.length_of(0) resp["NetworkInterfaces"].should.have.length_of(0)
resp = ec2_client.describe_network_interfaces( resp = ec2_client.describe_network_interfaces(
Filters=[{"Name": "tag:environment", "Values": ["dev"]}] Filters=[{"Name": "tag:environment", "Values": [dev_env]}]
) )
resp["NetworkInterfaces"].should.have.length_of(1) resp["NetworkInterfaces"].should.have.length_of(1)
resp["NetworkInterfaces"][0]["Description"].should.equal("dev interface") resp["NetworkInterfaces"][0]["Description"].should.equal("dev interface")
resp = ec2_client.describe_network_interfaces( resp = ec2_client.describe_network_interfaces(
Filters=[{"Name": "tag:environment", "Values": ["prod"]}] Filters=[{"Name": "tag:environment", "Values": [prod_env]}]
) )
resp["NetworkInterfaces"].should.have.length_of(1) resp["NetworkInterfaces"].should.have.length_of(1)
resp["NetworkInterfaces"][0]["Description"].should.equal("prod interface") resp["NetworkInterfaces"][0]["Description"].should.equal("prod interface")
resp = ec2_client.describe_network_interfaces( resp = ec2_client.describe_network_interfaces(
Filters=[{"Name": "tag:environment", "Values": ["dev", "prod"]}] Filters=[{"Name": "tag:environment", "Values": [dev_env, prod_env]}]
) )
resp["NetworkInterfaces"].should.have.length_of(2) resp["NetworkInterfaces"].should.have.length_of(2)

View File

@ -16,6 +16,7 @@ from moto import (
) )
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from moto.ec2.exceptions import FilterNotImplementedError from moto.ec2.exceptions import FilterNotImplementedError
from uuid import uuid4
@mock_s3 @mock_s3
@ -26,8 +27,9 @@ def test_create_flow_logs_s3():
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
bucket_name = str(uuid4())
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
@ -55,7 +57,7 @@ def test_create_flow_logs_s3():
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(1) response.should.have.length_of(1)
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(FlowLogIds=[response[0]])["FlowLogs"]
flow_logs.should.have.length_of(1) flow_logs.should.have.length_of(1)
flow_log = flow_logs[0] flow_log = flow_logs[0]
@ -80,7 +82,8 @@ def test_create_flow_logs_cloud_watch():
logs_client = boto3.client("logs", region_name="us-west-1") logs_client = boto3.client("logs", region_name="us-west-1")
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
logs_client.create_log_group(logGroupName="test-group") lg_name = str(uuid4())
logs_client.create_log_group(logGroupName=lg_name)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.create_flow_logs( client.create_flow_logs(
@ -88,7 +91,7 @@ def test_create_flow_logs_cloud_watch():
ResourceIds=[vpc["VpcId"]], ResourceIds=[vpc["VpcId"]],
TrafficType="ALL", TrafficType="ALL",
LogDestinationType="cloud-watch-logs", LogDestinationType="cloud-watch-logs",
LogGroupName="test-group", LogGroupName=lg_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
DryRun=True, DryRun=True,
) )
@ -103,12 +106,14 @@ def test_create_flow_logs_cloud_watch():
ResourceIds=[vpc["VpcId"]], ResourceIds=[vpc["VpcId"]],
TrafficType="ALL", TrafficType="ALL",
LogDestinationType="cloud-watch-logs", LogDestinationType="cloud-watch-logs",
LogGroupName="test-group", LogGroupName=lg_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(1) response.should.have.length_of(1)
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(
Filters=[{"Name": "resource-id", "Values": [vpc["VpcId"]]}]
)["FlowLogs"]
flow_logs.should.have.length_of(1) flow_logs.should.have.length_of(1)
flow_log = flow_logs[0] flow_log = flow_logs[0]
@ -119,7 +124,7 @@ def test_create_flow_logs_cloud_watch():
flow_log["ResourceId"].should.equal(vpc["VpcId"]) flow_log["ResourceId"].should.equal(vpc["VpcId"])
flow_log["TrafficType"].should.equal("ALL") flow_log["TrafficType"].should.equal("ALL")
flow_log["LogDestinationType"].should.equal("cloud-watch-logs") flow_log["LogDestinationType"].should.equal("cloud-watch-logs")
flow_log["LogGroupName"].should.equal("test-group") flow_log["LogGroupName"].should.equal(lg_name)
flow_log["DeliverLogsPermissionArn"].should.equal( flow_log["DeliverLogsPermissionArn"].should.equal(
"arn:aws:iam::" + ACCOUNT_ID + ":role/test-role" "arn:aws:iam::" + ACCOUNT_ID + ":role/test-role"
) )
@ -139,7 +144,7 @@ def test_create_flow_log_create():
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"] vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=str(uuid4()),
CreateBucketConfiguration={"LocationConstraint": "us-west-1",}, CreateBucketConfiguration={"LocationConstraint": "us-west-1",},
) )
@ -153,7 +158,7 @@ def test_create_flow_log_create():
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(2) response.should.have.length_of(2)
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(FlowLogIds=response)["FlowLogs"]
flow_logs.should.have.length_of(2) flow_logs.should.have.length_of(2)
flow_logs[0]["LogFormat"].should.equal( flow_logs[0]["LogFormat"].should.equal(
@ -174,7 +179,7 @@ def test_delete_flow_logs():
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"] vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=str(uuid4()),
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
@ -187,18 +192,19 @@ def test_delete_flow_logs():
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(2) response.should.have.length_of(2)
flow_logs = client.describe_flow_logs()["FlowLogs"] filters = [{"Name": "resource-id", "Values": [vpc1["VpcId"], vpc2["VpcId"]]}]
flow_logs = client.describe_flow_logs(Filters=filters)["FlowLogs"]
flow_logs.should.have.length_of(2) flow_logs.should.have.length_of(2)
client.delete_flow_logs(FlowLogIds=[response[0]]) client.delete_flow_logs(FlowLogIds=[response[0]])
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(Filters=filters)["FlowLogs"]
flow_logs.should.have.length_of(1) flow_logs.should.have.length_of(1)
flow_logs[0]["FlowLogId"].should.equal(response[1]) flow_logs[0]["FlowLogId"].should.equal(response[1])
client.delete_flow_logs(FlowLogIds=[response[1]]) client.delete_flow_logs(FlowLogIds=[response[1]])
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(Filters=filters)["FlowLogs"]
flow_logs.should.have.length_of(0) flow_logs.should.have.length_of(0)
@ -212,7 +218,7 @@ def test_delete_flow_logs_delete_many():
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"] vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=str(uuid4()),
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
@ -225,13 +231,15 @@ def test_delete_flow_logs_delete_many():
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(2) response.should.have.length_of(2)
flow_logs = client.describe_flow_logs()["FlowLogs"] all_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client)]
flow_logs.should.have.length_of(2) for fl_id in response:
all_ids.should.contain(fl_id)
client.delete_flow_logs(FlowLogIds=response) client.delete_flow_logs(FlowLogIds=response)
flow_logs = client.describe_flow_logs()["FlowLogs"] all_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client)]
flow_logs.should.have.length_of(0) for fl_id in response:
all_ids.shouldnt.contain(fl_id)
@mock_ec2 @mock_ec2
@ -295,7 +303,7 @@ def test_create_flow_logs_invalid_parameters():
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=str(uuid4()),
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
@ -377,11 +385,12 @@ def test_create_flow_logs_invalid_parameters():
"Error. There is an existing Flow Log with the same configuration and log destination." "Error. There is an existing Flow Log with the same configuration and log destination."
) )
lg_name = str(uuid4())
response = client.create_flow_logs( response = client.create_flow_logs(
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc["VpcId"]], ResourceIds=[vpc["VpcId"]],
TrafficType="ALL", TrafficType="ALL",
LogGroupName="test-group", LogGroupName=lg_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
)["FlowLogIds"] )["FlowLogIds"]
response.should.have.length_of(1) response.should.have.length_of(1)
@ -391,7 +400,7 @@ def test_create_flow_logs_invalid_parameters():
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc["VpcId"]], ResourceIds=[vpc["VpcId"]],
TrafficType="ALL", TrafficType="ALL",
LogGroupName="test-group", LogGroupName=lg_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
) )
ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists") ex.value.response["Error"]["Code"].should.equal("FlowLogAlreadyExists")
@ -400,9 +409,6 @@ def test_create_flow_logs_invalid_parameters():
"Error. There is an existing Flow Log with the same configuration and log destination." "Error. There is an existing Flow Log with the same configuration and log destination."
) )
flow_logs = client.describe_flow_logs()["FlowLogs"]
flow_logs.should.have.length_of(2)
@mock_s3 @mock_s3
@mock_ec2 @mock_ec2
@ -421,20 +427,22 @@ def test_describe_flow_logs_filtering():
] ]
bucket1 = s3.create_bucket( bucket1 = s3.create_bucket(
Bucket="test-flow-logs-1", Bucket=str(uuid4()),
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
logs_client.create_log_group(logGroupName="test-group") lg_name = str(uuid4())
logs_client.create_log_group(logGroupName=lg_name)
fl1 = client.create_flow_logs( fl1 = client.create_flow_logs(
ResourceType="Subnet", ResourceType="Subnet",
ResourceIds=[subnet1["SubnetId"]], ResourceIds=[subnet1["SubnetId"]],
TrafficType="ALL", TrafficType="ALL",
LogGroupName="test-group", LogGroupName=lg_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
)["FlowLogIds"][0] )["FlowLogIds"][0]
tag_key = str(uuid4())[0:6]
fl2 = client.create_flow_logs( fl2 = client.create_flow_logs(
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc2["VpcId"]], ResourceIds=[vpc2["VpcId"]],
@ -442,56 +450,60 @@ def test_describe_flow_logs_filtering():
LogDestinationType="s3", LogDestinationType="s3",
LogDestination="arn:aws:s3:::" + bucket1.name, LogDestination="arn:aws:s3:::" + bucket1.name,
TagSpecifications=[ TagSpecifications=[
{"ResourceType": "vpc-flow-log", "Tags": [{"Key": "foo", "Value": "bar"}]} {"ResourceType": "vpc-flow-log", "Tags": [{"Key": tag_key, "Value": "bar"}]}
], ],
)["FlowLogIds"][0] )["FlowLogIds"][0]
non_existing_group = str(uuid4())
fl3 = client.create_flow_logs( fl3 = client.create_flow_logs(
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc3["VpcId"]], ResourceIds=[vpc3["VpcId"]],
TrafficType="Reject", TrafficType="Reject",
LogGroupName="non-existing-group", LogGroupName=non_existing_group,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role",
)["FlowLogIds"][0] )["FlowLogIds"][0]
all_flow_logs = client.describe_flow_logs()["FlowLogs"] all_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client)]
all_flow_logs.should.have.length_of(3) all_ids.should.contain(fl1)
all_ids.should.contain(fl2)
all_ids.should.contain(fl3)
fl_by_deliver_status = client.describe_flow_logs( filters = [{"Name": "deliver-log-status", "Values": ["SUCCESS"]}]
Filters=[{"Name": "deliver-log-status", "Values": ["SUCCESS"]}], success_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client, filters)]
)["FlowLogs"] success_ids.should.contain(fl1)
fl_by_deliver_status.should.have.length_of(3) success_ids.should.contain(fl2)
success_ids.should.contain(fl3)
fl_by_s3_bucket = client.describe_flow_logs( filters = [{"Name": "log-destination-type", "Values": ["s3"]}]
Filters=[{"Name": "log-destination-type", "Values": ["s3"]}], all_s3_logs = retrieve_all_logs(client, filters)
)["FlowLogs"] s3_ids = [fl["FlowLogId"] for fl in all_s3_logs]
fl_by_s3_bucket.should.have.length_of(1) s3_ids.shouldnt.contain(fl1)
fl_by_s3_bucket[0]["FlowLogId"].should.equal(fl2) s3_ids.should.contain(fl2)
fl_by_s3_bucket[0]["ResourceId"].should.equal(vpc2["VpcId"]) s3_ids.shouldnt.contain(fl3)
our_flow_log = [fl for fl in all_s3_logs if fl["FlowLogId"] == fl2][0]
our_flow_log["ResourceId"].should.equal(vpc2["VpcId"])
fl_by_cloud_watch = client.describe_flow_logs( filters = [{"Name": "log-destination-type", "Values": ["cloud-watch-logs"]}]
Filters=[{"Name": "log-destination-type", "Values": ["cloud-watch-logs"]}], all_cw_logs = retrieve_all_logs(client, filters)
)["FlowLogs"] cw_ids = [fl["FlowLogId"] for fl in all_cw_logs]
fl_by_cloud_watch.should.have.length_of(2)
flow_logs_ids = tuple(map(lambda fl: fl["FlowLogId"], fl_by_cloud_watch)) fl1.should.be.within(cw_ids)
fl1.should.be.within(flow_logs_ids) fl2.shouldnt.be.within(cw_ids)
fl3.should.be.within(flow_logs_ids) fl3.should.be.within(cw_ids)
flow_logs_resource_ids = tuple(map(lambda fl: fl["ResourceId"], fl_by_cloud_watch)) flow_logs_resource_ids = tuple(map(lambda fl: fl["ResourceId"], all_cw_logs))
subnet1["SubnetId"].should.be.within(flow_logs_resource_ids) subnet1["SubnetId"].should.be.within(flow_logs_resource_ids)
vpc3["VpcId"].should.be.within(flow_logs_resource_ids) vpc3["VpcId"].should.be.within(flow_logs_resource_ids)
test_fl3 = next(fl for fl in fl_by_cloud_watch if fl["FlowLogId"] == fl3) test_fl3 = next(fl for fl in all_cw_logs if fl["FlowLogId"] == fl3)
test_fl3["DeliverLogsStatus"].should.equal("FAILED") test_fl3["DeliverLogsStatus"].should.equal("FAILED")
test_fl3["DeliverLogsErrorMessage"].should.equal("Access error") test_fl3["DeliverLogsErrorMessage"].should.equal("Access error")
fl_by_both = client.describe_flow_logs( filters = [{"Name": "log-destination-type", "Values": ["cloud-watch-logs", "s3"]}]
Filters=[ cw_s3_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client, filters)]
{"Name": "log-destination-type", "Values": ["cloud-watch-logs", "s3"]} cw_s3_ids.should.contain(fl1)
], cw_s3_ids.should.contain(fl2)
)["FlowLogs"] cw_s3_ids.should.contain(fl3)
fl_by_both.should.have.length_of(3)
fl_by_flow_log_ids = client.describe_flow_logs( fl_by_flow_log_ids = client.describe_flow_logs(
Filters=[{"Name": "flow-log-id", "Values": [fl1, fl3]}], Filters=[{"Name": "flow-log-id", "Values": [fl1, fl3]}],
@ -506,14 +518,14 @@ def test_describe_flow_logs_filtering():
vpc3["VpcId"].should.be.within(flow_logs_resource_ids) vpc3["VpcId"].should.be.within(flow_logs_resource_ids)
fl_by_group_name = client.describe_flow_logs( fl_by_group_name = client.describe_flow_logs(
Filters=[{"Name": "log-group-name", "Values": ["test-group"]}], Filters=[{"Name": "log-group-name", "Values": [lg_name]}],
)["FlowLogs"] )["FlowLogs"]
fl_by_group_name.should.have.length_of(1) fl_by_group_name.should.have.length_of(1)
fl_by_group_name[0]["FlowLogId"].should.equal(fl1) fl_by_group_name[0]["FlowLogId"].should.equal(fl1)
fl_by_group_name[0]["ResourceId"].should.equal(subnet1["SubnetId"]) fl_by_group_name[0]["ResourceId"].should.equal(subnet1["SubnetId"])
fl_by_group_name = client.describe_flow_logs( fl_by_group_name = client.describe_flow_logs(
Filters=[{"Name": "log-group-name", "Values": ["non-existing-group"]}], Filters=[{"Name": "log-group-name", "Values": [non_existing_group]}],
)["FlowLogs"] )["FlowLogs"]
fl_by_group_name.should.have.length_of(1) fl_by_group_name.should.have.length_of(1)
fl_by_group_name[0]["FlowLogId"].should.equal(fl3) fl_by_group_name[0]["FlowLogId"].should.equal(fl3)
@ -526,29 +538,26 @@ def test_describe_flow_logs_filtering():
fl_by_resource_id[0]["FlowLogId"].should.equal(fl2) fl_by_resource_id[0]["FlowLogId"].should.equal(fl2)
fl_by_resource_id[0]["ResourceId"].should.equal(vpc2["VpcId"]) fl_by_resource_id[0]["ResourceId"].should.equal(vpc2["VpcId"])
fl_by_traffic_type = client.describe_flow_logs( filters = [{"Name": "traffic-type", "Values": ["ALL"]}]
Filters=[{"Name": "traffic-type", "Values": ["ALL"]}], traffic_all = retrieve_all_logs(client, filters)
)["FlowLogs"] [fl["FlowLogId"] for fl in traffic_all].should.contain(fl1)
fl_by_traffic_type.should.have.length_of(1) our_flow_log = [fl for fl in traffic_all if fl["FlowLogId"] == fl1][0]
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl1) our_flow_log["ResourceId"].should.equal(subnet1["SubnetId"])
fl_by_traffic_type[0]["ResourceId"].should.equal(subnet1["SubnetId"])
fl_by_traffic_type = client.describe_flow_logs( filters = [{"Name": "traffic-type", "Values": ["Reject"]}]
Filters=[{"Name": "traffic-type", "Values": ["Reject"]}], traffic_reject = retrieve_all_logs(client, filters)
)["FlowLogs"] [fl["FlowLogId"] for fl in traffic_reject].should.contain(fl3)
fl_by_traffic_type.should.have.length_of(1) our_flow_log = [fl for fl in traffic_reject if fl["FlowLogId"] == fl3][0]
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl3) our_flow_log["ResourceId"].should.equal(vpc3["VpcId"])
fl_by_traffic_type[0]["ResourceId"].should.equal(vpc3["VpcId"])
fl_by_traffic_type = client.describe_flow_logs( filters = [{"Name": "traffic-type", "Values": ["Accept"]}]
Filters=[{"Name": "traffic-type", "Values": ["Accept"]}], traffic_accept = retrieve_all_logs(client, filters)
)["FlowLogs"] [fl["FlowLogId"] for fl in traffic_accept].should.contain(fl2)
fl_by_traffic_type.should.have.length_of(1) our_flow_log = [fl for fl in traffic_accept if fl["FlowLogId"] == fl2][0]
fl_by_traffic_type[0]["FlowLogId"].should.equal(fl2) our_flow_log["ResourceId"].should.equal(vpc2["VpcId"])
fl_by_traffic_type[0]["ResourceId"].should.equal(vpc2["VpcId"])
fl_by_tag_key = client.describe_flow_logs( fl_by_tag_key = client.describe_flow_logs(
Filters=[{"Name": "tag-key", "Values": ["foo"]}], Filters=[{"Name": "tag-key", "Values": [tag_key]}],
)["FlowLogs"] )["FlowLogs"]
fl_by_tag_key.should.have.length_of(1) fl_by_tag_key.should.have.length_of(1)
fl_by_tag_key[0]["FlowLogId"].should.equal(fl2) fl_by_tag_key[0]["FlowLogId"].should.equal(fl2)
@ -579,19 +588,21 @@ def test_flow_logs_by_ids():
vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"] vpc2 = client.create_vpc(CidrBlock="10.1.0.0/16")["Vpc"]
vpc3 = client.create_vpc(CidrBlock="10.2.0.0/16")["Vpc"] vpc3 = client.create_vpc(CidrBlock="10.2.0.0/16")["Vpc"]
lg1_name = str(uuid4())
fl1 = client.create_flow_logs( fl1 = client.create_flow_logs(
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc1["VpcId"]], ResourceIds=[vpc1["VpcId"]],
TrafficType="Reject", TrafficType="Reject",
LogGroupName="test-group-1", LogGroupName=lg1_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-1", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-1",
)["FlowLogIds"][0] )["FlowLogIds"][0]
lg3_name = str(uuid4())
fl2 = client.create_flow_logs( fl2 = client.create_flow_logs(
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc2["VpcId"]], ResourceIds=[vpc2["VpcId"]],
TrafficType="Reject", TrafficType="Reject",
LogGroupName="test-group-3", LogGroupName=lg3_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3",
)["FlowLogIds"][0] )["FlowLogIds"][0]
@ -599,7 +610,7 @@ def test_flow_logs_by_ids():
ResourceType="VPC", ResourceType="VPC",
ResourceIds=[vpc3["VpcId"]], ResourceIds=[vpc3["VpcId"]],
TrafficType="Reject", TrafficType="Reject",
LogGroupName="test-group-3", LogGroupName=lg3_name,
DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3", DeliverLogsPermissionArn="arn:aws:iam::" + ACCOUNT_ID + ":role/test-role-3",
)["FlowLogIds"][0] )["FlowLogIds"][0]
@ -618,11 +629,25 @@ def test_flow_logs_by_ids():
flow_logs = client.describe_flow_logs(FlowLogIds=[fl1, fl3])["FlowLogs"] flow_logs = client.describe_flow_logs(FlowLogIds=[fl1, fl3])["FlowLogs"]
flow_logs.should.have.length_of(0) flow_logs.should.have.length_of(0)
flow_logs = client.describe_flow_logs()["FlowLogs"] all_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client)]
flow_logs.should.have.length_of(1) all_ids.shouldnt.contain(fl1)
flow_logs[0]["FlowLogId"].should.equal(fl2) all_ids.should.contain(fl2)
flow_logs[0]["ResourceId"].should.equal(vpc2["VpcId"]) all_ids.shouldnt.contain(fl3)
flow_logs = client.delete_flow_logs(FlowLogIds=[fl2]) flow_logs = client.delete_flow_logs(FlowLogIds=[fl2])
flow_logs = client.describe_flow_logs()["FlowLogs"]
flow_logs.should.have.length_of(0) all_ids = [fl["FlowLogId"] for fl in retrieve_all_logs(client)]
all_ids.shouldnt.contain(fl1)
all_ids.shouldnt.contain(fl2)
all_ids.shouldnt.contain(fl3)
def retrieve_all_logs(client, filters=[]):
resp = client.describe_flow_logs(Filters=filters)
all_logs = resp["FlowLogs"]
token = resp.get("NextToken")
while token:
resp = client.describe_flow_logs(Filters=filters, NextToken=token)
all_logs.extend(resp["FlowLogs"])
token = resp.get("NextToken")
return all_logs

View File

@ -10,7 +10,9 @@ from moto import (
mock_ec2, mock_ec2,
mock_s3, mock_s3,
) )
from moto.core import ACCOUNT_ID
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from uuid import uuid4
@mock_cloudformation @mock_cloudformation
@ -23,8 +25,9 @@ def test_flow_logs_by_cloudformation():
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"] vpc = client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
bucket_name = str(uuid4())
bucket = s3.create_bucket( bucket = s3.create_bucket(
Bucket="test-flow-logs", Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": "us-west-1"}, CreateBucketConfiguration={"LocationConstraint": "us-west-1"},
) )
@ -47,11 +50,14 @@ def test_flow_logs_by_cloudformation():
}, },
} }
flow_log_template_json = json.dumps(flow_log_template) flow_log_template_json = json.dumps(flow_log_template)
stack_name = str(uuid4())
stack_id = cf_client.create_stack( stack_id = cf_client.create_stack(
StackName="test_stack", TemplateBody=flow_log_template_json StackName=stack_name, TemplateBody=flow_log_template_json
)["StackId"] )["StackId"]
flow_logs = client.describe_flow_logs()["FlowLogs"] flow_logs = client.describe_flow_logs(
Filters=[{"Name": "resource-id", "Values": [vpc["VpcId"]]}]
)["FlowLogs"]
flow_logs.should.have.length_of(1) flow_logs.should.have.length_of(1)
flow_logs[0]["ResourceId"].should.equal(vpc["VpcId"]) flow_logs[0]["ResourceId"].should.equal(vpc["VpcId"])
flow_logs[0]["LogDestination"].should.equal("arn:aws:s3:::" + bucket.name) flow_logs[0]["LogDestination"].should.equal("arn:aws:s3:::" + bucket.name)
@ -81,15 +87,26 @@ def test_cloudformation():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
cf_conn = boto3.client("cloudformation", region_name="us-east-1") cf_conn = boto3.client("cloudformation", region_name="us-east-1")
stack_name = str(uuid4())
cf_conn.create_stack( cf_conn.create_stack(
StackName="test_stack", TemplateBody=json.dumps(dummy_template_json) StackName=stack_name, TemplateBody=json.dumps(dummy_template_json)
) )
associations = client.describe_iam_instance_profile_associations()
associations["IamInstanceProfileAssociations"].should.have.length_of(1)
associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][
"Arn"
].should.contain("test_stack")
cf_conn.delete_stack(StackName="test_stack") resources = cf_conn.list_stack_resources(StackName=stack_name)[
associations = client.describe_iam_instance_profile_associations() "StackResourceSummaries"
associations["IamInstanceProfileAssociations"].should.have.length_of(0) ]
iam_id = resources[0]["PhysicalResourceId"]
iam_ip_arn = f"arn:aws:iam::{ACCOUNT_ID}:instance-profile/{iam_id}"
all_assocs = client.describe_iam_instance_profile_associations()[
"IamInstanceProfileAssociations"
]
our_assoc = [a for a in all_assocs if a["IamInstanceProfile"]["Arn"] == iam_ip_arn]
our_assoc[0]["IamInstanceProfile"]["Arn"].should.contain(stack_name)
our_assoc_id = our_assoc[0]["AssociationId"]
cf_conn.delete_stack(StackName=stack_name)
associations = client.describe_iam_instance_profile_associations()[
"IamInstanceProfileAssociations"
]
[a["AssociationId"] for a in associations].shouldnt.contain(our_assoc_id)

View File

@ -10,6 +10,7 @@ import sure # noqa
from moto import mock_ec2, mock_iam, mock_cloudformation from moto import mock_ec2, mock_iam, mock_cloudformation
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from uuid import uuid4
def quick_instance_creation(): def quick_instance_creation():
@ -35,7 +36,7 @@ def test_associate():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id = quick_instance_creation() instance_id = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn, instance_profile_name = quick_instance_profile_creation(
"test_profile" str(uuid4())
) )
association = client.associate_iam_instance_profile( association = client.associate_iam_instance_profile(
@ -58,7 +59,7 @@ def test_invalid_associate():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id = quick_instance_creation() instance_id = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn, instance_profile_name = quick_instance_profile_creation(
"test_profile" str(uuid4())
) )
client.associate_iam_instance_profile( client.associate_iam_instance_profile(
@ -109,81 +110,74 @@ def test_invalid_associate():
def test_describe(): def test_describe():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id = quick_instance_creation() instance_id1 = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn1, instance_profile_name1 = quick_instance_profile_creation(
"test_profile" str(uuid4())
) )
client.associate_iam_instance_profile( client.associate_iam_instance_profile(
IamInstanceProfile={ IamInstanceProfile={
"Arn": instance_profile_arn, "Arn": instance_profile_arn1,
"Name": instance_profile_name, "Name": instance_profile_name1,
}, },
InstanceId=instance_id, InstanceId=instance_id1,
) )
associations = client.describe_iam_instance_profile_associations() associations = client.describe_iam_instance_profile_associations()
associations["IamInstanceProfileAssociations"].should.have.length_of(1) associations = associations["IamInstanceProfileAssociations"]
associations["IamInstanceProfileAssociations"][0]["InstanceId"].should.equal( [a["IamInstanceProfile"]["Arn"] for a in associations].should.contain(
instance_id instance_profile_arn1
)
associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][
"Arn"
].should.equal(instance_profile_arn)
associations["IamInstanceProfileAssociations"][0]["State"].should.equal(
"associated"
) )
my_assoc = [
a
for a in associations
if a["IamInstanceProfile"]["Arn"] == instance_profile_arn1
][0]
my_assoc["InstanceId"].should.equal(instance_id1)
my_assoc["State"].should.equal("associated")
instance_id = quick_instance_creation() instance_id2 = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn2, instance_profile_name2 = quick_instance_profile_creation(
"test_profile1" str(uuid4())
) )
client.associate_iam_instance_profile( client.associate_iam_instance_profile(
IamInstanceProfile={ IamInstanceProfile={
"Arn": instance_profile_arn, "Arn": instance_profile_arn2,
"Name": instance_profile_name, "Name": instance_profile_name2,
}, },
InstanceId=instance_id, InstanceId=instance_id2,
) )
next_test_associations = client.describe_iam_instance_profile_associations() associations = client.describe_iam_instance_profile_associations()
next_test_associations["IamInstanceProfileAssociations"].should.have.length_of(2) associations = associations["IamInstanceProfileAssociations"]
[a["IamInstanceProfile"]["Arn"] for a in associations].should.contain(
instance_profile_arn1
)
[a["IamInstanceProfile"]["Arn"] for a in associations].should.contain(
instance_profile_arn2
)
my_assoc = [
a
for a in associations
if a["IamInstanceProfile"]["Arn"] == instance_profile_arn1
][0]
associations = client.describe_iam_instance_profile_associations( associations = client.describe_iam_instance_profile_associations(
AssociationIds=[ AssociationIds=[my_assoc["AssociationId"],]
next_test_associations["IamInstanceProfileAssociations"][0][
"AssociationId"
],
]
) )
associations["IamInstanceProfileAssociations"].should.have.length_of(1) associations["IamInstanceProfileAssociations"].should.have.length_of(1)
associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][ associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][
"Arn" "Arn"
].should.equal( ].should.equal(my_assoc["IamInstanceProfile"]["Arn"])
next_test_associations["IamInstanceProfileAssociations"][0][
"IamInstanceProfile"
]["Arn"]
)
associations = client.describe_iam_instance_profile_associations( associations = client.describe_iam_instance_profile_associations(
Filters=[ Filters=[
{ {"Name": "instance-id", "Values": [my_assoc["InstanceId"],],},
"Name": "instance-id",
"Values": [
next_test_associations["IamInstanceProfileAssociations"][0][
"InstanceId"
],
],
},
{"Name": "state", "Values": ["associated"]}, {"Name": "state", "Values": ["associated"]},
] ]
) )
associations["IamInstanceProfileAssociations"].should.have.length_of(1) associations["IamInstanceProfileAssociations"].should.have.length_of(1)
associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][ associations["IamInstanceProfileAssociations"][0]["IamInstanceProfile"][
"Arn" "Arn"
].should.equal( ].should.equal(my_assoc["IamInstanceProfile"]["Arn"])
next_test_associations["IamInstanceProfileAssociations"][0][
"IamInstanceProfile"
]["Arn"]
)
@mock_ec2 @mock_ec2
@ -192,10 +186,10 @@ def test_replace():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id1 = quick_instance_creation() instance_id1 = quick_instance_creation()
instance_profile_arn1, instance_profile_name1 = quick_instance_profile_creation( instance_profile_arn1, instance_profile_name1 = quick_instance_profile_creation(
"test_profile1" str(uuid4())
) )
instance_profile_arn2, instance_profile_name2 = quick_instance_profile_creation( instance_profile_arn2, instance_profile_name2 = quick_instance_profile_creation(
"test_profile2" str(uuid4())
) )
association = client.associate_iam_instance_profile( association = client.associate_iam_instance_profile(
@ -226,10 +220,10 @@ def test_invalid_replace():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id = quick_instance_creation() instance_id = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn, instance_profile_name = quick_instance_profile_creation(
"test_profile" str(uuid4())
) )
instance_profile_arn2, instance_profile_name2 = quick_instance_profile_creation( instance_profile_arn2, instance_profile_name2 = quick_instance_profile_creation(
"test_profile2" str(uuid4())
) )
association = client.associate_iam_instance_profile( association = client.associate_iam_instance_profile(
@ -268,7 +262,7 @@ def test_disassociate():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance_id = quick_instance_creation() instance_id = quick_instance_creation()
instance_profile_arn, instance_profile_name = quick_instance_profile_creation( instance_profile_arn, instance_profile_name = quick_instance_profile_creation(
"test_profile" str(uuid4())
) )
association = client.associate_iam_instance_profile( association = client.associate_iam_instance_profile(
@ -280,7 +274,10 @@ def test_disassociate():
) )
associations = client.describe_iam_instance_profile_associations() associations = client.describe_iam_instance_profile_associations()
associations["IamInstanceProfileAssociations"].should.have.length_of(1) associations = associations["IamInstanceProfileAssociations"]
[a["IamInstanceProfile"]["Arn"] for a in associations].should.contain(
instance_profile_arn
)
disassociation = client.disassociate_iam_instance_profile( disassociation = client.disassociate_iam_instance_profile(
AssociationId=association["IamInstanceProfileAssociation"]["AssociationId"], AssociationId=association["IamInstanceProfileAssociation"]["AssociationId"],
@ -294,7 +291,10 @@ def test_disassociate():
) )
associations = client.describe_iam_instance_profile_associations() associations = client.describe_iam_instance_profile_associations()
associations["IamInstanceProfileAssociations"].should.have.length_of(0) associations = associations["IamInstanceProfileAssociations"]
[a["IamInstanceProfile"]["Arn"] for a in associations].shouldnt.contain(
instance_profile_arn
)
@mock_ec2 @mock_ec2

View File

@ -16,8 +16,10 @@ from freezegun import freeze_time
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2, settings from moto import mock_ec2_deprecated, mock_ec2, settings
from moto.core import ACCOUNT_ID
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
from uuid import uuid4
decode_method = base64.decodebytes decode_method = base64.decodebytes
@ -44,10 +46,13 @@ def test_add_servers():
@mock_ec2 @mock_ec2
def test_add_servers_boto3(): def test_add_servers_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2) resp = client.run_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2)
for i in resp["Instances"]:
i["ImageId"].should.equal(EXAMPLE_AMI_ID)
reservations = client.describe_instances()["Reservations"] instances = client.describe_instances(
instances = reservations[0]["Instances"] InstanceIds=[i["InstanceId"] for i in resp["Instances"]]
)["Reservations"][0]["Instances"]
instances.should.have.length_of(2) instances.should.have.length_of(2)
for i in instances: for i in instances:
i["ImageId"].should.equal(EXAMPLE_AMI_ID) i["ImageId"].should.equal(EXAMPLE_AMI_ID)
@ -133,7 +138,7 @@ def test_instance_launch_and_terminate_boto3():
instance["State"].should.equal({"Code": 0, "Name": "pending"}) instance["State"].should.equal({"Code": 0, "Name": "pending"})
instance_id = instance["InstanceId"] instance_id = instance["InstanceId"]
reservations = client.describe_instances()["Reservations"] reservations = client.describe_instances(InstanceIds=[instance_id])["Reservations"]
reservations.should.have.length_of(1) reservations.should.have.length_of(1)
reservations[0]["ReservationId"].should.equal(reservation["ReservationId"]) reservations[0]["ReservationId"].should.equal(reservation["ReservationId"])
instances = reservations[0]["Instances"] instances = reservations[0]["Instances"]
@ -171,7 +176,7 @@ def test_instance_launch_and_terminate_boto3():
client.terminate_instances(InstanceIds=[instance_id]) client.terminate_instances(InstanceIds=[instance_id])
reservations = client.describe_instances()["Reservations"] reservations = client.describe_instances(InstanceIds=[instance_id])["Reservations"]
instance = reservations[0]["Instances"][0] instance = reservations[0]["Instances"][0]
instance["State"].should.equal({"Code": 48, "Name": "terminated"}) instance["State"].should.equal({"Code": 48, "Name": "terminated"})
@ -201,7 +206,9 @@ def test_instance_terminate_discard_volumes():
instance.terminate() instance.terminate()
instance.wait_until_terminated() instance.wait_until_terminated()
assert not list(ec2_resource.volumes.all()) all_volumes_ids = [v.id for v in list(ec2_resource.volumes.all())]
for my_id in instance_volume_ids:
all_volumes_ids.shouldnt.contain(my_id)
@mock_ec2 @mock_ec2
@ -229,7 +236,9 @@ def test_instance_terminate_keep_volumes_explicit():
instance.terminate() instance.terminate()
instance.wait_until_terminated() instance.wait_until_terminated()
assert len(list(ec2_resource.volumes.all())) == 1 all_volumes_ids = [v.id for v in list(ec2_resource.volumes.all())]
for my_id in instance_volume_ids:
all_volumes_ids.should.contain(my_id)
@mock_ec2 @mock_ec2
@ -269,14 +278,18 @@ def test_instance_terminate_detach_volumes():
], ],
) )
instance = result[0] instance = result[0]
my_volume_ids = []
for volume in instance.volumes.all(): for volume in instance.volumes.all():
my_volume_ids.append(volume.volume_id)
response = instance.detach_volume(VolumeId=volume.volume_id) response = instance.detach_volume(VolumeId=volume.volume_id)
response["State"].should.equal("detaching") response["State"].should.equal("detaching")
instance.terminate() instance.terminate()
instance.wait_until_terminated() instance.wait_until_terminated()
assert len(list(ec2_resource.volumes.all())) == 2 all_volumes_ids = [v.id for v in list(ec2_resource.volumes.all())]
for my_id in my_volume_ids:
all_volumes_ids.should.contain(my_id)
@mock_ec2 @mock_ec2
@ -452,17 +465,25 @@ def test_get_instances_by_id_boto3():
def test_get_paginated_instances(): def test_get_paginated_instances():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
conn = boto3.resource("ec2", "us-east-1") conn = boto3.resource("ec2", "us-east-1")
for i in range(100): instances = []
conn.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) for i in range(12):
resp = client.describe_instances(MaxResults=50) instances.extend(
reservations = resp["Reservations"] conn.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)
reservations.should.have.length_of(50) )
next_token = resp["NextToken"] instance_ids = [i.id for i in instances]
resp1 = client.describe_instances(InstanceIds=instance_ids, MaxResults=5)
res1 = resp1["Reservations"]
res1.should.have.length_of(5)
next_token = resp1["NextToken"]
next_token.should_not.be.none next_token.should_not.be.none
resp2 = client.describe_instances(NextToken=next_token)
reservations.extend(resp2["Reservations"]) resp2 = client.describe_instances(InstanceIds=instance_ids, NextToken=next_token)
reservations.should.have.length_of(100) resp2["Reservations"].should.have.length_of(7) # 12 total - 5 from the first call
assert "NextToken" not in resp2.keys() assert "NextToken" not in resp2 # This is it - no more pages
for i in instances:
i.terminate()
@mock_ec2 @mock_ec2
@ -566,14 +587,15 @@ def test_get_instances_filtering_by_state_boto3():
client.terminate_instances(InstanceIds=[instance1.id]) client.terminate_instances(InstanceIds=[instance1.id])
reservations = client.describe_instances( instances = retrieve_all_instances(
Filters=[{"Name": "instance-state-name", "Values": ["running"]}] client, [{"Name": "instance-state-name", "Values": ["running"]}]
)["Reservations"] )
reservations.should.have.length_of(1) instance_ids = [i["InstanceId"] for i in instances]
# Since we terminated instance1, only instance2 and instance3 should be # Since we terminated instance1, only instance2 and instance3 should be
# returned # returned
instance_ids = [instance["InstanceId"] for instance in reservations[0]["Instances"]] instance_ids.shouldnt.contain(instance1.id)
set(instance_ids).should.equal(set([instance2.id, instance3.id])) instance_ids.should.contain(instance2.id)
instance_ids.should.contain(instance3.id)
reservations = client.describe_instances( reservations = client.describe_instances(
InstanceIds=[instance2.id], InstanceIds=[instance2.id],
@ -590,8 +612,11 @@ def test_get_instances_filtering_by_state_boto3():
reservations.should.equal([]) reservations.should.equal([])
# get_all_reservations should still return all 3 # get_all_reservations should still return all 3
reservations = client.describe_instances()["Reservations"] instances = retrieve_all_instances(client, filters=[])
reservations[0]["Instances"].should.have.length_of(3) instance_ids = [i["InstanceId"] for i in instances]
instance_ids.should.contain(instance1.id)
instance_ids.should.contain(instance2.id)
instance_ids.should.contain(instance3.id)
if not settings.TEST_SERVER_MODE: if not settings.TEST_SERVER_MODE:
# ServerMode will just throw a generic 500 # ServerMode will just throw a generic 500
@ -703,33 +728,26 @@ def test_get_instances_filtering_by_instance_type_boto3():
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, InstanceType="t1.micro" ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, InstanceType="t1.micro"
)[0] )[0]
res = client.describe_instances( instances = retrieve_all_instances(
Filters=[{"Name": "instance-type", "Values": ["m1.small"]}] client, [{"Name": "instance-type", "Values": ["m1.small"]}]
)["Reservations"] )
# get_all_reservations should return instance1,2 instance_ids = [i["InstanceId"] for i in instances]
res.should.have.length_of(2) set(instance_ids).should.contain(instance1.id)
res[0]["Instances"].should.have.length_of(1) set(instance_ids).should.contain(instance2.id)
res[1]["Instances"].should.have.length_of(1)
instance_ids = [r["Instances"][0]["InstanceId"] for r in res]
set(instance_ids).should.equal(set([instance1.id, instance2.id]))
res = client.describe_instances( instances = retrieve_all_instances(
Filters=[{"Name": "instance-type", "Values": ["t1.micro"]}] client, [{"Name": "instance-type", "Values": ["t1.micro"]}]
)["Reservations"] )
# get_all_reservations should return one instance_ids = [i["InstanceId"] for i in instances]
res.should.have.length_of(1) instance_ids.should.contain(instance3.id)
res[0]["Instances"].should.have.length_of(1)
res[0]["Instances"][0]["InstanceId"].should.equal(instance3.id)
res = client.describe_instances( instances = retrieve_all_instances(
Filters=[{"Name": "instance-type", "Values": ["t1.micro", "m1.small"]}] client, [{"Name": "instance-type", "Values": ["t1.micro", "m1.small"]}]
)["Reservations"] )
res.should.have.length_of(3) instance_ids = [i["InstanceId"] for i in instances]
res[0]["Instances"].should.have.length_of(1) instance_ids.should.contain(instance1.id)
res[1]["Instances"].should.have.length_of(1) instance_ids.should.contain(instance2.id)
res[2]["Instances"].should.have.length_of(1) instance_ids.should.contain(instance3.id)
instance_ids = [r["Instances"][0]["InstanceId"] for r in res]
set(instance_ids).should.equal(set([instance1.id, instance2.id, instance3.id]))
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "instance-type", "Values": ["bogus"]}] Filters=[{"Name": "instance-type", "Values": ["bogus"]}]
@ -770,23 +788,22 @@ def test_get_instances_filtering_by_reason_code_boto3():
instance1.stop() instance1.stop()
instance2.terminate() instance2.terminate()
res = client.describe_instances( filters = [
Filters=[ {"Name": "state-reason-code", "Values": ["Client.UserInitiatedShutdown"]}
{"Name": "state-reason-code", "Values": ["Client.UserInitiatedShutdown"]} ]
] instances = retrieve_all_instances(client, filters)
)["Reservations"] instance_ids = [i["InstanceId"] for i in instances]
# get_all_reservations should return instance1 and instance2
res[0]["Instances"].should.have.length_of(2)
set([instance1.id, instance2.id]).should.equal(
set([i["InstanceId"] for i in res[0]["Instances"]])
)
res = client.describe_instances( instance_ids.should.contain(instance1.id)
Filters=[{"Name": "state-reason-code", "Values": [""]}] instance_ids.should.contain(instance2.id)
)["Reservations"] instance_ids.shouldnt.contain(instance3.id)
# get_all_reservations should return instance 3
res[0]["Instances"].should.have.length_of(1) filters = [{"Name": "state-reason-code", "Values": [""]}]
res[0]["Instances"][0]["InstanceId"].should.equal(instance3.id) instances = retrieve_all_instances(client, filters)
instance_ids = [i["InstanceId"] for i in instances]
instance_ids.should.contain(instance3.id)
instance_ids.shouldnt.contain(instance1.id)
instance_ids.shouldnt.contain(instance2.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -823,18 +840,18 @@ def test_get_instances_filtering_by_source_dest_check_boto3():
InstanceId=instance1.id, SourceDestCheck={"Value": False} InstanceId=instance1.id, SourceDestCheck={"Value": False}
) )
check_false = client.describe_instances( instances_false = retrieve_all_instances(
Filters=[{"Name": "source-dest-check", "Values": ["false"]}] client, [{"Name": "source-dest-check", "Values": ["false"]}]
)["Reservations"] )
check_true = client.describe_instances( instances_true = retrieve_all_instances(
Filters=[{"Name": "source-dest-check", "Values": ["true"]}] client, [{"Name": "source-dest-check", "Values": ["true"]}]
)["Reservations"] )
check_false[0]["Instances"].should.have.length_of(1) [i["InstanceId"] for i in instances_false].should.contain(instance1.id)
check_false[0]["Instances"][0]["InstanceId"].should.equal(instance1.id) [i["InstanceId"] for i in instances_false].shouldnt.contain(instance2.id)
check_true[0]["Instances"].should.have.length_of(1) [i["InstanceId"] for i in instances_true].shouldnt.contain(instance1.id)
check_true[0]["Instances"][0]["InstanceId"].should.equal(instance2.id) [i["InstanceId"] for i in instances_true].should.contain(instance2.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -937,20 +954,20 @@ def test_get_instances_filtering_by_image_id():
reservations = client.describe_instances( reservations = client.describe_instances(
Filters=[{"Name": "image-id", "Values": [EXAMPLE_AMI_ID]}] Filters=[{"Name": "image-id", "Values": [EXAMPLE_AMI_ID]}]
)["Reservations"] )["Reservations"]
reservations[0]["Instances"].should.have.length_of(1) assert len(reservations[0]["Instances"]) >= 1, "Should return just created instance"
@mock_ec2 @mock_ec2
def test_get_instances_filtering_by_account_id(): def test_get_instances_filtering_by_account_id():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
conn = boto3.resource("ec2", "us-east-1") conn = boto3.resource("ec2", "us-east-1")
conn.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1) instance = conn.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
reservations = client.describe_instances( instances = retrieve_all_instances(
Filters=[{"Name": "owner-id", "Values": ["123456789012"]}] client, filters=[{"Name": "owner-id", "Values": [ACCOUNT_ID]}]
)["Reservations"] )
reservations[0]["Instances"].should.have.length_of(1) [i["InstanceId"] for i in instances].should.contain(instance.id)
@mock_ec2 @mock_ec2
@ -987,12 +1004,13 @@ def test_get_instances_filtering_by_ni_private_dns():
@mock_ec2 @mock_ec2
def test_get_instances_filtering_by_instance_group_name(): def test_get_instances_filtering_by_instance_group_name():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
client.create_security_group(Description="test", GroupName="test_sg") sec_group_name = str(uuid4())[0:6]
client.create_security_group(Description="test", GroupName=sec_group_name)
client.run_instances( client.run_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=["test_sg"] ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=[sec_group_name]
) )
reservations = client.describe_instances( reservations = client.describe_instances(
Filters=[{"Name": "instance.group-name", "Values": ["test_sg"]}] Filters=[{"Name": "instance.group-name", "Values": [sec_group_name]}]
)["Reservations"] )["Reservations"]
reservations[0]["Instances"].should.have.length_of(1) reservations[0]["Instances"].should.have.length_of(1)
@ -1000,10 +1018,13 @@ def test_get_instances_filtering_by_instance_group_name():
@mock_ec2 @mock_ec2
def test_get_instances_filtering_by_instance_group_id(): def test_get_instances_filtering_by_instance_group_id():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
create_sg = client.create_security_group(Description="test", GroupName="test_sg") sec_group_name = str(uuid4())[0:6]
create_sg = client.create_security_group(
Description="test", GroupName=sec_group_name
)
group_id = create_sg["GroupId"] group_id = create_sg["GroupId"]
client.run_instances( client.run_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=["test_sg"] ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=[sec_group_name]
) )
reservations = client.describe_instances( reservations = client.describe_instances(
Filters=[{"Name": "instance.group-id", "Values": [group_id]}] Filters=[{"Name": "instance.group-id", "Values": [group_id]}]
@ -1088,11 +1109,17 @@ def test_get_instances_filtering_by_tag_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3) reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3)
instance1, instance2, instance3 = reservation instance1, instance2, instance3 = reservation
instance1.create_tags(Tags=[{"Key": "tag1", "Value": "value1"}])
instance1.create_tags(Tags=[{"Key": "tag2", "Value": "value2"}]) tag1_name = str(uuid4())[0:6]
instance2.create_tags(Tags=[{"Key": "tag1", "Value": "value1"}]) tag1_val = str(uuid4())
instance2.create_tags(Tags=[{"Key": "tag2", "Value": "wrong value"}]) tag2_name = str(uuid4())[0:6]
instance3.create_tags(Tags=[{"Key": "tag2", "Value": "value2"}]) tag2_val = str(uuid4())
instance1.create_tags(Tags=[{"Key": tag1_name, "Value": tag1_val}])
instance1.create_tags(Tags=[{"Key": tag2_name, "Value": tag2_val}])
instance2.create_tags(Tags=[{"Key": tag1_name, "Value": tag1_val}])
instance2.create_tags(Tags=[{"Key": tag2_name, "Value": "wrong value"}])
instance3.create_tags(Tags=[{"Key": tag2_name, "Value": tag2_val}])
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag:tag0", "Values": ["value0"]}] Filters=[{"Name": "tag:tag0", "Values": ["value0"]}]
@ -1101,7 +1128,7 @@ def test_get_instances_filtering_by_tag_boto3():
res["Reservations"].should.have.length_of(0) res["Reservations"].should.have.length_of(0)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag:tag1", "Values": ["value1"]}] Filters=[{"Name": f"tag:{tag1_name}", "Values": [tag1_val]}]
) )
# describe_instances should return both instances with this tag value # describe_instances should return both instances with this tag value
res["Reservations"].should.have.length_of(1) res["Reservations"].should.have.length_of(1)
@ -1111,8 +1138,8 @@ def test_get_instances_filtering_by_tag_boto3():
res = client.describe_instances( res = client.describe_instances(
Filters=[ Filters=[
{"Name": "tag:tag1", "Values": ["value1"]}, {"Name": f"tag:{tag1_name}", "Values": [tag1_val]},
{"Name": "tag:tag2", "Values": ["value2"]}, {"Name": f"tag:{tag2_name}", "Values": [tag2_val]},
] ]
) )
# describe_instances should return the instance with both tag values # describe_instances should return the instance with both tag values
@ -1121,7 +1148,7 @@ def test_get_instances_filtering_by_tag_boto3():
res["Reservations"][0]["Instances"][0]["InstanceId"].should.equal(instance1.id) res["Reservations"][0]["Instances"][0]["InstanceId"].should.equal(instance1.id)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag:tag2", "Values": ["value2", "bogus"]}] Filters=[{"Name": f"tag:{tag2_name}", "Values": [tag2_val, "bogus"]}]
) )
# describe_instances should return both instances with one of the # describe_instances should return both instances with one of the
# acceptable tag values # acceptable tag values
@ -1180,11 +1207,16 @@ def test_get_instances_filtering_by_tag_value_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3) reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3)
instance1, instance2, instance3 = reservation instance1, instance2, instance3 = reservation
instance1.create_tags(Tags=[{"Key": "tag1", "Value": "value1"}])
instance1.create_tags(Tags=[{"Key": "tag2", "Value": "value2"}]) tag1_name = str(uuid4())[0:6]
instance2.create_tags(Tags=[{"Key": "tag1", "Value": "value1"}]) tag1_val = str(uuid4())
instance2.create_tags(Tags=[{"Key": "tag2", "Value": "wrong value"}]) tag2_name = str(uuid4())[0:6]
instance3.create_tags(Tags=[{"Key": "tag2", "Value": "value2"}]) tag2_val = str(uuid4())
instance1.create_tags(Tags=[{"Key": tag1_name, "Value": tag1_val}])
instance1.create_tags(Tags=[{"Key": tag2_name, "Value": tag2_val}])
instance2.create_tags(Tags=[{"Key": tag1_name, "Value": tag1_val}])
instance2.create_tags(Tags=[{"Key": tag2_name, "Value": "wrong value"}])
instance3.create_tags(Tags=[{"Key": tag2_name, "Value": tag2_val}])
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["value0"]}] Filters=[{"Name": "tag-value", "Values": ["value0"]}]
@ -1193,7 +1225,7 @@ def test_get_instances_filtering_by_tag_value_boto3():
res["Reservations"].should.have.length_of(0) res["Reservations"].should.have.length_of(0)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["value1"]}] Filters=[{"Name": "tag-value", "Values": [tag1_val]}]
) )
# describe_instances should return both instances with this tag value # describe_instances should return both instances with this tag value
res["Reservations"].should.have.length_of(1) res["Reservations"].should.have.length_of(1)
@ -1202,7 +1234,7 @@ def test_get_instances_filtering_by_tag_value_boto3():
res["Reservations"][0]["Instances"][1]["InstanceId"].should.equal(instance2.id) res["Reservations"][0]["Instances"][1]["InstanceId"].should.equal(instance2.id)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["value2", "value1"]}] Filters=[{"Name": "tag-value", "Values": [tag2_val, tag1_val]}]
) )
# describe_instances should return both instances with one of the # describe_instances should return both instances with one of the
# acceptable tag values # acceptable tag values
@ -1213,7 +1245,7 @@ def test_get_instances_filtering_by_tag_value_boto3():
res["Reservations"][0]["Instances"][2]["InstanceId"].should.equal(instance3.id) res["Reservations"][0]["Instances"][2]["InstanceId"].should.equal(instance3.id)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag-value", "Values": ["value2", "bogus"]}] Filters=[{"Name": "tag-value", "Values": [tag2_val, "bogus"]}]
) )
# describe_instances should return both instances with one of the # describe_instances should return both instances with one of the
# acceptable tag values # acceptable tag values
@ -1262,17 +1294,21 @@ def test_get_instances_filtering_by_tag_name_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3) reservation = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=3, MaxCount=3)
instance1, instance2, instance3 = reservation instance1, instance2, instance3 = reservation
instance1.create_tags(Tags=[{"Key": "tag1", "Value": ""}])
tag1 = str(uuid4())
tag3 = str(uuid4())
instance1.create_tags(Tags=[{"Key": tag1, "Value": ""}])
instance1.create_tags(Tags=[{"Key": "tag2", "Value": ""}]) instance1.create_tags(Tags=[{"Key": "tag2", "Value": ""}])
instance2.create_tags(Tags=[{"Key": "tag1", "Value": ""}]) instance2.create_tags(Tags=[{"Key": tag1, "Value": ""}])
instance2.create_tags(Tags=[{"Key": "tag2X", "Value": ""}]) instance2.create_tags(Tags=[{"Key": "tag2X", "Value": ""}])
instance3.create_tags(Tags=[{"Key": "tag3", "Value": ""}]) instance3.create_tags(Tags=[{"Key": tag3, "Value": ""}])
res = client.describe_instances(Filters=[{"Name": "tag-key", "Values": ["tagX"]}]) res = client.describe_instances(Filters=[{"Name": "tag-key", "Values": ["tagX"]}])
# describe_instances should return no instances # describe_instances should return no instances
res["Reservations"].should.have.length_of(0) res["Reservations"].should.have.length_of(0)
res = client.describe_instances(Filters=[{"Name": "tag-key", "Values": ["tag1"]}]) res = client.describe_instances(Filters=[{"Name": "tag-key", "Values": [tag1]}])
# describe_instances should return both instances with this tag value # describe_instances should return both instances with this tag value
res["Reservations"].should.have.length_of(1) res["Reservations"].should.have.length_of(1)
res["Reservations"][0]["Instances"].should.have.length_of(2) res["Reservations"][0]["Instances"].should.have.length_of(2)
@ -1280,7 +1316,7 @@ def test_get_instances_filtering_by_tag_name_boto3():
res["Reservations"][0]["Instances"][1]["InstanceId"].should.equal(instance2.id) res["Reservations"][0]["Instances"][1]["InstanceId"].should.equal(instance2.id)
res = client.describe_instances( res = client.describe_instances(
Filters=[{"Name": "tag-key", "Values": ["tag1", "tag3"]}] Filters=[{"Name": "tag-key", "Values": [tag1, tag3]}]
) )
# describe_instances should return both instances with one of the # describe_instances should return both instances with one of the
# acceptable tag values # acceptable tag values
@ -1501,10 +1537,10 @@ def test_modify_instance_attribute_security_groups_boto3():
old_groups.should.equal([]) old_groups.should.equal([])
sg_id = ec2.create_security_group( sg_id = ec2.create_security_group(
GroupName="test security group", Description="this is a test security group" GroupName=str(uuid4()), Description="this is a test security group"
).id ).id
sg_id2 = ec2.create_security_group( sg_id2 = ec2.create_security_group(
GroupName="test security group 2", Description="this is a test security group 2" GroupName=str(uuid4()), Description="this is a test security group 2"
).id ).id
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -1697,8 +1733,12 @@ def test_run_instance_with_security_group_name():
def test_run_instance_with_security_group_name_boto3(): def test_run_instance_with_security_group_name_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
sec_group_name = str(uuid4())[0:6]
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
ec2.create_security_group(GroupName="group1", Description="d", DryRun=True) ec2.create_security_group(
GroupName=sec_group_name, Description="d", DryRun=True
)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation") ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal( ex.value.response["Error"]["Message"].should.equal(
@ -1706,16 +1746,16 @@ def test_run_instance_with_security_group_name_boto3():
) )
group = ec2.create_security_group( group = ec2.create_security_group(
GroupName="group1", Description="some description" GroupName=sec_group_name, Description="some description"
) )
res = ec2.create_instances( res = ec2.create_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=["group1"] ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=[sec_group_name]
) )
instance = res[0] instance = res[0]
instance.security_groups.should.equal( instance.security_groups.should.equal(
[{"GroupName": "group1", "GroupId": group.id}] [{"GroupName": sec_group_name, "GroupId": group.id}]
) )
@ -1734,15 +1774,16 @@ def test_run_instance_with_security_group_id():
@mock_ec2 @mock_ec2
def test_run_instance_with_security_group_id_boto3(): def test_run_instance_with_security_group_id_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
sec_group_name = str(uuid4())
group = ec2.create_security_group( group = ec2.create_security_group(
GroupName="group1", Description="some description" GroupName=sec_group_name, Description="some description"
) )
instance = ec2.create_instances( instance = ec2.create_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroupIds=[group.id] ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroupIds=[group.id]
)[0] )[0]
instance.security_groups.should.equal( instance.security_groups.should.equal(
[{"GroupName": "group1", "GroupId": group.id}] [{"GroupName": sec_group_name, "GroupId": group.id}]
) )
@ -1955,10 +1996,10 @@ def test_run_instance_with_nic_autocreated_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
security_group1 = ec2.create_security_group( security_group1 = ec2.create_security_group(
GroupName="test security group #1", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
security_group2 = ec2.create_security_group( security_group2 = ec2.create_security_group(
GroupName="test security group #2", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
private_ip = "10.0.0.1" private_ip = "10.0.0.1"
@ -1972,13 +2013,16 @@ def test_run_instance_with_nic_autocreated_boto3():
PrivateIpAddress=private_ip, PrivateIpAddress=private_ip,
)[0] )[0]
all_enis = client.describe_network_interfaces()["NetworkInterfaces"]
all_enis.should.have.length_of(1)
eni = all_enis[0]
instance_eni = instance.network_interfaces_attribute instance_eni = instance.network_interfaces_attribute
instance_eni.should.have.length_of(1) instance_eni.should.have.length_of(1)
instance_eni[0]["NetworkInterfaceId"].should.equal(eni["NetworkInterfaceId"])
nii = instance_eni[0]["NetworkInterfaceId"]
my_enis = client.describe_network_interfaces(NetworkInterfaceIds=[nii])[
"NetworkInterfaces"
]
my_enis.should.have.length_of(1)
eni = my_enis[0]
instance.subnet_id.should.equal(subnet.id) instance.subnet_id.should.equal(subnet.id)
instance.security_groups.should.have.length_of(2) instance.security_groups.should.have.length_of(2)
@ -2057,10 +2101,10 @@ def test_run_instance_with_nic_preexisting_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
security_group1 = ec2.create_security_group( security_group1 = ec2.create_security_group(
GroupName="test security group #1", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
security_group2 = ec2.create_security_group( security_group2 = ec2.create_security_group(
GroupName="test security group #2", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
private_ip = "54.0.0.1" private_ip = "54.0.0.1"
eni = ec2.create_network_interface( eni = ec2.create_network_interface(
@ -2080,7 +2124,11 @@ def test_run_instance_with_nic_preexisting_boto3():
instance.subnet_id.should.equal(subnet.id) instance.subnet_id.should.equal(subnet.id)
all_enis = client.describe_network_interfaces()["NetworkInterfaces"] nii = instance.network_interfaces_attribute[0]["NetworkInterfaceId"]
all_enis = client.describe_network_interfaces(NetworkInterfaceIds=[nii])[
"NetworkInterfaces"
]
all_enis.should.have.length_of(1) all_enis.should.have.length_of(1)
instance_enis = instance.network_interfaces_attribute instance_enis = instance.network_interfaces_attribute
@ -2186,10 +2234,10 @@ def test_instance_with_nic_attach_detach_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
security_group1 = ec2.create_security_group( security_group1 = ec2.create_security_group(
GroupName="test security group #1", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
security_group2 = ec2.create_security_group( security_group2 = ec2.create_security_group(
GroupName="test security group #2", Description="n/a" GroupName=str(uuid4()), Description="n/a"
) )
instance = ec2.create_instances( instance = ec2.create_instances(
@ -2342,9 +2390,9 @@ def test_run_instance_with_block_device_mappings():
"BlockDeviceMappings": [{"DeviceName": "/dev/sda2", "Ebs": {"VolumeSize": 50}}], "BlockDeviceMappings": [{"DeviceName": "/dev/sda2", "Ebs": {"VolumeSize": 50}}],
} }
ec2_client.run_instances(**kwargs) instance_id = ec2_client.run_instances(**kwargs)["Instances"][0]["InstanceId"]
instances = ec2_client.describe_instances() instances = ec2_client.describe_instances(InstanceIds=[instance_id])
volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][ volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][
"Ebs" "Ebs"
] ]
@ -2421,9 +2469,10 @@ def test_run_instance_with_block_device_mappings_from_snapshot():
], ],
} }
ec2_client.run_instances(**kwargs) resp = ec2_client.run_instances(**kwargs)
instance_id = resp["Instances"][0]["InstanceId"]
instances = ec2_client.describe_instances() instances = ec2_client.describe_instances(InstanceIds=[instance_id])
volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][ volume = instances["Reservations"][0]["Instances"][0]["BlockDeviceMappings"][0][
"Ebs" "Ebs"
] ]
@ -2444,6 +2493,8 @@ def test_describe_instance_status_no_instances():
@mock_ec2 @mock_ec2
def test_describe_instance_status_no_instances_boto3(): def test_describe_instance_status_no_instances_boto3():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
all_status = client.describe_instance_status()["InstanceStatuses"] all_status = client.describe_instance_status()["InstanceStatuses"]
all_status.should.have.length_of(0) all_status.should.have.length_of(0)
@ -2465,12 +2516,15 @@ def test_describe_instance_status_with_instances():
def test_describe_instance_status_with_instances_boto3(): def test_describe_instance_status_with_instances_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
all_status = client.describe_instance_status()["InstanceStatuses"] all_status = client.describe_instance_status()["InstanceStatuses"]
all_status.should.have.length_of(1) instance_ids = [s["InstanceId"] for s in all_status]
all_status[0]["InstanceStatus"]["Status"].should.equal("ok") instance_ids.should.contain(instance.id)
all_status[0]["SystemStatus"]["Status"].should.equal("ok")
my_status = [s for s in all_status if s["InstanceId"] == instance.id][0]
my_status["InstanceStatus"]["Status"].should.equal("ok")
my_status["SystemStatus"]["Status"].should.equal("ok")
# Has boto3 equivalent # Has boto3 equivalent
@ -2564,19 +2618,26 @@ def test_describe_instance_status_with_instance_filter():
IncludeAllInstances=True, Filters=state_name_filter["running_and_stopped"] IncludeAllInstances=True, Filters=state_name_filter["running_and_stopped"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(all_instance_ids) for _id in all_instance_ids:
found_instance_ids.should.contain(_id)
found_statuses = conn.describe_instance_status( found_statuses = conn.describe_instance_status(
IncludeAllInstances=True, Filters=state_name_filter["running"] IncludeAllInstances=True, Filters=state_name_filter["running"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(running_instance_ids) for _id in stopped_instance_ids:
found_instance_ids.shouldnt.contain(_id)
for _id in running_instance_ids:
found_instance_ids.should.contain(_id)
found_statuses = conn.describe_instance_status( found_statuses = conn.describe_instance_status(
IncludeAllInstances=True, Filters=state_name_filter["stopped"] IncludeAllInstances=True, Filters=state_name_filter["stopped"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(stopped_instance_ids) for _id in stopped_instance_ids:
found_instance_ids.should.contain(_id)
for _id in running_instance_ids:
found_instance_ids.shouldnt.contain(_id)
# Filter instance using the state code # Filter instance using the state code
state_code_filter = { state_code_filter = {
@ -2591,19 +2652,26 @@ def test_describe_instance_status_with_instance_filter():
IncludeAllInstances=True, Filters=state_code_filter["running_and_stopped"] IncludeAllInstances=True, Filters=state_code_filter["running_and_stopped"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(all_instance_ids) for _id in all_instance_ids:
found_instance_ids.should.contain(_id)
found_statuses = conn.describe_instance_status( found_statuses = conn.describe_instance_status(
IncludeAllInstances=True, Filters=state_code_filter["running"] IncludeAllInstances=True, Filters=state_code_filter["running"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(running_instance_ids) for _id in stopped_instance_ids:
found_instance_ids.shouldnt.contain(_id)
for _id in running_instance_ids:
found_instance_ids.should.contain(_id)
found_statuses = conn.describe_instance_status( found_statuses = conn.describe_instance_status(
IncludeAllInstances=True, Filters=state_code_filter["stopped"] IncludeAllInstances=True, Filters=state_code_filter["stopped"]
)["InstanceStatuses"] )["InstanceStatuses"]
found_instance_ids = [status["InstanceId"] for status in found_statuses] found_instance_ids = [status["InstanceId"] for status in found_statuses]
sorted(found_instance_ids).should.equal(stopped_instance_ids) for _id in stopped_instance_ids:
found_instance_ids.should.contain(_id)
for _id in running_instance_ids:
found_instance_ids.shouldnt.contain(_id)
# Has boto3 equivalent # Has boto3 equivalent
@ -2644,14 +2712,23 @@ def test_describe_instance_status_with_non_running_instances_boto3():
instance2.terminate() instance2.terminate()
all_running_status = client.describe_instance_status()["InstanceStatuses"] all_running_status = client.describe_instance_status()["InstanceStatuses"]
all_running_status.should.have.length_of(1) [status["InstanceId"] for status in all_running_status].shouldnt.contain(
all_running_status[0]["InstanceId"].should.equal(instance3.id) instance1.id
all_running_status[0]["InstanceState"].should.equal({"Code": 16, "Name": "running"}) )
[status["InstanceId"] for status in all_running_status].shouldnt.contain(
instance2.id
)
[status["InstanceId"] for status in all_running_status].should.contain(instance3.id)
my_status = [s for s in all_running_status if s["InstanceId"] == instance3.id][0]
my_status["InstanceState"].should.equal({"Code": 16, "Name": "running"})
all_status = client.describe_instance_status(IncludeAllInstances=True)[ all_status = client.describe_instance_status(IncludeAllInstances=True)[
"InstanceStatuses" "InstanceStatuses"
] ]
all_status.should.have.length_of(3) [status["InstanceId"] for status in all_status].should.contain(instance1.id)
[status["InstanceId"] for status in all_status].should.contain(instance2.id)
[status["InstanceId"] for status in all_status].should.contain(instance3.id)
status1 = next((s for s in all_status if s["InstanceId"] == instance1.id), None) status1 = next((s for s in all_status if s["InstanceId"] == instance1.id), None)
status1["InstanceState"].should.equal({"Code": 80, "Name": "stopped"}) status1["InstanceState"].should.equal({"Code": 80, "Name": "stopped"})
@ -2698,7 +2775,9 @@ def test_get_instance_by_security_group_boto3():
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
security_group = ec2.create_security_group(GroupName="test", Description="test") security_group = ec2.create_security_group(
GroupName=str(uuid4())[0:6], Description="test"
)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.modify_instance_attribute( client.modify_instance_attribute(
@ -2762,14 +2841,21 @@ def test_create_instance_ebs_optimized():
def test_run_multiple_instances_in_same_command(): def test_run_multiple_instances_in_same_command():
instance_count = 4 instance_count = 4
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
client.run_instances( instances = client.run_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=instance_count, MaxCount=instance_count ImageId=EXAMPLE_AMI_ID, MinCount=instance_count, MaxCount=instance_count
) )
reservations = client.describe_instances()["Reservations"] reservation_id = instances["ReservationId"]
reservations[0]["Instances"].should.have.length_of(instance_count) # TODO: use this filter when implemented
# client.describe_instances(Filters=[{"Name": "reservation-id", "Values": [instances["ReservationId"]]}])["Reservations"]
all_reservations = retrieve_all_reservations(client)
my_reservation = [
r for r in all_reservations if r["ReservationId"] == reservation_id
][0]
instances = reservations[0]["Instances"] my_reservation["Instances"].should.have.length_of(instance_count)
instances = my_reservation["Instances"]
for i in range(0, instance_count): for i in range(0, instance_count):
instances[i]["AmiLaunchIndex"].should.be(i) instances[i]["AmiLaunchIndex"].should.be(i)
@ -2778,17 +2864,15 @@ def test_run_multiple_instances_in_same_command():
def test_describe_instance_attribute(): def test_describe_instance_attribute():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
security_group_id = client.create_security_group( security_group_id = client.create_security_group(
GroupName="test security group", Description="this is a test security group" GroupName=str(uuid4()), Description="this is a test security group"
)["GroupId"] )["GroupId"]
client.run_instances( resp = client.run_instances(
ImageId=EXAMPLE_AMI_ID, ImageId=EXAMPLE_AMI_ID,
MinCount=1, MinCount=1,
MaxCount=1, MaxCount=1,
SecurityGroupIds=[security_group_id], SecurityGroupIds=[security_group_id],
) )
instance_id = client.describe_instances()["Reservations"][0]["Instances"][0][ instance_id = resp["Instances"][0]["InstanceId"]
"InstanceId"
]
valid_instance_attributes = [ valid_instance_attributes = [
"instanceType", "instanceType",
@ -2855,7 +2939,8 @@ def test_warn_on_invalid_ami():
def test_filter_wildcard_in_specified_tag_only(): def test_filter_wildcard_in_specified_tag_only():
ec2_client = boto3.client("ec2", region_name="us-west-1") ec2_client = boto3.client("ec2", region_name="us-west-1")
tags_name = [{"Key": "Name", "Value": "alice in wonderland"}] name = str(uuid4())[0:6]
tags_name = [{"Key": "Name", "Value": f"{name} in wonderland"}]
ec2_client.run_instances( ec2_client.run_instances(
ImageId=EXAMPLE_AMI_ID, ImageId=EXAMPLE_AMI_ID,
MaxCount=1, MaxCount=1,
@ -2863,7 +2948,7 @@ def test_filter_wildcard_in_specified_tag_only():
TagSpecifications=[{"ResourceType": "instance", "Tags": tags_name}], TagSpecifications=[{"ResourceType": "instance", "Tags": tags_name}],
) )
tags_owner = [{"Key": "Owner", "Value": "alice in wonderland"}] tags_owner = [{"Key": "Owner", "Value": f"{name} in wonderland"}]
ec2_client.run_instances( ec2_client.run_instances(
ImageId=EXAMPLE_AMI_ID, ImageId=EXAMPLE_AMI_ID,
MaxCount=1, MaxCount=1,
@ -2873,7 +2958,7 @@ def test_filter_wildcard_in_specified_tag_only():
# should only match the Name tag # should only match the Name tag
response = ec2_client.describe_instances( response = ec2_client.describe_instances(
Filters=[{"Name": "tag:Name", "Values": ["*alice*"]}] Filters=[{"Name": "tag:Name", "Values": [f"*{name}*"]}]
) )
instances = [i for r in response["Reservations"] for i in r["Instances"]] instances = [i for r in response["Reservations"] for i in r["Instances"]]
instances.should.have.length_of(1) instances.should.have.length_of(1)
@ -2946,8 +3031,7 @@ def test_create_instance_with_launch_template_id_produces_no_warning(
) )
template = client.create_launch_template( template = client.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateName=str(uuid4()), LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID},
LaunchTemplateData={"ImageId": EXAMPLE_AMI_ID},
)["LaunchTemplate"] )["LaunchTemplate"]
with pytest.warns(None) as captured_warnings: with pytest.warns(None) as captured_warnings:
@ -2958,3 +3042,19 @@ def test_create_instance_with_launch_template_id_produces_no_warning(
) )
assert len(captured_warnings) == 0 assert len(captured_warnings) == 0
def retrieve_all_reservations(client, filters=[]):
resp = client.describe_instances(Filters=filters)
all_reservations = resp["Reservations"]
next_token = resp.get("NextToken")
while next_token:
resp = client.describe_instances(Filters=filters, NextToken=next_token)
all_reservations.extend(resp["Reservations"])
next_token = resp.get("NextToken")
return all_reservations
def retrieve_all_instances(client, filters=[]):
reservations = retrieve_all_reservations(client, filters)
return [i for r in reservations for i in r["Instances"]]

View File

@ -13,6 +13,7 @@ from botocore.exceptions import ClientError
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from uuid import uuid4
VPC_CIDR = "10.0.0.0/16" VPC_CIDR = "10.0.0.0/16"
@ -50,8 +51,6 @@ def test_igw_create_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.create_internet_gateway(DryRun=True) client.create_internet_gateway(DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
@ -61,10 +60,11 @@ def test_igw_create_boto3():
) )
igw = ec2.create_internet_gateway() igw = ec2.create_internet_gateway()
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(1)
igw.id.should.match(r"igw-[0-9a-f]+") igw.id.should.match(r"igw-[0-9a-f]+")
igw = client.describe_internet_gateways()["InternetGateways"][0] igw = client.describe_internet_gateways(InternetGatewayIds=[igw.id])[
"InternetGateways"
][0]
igw["Attachments"].should.have.length_of(0) igw["Attachments"].should.have.length_of(0)
@ -109,7 +109,9 @@ def test_igw_attach_boto3():
vpc.attach_internet_gateway(InternetGatewayId=igw.id) vpc.attach_internet_gateway(InternetGatewayId=igw.id)
igw = client.describe_internet_gateways()["InternetGateways"][0] igw = client.describe_internet_gateways(InternetGatewayIds=[igw.id])[
"InternetGateways"
][0]
igw["Attachments"].should.equal([{"State": "available", "VpcId": vpc.id}]) igw["Attachments"].should.equal([{"State": "available", "VpcId": vpc.id}])
@ -216,7 +218,9 @@ def test_igw_detach_boto3():
) )
client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id) client.detach_internet_gateway(InternetGatewayId=igw.id, VpcId=vpc.id)
igw = client.describe_internet_gateways()["InternetGateways"][0] igw = igw = client.describe_internet_gateways(InternetGatewayIds=[igw.id])[
"InternetGateways"
][0]
igw["Attachments"].should.have.length_of(0) igw["Attachments"].should.have.length_of(0)
@ -345,9 +349,8 @@ def test_igw_delete_boto3():
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
ec2.create_vpc(CidrBlock=VPC_CIDR) ec2.create_vpc(CidrBlock=VPC_CIDR)
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0)
igw = ec2.create_internet_gateway() igw = ec2.create_internet_gateway()
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(1) [i["InternetGatewayId"] for i in (retrieve_all(client))].should.contain(igw.id)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_internet_gateway(InternetGatewayId=igw.id, DryRun=True) client.delete_internet_gateway(InternetGatewayId=igw.id, DryRun=True)
@ -358,7 +361,7 @@ def test_igw_delete_boto3():
) )
client.delete_internet_gateway(InternetGatewayId=igw.id) client.delete_internet_gateway(InternetGatewayId=igw.id)
client.describe_internet_gateways()["InternetGateways"].should.have.length_of(0) [i["InternetGatewayId"] for i in (retrieve_all(client))].shouldnt.contain(igw.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -495,13 +498,12 @@ def test_igw_filter_by_tags_boto3():
igw1 = ec2.create_internet_gateway() igw1 = ec2.create_internet_gateway()
igw2 = ec2.create_internet_gateway() igw2 = ec2.create_internet_gateway()
igw1.create_tags(Tags=[{"Key": "tests", "Value": "yes"}]) tag_value = str(uuid4())
igw1.create_tags(Tags=[{"Key": "tests", "Value": tag_value}])
result = client.describe_internet_gateways( result = retrieve_all(client, [{"Name": "tag:tests", "Values": [tag_value]}])
Filters=[{"Name": "tag:tests", "Values": ["yes"]}] result.should.have.length_of(1)
) result[0]["InternetGatewayId"].should.equal(igw1.id)
result["InternetGateways"].should.have.length_of(1)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -561,11 +563,10 @@ def test_igw_filter_by_attachment_state_boto3():
vpc = ec2.create_vpc(CidrBlock=VPC_CIDR) vpc = ec2.create_vpc(CidrBlock=VPC_CIDR)
client.attach_internet_gateway(InternetGatewayId=igw1.id, VpcId=vpc.id) client.attach_internet_gateway(InternetGatewayId=igw1.id, VpcId=vpc.id)
result = client.describe_internet_gateways( filters = [{"Name": "attachment.state", "Values": ["available"]}]
Filters=[{"Name": "attachment.state", "Values": ["available"]}] all_ids = [igw["InternetGatewayId"] for igw in (retrieve_all(client, filters))]
) all_ids.should.contain(igw1.id)
result["InternetGateways"].should.have.length_of(1) all_ids.shouldnt.contain(igw2.id)
result["InternetGateways"][0]["InternetGatewayId"].should.equal(igw1.id)
@mock_ec2 @mock_ec2
@ -582,3 +583,14 @@ def test_create_internet_gateway_with_tags():
) )
igw.tags.should.have.length_of(1) igw.tags.should.have.length_of(1)
igw.tags.should.equal([{"Key": "test", "Value": "TestRouteTable"}]) igw.tags.should.equal([{"Key": "test", "Value": "TestRouteTable"}])
def retrieve_all(client, filters=[]):
resp = client.describe_internet_gateways(Filters=filters)
all_igws = resp["InternetGateways"]
token = resp.get("NextToken")
while token:
resp = client.describe_internet_gateways(NextToken=token, Filters=filters)
all_igws.extend(resp["InternetGateways"])
token = resp.get("NextToken")
return all_igws

View File

@ -8,7 +8,9 @@ import sure # noqa
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated, settings
from uuid import uuid4
from unittest import SkipTest
from .helpers import rsa_check_private_key from .helpers import rsa_check_private_key
@ -55,6 +57,8 @@ def test_key_pairs_empty():
@mock_ec2 @mock_ec2
def test_key_pairs_empty_boto3(): def test_key_pairs_empty_boto3():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.describe_key_pairs()["KeyPairs"].should.be.empty client.describe_key_pairs()["KeyPairs"].should.be.empty
@ -78,7 +82,7 @@ def test_key_pairs_invalid_id_boto3():
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.describe_key_pairs(KeyNames=["foo"]) client.describe_key_pairs(KeyNames=[str(uuid4())])
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.NotFound") ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.NotFound")
@ -145,21 +149,24 @@ def test_key_pairs_create_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
kp = ec2.create_key_pair(KeyName="foo") key_name = str(uuid4())[0:6]
kp = ec2.create_key_pair(KeyName=key_name)
rsa_check_private_key(kp.key_material) rsa_check_private_key(kp.key_material)
# Verify the client can create a key_pair as well - should behave the same # Verify the client can create a key_pair as well - should behave the same
kp2 = client.create_key_pair(KeyName="foo2") key_name2 = str(uuid4())
kp2 = client.create_key_pair(KeyName=key_name2)
rsa_check_private_key(kp2["KeyMaterial"]) rsa_check_private_key(kp2["KeyMaterial"])
kp.key_material.shouldnt.equal(kp2["KeyMaterial"]) kp.key_material.shouldnt.equal(kp2["KeyMaterial"])
kps = client.describe_key_pairs()["KeyPairs"] kps = client.describe_key_pairs()["KeyPairs"]
kps.should.have.length_of(2) all_names = set([k["KeyName"] for k in kps])
set([k["KeyName"] for k in kps]).should.equal(set(["foo", "foo2"])) all_names.should.contain(key_name)
all_names.should.contain(key_name2)
kps = client.describe_key_pairs(KeyNames=["foo"])["KeyPairs"] kps = client.describe_key_pairs(KeyNames=[key_name])["KeyPairs"]
kps.should.have.length_of(1) kps.should.have.length_of(1)
kps[0].should.have.key("KeyName").equal("foo") kps[0].should.have.key("KeyName").equal(key_name)
kps[0].should.have.key("KeyFingerprint") kps[0].should.have.key("KeyFingerprint")
@ -180,10 +187,11 @@ def test_key_pairs_create_exist():
@mock_ec2 @mock_ec2
def test_key_pairs_create_exist_boto3(): def test_key_pairs_create_exist_boto3():
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.create_key_pair(KeyName="foo") key_name = str(uuid4())[0:6]
client.create_key_pair(KeyName=key_name)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.create_key_pair(KeyName="foo") client.create_key_pair(KeyName=key_name)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate") ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate")
@ -201,8 +209,7 @@ def test_key_pairs_delete_no_exist():
@mock_ec2 @mock_ec2
def test_key_pairs_delete_no_exist_boto3(): def test_key_pairs_delete_no_exist_boto3():
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.describe_key_pairs()["KeyPairs"].should.have.length_of(0) client.delete_key_pair(KeyName=str(uuid4())[0:6])
client.delete_key_pair(KeyName="non-existing")
# Has boto3 equivalent # Has boto3 equivalent
@ -228,18 +235,21 @@ def test_key_pairs_delete_exist():
def test_key_pairs_delete_exist_boto3(): def test_key_pairs_delete_exist_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.create_key_pair(KeyName="foo") key_name = str(uuid4())[0:6]
client.create_key_pair(KeyName=key_name)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_key_pair(KeyName="foo", DryRun=True) client.delete_key_pair(KeyName=key_name, DryRun=True)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation") ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Message"].should.equal( ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set"
) )
client.delete_key_pair(KeyName="foo") client.delete_key_pair(KeyName=key_name)
client.describe_key_pairs()["KeyPairs"].should.equal([]) [kp.get("Name") for kp in client.describe_key_pairs()["KeyPairs"]].shouldnt.contain(
key_name
)
# Has boto3 equivalent # Has boto3 equivalent
@ -274,9 +284,10 @@ def test_key_pairs_import_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
key_name = str(uuid4())[0:6]
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.import_key_pair( client.import_key_pair(
KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH, DryRun=True KeyName=key_name, PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH, DryRun=True
) )
ex.value.response["Error"]["Code"].should.equal("DryRunOperation") ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
@ -285,22 +296,23 @@ def test_key_pairs_import_boto3():
) )
kp1 = client.import_key_pair( kp1 = client.import_key_pair(
KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH KeyName=key_name, PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH
) )
print(kp1)
kp1.should.have.key("KeyName").equal("foo") kp1.should.have.key("KeyName").equal(key_name)
kp1.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT) kp1.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT)
key_name2 = str(uuid4())
kp2 = client.import_key_pair( kp2 = client.import_key_pair(
KeyName="foo2", PublicKeyMaterial=RSA_PUBLIC_KEY_RFC4716 KeyName=key_name2, PublicKeyMaterial=RSA_PUBLIC_KEY_RFC4716
) )
kp2.should.have.key("KeyName").equal("foo2") kp2.should.have.key("KeyName").equal(key_name2)
kp2.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT) kp2.should.have.key("KeyFingerprint").equal(RSA_PUBLIC_KEY_FINGERPRINT)
kps = client.describe_key_pairs()["KeyPairs"] all_kps = client.describe_key_pairs()["KeyPairs"]
kps.should.have.length_of(2) all_names = [kp["KeyName"] for kp in all_kps]
kps[0]["KeyName"].should.equal(kp1["KeyName"]) all_names.should.contain(kp1["KeyName"])
kps[1]["KeyName"].should.equal(kp2["KeyName"]) all_names.should.contain(kp2["KeyName"])
# Has boto3 equivalent # Has boto3 equivalent
@ -323,12 +335,16 @@ def test_key_pairs_import_exist_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
kp = client.import_key_pair(KeyName="foo", PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH) key_name = str(uuid4())[0:6]
kp["KeyName"].should.equal("foo") kp = client.import_key_pair(
client.describe_key_pairs()["KeyPairs"].should.have.length_of(1) KeyName=key_name, PublicKeyMaterial=RSA_PUBLIC_KEY_OPENSSH
)
kp["KeyName"].should.equal(key_name)
client.describe_key_pairs(KeyNames=[key_name])["KeyPairs"].should.have.length_of(1)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.create_key_pair(KeyName="foo") client.create_key_pair(KeyName=key_name)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate") ex.value.response["Error"]["Code"].should.equal("InvalidKeyPair.Duplicate")
@ -406,12 +422,15 @@ def test_key_pair_filters_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
_ = ec2.create_key_pair(KeyName="kpfltr1") key_name_1 = str(uuid4())[0:6]
kp2 = ec2.create_key_pair(KeyName="kpfltr2") key_name_2 = str(uuid4())[0:6]
kp3 = ec2.create_key_pair(KeyName="kpfltr3") key_name_3 = str(uuid4())[0:6]
_ = ec2.create_key_pair(KeyName=key_name_1)
kp2 = ec2.create_key_pair(KeyName=key_name_2)
kp3 = ec2.create_key_pair(KeyName=key_name_3)
kp_by_name = client.describe_key_pairs( kp_by_name = client.describe_key_pairs(
Filters=[{"Name": "key-name", "Values": ["kpfltr2"]}] Filters=[{"Name": "key-name", "Values": [key_name_2]}]
)["KeyPairs"] )["KeyPairs"]
set([kp["KeyName"] for kp in kp_by_name]).should.equal(set([kp2.name])) set([kp["KeyName"] for kp in kp_by_name]).should.equal(set([kp2.name]))

View File

@ -4,15 +4,17 @@ import sure # noqa
import pytest import pytest
from botocore.client import ClientError from botocore.client import ClientError
from moto import mock_ec2 from moto import mock_ec2, settings
from uuid import uuid4
@mock_ec2 @mock_ec2
def test_launch_template_create(): def test_launch_template_create():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
resp = cli.create_launch_template( resp = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
# the absolute minimum needed to create a template without other resources # the absolute minimum needed to create a template without other resources
LaunchTemplateData={ LaunchTemplateData={
"TagSpecifications": [ "TagSpecifications": [
@ -26,13 +28,13 @@ def test_launch_template_create():
resp.should.have.key("LaunchTemplate") resp.should.have.key("LaunchTemplate")
lt = resp["LaunchTemplate"] lt = resp["LaunchTemplate"]
lt["LaunchTemplateName"].should.equal("test-template") lt["LaunchTemplateName"].should.equal(template_name)
lt["DefaultVersionNumber"].should.equal(1) lt["DefaultVersionNumber"].should.equal(1)
lt["LatestVersionNumber"].should.equal(1) lt["LatestVersionNumber"].should.equal(1)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={ LaunchTemplateData={
"TagSpecifications": [ "TagSpecifications": [
{ {
@ -61,13 +63,14 @@ def test_describe_launch_template_versions():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template( create_resp = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData=template_data LaunchTemplateName=template_name, LaunchTemplateData=template_data
) )
# test using name # test using name
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", Versions=["1"] LaunchTemplateName=template_name, Versions=["1"]
) )
templ = resp["LaunchTemplateVersions"][0]["LaunchTemplateData"] templ = resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]
@ -87,12 +90,13 @@ def test_describe_launch_template_versions():
def test_create_launch_template_version(): def test_create_launch_template_version():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template( create_resp = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
version_resp = cli.create_launch_template_version( version_resp = cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
@ -111,8 +115,9 @@ def test_create_launch_template_version():
def test_create_launch_template_version_by_id(): def test_create_launch_template_version_by_id():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
create_resp = cli.create_launch_template( create_resp = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
version_resp = cli.create_launch_template_version( version_resp = cli.create_launch_template_version(
@ -135,17 +140,18 @@ def test_create_launch_template_version_by_id():
def test_describe_launch_template_versions_with_multiple_versions(): def test_describe_launch_template_versions_with_multiple_versions():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
resp = cli.describe_launch_template_versions(LaunchTemplateName="test-template") resp = cli.describe_launch_template_versions(LaunchTemplateName=template_name)
resp["LaunchTemplateVersions"].should.have.length_of(2) resp["LaunchTemplateVersions"].should.have.length_of(2)
resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal( resp["LaunchTemplateVersions"][0]["LaunchTemplateData"]["ImageId"].should.equal(
@ -160,24 +166,25 @@ def test_describe_launch_template_versions_with_multiple_versions():
def test_describe_launch_template_versions_with_versions_option(): def test_describe_launch_template_versions_with_versions_option():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"}, LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again", VersionDescription="new ami, again",
) )
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", Versions=["2", "3"] LaunchTemplateName=template_name, Versions=["2", "3"]
) )
resp["LaunchTemplateVersions"].should.have.length_of(2) resp["LaunchTemplateVersions"].should.have.length_of(2)
@ -193,24 +200,25 @@ def test_describe_launch_template_versions_with_versions_option():
def test_describe_launch_template_versions_with_min(): def test_describe_launch_template_versions_with_min():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"}, LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again", VersionDescription="new ami, again",
) )
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", MinVersion="2" LaunchTemplateName=template_name, MinVersion="2"
) )
resp["LaunchTemplateVersions"].should.have.length_of(2) resp["LaunchTemplateVersions"].should.have.length_of(2)
@ -226,24 +234,25 @@ def test_describe_launch_template_versions_with_min():
def test_describe_launch_template_versions_with_max(): def test_describe_launch_template_versions_with_max():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"}, LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again", VersionDescription="new ami, again",
) )
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", MaxVersion="2" LaunchTemplateName=template_name, MaxVersion="2"
) )
resp["LaunchTemplateVersions"].should.have.length_of(2) resp["LaunchTemplateVersions"].should.have.length_of(2)
@ -259,30 +268,31 @@ def test_describe_launch_template_versions_with_max():
def test_describe_launch_template_versions_with_min_and_max(): def test_describe_launch_template_versions_with_min_and_max():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-def456"}, LaunchTemplateData={"ImageId": "ami-def456"},
VersionDescription="new ami", VersionDescription="new ami",
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-hij789"}, LaunchTemplateData={"ImageId": "ami-hij789"},
VersionDescription="new ami, again", VersionDescription="new ami, again",
) )
cli.create_launch_template_version( cli.create_launch_template_version(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-345abc"}, LaunchTemplateData={"ImageId": "ami-345abc"},
VersionDescription="new ami, because why not", VersionDescription="new ami, because why not",
) )
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", MinVersion="2", MaxVersion="3" LaunchTemplateName=template_name, MinVersion="2", MaxVersion="3"
) )
resp["LaunchTemplateVersions"].should.have.length_of(2) resp["LaunchTemplateVersions"].should.have.length_of(2)
@ -299,81 +309,89 @@ def test_describe_launch_templates():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
lt_ids = [] lt_ids = []
template_name = str(uuid4())
r = cli.create_launch_template( r = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"]) lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"])
template_name2 = str(uuid4())
r = cli.create_launch_template( r = cli.create_launch_template(
LaunchTemplateName="test-template2", LaunchTemplateName=template_name2, LaunchTemplateData={"ImageId": "ami-abc123"},
LaunchTemplateData={"ImageId": "ami-abc123"},
) )
lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"]) lt_ids.append(r["LaunchTemplate"]["LaunchTemplateId"])
# general call, all templates # general call, all templates
resp = cli.describe_launch_templates() if not settings.TEST_SERVER_MODE:
resp.should.have.key("LaunchTemplates") # Bug: Only 15 launch templates are returned, ever
resp["LaunchTemplates"].should.have.length_of(2) # ServerMode may have many more templates, created in parallel
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal("test-template") all_templates = retrieve_all_templates(cli)
resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal("test-template2") my_templates = [t for t in all_templates if t["LaunchTemplateId"] in lt_ids]
my_templates[0]["LaunchTemplateName"].should.equal(template_name)
my_templates[1]["LaunchTemplateName"].should.equal(template_name2)
# filter by names # filter by names
resp = cli.describe_launch_templates( resp = cli.describe_launch_templates(
LaunchTemplateNames=["test-template2", "test-template"] LaunchTemplateNames=[template_name2, template_name]
) )
resp.should.have.key("LaunchTemplates") resp.should.have.key("LaunchTemplates")
resp["LaunchTemplates"].should.have.length_of(2) resp["LaunchTemplates"].should.have.length_of(2)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal("test-template2") resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name2)
resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal("test-template") resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal(template_name)
# filter by ids # filter by ids
resp = cli.describe_launch_templates(LaunchTemplateIds=lt_ids) resp = cli.describe_launch_templates(LaunchTemplateIds=lt_ids)
resp.should.have.key("LaunchTemplates") resp.should.have.key("LaunchTemplates")
resp["LaunchTemplates"].should.have.length_of(2) resp["LaunchTemplates"].should.have.length_of(2)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal("test-template") resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name)
resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal("test-template2") resp["LaunchTemplates"][1]["LaunchTemplateName"].should.equal(template_name2)
@mock_ec2 @mock_ec2
def test_describe_launch_templates_with_filters(): def test_describe_launch_templates_with_filters():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
r = cli.create_launch_template( r = cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name, LaunchTemplateData={"ImageId": "ami-abc123"}
) )
tag_value = str(uuid4())
cli.create_tags( cli.create_tags(
Resources=[r["LaunchTemplate"]["LaunchTemplateId"]], Resources=[r["LaunchTemplate"]["LaunchTemplateId"]],
Tags=[ Tags=[
{"Key": "tag1", "Value": "a value"}, {"Key": "tag1", "Value": tag_value},
{"Key": "another-key", "Value": "this value"}, {"Key": "another-key", "Value": "this value"},
], ],
) )
template_name_no_tags = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="no-tags", LaunchTemplateData={"ImageId": "ami-abc123"} LaunchTemplateName=template_name_no_tags,
LaunchTemplateData={"ImageId": "ami-abc123"},
) )
resp = cli.describe_launch_templates( resp = cli.describe_launch_templates(
Filters=[{"Name": "tag:tag1", "Values": ["a value"]}] Filters=[{"Name": "tag:tag1", "Values": [tag_value]}]
) )
resp["LaunchTemplates"].should.have.length_of(1) resp["LaunchTemplates"].should.have.length_of(1)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal("test-template") resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name)
resp = cli.describe_launch_templates( resp = cli.describe_launch_templates(
Filters=[{"Name": "launch-template-name", "Values": ["no-tags"]}] Filters=[{"Name": "launch-template-name", "Values": [template_name_no_tags]}]
) )
resp["LaunchTemplates"].should.have.length_of(1) resp["LaunchTemplates"].should.have.length_of(1)
resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal("no-tags") resp["LaunchTemplates"][0]["LaunchTemplateName"].should.equal(template_name_no_tags)
@mock_ec2 @mock_ec2
def test_create_launch_template_with_tag_spec(): def test_create_launch_template_with_tag_spec():
cli = boto3.client("ec2", region_name="us-east-1") cli = boto3.client("ec2", region_name="us-east-1")
template_name = str(uuid4())
cli.create_launch_template( cli.create_launch_template(
LaunchTemplateName="test-template", LaunchTemplateName=template_name,
LaunchTemplateData={"ImageId": "ami-abc123"}, LaunchTemplateData={"ImageId": "ami-abc123"},
TagSpecifications=[ TagSpecifications=[
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]} {"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]}
@ -381,7 +399,7 @@ def test_create_launch_template_with_tag_spec():
) )
resp = cli.describe_launch_template_versions( resp = cli.describe_launch_template_versions(
LaunchTemplateName="test-template", Versions=["1"] LaunchTemplateName=template_name, Versions=["1"]
) )
version = resp["LaunchTemplateVersions"][0] version = resp["LaunchTemplateVersions"][0]
@ -390,3 +408,14 @@ def test_create_launch_template_with_tag_spec():
version["LaunchTemplateData"]["TagSpecifications"][0].should.equal( version["LaunchTemplateData"]["TagSpecifications"][0].should.equal(
{"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]} {"ResourceType": "instance", "Tags": [{"Key": "key", "Value": "value"}]}
) )
def retrieve_all_templates(client, filters=[]):
resp = client.describe_launch_templates(Filters=filters)
all_templates = resp["LaunchTemplates"]
next_token = resp.get("NextToken")
while next_token:
resp = client.describe_launch_templates(Filters=filters, NextToken=next_token)
all_templates.extend(resp["LaunchTemplates"])
next_token = resp.get("NextToken")
return all_templates

View File

@ -2,11 +2,14 @@ from __future__ import unicode_literals
import boto3 import boto3
import sure # noqa import sure # noqa
from moto import mock_ec2 from moto import mock_ec2, settings
from unittest import SkipTest
@mock_ec2 @mock_ec2
def test_describe_nat_gateways(): def test_describe_nat_gateways():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to have no resources")
conn = boto3.client("ec2", "us-east-1") conn = boto3.client("ec2", "us-east-1")
response = conn.describe_nat_gateways() response = conn.describe_nat_gateways()
@ -43,7 +46,7 @@ def test_describe_nat_gateway_tags():
allocation_id = conn.allocate_address(Domain="vpc")["AllocationId"] allocation_id = conn.allocate_address(Domain="vpc")["AllocationId"]
subnet_id = subnet["Subnet"]["SubnetId"] subnet_id = subnet["Subnet"]["SubnetId"]
conn.create_nat_gateway( gateway = conn.create_nat_gateway(
SubnetId=subnet_id, SubnetId=subnet_id,
AllocationId=allocation_id, AllocationId=allocation_id,
TagSpecifications=[ TagSpecifications=[
@ -55,12 +58,15 @@ def test_describe_nat_gateway_tags():
], ],
} }
], ],
) )["NatGateway"]
describe_response = conn.describe_nat_gateways() describe_all = retrieve_all_gateways(conn)
[gw["VpcId"] for gw in describe_all].should.contain(vpc_id)
describe_gateway = [gw for gw in describe_all if gw["VpcId"] == vpc_id]
assert describe_response["NatGateways"][0]["VpcId"] == vpc_id assert describe_gateway[0]["NatGatewayId"] == gateway["NatGatewayId"]
assert describe_response["NatGateways"][0]["Tags"] == [ assert describe_gateway[0]["VpcId"] == vpc_id
assert describe_gateway[0]["Tags"] == [
{"Key": "name", "Value": "some-nat-gateway"}, {"Key": "name", "Value": "some-nat-gateway"},
{"Key": "name1", "Value": "some-nat-gateway-1"}, {"Key": "name1", "Value": "some-nat-gateway-1"},
] ]
@ -112,31 +118,27 @@ def test_create_and_describe_nat_gateway():
SubnetId=subnet_id, AllocationId=allocation_id SubnetId=subnet_id, AllocationId=allocation_id
) )
nat_gateway_id = create_response["NatGateway"]["NatGatewayId"] nat_gateway_id = create_response["NatGateway"]["NatGatewayId"]
describe_response = conn.describe_nat_gateways() net_interface_id = create_response["NatGateway"]["NatGatewayAddresses"][0][
"NetworkInterfaceId"
]
enis = conn.describe_network_interfaces()["NetworkInterfaces"]
eni_id = enis[0]["NetworkInterfaceId"]
public_ip = conn.describe_addresses(AllocationIds=[allocation_id])["Addresses"][0][ public_ip = conn.describe_addresses(AllocationIds=[allocation_id])["Addresses"][0][
"PublicIp" "PublicIp"
] ]
describe_response["NatGateways"].should.have.length_of(1) describe = conn.describe_nat_gateways(NatGatewayIds=[nat_gateway_id])["NatGateways"]
describe_response["NatGateways"][0]["NatGatewayId"].should.equal(nat_gateway_id)
describe_response["NatGateways"][0]["State"].should.equal("available") describe.should.have.length_of(1)
describe_response["NatGateways"][0]["SubnetId"].should.equal(subnet_id) describe[0]["NatGatewayId"].should.equal(nat_gateway_id)
describe_response["NatGateways"][0]["VpcId"].should.equal(vpc_id) describe[0]["State"].should.equal("available")
describe_response["NatGateways"][0]["NatGatewayAddresses"][0][ describe[0]["SubnetId"].should.equal(subnet_id)
"AllocationId" describe[0]["VpcId"].should.equal(vpc_id)
].should.equal(allocation_id) describe[0]["NatGatewayAddresses"][0]["AllocationId"].should.equal(allocation_id)
describe_response["NatGateways"][0]["NatGatewayAddresses"][0][ describe[0]["NatGatewayAddresses"][0]["NetworkInterfaceId"].should.equal(
"NetworkInterfaceId" net_interface_id
].should.equal(eni_id) )
assert describe_response["NatGateways"][0]["NatGatewayAddresses"][0][ assert describe[0]["NatGatewayAddresses"][0]["PrivateIp"].startswith("10.")
"PrivateIp" describe[0]["NatGatewayAddresses"][0]["PublicIp"].should.equal(public_ip)
].startswith("10.")
describe_response["NatGateways"][0]["NatGatewayAddresses"][0][
"PublicIp"
].should.equal(public_ip)
@mock_ec2 @mock_ec2
@ -204,8 +206,9 @@ def test_describe_nat_gateway_filter_by_subnet_id():
nat_gateway_id_1 = create_response_1["NatGateway"]["NatGatewayId"] nat_gateway_id_1 = create_response_1["NatGateway"]["NatGatewayId"]
# nat_gateway_id_2 = create_response_2["NatGateway"]["NatGatewayId"] # nat_gateway_id_2 = create_response_2["NatGateway"]["NatGatewayId"]
describe_response = conn.describe_nat_gateways() all_gws = retrieve_all_gateways(conn)
describe_response["NatGateways"].should.have.length_of(2) all_gw_ids = [gw["NatGatewayId"] for gw in all_gws]
all_gw_ids.should.contain(nat_gateway_id_1)
describe_response = conn.describe_nat_gateways( describe_response = conn.describe_nat_gateways(
Filters=[{"Name": "subnet-id", "Values": [subnet_id_1]}] Filters=[{"Name": "subnet-id", "Values": [subnet_id_1]}]
@ -244,9 +247,6 @@ def test_describe_nat_gateway_filter_vpc_id():
conn.create_nat_gateway(SubnetId=subnet_id_2, AllocationId=allocation_id_2) conn.create_nat_gateway(SubnetId=subnet_id_2, AllocationId=allocation_id_2)
nat_gateway_id_1 = create_response_1["NatGateway"]["NatGatewayId"] nat_gateway_id_1 = create_response_1["NatGateway"]["NatGatewayId"]
describe_response = conn.describe_nat_gateways()
describe_response["NatGateways"].should.have.length_of(2)
describe_response = conn.describe_nat_gateways( describe_response = conn.describe_nat_gateways(
Filters=[{"Name": "vpc-id", "Values": [vpc_id_1]}] Filters=[{"Name": "vpc-id", "Values": [vpc_id_1]}]
) )
@ -258,3 +258,14 @@ def test_describe_nat_gateway_filter_vpc_id():
describe_response["NatGateways"][0]["NatGatewayAddresses"][0][ describe_response["NatGateways"][0]["NatGatewayAddresses"][0][
"AllocationId" "AllocationId"
].should.equal(allocation_id_1) ].should.equal(allocation_id_1)
def retrieve_all_gateways(client, filters=[]):
resp = client.describe_nat_gateways(Filters=filters)
all_gws = resp["NatGateways"]
token = resp.get("NextToken")
while token:
resp = client.describe_nat_gateways(Filters=filters, NextToken=token)
all_gws.extend(resp["NatGateways"])
token = resp.get("NextToken")
return all_gws

View File

@ -5,8 +5,10 @@ import sure # noqa
import pytest import pytest
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2, settings
from moto.ec2.models import OWNER_ID from moto.ec2.models import OWNER_ID
from random import randint
from unittest import SkipTest
# Has boto3 equivalent # Has boto3 equivalent
@ -22,10 +24,12 @@ def test_default_network_acl_created_with_vpc():
def test_default_network_acl_created_with_vpc_boto3(): def test_default_network_acl_created_with_vpc_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
all_network_acls = client.describe_network_acls()["NetworkAcls"] all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(2) our_acl = [a for a in all_network_acls if a["VpcId"] == vpc.id]
our_acl.should.have.length_of(1)
our_acl[0].should.have.key("IsDefault").equals(True)
# Has boto3 equivalent # Has boto3 equivalent
@ -46,7 +50,6 @@ def test_network_create_and_list_acls_boto3():
created_acl = ec2.create_network_acl(VpcId=vpc.id) created_acl = ec2.create_network_acl(VpcId=vpc.id)
all_network_acls = client.describe_network_acls()["NetworkAcls"] all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
acl_found = [ acl_found = [
a for a in all_network_acls if a["NetworkAclId"] == created_acl.network_acl_id a for a in all_network_acls if a["NetworkAclId"] == created_acl.network_acl_id
@ -73,6 +76,8 @@ def test_new_subnet_associates_with_default_network_acl():
@mock_ec2 @mock_ec2
def test_new_subnet_associates_with_default_network_acl_boto3(): def test_new_subnet_associates_with_default_network_acl_boto3():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode will have conflicting CidrBlocks")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
default_vpc = client.describe_vpcs()["Vpcs"][0] default_vpc = client.describe_vpcs()["Vpcs"][0]
@ -135,7 +140,6 @@ def test_network_acl_entries_boto3():
) )
all_network_acls = client.describe_network_acls()["NetworkAcls"] all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
test_network_acl = next( test_network_acl = next(
na for na in all_network_acls if na["NetworkAclId"] == network_acl.id na for na in all_network_acls if na["NetworkAclId"] == network_acl.id
@ -335,14 +339,12 @@ def test_delete_network_acl_boto3():
network_acl = ec2.create_network_acl(VpcId=vpc.id) network_acl = ec2.create_network_acl(VpcId=vpc.id)
all_network_acls = client.describe_network_acls()["NetworkAcls"] all_network_acls = client.describe_network_acls()["NetworkAcls"]
all_network_acls.should.have.length_of(3)
any(acl["NetworkAclId"] == network_acl.id for acl in all_network_acls).should.be.ok any(acl["NetworkAclId"] == network_acl.id for acl in all_network_acls).should.be.ok
client.delete_network_acl(NetworkAclId=network_acl.id) client.delete_network_acl(NetworkAclId=network_acl.id)
updated_network_acls = client.describe_network_acls()["NetworkAcls"] updated_network_acls = client.describe_network_acls()["NetworkAcls"]
updated_network_acls.should.have.length_of(2)
any( any(
acl["NetworkAclId"] == network_acl.id for acl in updated_network_acls acl["NetworkAclId"] == network_acl.id for acl in updated_network_acls
@ -377,7 +379,9 @@ def test_network_acl_tagging_boto3():
network_acl.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) network_acl.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0] tag = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [network_acl.id]}]
)["Tags"][0]
tag.should.have.key("ResourceId").equal(network_acl.id) tag.should.have.key("ResourceId").equal(network_acl.id)
tag.should.have.key("Key").equal("a key") tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value") tag.should.have.key("Value").equal("some value")
@ -408,12 +412,27 @@ def test_new_subnet_in_new_vpc_associates_with_default_network_acl():
@mock_ec2 @mock_ec2
def test_default_network_acl_default_entries(): def test_default_network_acl_default_entries():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
default_network_acl = next(iter(ec2.network_acls.all()), None) client = boto3.client("ec2", region_name="us-west-1")
default_network_acl.is_default.should.be.ok
if not settings.TEST_SERVER_MODE:
# Can't know whether the first ACL is the default in ServerMode
default_network_acl = next(iter(ec2.network_acls.all()), None)
default_network_acl.is_default.should.be.ok
default_network_acl.entries.should.have.length_of(4)
vpc = client.create_vpc(CidrBlock="10.0.0.0/16")
vpc_id = vpc["Vpc"]["VpcId"]
default_acls = client.describe_network_acls(
Filters=[
{"Name": "default", "Values": ["true"]},
{"Name": "vpc-id", "Values": [vpc_id]},
]
)["NetworkAcls"]
default_acl = default_acls[0]
default_network_acl.entries.should.have.length_of(4)
unique_entries = [] unique_entries = []
for entry in default_network_acl.entries: for entry in default_acl["Entries"]:
entry["CidrBlock"].should.equal("0.0.0.0/0") entry["CidrBlock"].should.equal("0.0.0.0/0")
entry["Protocol"].should.equal("-1") entry["Protocol"].should.equal("-1")
entry["RuleNumber"].should.be.within([100, 32767]) entry["RuleNumber"].should.be.within([100, 32767])
@ -431,6 +450,10 @@ def test_default_network_acl_default_entries():
@mock_ec2 @mock_ec2
def test_delete_default_network_acl_default_entry(): def test_delete_default_network_acl_default_entry():
if settings.TEST_SERVER_MODE:
raise SkipTest(
"Don't want to mess with default ACLs in ServerMode, as other tests may need them"
)
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
default_network_acl = next(iter(ec2.network_acls.all()), None) default_network_acl = next(iter(ec2.network_acls.all()), None)
default_network_acl.is_default.should.be.ok default_network_acl.is_default.should.be.ok
@ -452,7 +475,7 @@ def test_duplicate_network_acl_entry():
default_network_acl = next(iter(ec2.network_acls.all()), None) default_network_acl = next(iter(ec2.network_acls.all()), None)
default_network_acl.is_default.should.be.ok default_network_acl.is_default.should.be.ok
rule_number = 200 rule_number = randint(0, 9999)
egress = True egress = True
default_network_acl.create_entry( default_network_acl.create_entry(
CidrBlock="0.0.0.0/0", CidrBlock="0.0.0.0/0",
@ -496,12 +519,12 @@ def test_describe_network_acls():
result[0]["NetworkAclId"].should.equal(network_acl_id) result[0]["NetworkAclId"].should.equal(network_acl_id)
resp2 = conn.describe_network_acls()["NetworkAcls"] resp2 = conn.describe_network_acls()["NetworkAcls"]
resp2.should.have.length_of(3) [na["NetworkAclId"] for na in resp2].should.contain(network_acl_id)
resp3 = conn.describe_network_acls( resp3 = conn.describe_network_acls(
Filters=[{"Name": "owner-id", "Values": [OWNER_ID]}] Filters=[{"Name": "owner-id", "Values": [OWNER_ID]}]
)["NetworkAcls"] )["NetworkAcls"]
resp3.should.have.length_of(3) [na["NetworkAclId"] for na in resp3].should.contain(network_acl_id)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
conn.describe_network_acls(NetworkAclIds=["1"]) conn.describe_network_acls(NetworkAclIds=["1"])

View File

@ -1,7 +1,7 @@
import boto3 import boto3
import sure # noqa import sure # noqa
from moto import mock_ec2 from moto import mock_ec2, settings
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
@ -47,15 +47,13 @@ def test_create_with_tags():
def test_describe_managed_prefix_lists(): def test_describe_managed_prefix_lists():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
default_lists = ec2.describe_managed_prefix_lists()["PrefixLists"] prefix_list = ec2.create_managed_prefix_list(
set([l["OwnerId"] for l in default_lists]).should.equal({"aws"})
ec2.create_managed_prefix_list(
PrefixListName="examplelist", MaxEntries=2, AddressFamily="?" PrefixListName="examplelist", MaxEntries=2, AddressFamily="?"
) )
pl_id = prefix_list["PrefixList"]["PrefixListId"]
all_lists = ec2.describe_managed_prefix_lists()["PrefixLists"] all_lists = ec2.describe_managed_prefix_lists()["PrefixLists"]
all_lists.should.have.length_of(len(default_lists) + 1) [pl["PrefixListId"] for pl in all_lists].should.contain(pl_id)
set([l["OwnerId"] for l in all_lists]).should.equal({"aws", ACCOUNT_ID}) set([l["OwnerId"] for l in all_lists]).should.equal({"aws", ACCOUNT_ID})
@ -64,7 +62,9 @@ def test_describe_managed_prefix_lists_with_prefix():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
default_lists = ec2.describe_managed_prefix_lists()["PrefixLists"] default_lists = ec2.describe_managed_prefix_lists()["PrefixLists"]
set([l["OwnerId"] for l in default_lists]).should.equal({"aws"}) if not settings.TEST_SERVER_MODE:
# ServerMode is not guaranteed to only have AWS prefix lists
set([l["OwnerId"] for l in default_lists]).should.equal({"aws"})
random_list_id = default_lists[0]["PrefixListId"] random_list_id = default_lists[0]["PrefixListId"]
@ -72,7 +72,8 @@ def test_describe_managed_prefix_lists_with_prefix():
"PrefixLists" "PrefixLists"
] ]
lists_by_id.should.have.length_of(1) lists_by_id.should.have.length_of(1)
lists_by_id[0]["OwnerId"].should.equal("aws") if not settings.TEST_SERVER_MODE:
lists_by_id[0]["OwnerId"].should.equal("aws")
@mock_ec2 @mock_ec2

View File

@ -11,6 +11,8 @@ from moto import mock_autoscaling, mock_ec2, mock_elb
from moto.ec2 import ec2_backends from moto.ec2 import ec2_backends
from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2 from tests import EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2
from uuid import uuid4
from .test_instances import retrieve_all_instances
def test_use_boto_regions(): def test_use_boto_regions():
@ -34,7 +36,7 @@ def add_servers_to_region(ami_id, count, region):
def add_servers_to_region_boto3(ami_id, count, region): def add_servers_to_region_boto3(ami_id, count, region):
ec2 = boto3.resource("ec2", region_name=region) ec2 = boto3.resource("ec2", region_name=region)
ec2.create_instances(ImageId=ami_id, MinCount=count, MaxCount=count) return ec2.create_instances(ImageId=ami_id, MinCount=count, MaxCount=count)
# Has boto3 equivalent # Has boto3 equivalent
@ -55,15 +57,16 @@ def test_add_servers_to_a_single_region():
@mock_ec2 @mock_ec2
def test_add_servers_to_a_single_region_boto3(): def test_add_servers_to_a_single_region_boto3():
region = "ap-northeast-1" region = "ap-northeast-1"
add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region) id_1 = add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region)[0].id
add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region) id_2 = add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region)[0].id
client = boto3.client("ec2", region_name=region) client = boto3.client("ec2", region_name=region)
reservations = client.describe_instances()["Reservations"] instances = retrieve_all_instances(client)
reservations.should.have.length_of(2)
image_ids = [r["Instances"][0]["ImageId"] for r in reservations] instance1 = [i for i in instances if i["InstanceId"] == id_1][0]
image_ids.should.equal([EXAMPLE_AMI_ID, EXAMPLE_AMI_ID2]) instance1["ImageId"].should.equal(EXAMPLE_AMI_ID)
instance2 = [i for i in instances if i["InstanceId"] == id_2][0]
instance2["ImageId"].should.equal(EXAMPLE_AMI_ID2)
# Has boto3 equivalent # Has boto3 equivalent
@ -90,19 +93,27 @@ def test_add_servers_to_multiple_regions():
def test_add_servers_to_multiple_regions_boto3(): def test_add_servers_to_multiple_regions_boto3():
region1 = "us-east-1" region1 = "us-east-1"
region2 = "ap-northeast-1" region2 = "ap-northeast-1"
add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region1) us_id = add_servers_to_region_boto3(EXAMPLE_AMI_ID, 1, region1)[0].id
add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region2) ap_id = add_servers_to_region_boto3(EXAMPLE_AMI_ID2, 1, region2)[0].id
us_client = boto3.client("ec2", region_name=region1) us_client = boto3.client("ec2", region_name=region1)
ap_client = boto3.client("ec2", region_name=region2) ap_client = boto3.client("ec2", region_name=region2)
us_reservations = us_client.describe_instances()["Reservations"] us_instances = retrieve_all_instances(us_client)
ap_reservations = ap_client.describe_instances()["Reservations"] ap_instances = retrieve_all_instances(ap_client)
us_reservations.should.have.length_of(1) [r["InstanceId"] for r in us_instances].should.contain(us_id)
ap_reservations.should.have.length_of(1) [r["InstanceId"] for r in us_instances].shouldnt.contain(ap_id)
[r["InstanceId"] for r in ap_instances].should.contain(ap_id)
[r["InstanceId"] for r in ap_instances].shouldnt.contain(us_id)
us_reservations[0]["Instances"][0]["ImageId"].should.equal(EXAMPLE_AMI_ID) us_instance = us_client.describe_instances(InstanceIds=[us_id])["Reservations"][0][
ap_reservations[0]["Instances"][0]["ImageId"].should.equal(EXAMPLE_AMI_ID2) "Instances"
][0]
us_instance["ImageId"].should.equal(EXAMPLE_AMI_ID)
ap_instance = ap_client.describe_instances(InstanceIds=[ap_id])["Reservations"][0][
"Instances"
][0]
ap_instance["ImageId"].should.equal(EXAMPLE_AMI_ID2)
# Has boto3 equivalent # Has boto3 equivalent
@ -213,9 +224,9 @@ def test_create_autoscaling_group_boto3():
regions = [("us-east-1", "c"), ("ap-northeast-1", "a")] regions = [("us-east-1", "c"), ("ap-northeast-1", "a")]
for region, zone in regions: for region, zone in regions:
a_zone = "{}{}".format(region, zone) a_zone = "{}{}".format(region, zone)
asg_name = "{}_tester_group".format(region) asg_name = "{}_tester_group_{}".format(region, str(uuid4())[0:6])
lb_name = "{}_lb".format(region) lb_name = "{}_lb_{}".format(region, str(uuid4())[0:6])
config_name = "{}_tester".format(region) config_name = "{}_tester_{}".format(region, str(uuid4())[0:6])
elb_client = boto3.client("elb", region_name=region) elb_client = boto3.client("elb", region_name=region)
elb_client.create_load_balancer( elb_client.create_load_balancer(
@ -254,7 +265,9 @@ def test_create_autoscaling_group_boto3():
TerminationPolicies=["OldestInstance", "NewestInstance"], TerminationPolicies=["OldestInstance", "NewestInstance"],
) )
groups = as_client.describe_auto_scaling_groups()["AutoScalingGroups"] groups = as_client.describe_auto_scaling_groups(
AutoScalingGroupNames=[asg_name]
)["AutoScalingGroups"]
groups.should.have.length_of(1) groups.should.have.length_of(1)
group = groups[0] group = groups[0]

View File

@ -11,6 +11,7 @@ import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated, settings from moto import mock_ec2, mock_ec2_deprecated, settings
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
from uuid import uuid4
# Has boto3 equivalent # Has boto3 equivalent
@ -212,13 +213,14 @@ def test_route_tables_filters_standard_boto3():
route_table2 = ec2.create_route_table(VpcId=vpc2.id) route_table2 = ec2.create_route_table(VpcId=vpc2.id)
all_route_tables = client.describe_route_tables()["RouteTables"] all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(5) all_ids = [rt["RouteTableId"] for rt in all_route_tables]
all_ids.should.contain(route_table1.id)
all_ids.should.contain(route_table2.id)
# Filter by main route table # Filter by main route table
main_route_tables = client.describe_route_tables( main_route_tables = client.describe_route_tables(
Filters=[{"Name": "association.main", "Values": ["true"]}] Filters=[{"Name": "association.main", "Values": ["true"]}]
)["RouteTables"] )["RouteTables"]
main_route_tables.should.have.length_of(3)
main_route_table_ids = [ main_route_table_ids = [
route_table["RouteTableId"] for route_table in main_route_tables route_table["RouteTableId"] for route_table in main_route_tables
] ]
@ -321,9 +323,6 @@ def test_route_tables_filters_associations_boto3():
client.associate_route_table(RouteTableId=route_table1.id, SubnetId=subnet2.id) client.associate_route_table(RouteTableId=route_table1.id, SubnetId=subnet2.id)
client.associate_route_table(RouteTableId=route_table2.id, SubnetId=subnet3.id) client.associate_route_table(RouteTableId=route_table2.id, SubnetId=subnet3.id)
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(4)
# Filter by association ID # Filter by association ID
association1_route_tables = client.describe_route_tables( association1_route_tables = client.describe_route_tables(
Filters=[ Filters=[
@ -430,9 +429,6 @@ def test_route_table_associations_boto3():
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
route_table = ec2.create_route_table(VpcId=vpc.id) route_table = ec2.create_route_table(VpcId=vpc.id)
all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(3)
# Refresh # Refresh
r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0] r = client.describe_route_tables(RouteTableIds=[route_table.id])["RouteTables"][0]
r["Associations"].should.have.length_of(0) r["Associations"].should.have.length_of(0)
@ -584,7 +580,9 @@ def test_route_table_replace_route_table_association_boto3():
route_table2_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"] all_route_tables = client.describe_route_tables()["RouteTables"]
all_route_tables.should.have.length_of(4) all_ids = [rt["RouteTableId"] for rt in all_route_tables]
all_ids.should.contain(route_table1_id)
all_ids.should.contain(route_table2_id)
# Refresh # Refresh
route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[ route_table1 = client.describe_route_tables(RouteTableIds=[route_table1_id])[
@ -691,16 +689,17 @@ def test_route_table_get_by_tag_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
route_table = ec2.create_route_table(VpcId=vpc.id) route_table = ec2.create_route_table(VpcId=vpc.id)
route_table.create_tags(Tags=[{"Key": "Name", "Value": "TestRouteTable"}]) tag_value = str(uuid4())
route_table.create_tags(Tags=[{"Key": "Name", "Value": tag_value}])
filters = [{"Name": "tag:Name", "Values": ["TestRouteTable"]}] filters = [{"Name": "tag:Name", "Values": [tag_value]}]
route_tables = list(ec2.route_tables.filter(Filters=filters)) route_tables = list(ec2.route_tables.filter(Filters=filters))
route_tables.should.have.length_of(1) route_tables.should.have.length_of(1)
route_tables[0].vpc_id.should.equal(vpc.id) route_tables[0].vpc_id.should.equal(vpc.id)
route_tables[0].id.should.equal(route_table.id) route_tables[0].id.should.equal(route_table.id)
route_tables[0].tags.should.have.length_of(1) route_tables[0].tags.should.have.length_of(1)
route_tables[0].tags[0].should.equal({"Key": "Name", "Value": "TestRouteTable"}) route_tables[0].tags[0].should.equal({"Key": "Name", "Value": tag_value})
# Has boto3 equivalent # Has boto3 equivalent
@ -1163,7 +1162,9 @@ def test_network_acl_tagging_boto3():
route_table = ec2.create_route_table(VpcId=vpc.id) route_table = ec2.create_route_table(VpcId=vpc.id)
route_table.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) route_table.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0] tag = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [route_table.id]}]
)["Tags"][0]
tag.should.have.key("ResourceType").equal("route-table") tag.should.have.key("ResourceType").equal("route-table")
tag.should.have.key("Key").equal("a key") tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value") tag.should.have.key("Value").equal("some value")

View File

@ -8,12 +8,16 @@ import pytest
import boto3 import boto3
import boto import boto
import boto.ec2
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated, settings from moto import mock_ec2, mock_ec2_deprecated, settings
from moto.ec2 import ec2_backend from moto.ec2 import ec2_backend
from random import randint
from uuid import uuid4
from unittest import SkipTest
# Has boto3 equivalent # Has boto3 equivalent
@ -67,25 +71,25 @@ def test_create_and_describe_security_group_boto3():
"An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set"
) )
security_group = ec2.create_security_group( sec_name = str(uuid4())
GroupName="test security group", Description="test" security_group = ec2.create_security_group(GroupName=sec_name, Description="test")
)
security_group.group_name.should.equal("test security group") security_group.group_name.should.equal(sec_name)
security_group.description.should.equal("test") security_group.description.should.equal("test")
# Trying to create another group with the same name should throw an error # Trying to create another group with the same name should throw an error
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.create_security_group(GroupName="test security group", Description="n/a") client.create_security_group(GroupName=sec_name, Description="n/a")
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate") ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate")
all_groups = client.describe_security_groups()["SecurityGroups"] all_groups = retrieve_all_sgs(client)
# The default group gets created automatically # The default group gets created automatically
all_groups.should.have.length_of(2) [g["GroupId"] for g in all_groups].should.contain(security_group.id)
group_names = [group["GroupName"] for group in all_groups] group_names = set([group["GroupName"] for group in all_groups])
set(group_names).should.equal(set(["default", "test security group"])) group_names.should.contain("default")
group_names.should.contain(sec_name)
# Has boto3 equivalent # Has boto3 equivalent
@ -123,9 +127,8 @@ def test_default_security_group():
@mock_ec2 @mock_ec2
def test_default_security_group_boto3(): def test_default_security_group_boto3():
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
groups = client.describe_security_groups()["SecurityGroups"] groups = retrieve_all_sgs(client)
groups.should.have.length_of(1) [g["GroupName"] for g in groups].should.contain("default")
groups[0]["GroupName"].should.equal("default")
# Has boto3 equivalent # Has boto3 equivalent
@ -165,16 +168,16 @@ def test_create_and_describe_vpc_security_group_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
name = "test secgr" name = str(uuid4())
vpc_id = "vpc-5300000c" vpc_id = f"vpc-{str(uuid4())[0:6]}"
security_group = ec2.create_security_group( group_with = ec2.create_security_group(
GroupName=name, Description="test", VpcId=vpc_id GroupName=name, Description="test", VpcId=vpc_id
) )
security_group.vpc_id.should.equal(vpc_id) group_with.vpc_id.should.equal(vpc_id)
security_group.group_name.should.equal(name) group_with.group_name.should.equal(name)
security_group.description.should.equal("test") group_with.description.should.equal("test")
# Trying to create another group with the same name in the same VPC should # Trying to create another group with the same name in the same VPC should
# throw an error # throw an error
@ -185,10 +188,13 @@ def test_create_and_describe_vpc_security_group_boto3():
ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate") ex.value.response["Error"]["Code"].should.equal("InvalidGroup.Duplicate")
# Trying to create another group in the same name without VPC should pass # Trying to create another group in the same name without VPC should pass
ec2.create_security_group(GroupName=name, Description="non-vpc-group") group_without = ec2.create_security_group(
GroupName=name, Description="non-vpc-group"
)
all_groups = client.describe_security_groups()["SecurityGroups"] all_groups = retrieve_all_sgs(client)
all_groups.should.have.length_of(3) # 1 default, 1 vpc, 1 no-vpc [a["GroupId"] for a in all_groups].should.contain(group_with.id)
[a["GroupId"] for a in all_groups].should.contain(group_without.id)
all_groups = client.describe_security_groups( all_groups = client.describe_security_groups(
Filters=[{"Name": "vpc-id", "Values": [vpc_id]}] Filters=[{"Name": "vpc-id", "Values": [vpc_id]}]
@ -226,19 +232,20 @@ def test_create_two_security_groups_with_same_name_in_different_vpc_boto3():
ec2 = boto3.resource("ec2", "us-east-1") ec2 = boto3.resource("ec2", "us-east-1")
client = boto3.client("ec2", "us-east-1") client = boto3.client("ec2", "us-east-1")
name = "test security group" name = str(uuid4())
vpc_id = "vpc-5300000c" vpc_id = "vpc-5300000c"
vpc_id2 = "vpc-5300000d" vpc_id2 = "vpc-5300000d"
ec2.create_security_group(GroupName=name, Description="n/a 1", VpcId=vpc_id) sg1 = ec2.create_security_group(GroupName=name, Description="n/a 1", VpcId=vpc_id)
ec2.create_security_group(GroupName=name, Description="n/a 2", VpcId=vpc_id2) sg2 = ec2.create_security_group(GroupName=name, Description="n/a 2", VpcId=vpc_id2)
all_groups = client.describe_security_groups()["SecurityGroups"] all_groups = retrieve_all_sgs(client)
group_ids = [group["GroupId"] for group in all_groups]
group_ids.should.contain(sg1.id)
group_ids.should.contain(sg2.id)
all_groups.should.have.length_of(3)
group_names = [group["GroupName"] for group in all_groups] group_names = [group["GroupName"] for group in all_groups]
# The default group is created automatically group_names.should.contain(name)
set(group_names).should.equal(set(["default", name]))
@mock_ec2 @mock_ec2
@ -247,7 +254,7 @@ def test_create_two_security_groups_in_vpc_with_ipv6_enabled():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16", AmazonProvidedIpv6CidrBlock=True) vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16", AmazonProvidedIpv6CidrBlock=True)
security_group = ec2.create_security_group( security_group = ec2.create_security_group(
GroupName="sg01", Description="Test security group sg01", VpcId=vpc.id GroupName=str(uuid4()), Description="Test security group sg01", VpcId=vpc.id
) )
# The security group must have two defaul egress rules (one for ipv4 and aonther for ipv6) # The security group must have two defaul egress rules (one for ipv4 and aonther for ipv6)
@ -291,10 +298,14 @@ def test_deleting_security_groups():
def test_deleting_security_groups_boto3(): def test_deleting_security_groups_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
security_group1 = ec2.create_security_group(GroupName="test1", Description="test1") sg_name1 = str(uuid4())
ec2.create_security_group(GroupName="test2", Description="test2") sg_name2 = str(uuid4())
group1 = ec2.create_security_group(GroupName=sg_name1, Description="test desc 1")
group2 = ec2.create_security_group(GroupName=sg_name2, Description="test desc 2")
client.describe_security_groups()["SecurityGroups"].should.have.length_of(3) all_groups = retrieve_all_sgs(client)
[g["GroupId"] for g in all_groups].should.contain(group1.id)
[g["GroupId"] for g in all_groups].should.contain(group2.id)
# Deleting a group that doesn't exist should throw an error # Deleting a group that doesn't exist should throw an error
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
@ -305,19 +316,24 @@ def test_deleting_security_groups_boto3():
# Delete by name # Delete by name
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_security_group(GroupName="test2", DryRun=True) client.delete_security_group(GroupName=sg_name2, DryRun=True)
ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412) ex.value.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(412)
ex.value.response["Error"]["Code"].should.equal("DryRunOperation") ex.value.response["Error"]["Code"].should.equal("DryRunOperation")
ex.value.response["Error"]["Message"].should.equal( ex.value.response["Error"]["Message"].should.equal(
"An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set"
) )
client.delete_security_group(GroupName="test2") client.delete_security_group(GroupName=sg_name2)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(2)
all_groups = retrieve_all_sgs(client)
[g["GroupId"] for g in all_groups].should.contain(group1.id)
[g["GroupId"] for g in all_groups].shouldnt.contain(group2.id)
# Delete by group id # Delete by group id
client.delete_security_group(GroupId=security_group1.id) client.delete_security_group(GroupId=group1.id)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1)
all_groups = retrieve_all_sgs(client)
[g["GroupId"] for g in all_groups].shouldnt.contain(group1.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -336,18 +352,18 @@ def test_delete_security_group_in_vpc_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1)
group = ec2.create_security_group( group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId="vpc-12345" GroupName=str(uuid4()), Description="test1", VpcId="vpc-12345"
) )
client.describe_security_groups()["SecurityGroups"].should.have.length_of(2) all_groups = retrieve_all_sgs(client)
[g["GroupId"] for g in all_groups].should.contain(group.id)
# this should not throw an exception # this should not throw an exception
client.delete_security_group(GroupId=group.id) client.delete_security_group(GroupId=group.id)
client.describe_security_groups()["SecurityGroups"].should.have.length_of(1) all_groups = retrieve_all_sgs(client)
[g["GroupId"] for g in all_groups].shouldnt.contain(group.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -492,7 +508,9 @@ def test_authorize_ip_range_and_revoke():
def test_authorize_ip_range_and_revoke_boto3(): def test_authorize_ip_range_and_revoke_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
security_group = ec2.create_security_group(GroupName="test", Description="test") security_group = ec2.create_security_group(
GroupName=str(uuid4()), Description="test"
)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
security_group.authorize_ingress( security_group.authorize_ingress(
@ -550,7 +568,7 @@ def test_authorize_ip_range_and_revoke_boto3():
# Test for egress as well # Test for egress as well
egress_security_group = ec2.create_security_group( egress_security_group = ec2.create_security_group(
GroupName="testegress", Description="testegress", VpcId="vpc-3432589" GroupName=str(uuid4()), Description="desc", VpcId="vpc-3432589"
) )
egress_permissions = [ egress_permissions = [
{ {
@ -656,11 +674,14 @@ def test_authorize_other_group_and_revoke():
def test_authorize_other_group_and_revoke_boto3(): def test_authorize_other_group_and_revoke_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
security_group = ec2.create_security_group(GroupName="test", Description="test") sg_name = str(uuid4())
other_security_group = ec2.create_security_group( security_group = ec2.create_security_group(
GroupName="other", Description="other" GroupName=sg_name, Description="test desc"
) )
ec2.create_security_group(GroupName="wrong", Description="wrong") other_security_group = ec2.create_security_group(
GroupName=str(uuid4()), Description="other"
)
ec2.create_security_group(GroupName=str(uuid4()), Description="wrong")
# Note: Should be easier to use the SourceSecurityGroupNames-parameter, but that's not supported atm # Note: Should be easier to use the SourceSecurityGroupNames-parameter, but that's not supported atm
permissions = [ permissions = [
@ -679,7 +700,7 @@ def test_authorize_other_group_and_revoke_boto3():
] ]
security_group.authorize_ingress(IpPermissions=permissions) security_group.authorize_ingress(IpPermissions=permissions)
found_sec_group = client.describe_security_groups(GroupNames=["test"])[ found_sec_group = client.describe_security_groups(GroupNames=[sg_name])[
"SecurityGroups" "SecurityGroups"
][0] ][0]
found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222) found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222)
@ -699,7 +720,7 @@ def test_authorize_other_group_and_revoke_boto3():
# Actually revoke # Actually revoke
security_group.revoke_ingress(IpPermissions=permissions) security_group.revoke_ingress(IpPermissions=permissions)
found_sec_group = client.describe_security_groups(GroupNames=["test"])[ found_sec_group = client.describe_security_groups(GroupNames=[sg_name])[
"SecurityGroups" "SecurityGroups"
][0] ][0]
found_sec_group["IpPermissions"].should.have.length_of(0) found_sec_group["IpPermissions"].should.have.length_of(0)
@ -712,10 +733,10 @@ def test_authorize_other_group_egress_and_revoke():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg01 = ec2.create_security_group( sg01 = ec2.create_security_group(
GroupName="sg01", Description="Test security group sg01", VpcId=vpc.id GroupName=str(uuid4()), Description="Test security group sg01", VpcId=vpc.id
) )
sg02 = ec2.create_security_group( sg02 = ec2.create_security_group(
GroupName="sg02", Description="Test security group sg02", VpcId=vpc.id GroupName=str(uuid4()), Description="Test security group sg02", VpcId=vpc.id
) )
ip_permission = { ip_permission = {
@ -788,11 +809,13 @@ def test_authorize_group_in_vpc_boto3():
vpc_id = "vpc-12345" vpc_id = "vpc-12345"
# create 2 groups in a vpc # create 2 groups in a vpc
sec_name1 = str(uuid4())
sec_name2 = str(uuid4())
security_group = ec2.create_security_group( security_group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId=vpc_id GroupName=sec_name1, Description="test desc 1", VpcId=vpc_id
) )
other_security_group = ec2.create_security_group( other_security_group = ec2.create_security_group(
GroupName="test2", Description="test2", VpcId=vpc_id GroupName=sec_name2, Description="test desc 2", VpcId=vpc_id
) )
permissions = [ permissions = [
@ -812,7 +835,7 @@ def test_authorize_group_in_vpc_boto3():
security_group.authorize_ingress(IpPermissions=permissions) security_group.authorize_ingress(IpPermissions=permissions)
# Check that the rule is accurate # Check that the rule is accurate
found_sec_group = client.describe_security_groups(GroupNames=["test1"])[ found_sec_group = client.describe_security_groups(GroupNames=[sec_name1])[
"SecurityGroups" "SecurityGroups"
][0] ][0]
found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222) found_sec_group["IpPermissions"][0]["ToPort"].should.equal(2222)
@ -824,7 +847,7 @@ def test_authorize_group_in_vpc_boto3():
security_group.revoke_ingress(IpPermissions=permissions) security_group.revoke_ingress(IpPermissions=permissions)
# And check that it gets revoked # And check that it gets revoked
found_sec_group = client.describe_security_groups(GroupNames=["test1"])[ found_sec_group = client.describe_security_groups(GroupNames=[sec_name1])[
"SecurityGroups" "SecurityGroups"
][0] ][0]
found_sec_group["IpPermissions"].should.have.length_of(0) found_sec_group["IpPermissions"].should.have.length_of(0)
@ -872,13 +895,13 @@ def test_get_all_security_groups():
def test_describe_security_groups(): def test_describe_security_groups():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
client = boto3.client("ec2", "us-west-1") client = boto3.client("ec2", "us-west-1")
vpc_id = "vpc-mjm05d27" vpc_id = f"vpc-{str(uuid4())[0:6]}"
sg1 = ec2.create_security_group( name_1 = str(uuid4())
GroupName="test1", Description="test1", VpcId=vpc_id desc_1 = str(uuid4())
) sg1 = ec2.create_security_group(GroupName=name_1, Description=desc_1, VpcId=vpc_id)
ec2.create_security_group(GroupName="test2", Description="test2") sg2 = ec2.create_security_group(GroupName=str(uuid4()), Description="test desc 2")
resp = client.describe_security_groups(GroupNames=["test1"])["SecurityGroups"] resp = client.describe_security_groups(GroupNames=[name_1])["SecurityGroups"]
resp.should.have.length_of(1) resp.should.have.length_of(1)
resp[0].should.have.key("GroupId").equal(sg1.id) resp[0].should.have.key("GroupId").equal(sg1.id)
@ -895,13 +918,15 @@ def test_describe_security_groups():
resp[0].should.have.key("GroupId").equal(sg1.id) resp[0].should.have.key("GroupId").equal(sg1.id)
resp = client.describe_security_groups( resp = client.describe_security_groups(
Filters=[{"Name": "description", "Values": ["test1"]}] Filters=[{"Name": "description", "Values": [desc_1]}]
)["SecurityGroups"] )["SecurityGroups"]
resp.should.have.length_of(1) resp.should.have.length_of(1)
resp[0].should.have.key("GroupId").equal(sg1.id) resp[0].should.have.key("GroupId").equal(sg1.id)
resp = client.describe_security_groups()["SecurityGroups"] all_sgs = retrieve_all_sgs(client)
resp.should.have.length_of(3) sg_ids = [sg["GroupId"] for sg in all_sgs]
sg_ids.should.contain(sg1.id)
sg_ids.should.contain(sg2.id)
# Has boto3 equivalent # Has boto3 equivalent
@ -921,7 +946,7 @@ def test_authorize_bad_cidr_throws_invalid_parameter_value():
@mock_ec2 @mock_ec2
def test_authorize_bad_cidr_throws_invalid_parameter_value_boto3(): def test_authorize_bad_cidr_throws_invalid_parameter_value_boto3():
ec2 = boto3.resource("ec2", "us-west-1") ec2 = boto3.resource("ec2", "us-west-1")
sec_group = ec2.create_security_group(GroupName="test", Description="test") sec_group = ec2.create_security_group(GroupName=str(uuid4()), Description="test")
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
permissions = [ permissions = [
{ {
@ -979,16 +1004,18 @@ def test_security_group_tag_filtering():
def test_security_group_tag_filtering_boto3(): def test_security_group_tag_filtering_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
sg = ec2.create_security_group(GroupName="test-sg", Description="Test SG") sg = ec2.create_security_group(GroupName=str(uuid4()), Description="Test SG")
sg.create_tags(Tags=[{"Key": "test-tag", "Value": "test-value"}]) tag_name = str(uuid4())[0:6]
tag_val = str(uuid4())
sg.create_tags(Tags=[{"Key": tag_name, "Value": tag_val}])
groups = client.describe_security_groups( groups = client.describe_security_groups(
Filters=[{"Name": "tag:test-tag", "Values": ["test-value"]}] Filters=[{"Name": f"tag:{tag_name}", "Values": [tag_val]}]
)["SecurityGroups"] )["SecurityGroups"]
groups.should.have.length_of(1) groups.should.have.length_of(1)
groups = client.describe_security_groups( groups = client.describe_security_groups(
Filters=[{"Name": "tag:test-tag", "Values": ["unknown"]}] Filters=[{"Name": f"tag:{tag_name}", "Values": ["unknown"]}]
)["SecurityGroups"] )["SecurityGroups"]
groups.should.have.length_of(0) groups.should.have.length_of(0)
@ -1011,12 +1038,13 @@ def test_authorize_all_protocols_with_no_port_specification():
def test_authorize_all_protocols_with_no_port_specification_boto3(): def test_authorize_all_protocols_with_no_port_specification_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
sg = ec2.create_security_group(GroupName="test", Description="test") sg_name = str(uuid4())
sg = ec2.create_security_group(GroupName=sg_name, Description="test desc")
permissions = [{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}] permissions = [{"IpProtocol": "-1", "IpRanges": [{"CidrIp": "0.0.0.0/0"}]}]
sg.authorize_ingress(IpPermissions=permissions) sg.authorize_ingress(IpPermissions=permissions)
sg = client.describe_security_groups(GroupNames=["test"])["SecurityGroups"][0] sg = client.describe_security_groups(GroupNames=[sg_name])["SecurityGroups"][0]
permission = sg["IpPermissions"][0] permission = sg["IpPermissions"][0]
permission.should.have.key("IpProtocol").equal("-1") permission.should.have.key("IpProtocol").equal("-1")
permission.should.have.key("IpRanges").equal([{"CidrIp": "0.0.0.0/0"}]) permission.should.have.key("IpRanges").equal([{"CidrIp": "0.0.0.0/0"}])
@ -1102,15 +1130,15 @@ def test_sec_group_rule_limit_boto3(use_vpc):
if use_vpc: if use_vpc:
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg = ec2.create_security_group( sg = ec2.create_security_group(
GroupName="test", Description="test", VpcId=vpc.id GroupName=str(uuid4()), Description="test", VpcId=vpc.id
) )
other_sg = ec2.create_security_group( other_sg = ec2.create_security_group(
GroupName="test_2", Description="test_other", VpcId=vpc.id GroupName=str(uuid4()), Description="test_other", VpcId=vpc.id
) )
else: else:
sg = ec2.create_security_group(GroupName="test", Description="test") sg = ec2.create_security_group(GroupName=str(uuid4()), Description="test")
other_sg = ec2.create_security_group( other_sg = ec2.create_security_group(
GroupName="test_2", Description="test_other" GroupName=str(uuid4()), Description="test_other"
) )
# INGRESS # INGRESS
@ -1383,7 +1411,7 @@ def test_description_in_ip_permissions():
def test_security_group_tagging_boto3(): def test_security_group_tagging_boto3():
conn = boto3.client("ec2", region_name="us-east-1") conn = boto3.client("ec2", region_name="us-east-1")
sg = conn.create_security_group(GroupName="test-sg", Description="Test SG") sg = conn.create_security_group(GroupName=str(uuid4()), Description="Test SG")
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
conn.create_tags( conn.create_tags(
@ -1397,26 +1425,34 @@ def test_security_group_tagging_boto3():
"An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set" "An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set"
) )
conn.create_tags(Resources=[sg["GroupId"]], Tags=[{"Key": "Test", "Value": "Tag"}]) tag_val = str(uuid4())
conn.create_tags(
Resources=[sg["GroupId"]], Tags=[{"Key": "Test", "Value": tag_val}]
)
describe = conn.describe_security_groups( describe = conn.describe_security_groups(
Filters=[{"Name": "tag-value", "Values": ["Tag"]}] Filters=[{"Name": "tag-value", "Values": [tag_val]}]
) )
tag = describe["SecurityGroups"][0]["Tags"][0] tag = describe["SecurityGroups"][0]["Tags"][0]
tag["Value"].should.equal("Tag") tag["Value"].should.equal(tag_val)
tag["Key"].should.equal("Test") tag["Key"].should.equal("Test")
@mock_ec2 @mock_ec2
def test_security_group_wildcard_tag_filter_boto3(): def test_security_group_wildcard_tag_filter_boto3():
conn = boto3.client("ec2", region_name="us-east-1") conn = boto3.client("ec2", region_name="us-east-1")
sg = conn.create_security_group(GroupName="test-sg", Description="Test SG") sg = conn.create_security_group(GroupName=str(uuid4()), Description="Test SG")
conn.create_tags(Resources=[sg["GroupId"]], Tags=[{"Key": "Test", "Value": "Tag"}])
rand_name = str(uuid4())[0:6]
tag_val = f"random {rand_name} things"
conn.create_tags(
Resources=[sg["GroupId"]], Tags=[{"Key": "Test", "Value": tag_val}]
)
describe = conn.describe_security_groups( describe = conn.describe_security_groups(
Filters=[{"Name": "tag-value", "Values": ["*"]}] Filters=[{"Name": "tag-value", "Values": [f"*{rand_name}*"]}]
) )
tag = describe["SecurityGroups"][0]["Tags"][0] tag = describe["SecurityGroups"][0]["Tags"][0]
tag["Value"].should.equal("Tag") tag["Value"].should.equal(tag_val)
tag["Key"].should.equal("Test") tag["Key"].should.equal("Test")
@ -1426,22 +1462,40 @@ def test_security_group_filter_ip_permission():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
conn = boto3.client("ec2", region_name="us-east-1") conn = boto3.client("ec2", region_name="us-east-1")
sg_name = str(uuid4())[0:6]
sg = ec2.create_security_group( sg = ec2.create_security_group(
GroupName="test-sg", Description="Test SG", VpcId=vpc.id GroupName=sg_name, Description="Test SG", VpcId=vpc.id
) )
from_port = randint(0, 65535)
to_port = randint(0, 65535)
ip_permissions = [ ip_permissions = [
{"IpProtocol": "tcp", "FromPort": 27017, "ToPort": 27017, "IpRanges": [],}, {
"IpProtocol": "tcp",
"FromPort": from_port,
"ToPort": to_port,
"IpRanges": [],
},
] ]
sg.authorize_ingress(IpPermissions=ip_permissions) sg.authorize_ingress(IpPermissions=ip_permissions)
describe = conn.describe_security_groups( filters = [{"Name": "ip-permission.from-port", "Values": [f"{from_port}"]}]
Filters=[{"Name": "ip-permission.from-port", "Values": ["27017"]}] describe = retrieve_all_sgs(conn, filters)
)["SecurityGroups"]
describe.should.have.length_of(1) describe.should.have.length_of(1)
describe[0]["GroupName"].should.equal("test-sg") describe[0]["GroupName"].should.equal(sg_name)
def retrieve_all_sgs(conn, filters=[]):
res = conn.describe_security_groups(Filters=filters)
all_groups = res["SecurityGroups"]
next_token = res.get("NextToken")
while next_token:
res = conn.describe_security_groups(Filters=filters)
all_groups.extend(res["SecurityGroups"])
next_token = res.get("NextToken")
return all_groups
@mock_ec2 @mock_ec2
@ -1451,17 +1505,13 @@ def test_authorize_and_revoke_in_bulk():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg01 = ec2.create_security_group( sg01 = ec2.create_security_group(
GroupName="sg01", Description="Test security group sg01", VpcId=vpc.id GroupName=str(uuid4()), Description="Test sg01", VpcId=vpc.id
) )
sg02 = ec2.create_security_group( sg02 = ec2.create_security_group(
GroupName="sg02", Description="Test security group sg02", VpcId=vpc.id GroupName=str(uuid4()), Description="Test sg02", VpcId=vpc.id
)
sg03 = ec2.create_security_group(
GroupName="sg03", Description="Test security group sg03"
)
sg04 = ec2.create_security_group(
GroupName="sg04", Description="Test security group sg04"
) )
sg03 = ec2.create_security_group(GroupName=str(uuid4()), Description="Test sg03")
sg04 = ec2.create_security_group(GroupName=str(uuid4()), Description="Test sg04")
ip_permissions = [ ip_permissions = [
{ {
"IpProtocol": "tcp", "IpProtocol": "tcp",
@ -1595,7 +1645,7 @@ def test_authorize_and_revoke_in_bulk():
@mock_ec2 @mock_ec2
def test_security_group_ingress_without_multirule(): def test_security_group_ingress_without_multirule():
ec2 = boto3.resource("ec2", "ca-central-1") ec2 = boto3.resource("ec2", "ca-central-1")
sg = ec2.create_security_group(Description="Test SG", GroupName="test-sg") sg = ec2.create_security_group(Description="Test SG", GroupName=str(uuid4()))
assert len(sg.ip_permissions) == 0 assert len(sg.ip_permissions) == 0
sg.authorize_ingress( sg.authorize_ingress(
@ -1609,7 +1659,7 @@ def test_security_group_ingress_without_multirule():
@mock_ec2 @mock_ec2
def test_security_group_ingress_without_multirule_after_reload(): def test_security_group_ingress_without_multirule_after_reload():
ec2 = boto3.resource("ec2", "ca-central-1") ec2 = boto3.resource("ec2", "ca-central-1")
sg = ec2.create_security_group(Description="Test SG", GroupName="test-sg") sg = ec2.create_security_group(Description="Test SG", GroupName=str(uuid4()))
assert len(sg.ip_permissions) == 0 assert len(sg.ip_permissions) == 0
sg.authorize_ingress( sg.authorize_ingress(
@ -1650,10 +1700,10 @@ def test_get_all_security_groups_filter_with_same_vpc_id_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
vpc_id = "vpc-5300000c" vpc_id = "vpc-5300000c"
security_group = ec2.create_security_group( security_group = ec2.create_security_group(
GroupName="test1", Description="test1", VpcId=vpc_id GroupName=str(uuid4()), Description="test1", VpcId=vpc_id
) )
security_group2 = ec2.create_security_group( security_group2 = ec2.create_security_group(
GroupName="test2", Description="test2", VpcId=vpc_id GroupName=str(uuid4()), Description="test2", VpcId=vpc_id
) )
security_group.vpc_id.should.equal(vpc_id) security_group.vpc_id.should.equal(vpc_id)
@ -1676,7 +1726,7 @@ def test_revoke_security_group_egress():
ec2 = boto3.resource("ec2", "us-east-1") ec2 = boto3.resource("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg = ec2.create_security_group( sg = ec2.create_security_group(
Description="Test SG", GroupName="test-sg", VpcId=vpc.id Description="Test SG", GroupName=str(uuid4()), VpcId=vpc.id
) )
sg.ip_permissions_egress.should.equal( sg.ip_permissions_egress.should.equal(
@ -1712,8 +1762,9 @@ def test_update_security_group_rule_descriptions_egress():
ec2 = boto3.resource("ec2", "us-east-1") ec2 = boto3.resource("ec2", "us-east-1")
client = boto3.client("ec2", "us-east-1") client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg_name = str(uuid4())
sg = ec2.create_security_group( sg = ec2.create_security_group(
Description="Test SG", GroupName="test-sg", VpcId=vpc.id Description="Test SG", GroupName=sg_name, VpcId=vpc.id
) )
sg_id = sg.id sg_id = sg.id
@ -1724,7 +1775,7 @@ def test_update_security_group_rule_descriptions_egress():
ip_ranges[0].should.equal({"CidrIp": "0.0.0.0/0"}) ip_ranges[0].should.equal({"CidrIp": "0.0.0.0/0"})
client.update_security_group_rule_descriptions_egress( client.update_security_group_rule_descriptions_egress(
GroupName="test-sg", GroupName=sg_name,
IpPermissions=[ IpPermissions=[
{ {
"IpProtocol": "-1", "IpProtocol": "-1",
@ -1748,8 +1799,9 @@ def test_update_security_group_rule_descriptions_ingress():
ec2 = boto3.resource("ec2", "us-east-1") ec2 = boto3.resource("ec2", "us-east-1")
client = boto3.client("ec2", "us-east-1") client = boto3.client("ec2", "us-east-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
sg_name = str(uuid4())
sg = ec2.create_security_group( sg = ec2.create_security_group(
Description="Test SG", GroupName="test-sg", VpcId=vpc.id Description="Test SG", GroupName=sg_name, VpcId=vpc.id
) )
sg_id = sg.id sg_id = sg.id
@ -1770,7 +1822,7 @@ def test_update_security_group_rule_descriptions_ingress():
ip_ranges[0].should.equal({"CidrIp": "1.2.3.4/32", "Description": "first desc"}) ip_ranges[0].should.equal({"CidrIp": "1.2.3.4/32", "Description": "first desc"})
client.update_security_group_rule_descriptions_ingress( client.update_security_group_rule_descriptions_ingress(
GroupName="test-sg", GroupName=sg_name,
IpPermissions=[ IpPermissions=[
{ {
"IpProtocol": "tcp", "IpProtocol": "tcp",
@ -1811,7 +1863,7 @@ def test_security_group_rules_added_via_the_backend_can_be_revoked_via_the_api()
ec2_resource = boto3.resource("ec2", region_name="us-east-1") ec2_resource = boto3.resource("ec2", region_name="us-east-1")
ec2_client = boto3.client("ec2", region_name="us-east-1") ec2_client = boto3.client("ec2", region_name="us-east-1")
vpc = ec2_resource.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2_resource.create_vpc(CidrBlock="10.0.0.0/16")
group_name = "test-backend-authorize" group_name = str(uuid4())
sg = ec2_resource.create_security_group( sg = ec2_resource.create_security_group(
GroupName=group_name, Description="test", VpcId=vpc.id GroupName=group_name, Description="test", VpcId=vpc.id
) )
@ -1859,8 +1911,9 @@ def test_filter_description():
ec2r = boto3.resource("ec2", region_name="us-west-1") ec2r = boto3.resource("ec2", region_name="us-west-1")
vpc = ec2r.create_vpc(CidrBlock="10.250.0.0/16") vpc = ec2r.create_vpc(CidrBlock="10.250.0.0/16")
unique = str(uuid4())
sg1 = vpc.create_security_group( sg1 = vpc.create_security_group(
Description="An Excellent Description", GroupName="test-1" Description=(f"A {unique} Description"), GroupName="test-1"
) )
sg2 = vpc.create_security_group( sg2 = vpc.create_security_group(
Description="Another Description That Awes The Human Mind", GroupName="test-2" Description="Another Description That Awes The Human Mind", GroupName="test-2"
@ -1868,7 +1921,7 @@ def test_filter_description():
filter_to_match_group_1_description = { filter_to_match_group_1_description = {
"Name": "description", "Name": "description",
"Values": ["Excellent"], "Values": [unique],
} }
security_groups = ec2r.security_groups.filter( security_groups = ec2r.security_groups.filter(
@ -1882,6 +1935,10 @@ def test_filter_description():
@mock_ec2 @mock_ec2
def test_filter_egress__ip_permission__cidr(): def test_filter_egress__ip_permission__cidr():
if settings.TEST_SERVER_MODE:
raise SkipTest(
"CIDR's might already exist due to other tests creating IP ranges"
)
ec2r = boto3.resource("ec2", region_name="us-west-1") ec2r = boto3.resource("ec2", region_name="us-west-1")
vpc = ec2r.create_vpc(CidrBlock="10.250.1.0/16") vpc = ec2r.create_vpc(CidrBlock="10.250.1.0/16")
@ -1935,10 +1992,11 @@ def test_filter_egress__ip_permission__from_port():
Description="Another Description That Awes The Human Mind", GroupName="test-2" Description="Another Description That Awes The Human Mind", GroupName="test-2"
) )
from_port = randint(1, 9999)
sg1.authorize_egress( sg1.authorize_egress(
IpPermissions=[ IpPermissions=[
{ {
"FromPort": 7357, "FromPort": from_port,
"ToPort": 7359, "ToPort": 7359,
"IpProtocol": "tcp", "IpProtocol": "tcp",
"IpRanges": [{"CidrIp": "10.250.0.0/16"}, {"CidrIp": "10.251.0.0/16"}], "IpRanges": [{"CidrIp": "10.250.0.0/16"}, {"CidrIp": "10.251.0.0/16"}],
@ -1957,7 +2015,7 @@ def test_filter_egress__ip_permission__from_port():
) )
filter_to_match_group_1 = { filter_to_match_group_1 = {
"Name": "egress.ip-permission.from-port", "Name": "egress.ip-permission.from-port",
"Values": ["7357"], "Values": [f"{from_port}"],
} }
security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1]) security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1])
@ -2162,9 +2220,9 @@ def test_filter_egress__ip_permission__protocol():
} }
security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1]) security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1])
security_groups = list(security_groups) group_ids = [sg.group_id for sg in security_groups]
assert len(security_groups) == 1 group_ids.should.contain(sg1.group_id)
assert security_groups[0].group_id == sg1.group_id group_ids.shouldnt.contain(sg2.group_id)
@mock_ec2 @mock_ec2
@ -2179,11 +2237,12 @@ def test_filter_egress__ip_permission__to_port():
Description="Another Description That Awes The Human Mind", GroupName="test-2" Description="Another Description That Awes The Human Mind", GroupName="test-2"
) )
to_port = randint(1, 9999)
sg1.authorize_egress( sg1.authorize_egress(
IpPermissions=[ IpPermissions=[
{ {
"FromPort": 7357, "FromPort": 7357,
"ToPort": 7359, "ToPort": to_port,
"IpProtocol": "tcp", "IpProtocol": "tcp",
"IpRanges": [{"CidrIp": "10.250.0.0/16"}, {"CidrIp": "10.251.0.0/16"}], "IpRanges": [{"CidrIp": "10.250.0.0/16"}, {"CidrIp": "10.251.0.0/16"}],
} }
@ -2201,7 +2260,7 @@ def test_filter_egress__ip_permission__to_port():
) )
filter_to_match_group_1 = { filter_to_match_group_1 = {
"Name": "egress.ip-permission.to-port", "Name": "egress.ip-permission.to-port",
"Values": ["7359"], "Values": [f"{to_port}"],
} }
security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1]) security_groups = ec2r.security_groups.filter(Filters=[filter_to_match_group_1])

View File

@ -3,9 +3,13 @@ import json
import sure # noqa import sure # noqa
from moto import mock_cloudformation, mock_ec2 from moto import mock_cloudformation, mock_ec2
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from string import Template
from uuid import uuid4
from .test_instances import retrieve_all_instances
SEC_GROUP_INGRESS = """{ SEC_GROUP_INGRESS = Template(
"""{
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Template to create an EC2 instance", "Description": "AWS CloudFormation Template to create an EC2 instance",
"Parameters": { "Parameters": {
@ -20,7 +24,7 @@ SEC_GROUP_INGRESS = """{
"Type": "AWS::EC2::SecurityGroup", "Type": "AWS::EC2::SecurityGroup",
"Properties": { "Properties": {
"GroupDescription": "Test VPC security group", "GroupDescription": "Test VPC security group",
"GroupName": "My-SG", "GroupName": $group_name,
"VpcId": { "VpcId": {
"Ref": "VPCId" "Ref": "VPCId"
} }
@ -45,9 +49,11 @@ SEC_GROUP_INGRESS = """{
} }
} }
""" """
)
SEC_GROUP_INGRESS_WITHOUT_DESC = """{ SEC_GROUP_INGRESS_WITHOUT_DESC = Template(
"""{
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Description": "AWS CloudFormation Template to create an EC2 instance", "Description": "AWS CloudFormation Template to create an EC2 instance",
"Parameters": { "Parameters": {
@ -62,7 +68,7 @@ SEC_GROUP_INGRESS_WITHOUT_DESC = """{
"Type": "AWS::EC2::SecurityGroup", "Type": "AWS::EC2::SecurityGroup",
"Properties": { "Properties": {
"GroupDescription": "Test VPC security group", "GroupDescription": "Test VPC security group",
"GroupName": "My-SG", "GroupName": "$group_name",
"VpcId": { "VpcId": {
"Ref": "VPCId" "Ref": "VPCId"
} }
@ -86,6 +92,7 @@ SEC_GROUP_INGRESS_WITHOUT_DESC = """{
} }
} }
""" """
)
SEC_GROUP_SOURCE = { SEC_GROUP_SOURCE = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
@ -133,17 +140,18 @@ def test_security_group_ingress():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
ec2_client = boto3.client("ec2", region_name="us-east-1") ec2_client = boto3.client("ec2", region_name="us-east-1")
group_name = str(uuid4())
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
cf_client.create_stack( cf_client.create_stack(
StackName="test_stack", StackName=str(uuid4()),
TemplateBody=SEC_GROUP_INGRESS, TemplateBody=SEC_GROUP_INGRESS.substitute(group_name=group_name),
Parameters=[{"ParameterKey": "VPCId", "ParameterValue": vpc.id}], Parameters=[{"ParameterKey": "VPCId", "ParameterValue": vpc.id}],
Capabilities=["CAPABILITY_NAMED_IAM"], Capabilities=["CAPABILITY_NAMED_IAM"],
OnFailure="DELETE", OnFailure="DELETE",
) )
groups = ec2_client.describe_security_groups()["SecurityGroups"] groups = ec2_client.describe_security_groups()["SecurityGroups"]
group = [g for g in groups if g["GroupName"] == "My-SG"][0] group = [g for g in groups if g["GroupName"] == group_name][0]
group["Description"].should.equal("Test VPC security group") group["Description"].should.equal("Test VPC security group")
len(group["IpPermissions"]).should.be(1) len(group["IpPermissions"]).should.be(1)
ingress = group["IpPermissions"][0] ingress = group["IpPermissions"][0]
@ -162,17 +170,18 @@ def test_security_group_ingress_without_description():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
ec2_client = boto3.client("ec2", region_name="us-east-1") ec2_client = boto3.client("ec2", region_name="us-east-1")
group_name = str(uuid4())
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
cf_client.create_stack( cf_client.create_stack(
StackName="test_stack", StackName=str(uuid4()),
TemplateBody=SEC_GROUP_INGRESS_WITHOUT_DESC, TemplateBody=SEC_GROUP_INGRESS_WITHOUT_DESC.substitute(group_name=group_name),
Parameters=[{"ParameterKey": "VPCId", "ParameterValue": vpc.id}], Parameters=[{"ParameterKey": "VPCId", "ParameterValue": vpc.id}],
Capabilities=["CAPABILITY_NAMED_IAM"], Capabilities=["CAPABILITY_NAMED_IAM"],
OnFailure="DELETE", OnFailure="DELETE",
) )
groups = ec2_client.describe_security_groups()["SecurityGroups"] groups = ec2_client.describe_security_groups()["SecurityGroups"]
group = [g for g in groups if g["GroupName"] == "My-SG"][0] group = [g for g in groups if g["GroupName"] == group_name][0]
group["Description"].should.equal("Test VPC security group") group["Description"].should.equal("Test VPC security group")
len(group["IpPermissions"]).should.be(1) len(group["IpPermissions"]).should.be(1)
ingress = group["IpPermissions"][0] ingress = group["IpPermissions"][0]
@ -183,28 +192,46 @@ def test_security_group_ingress_without_description():
@mock_cloudformation @mock_cloudformation
def test_stack_security_groups(): def test_stack_security_groups():
template = json.dumps(SEC_GROUP_SOURCE) first_desc = str(uuid4())
second_desc = str(uuid4())
our_template = SEC_GROUP_SOURCE.copy()
our_template["Resources"]["my-security-group"]["Properties"][
"GroupDescription"
] = second_desc
our_template["Resources"]["InstanceSecurityGroup"]["Properties"][
"GroupDescription"
] = first_desc
template = json.dumps(our_template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
stack_name = str(uuid4())[0:6]
cf.create_stack( cf.create_stack(
StackName="security_group_stack", StackName=stack_name,
TemplateBody=template, TemplateBody=template,
Tags=[{"Key": "foo", "Value": "bar"}], Tags=[{"Key": "foo", "Value": "bar"}],
) )
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
instance_group = ec2.describe_security_groups( instance_group = ec2.describe_security_groups(
Filters=[{"Name": "description", "Values": ["My security group"]}] Filters=[{"Name": "description", "Values": [first_desc]}]
)["SecurityGroups"][0] )["SecurityGroups"][0]
instance_group.should.have.key("Description").equal("My security group") instance_group.should.have.key("Description").equal(first_desc)
instance_group.should.have.key("Tags") instance_group.should.have.key("Tags")
instance_group["Tags"].should.contain({"Key": "bar", "Value": "baz"}) instance_group["Tags"].should.contain({"Key": "bar", "Value": "baz"})
instance_group["Tags"].should.contain({"Key": "foo", "Value": "bar"}) instance_group["Tags"].should.contain({"Key": "foo", "Value": "bar"})
other_group = ec2.describe_security_groups( other_group = ec2.describe_security_groups(
Filters=[{"Name": "description", "Values": ["My other group"]}] Filters=[{"Name": "description", "Values": [second_desc]}]
)["SecurityGroups"][0] )["SecurityGroups"][0]
ec2_instance = ec2.describe_instances()["Reservations"][0]["Instances"][0] instance = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"][
1
]
instance_id = instance["PhysicalResourceId"]
ec2_instance = ec2.describe_instances(InstanceIds=[instance_id])["Reservations"][0][
"Instances"
][0]
ec2_instance["NetworkInterfaces"][0]["Groups"][0]["GroupId"].should.equal( ec2_instance["NetworkInterfaces"][0]["Groups"][0]["GroupId"].should.equal(
instance_group["GroupId"] instance_group["GroupId"]

View File

@ -3,6 +3,7 @@ import pytest
import datetime import datetime
import boto import boto
import boto.ec2
import boto3 import boto3
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
@ -13,6 +14,8 @@ from moto import mock_ec2, mock_ec2_deprecated, settings
from moto.ec2.models import ec2_backends from moto.ec2.models import ec2_backends
from moto.core.utils import iso_8601_datetime_with_milliseconds from moto.core.utils import iso_8601_datetime_with_milliseconds
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from uuid import uuid4
from unittest import SkipTest
@mock_ec2 @mock_ec2
@ -24,8 +27,10 @@ def test_request_spot_instances():
)["Subnet"] )["Subnet"]
subnet_id = subnet["SubnetId"] subnet_id = subnet["SubnetId"]
conn.create_security_group(GroupName="group1", Description="description") sec_name_1 = str(uuid4())
conn.create_security_group(GroupName="group2", Description="description") sec_name_2 = str(uuid4())
conn.create_security_group(GroupName=sec_name_1, Description="description")
conn.create_security_group(GroupName=sec_name_2, Description="description")
start_dt = datetime.datetime(2013, 1, 1).replace(tzinfo=pytz.utc) start_dt = datetime.datetime(2013, 1, 1).replace(tzinfo=pytz.utc)
end_dt = datetime.datetime(2013, 1, 2).replace(tzinfo=pytz.utc) end_dt = datetime.datetime(2013, 1, 2).replace(tzinfo=pytz.utc)
@ -44,7 +49,7 @@ def test_request_spot_instances():
LaunchSpecification={ LaunchSpecification={
"ImageId": EXAMPLE_AMI_ID, "ImageId": EXAMPLE_AMI_ID,
"KeyName": "test", "KeyName": "test",
"SecurityGroups": ["group1", "group2"], "SecurityGroups": [sec_name_1, sec_name_2],
"UserData": "some test data", "UserData": "some test data",
"InstanceType": "m1.small", "InstanceType": "m1.small",
"Placement": {"AvailabilityZone": "us-east-1c"}, "Placement": {"AvailabilityZone": "us-east-1c"},
@ -72,7 +77,7 @@ def test_request_spot_instances():
LaunchSpecification={ LaunchSpecification={
"ImageId": EXAMPLE_AMI_ID, "ImageId": EXAMPLE_AMI_ID,
"KeyName": "test", "KeyName": "test",
"SecurityGroups": ["group1", "group2"], "SecurityGroups": [sec_name_1, sec_name_2],
"UserData": "some test data", "UserData": "some test data",
"InstanceType": "m1.small", "InstanceType": "m1.small",
"Placement": {"AvailabilityZone": "us-east-1c"}, "Placement": {"AvailabilityZone": "us-east-1c"},
@ -82,8 +87,10 @@ def test_request_spot_instances():
"SubnetId": subnet_id, "SubnetId": subnet_id,
}, },
) )
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"] all_requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"]
requests = [r for r in all_requests if r["SpotInstanceRequestId"] == request_id]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
@ -99,7 +106,7 @@ def test_request_spot_instances():
security_group_names = [ security_group_names = [
group["GroupName"] for group in launch_spec["SecurityGroups"] group["GroupName"] for group in launch_spec["SecurityGroups"]
] ]
set(security_group_names).should.equal(set(["group1", "group2"])) set(security_group_names).should.equal(set([sec_name_1, sec_name_2]))
launch_spec["ImageId"].should.equal(EXAMPLE_AMI_ID) launch_spec["ImageId"].should.equal(EXAMPLE_AMI_ID)
launch_spec["KeyName"].should.equal("test") launch_spec["KeyName"].should.equal("test")
@ -119,8 +126,10 @@ def test_request_spot_instances_default_arguments():
request = conn.request_spot_instances( request = conn.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
) )
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"] all_requests = conn.describe_spot_instance_requests()["SpotInstanceRequests"]
requests = [r for r in all_requests if r["SpotInstanceRequestId"] == request_id]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
@ -175,11 +184,14 @@ def test_cancel_spot_instance_request():
def test_cancel_spot_instance_request_boto3(): def test_cancel_spot_instance_request_boto3():
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
client.request_spot_instances( rsi = client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
) )
spot_id = rsi["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"] requests = client.describe_spot_instance_requests(SpotInstanceRequestIds=[spot_id])[
"SpotInstanceRequests"
]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
request.should.have.key("CreateTime") request.should.have.key("CreateTime")
@ -202,7 +214,9 @@ def test_cancel_spot_instance_request_boto3():
SpotInstanceRequestIds=[request["SpotInstanceRequestId"]] SpotInstanceRequestIds=[request["SpotInstanceRequestId"]]
) )
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"] requests = client.describe_spot_instance_requests(SpotInstanceRequestIds=[spot_id])[
"SpotInstanceRequests"
]
requests.should.have.length_of(0) requests.should.have.length_of(0)
@ -245,7 +259,9 @@ def test_request_spot_instances_fulfilled_boto3():
) )
request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"] request_id = request["SpotInstanceRequests"][0]["SpotInstanceRequestId"]
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"] requests = client.describe_spot_instance_requests(
SpotInstanceRequestIds=[request_id]
)["SpotInstanceRequests"]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
@ -254,7 +270,9 @@ def test_request_spot_instances_fulfilled_boto3():
if not settings.TEST_SERVER_MODE: if not settings.TEST_SERVER_MODE:
ec2_backends["us-east-1"].spot_instance_requests[request_id].state = "active" ec2_backends["us-east-1"].spot_instance_requests[request_id].state = "active"
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"] requests = client.describe_spot_instance_requests(
SpotInstanceRequestIds=[request_id]
)["SpotInstanceRequests"]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
@ -297,7 +315,9 @@ def test_tag_spot_instance_request_boto3():
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}], Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}],
) )
requests = client.describe_spot_instance_requests()["SpotInstanceRequests"] requests = client.describe_spot_instance_requests(
SpotInstanceRequestIds=[request_id]
)["SpotInstanceRequests"]
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
@ -355,33 +375,38 @@ def test_get_all_spot_instance_requests_filtering_boto3():
client.request_spot_instances( client.request_spot_instances(
SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID} SpotPrice="0.5", LaunchSpecification={"ImageId": EXAMPLE_AMI_ID}
) )
tag_value1 = str(uuid4())
client.create_tags( client.create_tags(
Resources=[request1_id], Resources=[request1_id],
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "value2"}], Tags=[{"Key": "tag1", "Value": tag_value1}, {"Key": "tag2", "Value": "value2"}],
) )
client.create_tags( client.create_tags(
Resources=[request2_id], Resources=[request2_id],
Tags=[{"Key": "tag1", "Value": "value1"}, {"Key": "tag2", "Value": "wrong"}], Tags=[{"Key": "tag1", "Value": tag_value1}, {"Key": "tag2", "Value": "wrong"}],
) )
requests = client.describe_spot_instance_requests( requests = client.describe_spot_instance_requests(
Filters=[{"Name": "state", "Values": ["active"]}] Filters=[{"Name": "state", "Values": ["active"]}]
)["SpotInstanceRequests"] )["SpotInstanceRequests"]
requests.should.have.length_of(0) r_ids = [r["SpotInstanceRequestId"] for r in requests]
r_ids.shouldnt.contain(request1_id)
r_ids.shouldnt.contain(request2_id)
requests = client.describe_spot_instance_requests( requests = client.describe_spot_instance_requests(
Filters=[{"Name": "state", "Values": ["open"]}] Filters=[{"Name": "state", "Values": ["open"]}]
)["SpotInstanceRequests"] )["SpotInstanceRequests"]
requests.should.have.length_of(3) r_ids = [r["SpotInstanceRequestId"] for r in requests]
r_ids.should.contain(request1_id)
r_ids.should.contain(request2_id)
requests = client.describe_spot_instance_requests( requests = client.describe_spot_instance_requests(
Filters=[{"Name": "tag:tag1", "Values": ["value1"]}] Filters=[{"Name": "tag:tag1", "Values": [tag_value1]}]
)["SpotInstanceRequests"] )["SpotInstanceRequests"]
requests.should.have.length_of(2) requests.should.have.length_of(2)
requests = client.describe_spot_instance_requests( requests = client.describe_spot_instance_requests(
Filters=[ Filters=[
{"Name": "tag:tag1", "Values": ["value1"]}, {"Name": "tag:tag1", "Values": [tag_value1]},
{"Name": "tag:tag2", "Values": ["value2"]}, {"Name": "tag:tag2", "Values": ["value2"]},
] ]
)["SpotInstanceRequests"] )["SpotInstanceRequests"]
@ -406,6 +431,10 @@ def test_request_spot_instances_setting_instance_id():
@mock_ec2 @mock_ec2
def test_request_spot_instances_instance_lifecycle(): def test_request_spot_instances_instance_lifecycle():
if settings.TEST_SERVER_MODE:
# Currently no easy way to check which instance was created by request_spot_instance
# And we can't just pick the first instance in ServerMode and expect it to be the right one
raise SkipTest("ServerMode is not guaranteed to be empty")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
request = client.request_spot_instances(SpotPrice="0.5") request = client.request_spot_instances(SpotPrice="0.5")
@ -431,9 +460,10 @@ def test_launch_spot_instance_instance_lifecycle():
"InstanceMarketOptions": {"MarketType": "spot"}, "InstanceMarketOptions": {"MarketType": "spot"},
} }
client.run_instances(**kwargs)["Instances"][0] instance = client.run_instances(**kwargs)["Instances"][0]
instance_id = instance["InstanceId"]
response = client.describe_instances() response = client.describe_instances(InstanceIds=[instance_id])
instance = response["Reservations"][0]["Instances"][0] instance = response["Reservations"][0]["Instances"][0]
instance["InstanceLifecycle"].should.equal("spot") instance["InstanceLifecycle"].should.equal("spot")
@ -453,9 +483,10 @@ def test_launch_instance_instance_lifecycle():
], ],
} }
client.run_instances(**kwargs)["Instances"][0] instance = client.run_instances(**kwargs)["Instances"][0]
instance_id = instance["InstanceId"]
response = client.describe_instances() response = client.describe_instances(InstanceIds=[instance_id])
instance = response["Reservations"][0]["Instances"][0] instance = response["Reservations"][0]["Instances"][0]
instance.get("InstanceLifecycle").should.equal(None) instance.get("InstanceLifecycle").should.equal(None)

View File

@ -12,6 +12,8 @@ from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2, mock_ec2_deprecated, settings from moto import mock_ec2, mock_ec2_deprecated, settings
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from uuid import uuid4
from unittest import SkipTest
# Has boto3 equivalent # Has boto3 equivalent
@ -44,14 +46,15 @@ def test_subnets_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18") subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock="10.0.0.0/18")
all_subnets = client.describe_subnets()["Subnets"] ours = client.describe_subnets(SubnetIds=[subnet.id])["Subnets"]
nr_of_a_zones = len(client.describe_availability_zones()["AvailabilityZones"]) ours.should.have.length_of(1)
all_subnets.should.have.length_of(1 + nr_of_a_zones)
client.delete_subnet(SubnetId=subnet.id) client.delete_subnet(SubnetId=subnet.id)
all_subnets = client.describe_subnets()["Subnets"] with pytest.raises(ClientError) as ex:
all_subnets.should.have.length_of(nr_of_a_zones) client.describe_subnets(SubnetIds=[subnet.id])
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidSubnetID.NotFound")
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_subnet(SubnetId=subnet.id) client.delete_subnet(SubnetId=subnet.id)
@ -111,7 +114,9 @@ def test_subnet_tagging_boto3():
subnet.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) subnet.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0] tag = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [subnet.id]}]
)["Tags"][0]
tag["Key"].should.equal("a key") tag["Key"].should.equal("a key")
tag["Value"].should.equal("some value") tag["Value"].should.equal("some value")
@ -153,6 +158,8 @@ def test_availability_zone_in_create_subnet():
@mock_ec2 @mock_ec2
def test_default_subnet(): def test_default_subnet():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode will have conflicting CidrBlocks")
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
default_vpc = list(ec2.vpcs.all())[0] default_vpc = list(ec2.vpcs.all())[0]
@ -202,11 +209,13 @@ def test_modify_subnet_attribute_public_ip_on_launch():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
# Get the default VPC random_ip = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
vpc = list(ec2.vpcs.all())[0] vpc = ec2.create_vpc(CidrBlock=f"{random_ip}/16")
random_subnet_cidr = f"{random_ip}/20" # Same block as the VPC
subnet = ec2.create_subnet( subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="172.31.48.0/20", AvailabilityZone="us-west-1a" VpcId=vpc.id, CidrBlock=random_subnet_cidr, AvailabilityZone="us-west-1a"
) )
# 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action # 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action
@ -233,11 +242,13 @@ def test_modify_subnet_attribute_assign_ipv6_address_on_creation():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
# Get the default VPC random_ip = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
vpc = list(ec2.vpcs.all())[0] vpc = ec2.create_vpc(CidrBlock=f"{random_ip}/16")
random_subnet_cidr = f"{random_ip}/20" # Same block as the VPC
subnet = ec2.create_subnet( subnet = ec2.create_subnet(
VpcId=vpc.id, CidrBlock="172.31.112.0/20", AvailabilityZone="us-west-1a" VpcId=vpc.id, CidrBlock=random_subnet_cidr, AvailabilityZone="us-west-1a"
) )
# 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action # 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action
@ -423,7 +434,14 @@ def test_get_subnets_filtering_boto3():
nr_of_a_zones = len(client.describe_availability_zones()["AvailabilityZones"]) nr_of_a_zones = len(client.describe_availability_zones()["AvailabilityZones"])
all_subnets = client.describe_subnets()["Subnets"] all_subnets = client.describe_subnets()["Subnets"]
all_subnets.should.have.length_of(3 + nr_of_a_zones) if settings.TEST_SERVER_MODE:
# ServerMode may have other tests running that are creating subnets
all_subnet_ids = [s["SubnetId"] for s in all_subnets]
all_subnet_ids.should.contain(subnetA.id)
all_subnet_ids.should.contain(subnetB1.id)
all_subnet_ids.should.contain(subnetB2.id)
else:
all_subnets.should.have.length_of(3 + nr_of_a_zones)
# Filter by VPC ID # Filter by VPC ID
subnets_by_vpc = client.describe_subnets( subnets_by_vpc = client.describe_subnets(
@ -438,26 +456,26 @@ def test_get_subnets_filtering_boto3():
subnets_by_cidr1 = client.describe_subnets( subnets_by_cidr1 = client.describe_subnets(
Filters=[{"Name": "cidr", "Values": ["10.0.0.0/24"]}] Filters=[{"Name": "cidr", "Values": ["10.0.0.0/24"]}]
)["Subnets"] )["Subnets"]
subnets_by_cidr1.should.have.length_of(2) subnets_by_cidr1 = [s["SubnetId"] for s in subnets_by_cidr1]
set([subnet["SubnetId"] for subnet in subnets_by_cidr1]).should.equal( subnets_by_cidr1.should.contain(subnetA.id)
set([subnetA.id, subnetB1.id]) subnets_by_cidr1.should.contain(subnetB1.id)
) subnets_by_cidr1.shouldnt.contain(subnetB2.id)
subnets_by_cidr2 = client.describe_subnets( subnets_by_cidr2 = client.describe_subnets(
Filters=[{"Name": "cidr-block", "Values": ["10.0.0.0/24"]}] Filters=[{"Name": "cidr-block", "Values": ["10.0.0.0/24"]}]
)["Subnets"] )["Subnets"]
subnets_by_cidr2.should.have.length_of(2) subnets_by_cidr2 = [s["SubnetId"] for s in subnets_by_cidr2]
set([subnet["SubnetId"] for subnet in subnets_by_cidr2]).should.equal( subnets_by_cidr2.should.contain(subnetA.id)
set([subnetA.id, subnetB1.id]) subnets_by_cidr2.should.contain(subnetB1.id)
) subnets_by_cidr2.shouldnt.contain(subnetB2.id)
subnets_by_cidr3 = client.describe_subnets( subnets_by_cidr3 = client.describe_subnets(
Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/24"]}] Filters=[{"Name": "cidrBlock", "Values": ["10.0.0.0/24"]}]
)["Subnets"] )["Subnets"]
subnets_by_cidr3.should.have.length_of(2) subnets_by_cidr3 = [s["SubnetId"] for s in subnets_by_cidr3]
set([subnet["SubnetId"] for subnet in subnets_by_cidr3]).should.equal( subnets_by_cidr3.should.contain(subnetA.id)
set([subnetA.id, subnetB1.id]) subnets_by_cidr3.should.contain(subnetB1.id)
) subnets_by_cidr3.shouldnt.contain(subnetB2.id)
# Filter by VPC ID and CIDR # Filter by VPC ID and CIDR
subnets_by_vpc_and_cidr = client.describe_subnets( subnets_by_vpc_and_cidr = client.describe_subnets(
@ -486,14 +504,14 @@ def test_get_subnets_filtering_boto3():
subnets_by_az.should.have.length_of(1) subnets_by_az.should.have.length_of(1)
subnets_by_az[0]["SubnetId"].should.equal(subnetB1.id) subnets_by_az[0]["SubnetId"].should.equal(subnetB1.id)
# Filter by defaultForAz
subnets_by_az = client.describe_subnets(
Filters=[{"Name": "defaultForAz", "Values": ["true"]}]
)["Subnets"]
subnets_by_az.should.have.length_of(nr_of_a_zones)
# Unsupported filter
if not settings.TEST_SERVER_MODE: if not settings.TEST_SERVER_MODE:
# Filter by defaultForAz
subnets_by_az = client.describe_subnets(
Filters=[{"Name": "defaultForAz", "Values": ["true"]}]
)["Subnets"]
subnets_by_az.should.have.length_of(nr_of_a_zones)
# Unsupported filter
filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}] filters = [{"Name": "not-implemented-filter", "Values": ["foobar"]}]
client.describe_subnets.when.called_with(Filters=filters).should.throw( client.describe_subnets.when.called_with(Filters=filters).should.throw(
NotImplementedError NotImplementedError
@ -709,9 +727,14 @@ def test_create_subnet_with_tags():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="172.31.0.0/16") vpc = ec2.create_vpc(CidrBlock="172.31.0.0/16")
random_ip = "172.31." + ".".join(
map(str, (random.randint(10, 40) for _ in range(2)))
)
random_cidr = f"{random_ip}/20"
subnet = ec2.create_subnet( subnet = ec2.create_subnet(
VpcId=vpc.id, VpcId=vpc.id,
CidrBlock="172.31.48.0/20", CidrBlock=random_cidr,
AvailabilityZoneId="use1-az6", AvailabilityZoneId="use1-az6",
TagSpecifications=[ TagSpecifications=[
{"ResourceType": "subnet", "Tags": [{"Key": "name", "Value": "some-vpc"}]} {"ResourceType": "subnet", "Tags": [{"Key": "name", "Value": "some-vpc"}]}
@ -723,6 +746,10 @@ def test_create_subnet_with_tags():
@mock_ec2 @mock_ec2
def test_available_ip_addresses_in_subnet(): def test_available_ip_addresses_in_subnet():
if settings.TEST_SERVER_MODE:
raise SkipTest(
"ServerMode is not guaranteed to be empty - other subnets will affect the count"
)
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
@ -748,6 +775,10 @@ def test_available_ip_addresses_in_subnet():
@mock_ec2 @mock_ec2
def test_available_ip_addresses_in_subnet_with_enis(): def test_available_ip_addresses_in_subnet_with_enis():
if settings.TEST_SERVER_MODE:
raise SkipTest(
"ServerMode is not guaranteed to be empty - other ENI's will affect the count"
)
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="us-west-1")
@ -848,15 +879,20 @@ def validate_subnet_details_after_creating_eni(
@mock_ec2 @mock_ec2
def test_run_instances_should_attach_to_default_subnet(): def test_run_instances_should_attach_to_default_subnet():
# https://github.com/spulec/moto/issues/2877 # https://github.com/spulec/moto/issues/2877
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="sa-east-1")
client = boto3.client("ec2", region_name="us-west-1") client = boto3.client("ec2", region_name="sa-east-1")
ec2.create_security_group(GroupName="sg01", Description="Test security group sg01") sec_group_name = str(uuid4())[0:6]
ec2.create_security_group(
GroupName=sec_group_name, Description="Test security group sg01"
)
# run_instances # run_instances
instances = client.run_instances( instances = client.run_instances(
ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=["sg01"], ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1, SecurityGroups=[sec_group_name],
) )
# Assert subnet is created appropriately # Assert subnet is created appropriately
subnets = client.describe_subnets()["Subnets"] subnets = client.describe_subnets(
Filters=[{"Name": "defaultForAz", "Values": ["true"]}]
)["Subnets"]
default_subnet_id = subnets[0]["SubnetId"] default_subnet_id = subnets[0]["SubnetId"]
if len(subnets) > 1: if len(subnets) > 1:
default_subnet_id1 = subnets[1]["SubnetId"] default_subnet_id1 = subnets[1]["SubnetId"]
@ -866,10 +902,13 @@ def test_run_instances_should_attach_to_default_subnet():
or instances["Instances"][0]["NetworkInterfaces"][0]["SubnetId"] or instances["Instances"][0]["NetworkInterfaces"][0]["SubnetId"]
== default_subnet_id1 == default_subnet_id1
) )
assert (
subnets[0]["AvailableIpAddressCount"] == 4090 if not settings.TEST_SERVER_MODE:
or subnets[1]["AvailableIpAddressCount"] == 4090 # Available IP addresses will depend on other resources that might be created in parallel
) assert (
subnets[0]["AvailableIpAddressCount"] == 4090
or subnets[1]["AvailableIpAddressCount"] == 4090
)
@mock_ec2 @mock_ec2

View File

@ -13,6 +13,8 @@ import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
import pytest import pytest
from tests import EXAMPLE_AMI_ID from tests import EXAMPLE_AMI_ID
from .test_instances import retrieve_all_instances
from uuid import uuid4
# Has boto3 equivalent # Has boto3 equivalent
@ -57,13 +59,9 @@ def test_instance_create_tags():
) )
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
chain = itertools.chain.from_iterable existing_instances = retrieve_all_instances(client)
existing_instances = list( ours = [i for i in existing_instances if i["InstanceId"] == instance.id][0]
chain([res["Instances"] for res in client.describe_instances()["Reservations"]]) ours["Tags"].should.equal([{"Key": "a key", "Value": "some value"}])
)
existing_instances.should.have.length_of(1)
existing_instance = existing_instances[0]
existing_instance["Tags"].should.equal([{"Key": "a key", "Value": "some value"}])
# Has boto3 equivalent # Has boto3 equivalent
@ -104,7 +102,9 @@ def test_instance_delete_tags():
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tags = client.describe_tags()["Tags"] tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [instance.id]}]
)["Tags"]
tag = tags[0] tag = tags[0]
tag.should.have.key("Key").equal("a key") tag.should.have.key("Key").equal("a key")
tag.should.have.key("Value").equal("some value") tag.should.have.key("Value").equal("some value")
@ -119,14 +119,20 @@ def test_instance_delete_tags():
# Specifying key only # Specifying key only
instance.delete_tags(Tags=[{"Key": "a key"}]) instance.delete_tags(Tags=[{"Key": "a key"}])
client.describe_tags()["Tags"].should.have.length_of(0) client.describe_tags(Filters=[{"Name": "resource-id", "Values": [instance.id]}])[
"Tags"
].should.have.length_of(0)
instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) instance.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
client.describe_tags()["Tags"].should.have.length_of(1) client.describe_tags(Filters=[{"Name": "resource-id", "Values": [instance.id]}])[
"Tags"
].should.have.length_of(1)
# Specifying key and value # Specifying key and value
instance.delete_tags(Tags=[{"Key": "a key", "Value": "some value"}]) instance.delete_tags(Tags=[{"Key": "a key", "Value": "some value"}])
client.describe_tags()["Tags"].should.have.length_of(0) client.describe_tags(Filters=[{"Name": "resource-id", "Values": [instance.id]}])[
"Tags"
].should.have.length_of(0)
# Has boto3 equivalent # Has boto3 equivalent
@ -165,10 +171,13 @@ def test_get_all_tags_with_special_characters_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
instance.create_tags(Tags=[{"Key": "a key", "Value": "some<> value"}]) tag_key = str(uuid4())
instance.create_tags(Tags=[{"Key": tag_key, "Value": "some<> value"}])
tag = client.describe_tags()["Tags"][0] tag = client.describe_tags(Filters=[{"Name": "key", "Values": [tag_key]}])["Tags"][
tag.should.have.key("Key").equal("a key") 0
]
tag.should.have.key("Key").equal(tag_key)
tag.should.have.key("Value").equal("some<> value") tag.should.have.key("Value").equal("some<> value")
@ -220,7 +229,9 @@ def test_create_tags_boto3():
) )
client.create_tags(Resources=[instance.id], Tags=tag_list) client.create_tags(Resources=[instance.id], Tags=tag_list)
tags = client.describe_tags()["Tags"] tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [instance.id]}]
)["Tags"]
tags.should.have.length_of(3) tags.should.have.length_of(3)
for expected_tag in tag_list: for expected_tag in tag_list:
tags.should.contain( tags.should.contain(
@ -285,7 +296,9 @@ def test_tag_limit_exceeded_boto3():
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("TagLimitExceeded") ex.value.response["Error"]["Code"].should.equal("TagLimitExceeded")
tags = client.describe_tags()["Tags"] tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [instance.id]}]
)["Tags"]
tags.should.have.length_of(1) tags.should.have.length_of(1)
tags[0].should.have.key("Key").equal("a key") tags[0].should.have.key("Key").equal("a key")
tags[0].should.have.key("Value").equal("a value") tags[0].should.have.key("Value").equal("a value")
@ -375,30 +388,30 @@ def test_get_all_tags_resource_filter_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
inst_tag_key = str(uuid4())[0:6]
client.create_tags( client.create_tags(
Resources=[instance.id], Resources=[instance.id], Tags=[{"Key": inst_tag_key, "Value": "some value"}],
Tags=[{"Key": "an instance key", "Value": "some value"}],
) )
image = instance.create_image(Name="test-ami", Description="this is a test ami") image = instance.create_image(Name="test-ami", Description="this is a test ami")
image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}]) image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}])
expected = { expected = {
"Key": "an instance key", "Key": inst_tag_key,
"ResourceId": instance.id, "ResourceId": instance.id,
"ResourceType": "instance", "ResourceType": "instance",
"Value": "some value", "Value": "some value",
} }
tags = client.describe_tags( our_tags = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [instance.id]}] Filters=[{"Name": "resource-id", "Values": [instance.id]}]
)["Tags"] )["Tags"]
tags.should.equal([expected]) our_tags.should.equal([expected])
tags = client.describe_tags( instances = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["instance"]}] Filters=[{"Name": "resource-type", "Values": ["instance"]}]
)["Tags"] )["Tags"]
tags.should.equal([expected]) instances.should.contain(expected)
tags = client.describe_tags( tags = client.describe_tags(Filters=[{"Name": "key", "Values": [inst_tag_key]}])[
Filters=[{"Name": "key", "Values": ["an instance key"]}] "Tags"
)["Tags"] ]
tags.should.equal([expected]) tags.should.equal([expected])
expected = { expected = {
@ -407,14 +420,14 @@ def test_get_all_tags_resource_filter_boto3():
"ResourceType": "image", "ResourceType": "image",
"Value": "some value", "Value": "some value",
} }
tags = client.describe_tags( my_image = client.describe_tags(
Filters=[{"Name": "resource-id", "Values": [image.id]}] Filters=[{"Name": "resource-id", "Values": [image.id]}]
)["Tags"] )["Tags"]
tags.should.equal([expected]) my_image.should.equal([expected])
tags = client.describe_tags( all_images = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["image"]}] Filters=[{"Name": "resource-type", "Values": ["image"]}]
)["Tags"] )["Tags"]
tags.should.equal([expected]) all_images.should.contain(expected)
tags = client.describe_tags( tags = client.describe_tags(
Filters=[{"Name": "resource-type", "Values": ["unknown"]}] Filters=[{"Name": "resource-type", "Values": ["unknown"]}]
@ -538,9 +551,11 @@ def test_get_all_tags_value_filter_boto3():
image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}]) image.create_tags(Tags=[{"Key": "an image key", "Value": "some value"}])
def filter_by_value(query, expected): def filter_by_value(query, expected):
filter = {"Name": "value", "Values": [query]} filters = [{"Name": "value", "Values": [query]}]
tags = client.describe_tags(Filters=[filter])["Tags"] tags = retrieve_all_tagged(client, filters)
set([t["ResourceId"] for t in tags]).should.equal(set(expected)) actual = set([t["ResourceId"] for t in tags])
for e in expected:
actual.should.contain(e)
filter_by_value("some value", [instance_a.id, image.id]) filter_by_value("some value", [instance_a.id, image.id])
filter_by_value("some*value", [instance_a.id, instance_b.id, image.id]) filter_by_value("some*value", [instance_a.id, instance_b.id, image.id])
@ -593,17 +608,17 @@ def test_retrieved_instances_must_contain_their_tags_boto3():
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=1, MaxCount=1)[0]
reservations = client.describe_instances()["Reservations"] all_instances = retrieve_all_instances(client)
reservations.should.have.length_of(1) ours = [i for i in all_instances if i["InstanceId"] == instance.id]
instances = reservations[0]["Instances"] ours.should.have.length_of(1)
instances.should.have.length_of(1) ours[0]["InstanceId"].should.equal(instance.id)
instances[0]["InstanceId"].should.equal(instance.id) ours[0].shouldnt.have.key("Tags")
instances[0].shouldnt.have.key("Tags")
client.create_tags(Resources=[instance.id], Tags=[tags_to_be_set]) client.create_tags(Resources=[instance.id], Tags=[tags_to_be_set])
reservations = client.describe_instances()["Reservations"]
instance = reservations[0]["Instances"][0] all_instances = retrieve_all_instances(client)
retrieved_tags = instance["Tags"] ours = [i for i in all_instances if i["InstanceId"] == instance.id]
retrieved_tags = ours[0]["Tags"]
# Check whether tag is present with correct value # Check whether tag is present with correct value
retrieved_tags.should.equal([{"Key": tag_key, "Value": tag_value}]) retrieved_tags.should.equal([{"Key": tag_key, "Value": tag_value}])
@ -822,30 +837,43 @@ def test_delete_tag_empty_resource():
def test_retrieve_resource_with_multiple_tags(): def test_retrieve_resource_with_multiple_tags():
ec2 = boto3.resource("ec2", region_name="us-west-1") ec2 = boto3.resource("ec2", region_name="us-west-1")
blue, green = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2) blue, green = ec2.create_instances(ImageId=EXAMPLE_AMI_ID, MinCount=2, MaxCount=2)
tag_val1 = str(uuid4())
ec2.create_tags( ec2.create_tags(
Resources=[blue.instance_id], Resources=[blue.instance_id],
Tags=[ Tags=[
{"Key": "environment", "Value": "blue"}, {"Key": "environment", "Value": tag_val1},
{"Key": "application", "Value": "api"}, {"Key": "application", "Value": "api"},
], ],
) )
tag_val2 = str(uuid4())
ec2.create_tags( ec2.create_tags(
Resources=[green.instance_id], Resources=[green.instance_id],
Tags=[ Tags=[
{"Key": "environment", "Value": "green"}, {"Key": "environment", "Value": tag_val2},
{"Key": "application", "Value": "api"}, {"Key": "application", "Value": "api"},
], ],
) )
green_instances = list(ec2.instances.filter(Filters=(get_filter("green")))) green_instances = list(ec2.instances.filter(Filters=(get_filter(tag_val2))))
green_instances.should.equal([green]) green_instances.should.equal([green])
blue_instances = list(ec2.instances.filter(Filters=(get_filter("blue")))) blue_instances = list(ec2.instances.filter(Filters=(get_filter(tag_val1))))
blue_instances.should.equal([blue]) blue_instances.should.equal([blue])
def get_filter(color): def get_filter(tag_val):
return [ return [
{"Name": "tag-key", "Values": ["application"]}, {"Name": "tag-key", "Values": ["application"]},
{"Name": "tag-value", "Values": ["api"]}, {"Name": "tag-value", "Values": ["api"]},
{"Name": "tag-key", "Values": ["environment"]}, {"Name": "tag-key", "Values": ["environment"]},
{"Name": "tag-value", "Values": [color]}, {"Name": "tag-value", "Values": [tag_val]},
] ]
def retrieve_all_tagged(client, filters=[]):
resp = client.describe_tags(Filters=filters)
tags = resp["Tags"]
token = resp.get("NextToken")
while token:
resp = client.describe_tags(Filters=filters, NextToken=token)
tags.extend(resp["Tags"])
token = resp.get("Token")
return tags

View File

@ -1,11 +1,14 @@
import boto3 import boto3
import sure # noqa import sure # noqa
from moto import mock_ec2 from moto import mock_ec2, settings
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from unittest import SkipTest
@mock_ec2 @mock_ec2
def test_describe_transit_gateways(): def test_describe_transit_gateways():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
response = ec2.describe_transit_gateways() response = ec2.describe_transit_gateways()
response.should.have.key("TransitGateways").equal([]) response.should.have.key("TransitGateways").equal([])
@ -34,8 +37,14 @@ def test_create_transit_gateway():
options.should.have.key("DnsSupport").equal("disable") options.should.have.key("DnsSupport").equal("disable")
# #
# Verify we can retrieve it # Verify we can retrieve it
response = ec2.describe_transit_gateways() all_gateways = retrieve_all_transit_gateways(ec2)
gateways = response["TransitGateways"] [gw["TransitGatewayId"] for gw in all_gateways].should.contain(
gateway["TransitGatewayId"]
)
gateways = ec2.describe_transit_gateways(
TransitGatewayIds=[gateway["TransitGatewayId"]]
)["TransitGateways"]
gateways.should.have.length_of(1) gateways.should.have.length_of(1)
gateways[0].should.have.key("CreationTime") gateways[0].should.have.key("CreationTime")
gateways[0].should.have.key("TransitGatewayArn").equal( gateways[0].should.have.key("TransitGatewayArn").equal(
@ -79,32 +88,57 @@ def test_create_transit_gateway_with_tags():
def test_delete_transit_gateway(): def test_delete_transit_gateway():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
g = ec2.create_transit_gateway(Description="my first gateway")["TransitGateway"] g = ec2.create_transit_gateway(Description="my first gateway")["TransitGateway"]
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(1) g_id = g["TransitGatewayId"]
ec2.delete_transit_gateway(TransitGatewayId=g["TransitGatewayId"]) all_gateways = retrieve_all_transit_gateways(ec2)
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(0) [g["TransitGatewayId"] for g in all_gateways].should.contain(g_id)
ec2.delete_transit_gateway(TransitGatewayId=g_id)
all_gateways = retrieve_all_transit_gateways(ec2)
[g["TransitGatewayId"] for g in all_gateways].shouldnt.contain(g_id)
@mock_ec2
def test_describe_transit_gateway_by_id():
ec2 = boto3.client("ec2", region_name="us-west-1")
g1 = ec2.create_transit_gateway(Description="my first gatway")["TransitGateway"]
g2 = ec2.create_transit_gateway(Description="my second gatway")["TransitGateway"]
g2_id = g2["TransitGatewayId"]
g3 = ec2.create_transit_gateway(Description="my third gatway")["TransitGateway"]
my_gateway = ec2.describe_transit_gateways(TransitGatewayIds=[g2_id])[
"TransitGateways"
][0]
my_gateway["TransitGatewayId"].should.equal(g2_id)
my_gateway["Description"].should.equal("my second gatway")
@mock_ec2 @mock_ec2
def test_modify_transit_gateway(): def test_modify_transit_gateway():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
g = ec2.create_transit_gateway(Description="my first gatway")["TransitGateway"] g = ec2.create_transit_gateway(Description="my first gatway")["TransitGateway"]
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(1) g_id = g["TransitGatewayId"]
ec2.describe_transit_gateways()["TransitGateways"][0]["Description"].should.equal(
"my first gatway" my_gateway = ec2.describe_transit_gateways(TransitGatewayIds=[g_id])[
"TransitGateways"
][0]
my_gateway["Description"].should.equal("my first gatway")
resp = ec2.modify_transit_gateway(
TransitGatewayId=g_id, Description="my first gateway"
) )
ec2.modify_transit_gateway( my_gateway = ec2.describe_transit_gateways(TransitGatewayIds=[g_id])[
TransitGatewayId=g["TransitGatewayId"], Description="my first gateway" "TransitGateways"
) ][0]
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(1) my_gateway["Description"].should.equal("my first gateway")
ec2.describe_transit_gateways()["TransitGateways"][0]["Description"].should.equal(
"my first gateway"
)
@mock_ec2 @mock_ec2
def test_describe_transit_gateway_vpc_attachments(): def test_describe_transit_gateway_vpc_attachments():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
response = ec2.describe_transit_gateway_vpc_attachments() response = ec2.describe_transit_gateway_vpc_attachments()
response.should.have.key("TransitGatewayVpcAttachments").equal([]) response.should.have.key("TransitGatewayVpcAttachments").equal([])
@ -112,11 +146,24 @@ def test_describe_transit_gateway_vpc_attachments():
@mock_ec2 @mock_ec2
def test_describe_transit_gateway_attachments(): def test_describe_transit_gateway_attachments():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
response = ec2.describe_transit_gateway_attachments() response = ec2.describe_transit_gateway_attachments()
response.should.have.key("TransitGatewayAttachments").equal([]) response.should.have.key("TransitGatewayAttachments").equal([])
def retrieve_all_transit_gateways(ec2):
resp = ec2.describe_transit_gateways()
all_tg = resp["TransitGateways"]
token = resp.get("NextToken")
while token:
resp = ec2.describe_transit_gateways(NextToken=token)
all_tg.extend(resp["TransitGateways"])
token = resp.get("NextToken")
return all_tg
@mock_ec2 @mock_ec2
def test_create_transit_gateway_vpn_attachment(): def test_create_transit_gateway_vpn_attachment():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
@ -130,19 +177,29 @@ def test_create_transit_gateway_vpn_attachment():
VpnGatewayId=vpn_gateway["VpnGatewayId"], VpnGatewayId=vpn_gateway["VpnGatewayId"],
CustomerGatewayId=customer_gateway["CustomerGatewayId"], CustomerGatewayId=customer_gateway["CustomerGatewayId"],
TransitGatewayId="gateway_id", TransitGatewayId="gateway_id",
).get("VpnConnection", {}) )["VpnConnection"]
vpn_conn_id = vpn_connection["VpnConnectionId"]
# #
# Verify we can retrieve it as a general attachment # Verify we can retrieve it as a general attachment
attachments = ec2.describe_transit_gateway_attachments()[ attachments = retrieve_all_attachments(ec2)
"TransitGatewayAttachments" [a["ResourceId"] for a in attachments].should.contain(vpn_conn_id)
]
attachments.should.have.length_of(1)
attachments[0].should.have.key("ResourceType").equal("vpn") my_attachments = [a for a in attachments if a["ResourceId"] == vpn_conn_id]
attachments[0].should.have.key("ResourceId").equal( my_attachments.should.have.length_of(1)
vpn_connection["VpnConnectionId"]
) my_attachments[0].should.have.key("ResourceType").equal("vpn")
def retrieve_all_attachments(client):
resp = client.describe_transit_gateway_attachments()
att = resp["TransitGatewayAttachments"]
token = resp.get("NextToken")
while token:
resp = client.describe_transit_gateway_attachments(NextToken=token)
att.extend(resp["TransitGatewayAttachments"])
token = resp.get("NextToken")
return att
@mock_ec2 @mock_ec2
@ -168,18 +225,18 @@ def test_create_and_describe_transit_gateway_vpc_attachment():
attachment.should.have.key("Tags").equal([]) attachment.should.have.key("Tags").equal([])
# #
# Verify we can retrieve it as a VPC attachment # Verify we can retrieve it as a VPC attachment
attachments = ec2.describe_transit_gateway_vpc_attachments()[ attachments = ec2.describe_transit_gateway_vpc_attachments(
"TransitGatewayVpcAttachments" TransitGatewayAttachmentIds=[attachment["TransitGatewayAttachmentId"]]
] )["TransitGatewayVpcAttachments"]
attachments.should.have.length_of(1) attachments.should.have.length_of(1)
attachments[0].should.have.key("CreationTime") attachments[0].should.have.key("CreationTime")
del attachments[0]["CreationTime"] del attachments[0]["CreationTime"]
attachment.should.equal(attachments[0]) attachment.should.equal(attachments[0])
# #
# Verify we can retrieve it as a general attachment # Verify we can retrieve it as a general attachment
attachments = ec2.describe_transit_gateway_attachments()[ attachments = ec2.describe_transit_gateway_attachments(
"TransitGatewayAttachments" TransitGatewayAttachmentIds=[attachment["TransitGatewayAttachmentId"]]
] )["TransitGatewayAttachments"]
attachments.should.have.length_of(1) attachments.should.have.length_of(1)
attachments[0].should.have.key("CreationTime") attachments[0].should.have.key("CreationTime")
attachments[0].should.have.key("TransitGatewayOwnerId").equal(ACCOUNT_ID) attachments[0].should.have.key("TransitGatewayOwnerId").equal(ACCOUNT_ID)
@ -196,6 +253,8 @@ def test_create_and_describe_transit_gateway_vpc_attachment():
@mock_ec2 @mock_ec2
def test_describe_transit_gateway_route_tables(): def test_describe_transit_gateway_route_tables():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
response = ec2.describe_transit_gateway_route_tables() response = ec2.describe_transit_gateway_route_tables()
response.should.have.key("TransitGatewayRouteTables").equal([]) response.should.have.key("TransitGatewayRouteTables").equal([])
@ -204,8 +263,6 @@ def test_describe_transit_gateway_route_tables():
@mock_ec2 @mock_ec2
def test_create_transit_gateway_route_table(): def test_create_transit_gateway_route_table():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"]
tables.should.equal([])
gateway_id = ec2.create_transit_gateway(Description="g")["TransitGateway"][ gateway_id = ec2.create_transit_gateway(Description="g")["TransitGateway"][
"TransitGatewayId" "TransitGatewayId"
@ -221,8 +278,10 @@ def test_create_transit_gateway_route_table():
table.should.have.key("CreationTime") table.should.have.key("CreationTime")
table.should.have.key("Tags").equals([]) table.should.have.key("Tags").equals([])
tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] tables = ec2.describe_transit_gateway_route_tables(
tables.should.have.length_of(2) TransitGatewayRouteTableIds=[table["TransitGatewayRouteTableId"]]
)["TransitGatewayRouteTables"]
tables.should.have.length_of(1)
@mock_ec2 @mock_ec2
@ -260,18 +319,23 @@ def test_delete_transit_gateway_route_table():
table = ec2.create_transit_gateway_route_table(TransitGatewayId=gateway_id)[ table = ec2.create_transit_gateway_route_table(TransitGatewayId=gateway_id)[
"TransitGatewayRouteTable" "TransitGatewayRouteTable"
] ]
table_id = table["TransitGatewayRouteTableId"]
tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] tables = ec2.describe_transit_gateway_route_tables(
tables.should.have.length_of(2) TransitGatewayRouteTableIds=[table_id]
)["TransitGatewayRouteTables"]
tables.should.have.length_of(1)
tables[0]["State"].should.equal("available")
table = ec2.delete_transit_gateway_route_table( table = ec2.delete_transit_gateway_route_table(TransitGatewayRouteTableId=table_id)
TransitGatewayRouteTableId=table["TransitGatewayRouteTableId"]
)
table["TransitGatewayRouteTable"].should.have.key("State").equals("deleted") table["TransitGatewayRouteTable"].should.have.key("State").equals("deleted")
tables = ec2.describe_transit_gateway_route_tables()["TransitGatewayRouteTables"] tables = ec2.describe_transit_gateway_route_tables(
tables.should.have.length_of(2) TransitGatewayRouteTableIds=[table_id]
)["TransitGatewayRouteTables"]
tables.should.have.length_of(1)
tables[0]["State"].should.equal("deleted")
@mock_ec2 @mock_ec2
@ -528,7 +592,8 @@ def test_delete_transit_gateway_vpc_attachment():
)["TransitGatewayVpcAttachment"]["TransitGatewayAttachmentId"] )["TransitGatewayVpcAttachment"]["TransitGatewayAttachmentId"]
available = ec2.describe_transit_gateway_vpc_attachments( available = ec2.describe_transit_gateway_vpc_attachments(
Filters=[{"Name": "state", "Values": ["available"]}] TransitGatewayAttachmentIds=[a1, a2],
Filters=[{"Name": "state", "Values": ["available"]}],
)["TransitGatewayVpcAttachments"] )["TransitGatewayVpcAttachments"]
available.should.have.length_of(2) available.should.have.length_of(2)
@ -538,9 +603,9 @@ def test_delete_transit_gateway_vpc_attachment():
a1_removed.should.have.key("TransitGatewayAttachmentId").equal(a1) a1_removed.should.have.key("TransitGatewayAttachmentId").equal(a1)
a1_removed.should.have.key("State").equal("deleted") a1_removed.should.have.key("State").equal("deleted")
all_attchmnts = ec2.describe_transit_gateway_vpc_attachments()[ all_attchmnts = ec2.describe_transit_gateway_vpc_attachments(
"TransitGatewayVpcAttachments" TransitGatewayAttachmentIds=[a1, a2]
] )["TransitGatewayVpcAttachments"]
all_attchmnts.should.have.length_of(1) all_attchmnts.should.have.length_of(1)
[a["TransitGatewayAttachmentId"] for a in all_attchmnts].should.equal([a2]) [a["TransitGatewayAttachmentId"] for a in all_attchmnts].should.equal([a2])

View File

@ -9,6 +9,7 @@ from moto import (
mock_cloudformation, mock_cloudformation,
mock_ec2, mock_ec2,
) )
from uuid import uuid4
@mock_cloudformation @mock_cloudformation
@ -17,8 +18,6 @@ def test_transit_gateway_by_cloudformation_simple():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
cf_client = boto3.client("cloudformation", "us-east-1") cf_client = boto3.client("cloudformation", "us-east-1")
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(0)
template = { template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Description": "Template for Transit Gateway creation.", "Description": "Template for Transit Gateway creation.",
@ -30,9 +29,17 @@ def test_transit_gateway_by_cloudformation_simple():
}, },
} }
template = json.dumps(template) template = json.dumps(template)
cf_client.create_stack(StackName="test_stack", TemplateBody=template) stack_name = str(uuid4())
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
gateways = ec2.describe_transit_gateways()["TransitGateways"] resources = cf_client.list_stack_resources(StackName=stack_name)[
"StackResourceSummaries"
]
gateway_id = resources[0]["PhysicalResourceId"]
gateways = ec2.describe_transit_gateways(TransitGatewayIds=[gateway_id])[
"TransitGateways"
]
gateways.should.have.length_of(1) gateways.should.have.length_of(1)
gateways[0]["TransitGatewayId"].should.match("tgw-[0-9a-z]+") gateways[0]["TransitGatewayId"].should.match("tgw-[0-9a-z]+")
gateways[0]["State"].should.equal("available") gateways[0]["State"].should.equal("available")
@ -50,8 +57,6 @@ def test_transit_gateway_by_cloudformation():
ec2 = boto3.client("ec2", region_name="us-east-1") ec2 = boto3.client("ec2", region_name="us-east-1")
cf_client = boto3.client("cloudformation", "us-east-1") cf_client = boto3.client("cloudformation", "us-east-1")
ec2.describe_transit_gateways()["TransitGateways"].should.have.length_of(0)
template = { template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Description": "Template for Transit Gateway creation.", "Description": "Template for Transit Gateway creation.",
@ -69,9 +74,17 @@ def test_transit_gateway_by_cloudformation():
}, },
} }
template = json.dumps(template) template = json.dumps(template)
cf_client.create_stack(StackName="test_stack", TemplateBody=template) stack_name = str(uuid4())
cf_client.create_stack(StackName=stack_name, TemplateBody=template)
gateways = ec2.describe_transit_gateways()["TransitGateways"] resources = cf_client.list_stack_resources(StackName=stack_name)[
"StackResourceSummaries"
]
gateway_id = resources[0]["PhysicalResourceId"]
gateways = ec2.describe_transit_gateways(TransitGatewayIds=[gateway_id])[
"TransitGateways"
]
gateways.should.have.length_of(1) gateways.should.have.length_of(1)
gateways[0]["TransitGatewayId"].should.match("tgw-[0-9a-z]+") gateways[0]["TransitGatewayId"].should.match("tgw-[0-9a-z]+")
gateways[0]["State"].should.equal("available") gateways[0]["State"].should.equal("available")
@ -82,5 +95,5 @@ def test_transit_gateway_by_cloudformation():
tags = gateways[0].get("Tags", {}) tags = gateways[0].get("Tags", {})
tags.should.have.length_of(4) tags.should.have.length_of(4)
tags.should.contain({"Key": "foo", "Value": "bar"}) tags.should.contain({"Key": "foo", "Value": "bar"})
tags.should.contain({"Key": "aws:cloudformation:stack-name", "Value": "test_stack"}) tags.should.contain({"Key": "aws:cloudformation:stack-name", "Value": stack_name})
tags.should.contain({"Key": "aws:cloudformation:logical-id", "Value": "ttg"}) tags.should.contain({"Key": "aws:cloudformation:logical-id", "Value": "ttg"})

View File

@ -1,11 +1,14 @@
import boto3 import boto3
import sure # noqa import sure # noqa
from moto import mock_ec2 from moto import mock_ec2, settings
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from unittest import SkipTest
@mock_ec2 @mock_ec2
def test_describe_transit_gateway_peering_attachment_empty(): def test_describe_transit_gateway_peering_attachment_empty():
if settings.TEST_SERVER_MODE:
raise SkipTest("ServerMode is not guaranteed to be empty")
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
all_attachments = ec2.describe_transit_gateway_peering_attachments()[ all_attachments = ec2.describe_transit_gateway_peering_attachments()[
@ -40,7 +43,12 @@ def test_create_and_describe_transit_gateway_peering_attachment():
all_attachments = ec2.describe_transit_gateway_peering_attachments()[ all_attachments = ec2.describe_transit_gateway_peering_attachments()[
"TransitGatewayPeeringAttachments" "TransitGatewayPeeringAttachments"
] ]
all_attachments.should.equal([attachment]) our_attachment = [
att
for att in all_attachments
if att["TransitGatewayAttachmentId"] == attachment["TransitGatewayAttachmentId"]
]
our_attachment.should.equal([attachment])
@mock_ec2 @mock_ec2
@ -62,7 +70,12 @@ def test_describe_transit_gateway_peering_attachment_by_filters():
all_attachments = ec2.describe_transit_gateway_peering_attachments()[ all_attachments = ec2.describe_transit_gateway_peering_attachments()[
"TransitGatewayPeeringAttachments" "TransitGatewayPeeringAttachments"
] ]
all_attachments.should.have.length_of(3) ours = [
a
for a in all_attachments
if a["TransitGatewayAttachmentId"] in [attchmnt1, attchmnt2, attchmnt3]
]
ours.should.have.length_of(3)
find_1 = ec2.describe_transit_gateway_peering_attachments( find_1 = ec2.describe_transit_gateway_peering_attachments(
TransitGatewayAttachmentIds=[attchmnt1] TransitGatewayAttachmentIds=[attchmnt1]
@ -81,12 +94,12 @@ def test_describe_transit_gateway_peering_attachment_by_filters():
)["TransitGatewayPeeringAttachments"] )["TransitGatewayPeeringAttachments"]
[a["TransitGatewayAttachmentId"] for a in find_3].should.equal([attchmnt3]) [a["TransitGatewayAttachmentId"] for a in find_3].should.equal([attchmnt3])
find_all = ec2.describe_transit_gateway_peering_attachments( filters = [{"Name": "state", "Values": ["available"]}]
Filters=[{"Name": "state", "Values": ["available"]}] find_all = retrieve_all_attachments(ec2, filters)
)["TransitGatewayPeeringAttachments"] all_ids = [a["TransitGatewayAttachmentId"] for a in find_all]
[a["TransitGatewayAttachmentId"] for a in find_all].should.equal( all_ids.should.contain(attchmnt1)
[attchmnt1, attchmnt2, attchmnt3] all_ids.should.contain(attchmnt2)
) all_ids.should.contain(attchmnt3)
find_none = ec2.describe_transit_gateway_peering_attachments( find_none = ec2.describe_transit_gateway_peering_attachments(
Filters=[{"Name": "state", "Values": ["unknown"]}] Filters=[{"Name": "state", "Values": ["unknown"]}]
@ -117,9 +130,9 @@ def test_create_and_accept_transit_gateway_peering_attachment():
TransitGatewayAttachmentId=attchment_id TransitGatewayAttachmentId=attchment_id
) )
attachment = ec2.describe_transit_gateway_peering_attachments()[ attachment = ec2.describe_transit_gateway_peering_attachments(
"TransitGatewayPeeringAttachments" TransitGatewayAttachmentIds=[attchment_id]
][0] )["TransitGatewayPeeringAttachments"][0]
attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id) attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id)
attachment.should.have.key("State").equal("available") attachment.should.have.key("State").equal("available")
@ -139,9 +152,9 @@ def test_create_and_reject_transit_gateway_peering_attachment():
TransitGatewayAttachmentId=attchment_id TransitGatewayAttachmentId=attchment_id
) )
attachment = ec2.describe_transit_gateway_peering_attachments()[ attachment = ec2.describe_transit_gateway_peering_attachments(
"TransitGatewayPeeringAttachments" TransitGatewayAttachmentIds=[attchment_id]
][0] )["TransitGatewayPeeringAttachments"][0]
attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id) attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id)
attachment.should.have.key("State").equal("rejected") attachment.should.have.key("State").equal("rejected")
@ -161,9 +174,9 @@ def test_create_and_delete_transit_gateway_peering_attachment():
TransitGatewayAttachmentId=attchment_id TransitGatewayAttachmentId=attchment_id
) )
attachment = ec2.describe_transit_gateway_peering_attachments()[ attachment = ec2.describe_transit_gateway_peering_attachments(
"TransitGatewayPeeringAttachments" TransitGatewayAttachmentIds=[attchment_id]
][0] )["TransitGatewayPeeringAttachments"][0]
attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id) attachment.should.have.key("TransitGatewayAttachmentId").equal(attchment_id)
attachment.should.have.key("State").equal("deleted") attachment.should.have.key("State").equal("deleted")
@ -175,3 +188,16 @@ def create_peering_attachment(ec2, gateway_id1, gateway_id2):
PeerAccountId=ACCOUNT_ID, PeerAccountId=ACCOUNT_ID,
PeerRegion="us-east-1", PeerRegion="us-east-1",
)["TransitGatewayPeeringAttachment"]["TransitGatewayAttachmentId"] )["TransitGatewayPeeringAttachment"]["TransitGatewayAttachmentId"]
def retrieve_all_attachments(client, filters=[]):
resp = client.describe_transit_gateway_peering_attachments(Filters=filters)
attmnts = resp["TransitGatewayPeeringAttachments"]
token = resp.get("NextToken")
while token:
resp = client.describe_transit_gateway_peering_attachments(
Filters=filters, NextToken=token
)
attmnts.extend(resp["TransitGatewayPeeringAttachments"])
token = resp.get("NextToken")
return attmnts

View File

@ -6,6 +6,7 @@ import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from .test_tags import retrieve_all_tagged
@mock_ec2 @mock_ec2
@ -146,7 +147,9 @@ def test_describe_vpn_gateway_boto3():
Type="ipsec.1", AvailabilityZone="us-east-1a" Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"] )["VpnGateway"]
vgws = client.describe_vpn_gateways()["VpnGateways"] vgws = client.describe_vpn_gateways(VpnGatewayIds=[vpn_gateway["VpnGatewayId"]])[
"VpnGateways"
]
vgws.should.have.length_of(1) vgws.should.have.length_of(1)
gateway = vgws[0] gateway = vgws[0]
@ -171,15 +174,15 @@ def test_describe_vpn_connections_state_filter_attached():
ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id) ec2.attach_vpn_gateway(VpcId=vpc_id, VpnGatewayId=gateway_id)
gateways = ec2.describe_vpn_gateways( all_gateways = retrieve_all(
Filters=[{"Name": "attachment.state", "Values": ["attached"]}] ec2, [{"Name": "attachment.state", "Values": ["attached"]}]
) )
gateways["VpnGateways"].should.have.length_of(1) [gw["VpnGatewayId"] for gw in all_gateways].should.contain(gateway_id)
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
gateways["VpnGateways"][0]["VpcAttachments"].should.contain( my_gateway = [gw for gw in all_gateways if gw["VpnGatewayId"] == gateway_id][0]
{"State": "attached", "VpcId": vpc_id}
) my_gateway["VpcAttachments"].should.contain({"State": "attached", "VpcId": vpc_id})
@mock_ec2 @mock_ec2
@ -223,12 +226,9 @@ def test_describe_vpn_connections_type_filter_match():
gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1") gateway = ec2.create_vpn_gateway(AvailabilityZone="us-east-1a", Type="ipsec.1")
gateway_id = gateway["VpnGateway"]["VpnGatewayId"] gateway_id = gateway["VpnGateway"]["VpnGatewayId"]
gateways = ec2.describe_vpn_gateways( my_gateways = retrieve_all(ec2, [{"Name": "type", "Values": ["ipsec.1"]}])
Filters=[{"Name": "type", "Values": ["ipsec.1"]}]
)
gateways["VpnGateways"].should.have.length_of(1) [gw["VpnGatewayId"] for gw in my_gateways].should.contain(gateway_id)
gateways["VpnGateways"][0]["VpnGatewayId"].should.equal(gateway_id)
@mock_ec2 @mock_ec2
@ -270,10 +270,11 @@ def test_vpn_gateway_vpc_attachment_boto3():
vpn_gateway = client.create_vpn_gateway( vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a" Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"] )["VpnGateway"]
vpng_id = vpn_gateway["VpnGatewayId"]
client.attach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id) client.attach_vpn_gateway(VpnGatewayId=vpng_id, VpcId=vpc.id)
gateway = client.describe_vpn_gateways()["VpnGateways"][0] gateway = client.describe_vpn_gateways(VpnGatewayIds=[vpng_id])["VpnGateways"][0]
attachments = gateway["VpcAttachments"] attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "attached", "VpcId": vpc.id}]) attachments.should.equal([{"State": "attached", "VpcId": vpc.id}])
@ -297,9 +298,10 @@ def test_delete_vpn_gateway_boto3():
vpn_gateway = client.create_vpn_gateway( vpn_gateway = client.create_vpn_gateway(
Type="ipsec.1", AvailabilityZone="us-east-1a" Type="ipsec.1", AvailabilityZone="us-east-1a"
)["VpnGateway"] )["VpnGateway"]
vpng_id = vpn_gateway["VpnGatewayId"]
client.delete_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"]) client.delete_vpn_gateway(VpnGatewayId=vpng_id)
gateways = client.describe_vpn_gateways()["VpnGateways"] gateways = client.describe_vpn_gateways(VpnGatewayIds=[vpng_id])["VpnGateways"]
gateways.should.have.length_of(1) gateways.should.have.length_of(1)
gateways[0].should.have.key("State").equal("deleted") gateways[0].should.have.key("State").equal("deleted")
@ -333,9 +335,10 @@ def test_vpn_gateway_tagging_boto3():
Tags=[{"Key": "a key", "Value": "some value"}], Tags=[{"Key": "a key", "Value": "some value"}],
) )
tag = client.describe_tags()["Tags"][0] all_tags = retrieve_all_tagged(client)
tag.should.have.key("Key").equal("a key") ours = [a for a in all_tags if a["ResourceId"] == vpn_gateway["VpnGatewayId"]][0]
tag.should.have.key("Value").equal("some value") ours.should.have.key("Key").equal("a key")
ours.should.have.key("Value").equal("some value")
vpn_gateway = client.describe_vpn_gateways()["VpnGateways"][0] vpn_gateway = client.describe_vpn_gateways()["VpnGateways"][0]
# TODO: Fixme: Tags is currently empty # TODO: Fixme: Tags is currently empty
@ -376,15 +379,27 @@ def test_detach_vpn_gateway_boto3():
Type="ipsec.1", AvailabilityZone="us-east-1a" Type="ipsec.1", AvailabilityZone="us-east-1a"
) )
vpn_gateway = vpn_gateway["VpnGateway"] vpn_gateway = vpn_gateway["VpnGateway"]
vpng_id = vpn_gateway["VpnGatewayId"]
client.attach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id) client.attach_vpn_gateway(VpnGatewayId=vpng_id, VpcId=vpc.id)
gateway = client.describe_vpn_gateways()["VpnGateways"][0] gateway = client.describe_vpn_gateways(VpnGatewayIds=[vpng_id])["VpnGateways"][0]
attachments = gateway["VpcAttachments"] attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "attached", "VpcId": vpc.id}]) attachments.should.equal([{"State": "attached", "VpcId": vpc.id}])
client.detach_vpn_gateway(VpnGatewayId=vpn_gateway["VpnGatewayId"], VpcId=vpc.id) client.detach_vpn_gateway(VpnGatewayId=vpng_id, VpcId=vpc.id)
gateway = client.describe_vpn_gateways()["VpnGateways"][0] gateway = client.describe_vpn_gateways(VpnGatewayIds=[vpng_id])["VpnGateways"][0]
attachments = gateway["VpcAttachments"] attachments = gateway["VpcAttachments"]
attachments.should.equal([{"State": "detached", "VpcId": vpc.id}]) attachments.should.equal([{"State": "detached", "VpcId": vpc.id}])
def retrieve_all(client, filters=[]):
resp = client.describe_vpn_gateways(Filters=filters)
all_gateways = resp["VpnGateways"]
token = resp.get("NextToken")
while token:
resp = client.describe_vpn_gateways(Filters=filters)
all_gateways.extend(resp["VpnGateways"])
token = resp.get("NextToken")
return all_gateways

View File

@ -4,11 +4,16 @@ import pytest
import boto3 import boto3
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_ec2 from moto import mock_ec2, settings
from unittest import SkipTest
@mock_ec2 @mock_ec2
def test_describe_vpc_endpoint_services_bad_args(): def test_describe_vpc_endpoint_services_bad_args():
if settings.TEST_SERVER_MODE:
# Long-running operation - doesn't quite work in ServerMode, with parallel tests
# Probably needs some locking to force the initialization to only occur once
raise SkipTest("Can't run in ServerMode")
"""Verify exceptions are raised for bad arguments.""" """Verify exceptions are raised for bad arguments."""
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")

View File

@ -64,10 +64,18 @@ def test_vpc_peering_connections_get_all_boto3():
ec2 = boto3.resource("ec2", region_name="us-east-1") ec2 = boto3.resource("ec2", region_name="us-east-1")
client = boto3.client("ec2", region_name="us-east-1") client = boto3.client("ec2", region_name="us-east-1")
vpc_pcx = create_vpx_pcx(ec2, client) vpc_pcx = create_vpx_pcx(ec2, client)
vpc_pcx_id = vpc_pcx["VpcPeeringConnectionId"]
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"] all_vpc_pcxs = retrieve_all(client)
all_vpc_pcxs.should.have.length_of(1) [vpc_pcx["VpcPeeringConnectionId"] for vpc_pcx in all_vpc_pcxs].should.contain(
all_vpc_pcxs[0]["Status"]["Code"].should.equal("pending-acceptance") vpc_pcx_id
)
my_vpc_pcx = [
vpc_pcx
for vpc_pcx in all_vpc_pcxs
if vpc_pcx["VpcPeeringConnectionId"] == vpc_pcx_id
][0]
my_vpc_pcx["Status"]["Code"].should.equal("pending-acceptance")
# Has boto3 equivalent # Has boto3 equivalent
@ -108,9 +116,11 @@ def test_vpc_peering_connections_accept_boto3():
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition") ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition")
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"] my_vpc_pcxs = client.describe_vpc_peering_connections(
all_vpc_pcxs.should.have.length_of(1) VpcPeeringConnectionIds=[vpc_pcx_id]
all_vpc_pcxs[0]["Status"]["Code"].should.equal("active") )["VpcPeeringConnections"]
my_vpc_pcxs.should.have.length_of(1)
my_vpc_pcxs[0]["Status"]["Code"].should.equal("active")
# Has boto3 equivalent # Has boto3 equivalent
@ -149,9 +159,11 @@ def test_vpc_peering_connections_reject_boto3():
ex.value.response["ResponseMetadata"].should.have.key("RequestId") ex.value.response["ResponseMetadata"].should.have.key("RequestId")
ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition") ex.value.response["Error"]["Code"].should.equal("InvalidStateTransition")
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"] my_pcxs = client.describe_vpc_peering_connections(
all_vpc_pcxs.should.have.length_of(1) VpcPeeringConnectionIds=[vpc_pcx_id]
all_vpc_pcxs[0]["Status"]["Code"].should.equal("rejected") )["VpcPeeringConnections"]
my_pcxs.should.have.length_of(1)
my_pcxs[0]["Status"]["Code"].should.equal("rejected")
# Has boto3 equivalent # Has boto3 equivalent
@ -184,9 +196,13 @@ def test_vpc_peering_connections_delete_boto3():
client.delete_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id) client.delete_vpc_peering_connection(VpcPeeringConnectionId=vpc_pcx_id)
all_vpc_pcxs = client.describe_vpc_peering_connections()["VpcPeeringConnections"] all_vpc_pcxs = retrieve_all(client)
all_vpc_pcxs.should.have.length_of(1) [vpcx["VpcPeeringConnectionId"] for vpcx in all_vpc_pcxs].should.contain(vpc_pcx_id)
all_vpc_pcxs[0]["Status"]["Code"].should.equal("deleted")
my_vpcx = [
vpcx for vpcx in all_vpc_pcxs if vpcx["VpcPeeringConnectionId"] == vpc_pcx_id
][0]
my_vpcx["Status"]["Code"].should.equal("deleted")
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_vpc_peering_connection(VpcPeeringConnectionId="pcx-1234abcd") client.delete_vpc_peering_connection(VpcPeeringConnectionId="pcx-1234abcd")
@ -342,8 +358,10 @@ def test_describe_vpc_peering_connections_only_returns_requested_id():
) )
# describe peering # describe peering
ec2_usw1 = boto3.client("ec2", region_name="us-west-1") ec2_usw1 = boto3.client("ec2", region_name="us-west-1")
all_pcx = ec2_usw1.describe_vpc_peering_connections()["VpcPeeringConnections"] our_vpcx = [vpcx["VpcPeeringConnectionId"] for vpcx in retrieve_all(ec2_usw1)]
all_pcx.should.have.length_of(2) our_vpcx.should.contain(vpc_pcx_usw1.id)
our_vpcx.should.contain(vpc_pcx_usw2.id)
our_vpcx.shouldnt.contain(vpc_apn1.id)
both_pcx = ec2_usw1.describe_vpc_peering_connections( both_pcx = ec2_usw1.describe_vpc_peering_connections(
VpcPeeringConnectionIds=[vpc_pcx_usw1.id, vpc_pcx_usw2.id] VpcPeeringConnectionIds=[vpc_pcx_usw1.id, vpc_pcx_usw2.id]
@ -507,3 +525,14 @@ def test_vpc_peering_connections_cross_region_reject_wrong_region():
"rejected in region {2}".format("us-west-1", vpc_pcx_usw1.id, "ap-northeast-1") "rejected in region {2}".format("us-west-1", vpc_pcx_usw1.id, "ap-northeast-1")
) )
cm.value.response["Error"]["Message"].should.equal(exp_msg) cm.value.response["Error"]["Message"].should.equal(exp_msg)
def retrieve_all(client):
resp = client.describe_vpc_peering_connections()
all_vpx = resp["VpcPeeringConnections"]
token = resp.get("NextToken")
while token:
resp = client.describe_vpc_peering_connections(NextToken=token)
all_vpx.extend(resp["VpcPeeringConnections"])
token = resp.get("NextToken")
return all_vpx

View File

@ -9,8 +9,11 @@ import boto
from boto.exception import EC2ResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
import random
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated
from uuid import uuid4
from .test_tags import retrieve_all_tagged
SAMPLE_DOMAIN_NAME = "example.com" SAMPLE_DOMAIN_NAME = "example.com"
SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"] SAMPLE_NAME_SERVERS = ["10.0.0.6", "10.0.0.7"]
@ -45,13 +48,13 @@ def test_create_and_delete_vpc():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc.cidr_block.should.equal("10.0.0.0/16") vpc.cidr_block.should.equal("10.0.0.0/16")
all_vpcs = client.describe_vpcs()["Vpcs"] all_vpcs = retrieve_all_vpcs(client)
all_vpcs.should.have.length_of(2) [v["VpcId"] for v in all_vpcs].should.contain(vpc.id)
vpc.delete() vpc.delete()
all_vpcs = client.describe_vpcs()["Vpcs"] all_vpcs = retrieve_all_vpcs(client)
all_vpcs.should.have.length_of(1) [v["VpcId"] for v in all_vpcs].shouldnt.contain(vpc.id)
with pytest.raises(ClientError) as ex: with pytest.raises(ClientError) as ex:
client.delete_vpc(VpcId="vpc-1234abcd") client.delete_vpc(VpcId="vpc-1234abcd")
@ -83,17 +86,21 @@ def test_vpc_defaults_boto3():
client = boto3.client("ec2", region_name="eu-north-1") client = boto3.client("ec2", region_name="eu-north-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
client.describe_vpcs()["Vpcs"].should.have.length_of(2) filters = [{"Name": "vpc-id", "Values": [vpc.id]}]
client.describe_route_tables()["RouteTables"].should.have.length_of(2)
client.describe_security_groups(Filters=[{"Name": "vpc-id", "Values": [vpc.id]}])[ client.describe_route_tables(Filters=filters)["RouteTables"].should.have.length_of(
1
)
client.describe_security_groups(Filters=filters)[
"SecurityGroups" "SecurityGroups"
].should.have.length_of(1) ].should.have.length_of(1)
vpc.delete() vpc.delete()
client.describe_vpcs()["Vpcs"].should.have.length_of(1) client.describe_route_tables(Filters=filters)["RouteTables"].should.have.length_of(
client.describe_route_tables()["RouteTables"].should.have.length_of(1) 0
client.describe_security_groups(Filters=[{"Name": "vpc-id", "Values": [vpc.id]}])[ )
client.describe_security_groups(Filters=filters)[
"SecurityGroups" "SecurityGroups"
].should.have.length_of(0) ].should.have.length_of(0)
@ -144,12 +151,10 @@ def test_multiple_vpcs_default_filter_boto3():
ec2.create_vpc(CidrBlock="10.8.0.0/16") ec2.create_vpc(CidrBlock="10.8.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/16") ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="192.168.0.0/16") ec2.create_vpc(CidrBlock="192.168.0.0/16")
client.describe_vpcs()["Vpcs"].should.have.length_of(4) default_vpcs = retrieve_all_vpcs(
vpc = client.describe_vpcs(Filters=[{"Name": "isDefault", "Values": ["true"]}])[ client, [{"Name": "isDefault", "Values": ["true"]}]
"Vpcs" )
] [v["CidrBlock"] for v in default_vpcs].should.contain("172.31.0.0/16")
vpc.should.have.length_of(1)
vpc[0]["CidrBlock"].should.equal("172.31.0.0/16")
# Has boto3 equivalent # Has boto3 equivalent
@ -167,15 +172,29 @@ def test_vpc_state_available_filter():
def test_vpc_state_available_filter_boto3(): def test_vpc_state_available_filter_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1") ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1") client = boto3.client("ec2", region_name="eu-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.1.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.1.0.0/16")
client.describe_vpcs(Filters=[{"Name": "state", "Values": ["available"]}])[
"Vpcs" available = retrieve_all_vpcs(client, [{"Name": "state", "Values": ["available"]}])
].should.have.length_of(3) [v["VpcId"] for v in available].should.contain(vpc1.id)
vpc.delete() [v["VpcId"] for v in available].should.contain(vpc2.id)
client.describe_vpcs(Filters=[{"Name": "state", "Values": ["available"]}])[
"Vpcs" vpc1.delete()
].should.have.length_of(2)
available = retrieve_all_vpcs(client, [{"Name": "state", "Values": ["available"]}])
[v["VpcId"] for v in available].shouldnt.contain(vpc1.id)
[v["VpcId"] for v in available].should.contain(vpc2.id)
def retrieve_all_vpcs(client, filters=[]):
resp = client.describe_vpcs(Filters=filters)
all_vpcs = resp["Vpcs"]
token = resp.get("NextToken")
while token:
resp = client.describe_vpcs(Filters=filters, NextToken=token)
all_vpcs.extend(resp["Vpcs"])
token = resp.get("NextToken")
return all_vpcs
# Has boto3 equivalent # Has boto3 equivalent
@ -202,9 +221,11 @@ def test_vpc_tagging_boto3():
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc.create_tags(Tags=[{"Key": "a key", "Value": "some value"}]) vpc.create_tags(Tags=[{"Key": "a key", "Value": "some value"}])
tag = client.describe_tags()["Tags"][0]
tag.should.have.key("Key").equal("a key") all_tags = retrieve_all_tagged(client)
tag.should.have.key("Value").equal("some value") ours = [t for t in all_tags if t["ResourceId"] == vpc.id][0]
ours.should.have.key("Key").equal("a key")
ours.should.have.key("Value").equal("some value")
# Refresh the vpc # Refresh the vpc
vpc = client.describe_vpcs(VpcIds=[vpc.id])["Vpcs"][0] vpc = client.describe_vpcs(VpcIds=[vpc.id])["Vpcs"][0]
@ -272,17 +293,16 @@ def test_vpc_get_by_cidr_block():
def test_vpc_get_by_cidr_block_boto3(): def test_vpc_get_by_cidr_block_boto3():
ec2 = boto3.resource("ec2", region_name="eu-west-1") ec2 = boto3.resource("ec2", region_name="eu-west-1")
client = boto3.client("ec2", region_name="eu-west-1") client = boto3.client("ec2", region_name="eu-west-1")
vpc1 = ec2.create_vpc(CidrBlock="10.0.0.0/16") random_ip = ".".join(map(str, (random.randint(0, 99) for _ in range(4))))
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") random_cidr = f"{random_ip}/16"
vpc1 = ec2.create_vpc(CidrBlock=random_cidr)
vpc2 = ec2.create_vpc(CidrBlock=random_cidr)
ec2.create_vpc(CidrBlock="10.0.0.0/24") ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpcs = client.describe_vpcs(Filters=[{"Name": "cidr", "Values": ["10.0.0.0/16"]}])[ vpcs = client.describe_vpcs(Filters=[{"Name": "cidr", "Values": [random_cidr]}])[
"Vpcs" "Vpcs"
] ]
vpcs.should.have.length_of(2) set([vpc["VpcId"] for vpc in vpcs]).should.equal(set([vpc1.id, vpc2.id]))
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent # Has boto3 equivalent
@ -357,17 +377,16 @@ def test_vpc_get_by_tag_boto3():
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24") vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) value1 = str(uuid4())
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) vpc1.create_tags(Tags=[{"Key": "Name", "Value": value1}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": value1}])
vpc3.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC2"}]) vpc3.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag:Name", "Values": ["TestVPC"]}])[ vpcs = client.describe_vpcs(Filters=[{"Name": "tag:Name", "Values": [value1]}])[
"Vpcs" "Vpcs"
] ]
vpcs.should.have.length_of(2) vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs)) set([vpc["VpcId"] for vpc in vpcs]).should.equal(set([vpc1.id, vpc2.id]))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent # Has boto3 equivalent
@ -399,19 +418,18 @@ def test_vpc_get_by_tag_key_superset_boto3():
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24") vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) tag_key = str(uuid4())[0:6]
vpc1.create_tags(Tags=[{"Key": tag_key, "Value": "TestVPC"}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) vpc2.create_tags(Tags=[{"Key": tag_key, "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag-key", "Values": ["Name"]}])[ vpcs = client.describe_vpcs(Filters=[{"Name": "tag-key", "Values": [tag_key]}])[
"Vpcs" "Vpcs"
] ]
vpcs.should.have.length_of(2) vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs)) set([vpc["VpcId"] for vpc in vpcs]).should.equal(set([vpc1.id, vpc2.id]))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent # Has boto3 equivalent
@ -443,19 +461,19 @@ def test_vpc_get_by_tag_key_subset_boto3():
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24") vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) tag_key1 = str(uuid4())[0:6]
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) tag_key2 = str(uuid4())[0:6]
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) vpc1.create_tags(Tags=[{"Key": tag_key1, "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc1.create_tags(Tags=[{"Key": tag_key2, "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": tag_key1, "Value": "TestVPC"}])
vpc2.create_tags(Tags=[{"Key": tag_key2, "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Test", "Value": "TestVPC2"}]) vpc3.create_tags(Tags=[{"Key": "Test", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs( vpcs = client.describe_vpcs(
Filters=[{"Name": "tag-key", "Values": ["Name", "Key"]}] Filters=[{"Name": "tag-key", "Values": [tag_key1, tag_key2]}]
)["Vpcs"] )["Vpcs"]
vpcs.should.have.length_of(2) vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs)) set([vpc["VpcId"] for vpc in vpcs]).should.equal(set([vpc1.id, vpc2.id]))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent # Has boto3 equivalent
@ -487,19 +505,18 @@ def test_vpc_get_by_tag_value_superset_boto3():
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24") vpc3 = ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) tag_value = str(uuid4())
vpc1.create_tags(Tags=[{"Key": "Name", "Value": tag_value}])
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) vpc2.create_tags(Tags=[{"Key": "Name", "Value": tag_value}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc3.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}])
vpcs = client.describe_vpcs(Filters=[{"Name": "tag-value", "Values": ["TestVPC"]}])[ vpcs = client.describe_vpcs(Filters=[{"Name": "tag-value", "Values": [tag_value]}])[
"Vpcs" "Vpcs"
] ]
vpcs.should.have.length_of(2) vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs)) set([vpc["VpcId"] for vpc in vpcs]).should.equal(set([vpc1.id, vpc2.id]))
vpc1.id.should.be.within(vpc_ids)
vpc2.id.should.be.within(vpc_ids)
# Has boto3 equivalent # Has boto3 equivalent
@ -530,13 +547,15 @@ def test_vpc_get_by_tag_value_subset_boto3():
vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc2 = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.create_vpc(CidrBlock="10.0.0.0/24") ec2.create_vpc(CidrBlock="10.0.0.0/24")
vpc1.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) value1 = str(uuid4())[0:6]
vpc1.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) value2 = str(uuid4())[0:6]
vpc2.create_tags(Tags=[{"Key": "Name", "Value": "TestVPC"}]) vpc1.create_tags(Tags=[{"Key": "Name", "Value": value1}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": "TestVPC2"}]) vpc1.create_tags(Tags=[{"Key": "Key", "Value": value2}])
vpc2.create_tags(Tags=[{"Key": "Name", "Value": value1}])
vpc2.create_tags(Tags=[{"Key": "Key", "Value": value2}])
vpcs = client.describe_vpcs( vpcs = client.describe_vpcs(
Filters=[{"Name": "tag-value", "Values": ["TestVPC", "TestVPC2"]}] Filters=[{"Name": "tag-value", "Values": [value1, value2]}]
)["Vpcs"] )["Vpcs"]
vpcs.should.have.length_of(2) vpcs.should.have.length_of(2)
vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs)) vpc_ids = tuple(map(lambda v: v["VpcId"], vpcs))
@ -842,8 +861,9 @@ def test_cidr_block_association_filters():
] ]
) )
) )
filtered_vpcs.should.be.length_of(1) [vpc.id for vpc in filtered_vpcs].shouldnt.contain(vpc1.id)
filtered_vpcs[0].id.should.equal(vpc2.id) [vpc.id for vpc in filtered_vpcs].should.contain(vpc2.id)
[vpc.id for vpc in filtered_vpcs].shouldnt.contain(vpc3.id)
# Test filter for association id in VPCs # Test filter for association id in VPCs
association_id = vpc3_assoc_response["CidrBlockAssociation"]["AssociationId"] association_id = vpc3_assoc_response["CidrBlockAssociation"]["AssociationId"]
@ -980,14 +1000,18 @@ def test_ipv6_cidr_block_association_filters():
filtered_vpcs[0].id.should.equal(vpc2.id) filtered_vpcs[0].id.should.equal(vpc2.id)
# Test filter for association state in VPC - this will never show anything in this test # Test filter for association state in VPC - this will never show anything in this test
filtered_vpcs = list( assoc_vpcs = [
ec2.vpcs.filter( vpc.id
for vpc in ec2.vpcs.filter(
Filters=[ Filters=[
{"Name": "ipv6-cidr-block-association.state", "Values": ["associated"]} {"Name": "ipv6-cidr-block-association.state", "Values": ["associated"]}
] ]
) )
) ]
filtered_vpcs.should.be.length_of(2) # 2 of 4 VPCs assoc_vpcs.shouldnt.contain(vpc1.id)
assoc_vpcs.should.contain(vpc2.id)
assoc_vpcs.should.contain(vpc3.id)
assoc_vpcs.shouldnt.contain(vpc4.id)
@mock_ec2 @mock_ec2
@ -1181,81 +1205,94 @@ def test_describe_classic_link_dns_support_multiple():
@mock_ec2 @mock_ec2
def test_describe_vpc_end_points(): def test_describe_vpc_end_points():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
route_table = ec2.create_route_table(VpcId=vpc["Vpc"]["VpcId"]) route_table = ec2.create_route_table(VpcId=vpc["VpcId"])["RouteTable"]
vpc_end_point = ec2.create_vpc_endpoint( vpc_end_point = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"], VpcId=vpc["VpcId"],
ServiceName="com.amazonaws.us-east-1.s3", ServiceName="com.amazonaws.us-east-1.s3",
RouteTableIds=[route_table["RouteTable"]["RouteTableId"]], RouteTableIds=[route_table["RouteTableId"]],
VpcEndpointType="gateway", VpcEndpointType="gateway",
) )["VpcEndpoint"]
our_id = vpc_end_point["VpcEndpointId"]
vpc_endpoints = ec2.describe_vpc_endpoints() all_endpoints = retrieve_all_endpoints(ec2)
assert ( [e["VpcEndpointId"] for e in all_endpoints].should.contain(our_id)
vpc_endpoints.get("VpcEndpoints")[0].get("PrivateDnsEnabled") our_endpoint = [e for e in all_endpoints if e["VpcEndpointId"] == our_id][0]
is vpc_end_point.get("VpcEndpoint").get("PrivateDnsEnabled") vpc_end_point["PrivateDnsEnabled"].should.be.true
is True our_endpoint["PrivateDnsEnabled"].should.be.true
)
assert vpc_endpoints.get("VpcEndpoints")[0].get(
"VpcEndpointId"
) == vpc_end_point.get("VpcEndpoint").get("VpcEndpointId")
assert vpc_endpoints.get("VpcEndpoints")[0].get("VpcId") == vpc["Vpc"]["VpcId"]
assert vpc_endpoints.get("VpcEndpoints")[0].get("RouteTableIds") == [
route_table.get("RouteTable").get("RouteTableId")
]
assert "VpcEndpointType" in vpc_endpoints.get("VpcEndpoints")[0]
assert "ServiceName" in vpc_endpoints.get("VpcEndpoints")[0]
assert "State" in vpc_endpoints.get("VpcEndpoints")[0]
vpc_endpoints = ec2.describe_vpc_endpoints( our_endpoint["VpcId"].should.equal(vpc["VpcId"])
VpcEndpointIds=[vpc_end_point.get("VpcEndpoint").get("VpcEndpointId")] our_endpoint["RouteTableIds"].should.equal([route_table["RouteTableId"]])
)
assert vpc_endpoints.get("VpcEndpoints")[0].get(
"VpcEndpointId"
) == vpc_end_point.get("VpcEndpoint").get("VpcEndpointId")
assert vpc_endpoints.get("VpcEndpoints")[0].get("VpcId") == vpc["Vpc"]["VpcId"]
assert vpc_endpoints.get("VpcEndpoints")[0].get("RouteTableIds") == [
route_table.get("RouteTable").get("RouteTableId")
]
assert "VpcEndpointType" in vpc_endpoints.get("VpcEndpoints")[0]
assert "ServiceName" in vpc_endpoints.get("VpcEndpoints")[0]
assert "State" in vpc_endpoints.get("VpcEndpoints")[0]
try: our_endpoint.should.have.key("VpcEndpointType").equal("gateway")
ec2.describe_vpc_endpoints( our_endpoint.should.have.key("ServiceName").equal("com.amazonaws.us-east-1.s3")
VpcEndpointIds=[route_table.get("RouteTable").get("RouteTableId")] our_endpoint.should.have.key("State").equal("available")
)
except ClientError as err: endpoint_by_id = ec2.describe_vpc_endpoints(VpcEndpointIds=[our_id])[
assert err.response["Error"]["Code"] == "InvalidVpcEndpointId.NotFound" "VpcEndpoints"
][0]
endpoint_by_id["VpcEndpointId"].should.equal(our_id)
endpoint_by_id["VpcId"].should.equal(vpc["VpcId"])
endpoint_by_id["RouteTableIds"].should.equal([route_table["RouteTableId"]])
endpoint_by_id["VpcEndpointType"].should.equal("gateway")
endpoint_by_id["ServiceName"].should.equal("com.amazonaws.us-east-1.s3")
endpoint_by_id["State"].should.equal("available")
with pytest.raises(ClientError) as ex:
ec2.describe_vpc_endpoints(VpcEndpointIds=[route_table["RouteTableId"]])
err = ex.value.response["Error"]
err["Code"].should.equal("InvalidVpcEndpointId.NotFound")
def retrieve_all_endpoints(ec2):
resp = ec2.describe_vpc_endpoints()
all_endpoints = resp["VpcEndpoints"]
next_token = resp.get("NextToken")
while next_token:
resp = ec2.describe_vpc_endpoints(NextToken=next_token)
all_endpoints.extend(resp["VpcEndpoints"])
next_token = resp.get("NextToken")
return all_endpoints
@mock_ec2 @mock_ec2
def test_delete_vpc_end_points(): def test_delete_vpc_end_points():
ec2 = boto3.client("ec2", region_name="us-west-1") ec2 = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16") vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]
route_table = ec2.create_route_table(VpcId=vpc["Vpc"]["VpcId"]) route_table = ec2.create_route_table(VpcId=vpc["VpcId"])["RouteTable"]
vpc_end_point1 = ec2.create_vpc_endpoint( vpc_end_point1 = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"], VpcId=vpc["VpcId"],
ServiceName="com.amazonaws.us-west-1.s3", ServiceName="com.amazonaws.us-west-1.s3",
RouteTableIds=[route_table["RouteTable"]["RouteTableId"]], RouteTableIds=[route_table["RouteTableId"]],
VpcEndpointType="gateway", VpcEndpointType="gateway",
)["VpcEndpoint"] )["VpcEndpoint"]
vpc_end_point2 = ec2.create_vpc_endpoint( vpc_end_point2 = ec2.create_vpc_endpoint(
VpcId=vpc["Vpc"]["VpcId"], VpcId=vpc["VpcId"],
ServiceName="com.amazonaws.us-west-1.s3", ServiceName="com.amazonaws.us-west-1.s3",
RouteTableIds=[route_table["RouteTable"]["RouteTableId"]], RouteTableIds=[route_table["RouteTableId"]],
VpcEndpointType="gateway", VpcEndpointType="gateway",
) )["VpcEndpoint"]
vpc_endpoints = ec2.describe_vpc_endpoints()["VpcEndpoints"] vpc_endpoints = retrieve_all_endpoints(ec2)
vpc_endpoints.should.have.length_of(2) all_ids = [e["VpcEndpointId"] for e in vpc_endpoints]
all_ids.should.contain(vpc_end_point1["VpcEndpointId"])
all_ids.should.contain(vpc_end_point2["VpcEndpointId"])
ec2.delete_vpc_endpoints(VpcEndpointIds=[vpc_end_point1["VpcEndpointId"]]) ec2.delete_vpc_endpoints(VpcEndpointIds=[vpc_end_point1["VpcEndpointId"]])
vpc_endpoints = ec2.describe_vpc_endpoints()["VpcEndpoints"] vpc_endpoints = retrieve_all_endpoints(ec2)
vpc_endpoints.should.have.length_of(2) all_ids = [e["VpcEndpointId"] for e in vpc_endpoints]
all_ids.should.contain(vpc_end_point1["VpcEndpointId"])
all_ids.should.contain(vpc_end_point2["VpcEndpointId"])
states = set([vpce["State"] for vpce in vpc_endpoints]) ep1 = ec2.describe_vpc_endpoints(VpcEndpointIds=[vpc_end_point1["VpcEndpointId"]])[
states.should.equal({"available", "deleted"}) "VpcEndpoints"
][0]
ep1["State"].should.equal("deleted")
ep2 = ec2.describe_vpc_endpoints(VpcEndpointIds=[vpc_end_point2["VpcEndpointId"]])[
"VpcEndpoints"
][0]
ep2["State"].should.equal("available")

View File

@ -52,14 +52,21 @@ def test_delete_vpn_connections_boto3():
Type="ipsec.1", VpnGatewayId="vgw-0123abcd", CustomerGatewayId="cgw-0123abcd" Type="ipsec.1", VpnGatewayId="vgw-0123abcd", CustomerGatewayId="cgw-0123abcd"
)["VpnConnection"] )["VpnConnection"]
cnx = client.describe_vpn_connections()["VpnConnections"] conns = retrieve_all_vpncs(client)
cnx.should.have.length_of(1) [c["VpnConnectionId"] for c in conns].should.contain(
vpn_connection["VpnConnectionId"]
)
client.delete_vpn_connection(VpnConnectionId=vpn_connection["VpnConnectionId"]) client.delete_vpn_connection(VpnConnectionId=vpn_connection["VpnConnectionId"])
cnx = client.describe_vpn_connections()["VpnConnections"] conns = retrieve_all_vpncs(client)
cnx.should.have.length_of(1) [c["VpnConnectionId"] for c in conns].should.contain(
cnx[0].should.have.key("State").equal("deleted") vpn_connection["VpnConnectionId"]
)
my_cnx = [
c for c in conns if c["VpnConnectionId"] == vpn_connection["VpnConnectionId"]
][0]
my_cnx.should.have.key("State").equal("deleted")
# Has boto3 equivalent # Has boto3 equivalent
@ -125,7 +132,7 @@ def test_describe_vpn_connections_boto3():
customer_gateway = client.create_customer_gateway( customer_gateway = client.create_customer_gateway(
Type="ipsec.1", PublicIp="205.251.242.54", BgpAsn=65534, Type="ipsec.1", PublicIp="205.251.242.54", BgpAsn=65534,
).get("CustomerGateway", {}) ).get("CustomerGateway", {})
client.create_vpn_connection( vpn_connection1 = client.create_vpn_connection(
Type="ipsec.1", Type="ipsec.1",
VpnGatewayId=vpn_gateway["VpnGatewayId"], VpnGatewayId=vpn_gateway["VpnGatewayId"],
CustomerGatewayId=customer_gateway["CustomerGatewayId"], CustomerGatewayId=customer_gateway["CustomerGatewayId"],
@ -136,8 +143,13 @@ def test_describe_vpn_connections_boto3():
CustomerGatewayId=customer_gateway["CustomerGatewayId"], CustomerGatewayId=customer_gateway["CustomerGatewayId"],
)["VpnConnection"] )["VpnConnection"]
conns = client.describe_vpn_connections()["VpnConnections"] conns = retrieve_all_vpncs(client)
conns.should.have.length_of(2) [c["VpnConnectionId"] for c in conns].should.contain(
vpn_connection1["VpnConnectionId"]
)
[c["VpnConnectionId"] for c in conns].should.contain(
vpn_connection2["VpnConnectionId"]
)
conns = client.describe_vpn_connections( conns = client.describe_vpn_connections(
VpnConnectionIds=[vpn_connection2["VpnConnectionId"]] VpnConnectionIds=[vpn_connection2["VpnConnectionId"]]
@ -159,3 +171,14 @@ def test_describe_vpn_connections_unknown():
err = ex.value.response["Error"] err = ex.value.response["Error"]
err["Message"].should.equal("The vpnConnection ID '?' does not exist") err["Message"].should.equal("The vpnConnection ID '?' does not exist")
err["Code"].should.equal("InvalidVpnConnectionID.NotFound") err["Code"].should.equal("InvalidVpnConnectionID.NotFound")
def retrieve_all_vpncs(client, filters=[]):
resp = client.describe_vpn_connections(Filters=filters)
all_vpncs = resp["VpnConnections"]
token = resp.get("NextToken")
while token:
resp = client.describe_vpn_connections(NextToken=token, Filters=filters)
all_vpncs.extend(resp["VpnConnections"])
token = resp.get("NextToken")
return all_vpncs

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,25 @@
import boto3 import boto3
import json import json
import sure # noqa import sure # noqa
from moto import mock_sqs, mock_cloudformation from moto import mock_sqs, mock_cloudformation
from moto.core import ACCOUNT_ID from moto.core import ACCOUNT_ID
from string import Template
from random import randint
from uuid import uuid4
simple_queue = Template(
simple_queue = { """{
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
"QueueGroup": { "QueueGroup": {
"Type": "AWS::SQS::Queue", "Type": "AWS::SQS::Queue",
"Properties": {"QueueName": "my-queue", "VisibilityTimeout": 60}, "Properties": {"QueueName": $q_name, "VisibilityTimeout": 60},
} }
}, },
} }"""
simple_queue_json = json.dumps(simple_queue) )
sqs_template_with_tags = """ sqs_template_with_tags = """
{ {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
@ -46,16 +50,19 @@ def test_describe_stack_subresources():
cf = boto3.client("cloudformation", region_name="us-east-1") cf = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("sqs", region_name="us-east-1") client = boto3.client("sqs", region_name="us-east-1")
cf.create_stack(StackName="test_sqs", TemplateBody=simple_queue_json) stack_name = str(uuid4())[0:6]
q_name = str(uuid4())[0:6]
template_body = simple_queue.substitute(q_name=q_name)
cf.create_stack(StackName=stack_name, TemplateBody=template_body)
queue_url = client.list_queues()["QueueUrls"][0] queue_urls = client.list_queues()["QueueUrls"]
queue_url.should.contain("{}/{}".format(ACCOUNT_ID, "my-queue")) assert any(["{}/{}".format(ACCOUNT_ID, q_name) in url for url in queue_urls])
stack = res.Stack("test_sqs") stack = res.Stack(stack_name)
for s in stack.resource_summaries.all(): for s in stack.resource_summaries.all():
s.resource_type.should.equal("AWS::SQS::Queue") s.resource_type.should.equal("AWS::SQS::Queue")
s.logical_id.should.equal("QueueGroup") s.logical_id.should.equal("QueueGroup")
s.physical_resource_id.should.equal("my-queue") s.physical_resource_id.should.equal(q_name)
@mock_sqs @mock_sqs
@ -64,16 +71,19 @@ def test_list_stack_resources():
cf = boto3.client("cloudformation", region_name="us-east-1") cf = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("sqs", region_name="us-east-1") client = boto3.client("sqs", region_name="us-east-1")
cf.create_stack(StackName="test_sqs", TemplateBody=simple_queue_json) stack_name = str(uuid4())[0:6]
q_name = str(uuid4())[0:6]
template_body = simple_queue.substitute(q_name=q_name)
cf.create_stack(StackName=stack_name, TemplateBody=template_body)
queue_url = client.list_queues()["QueueUrls"][0] queue_urls = client.list_queues()["QueueUrls"]
queue_url.should.contain("{}/{}".format(ACCOUNT_ID, "my-queue")) assert any(["{}/{}".format(ACCOUNT_ID, q_name) in url for url in queue_urls])
queue = cf.list_stack_resources(StackName="test_sqs")["StackResourceSummaries"][0] queue = cf.list_stack_resources(StackName=stack_name)["StackResourceSummaries"][0]
queue.should.have.key("ResourceType").equal("AWS::SQS::Queue") queue.should.have.key("ResourceType").equal("AWS::SQS::Queue")
queue.should.have.key("LogicalResourceId").should.equal("QueueGroup") queue.should.have.key("LogicalResourceId").should.equal("QueueGroup")
queue.should.have.key("PhysicalResourceId").should.equal("my-queue") queue.should.have.key("PhysicalResourceId").should.equal(q_name)
@mock_sqs @mock_sqs
@ -82,9 +92,14 @@ def test_create_from_cloudformation_json_with_tags():
cf = boto3.client("cloudformation", region_name="us-east-1") cf = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("sqs", region_name="us-east-1") client = boto3.client("sqs", region_name="us-east-1")
cf.create_stack(StackName="test-sqs", TemplateBody=sqs_template_with_tags) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=sqs_template_with_tags)
queue_url = client.list_queues()["QueueUrls"][0] response = cf.describe_stack_resources(StackName=stack_name)
q_name = response["StackResources"][0]["PhysicalResourceId"]
all_urls = client.list_queues()["QueueUrls"]
queue_url = [url for url in all_urls if url.endswith(q_name)][0]
queue_tags = client.list_queue_tags(QueueUrl=queue_url)["Tags"] queue_tags = client.list_queue_tags(QueueUrl=queue_url)["Tags"]
queue_tags.should.equal({"keyname1": "value1", "keyname2": "value2"}) queue_tags.should.equal({"keyname1": "value1", "keyname2": "value2"})
@ -93,22 +108,24 @@ def test_create_from_cloudformation_json_with_tags():
@mock_cloudformation @mock_cloudformation
@mock_sqs @mock_sqs
def test_update_stack(): def test_update_stack():
q_name = str(uuid4())[0:6]
sqs_template = { sqs_template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
"QueueGroup": { "QueueGroup": {
"Type": "AWS::SQS::Queue", "Type": "AWS::SQS::Queue",
"Properties": {"QueueName": "my-queue", "VisibilityTimeout": 60}, "Properties": {"QueueName": q_name, "VisibilityTimeout": 60},
} }
}, },
} }
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=sqs_template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=sqs_template_json)
client = boto3.client("sqs", region_name="us-west-1") client = boto3.client("sqs", region_name="us-west-1")
queues = client.list_queues()["QueueUrls"] queues = client.list_queues(QueueNamePrefix=q_name)["QueueUrls"]
queues.should.have.length_of(1) queues.should.have.length_of(1)
attrs = client.get_queue_attributes(QueueUrl=queues[0], AttributeNames=["All"])[ attrs = client.get_queue_attributes(QueueUrl=queues[0], AttributeNames=["All"])[
"Attributes" "Attributes"
@ -118,10 +135,10 @@ def test_update_stack():
# when updating # when updating
sqs_template["Resources"]["QueueGroup"]["Properties"]["VisibilityTimeout"] = 100 sqs_template["Resources"]["QueueGroup"]["Properties"]["VisibilityTimeout"] = 100
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
cf.update_stack(StackName="test_stack", TemplateBody=sqs_template_json) cf.update_stack(StackName=stack_name, TemplateBody=sqs_template_json)
# then the attribute should be updated # then the attribute should be updated
queues = client.list_queues()["QueueUrls"] queues = client.list_queues(QueueNamePrefix=q_name)["QueueUrls"]
queues.should.have.length_of(1) queues.should.have.length_of(1)
attrs = client.get_queue_attributes(QueueUrl=queues[0], AttributeNames=["All"])[ attrs = client.get_queue_attributes(QueueUrl=queues[0], AttributeNames=["All"])[
"Attributes" "Attributes"
@ -132,30 +149,31 @@ def test_update_stack():
@mock_cloudformation @mock_cloudformation
@mock_sqs @mock_sqs
def test_update_stack_and_remove_resource(): def test_update_stack_and_remove_resource():
q_name = str(uuid4())[0:6]
sqs_template = { sqs_template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
"QueueGroup": { "QueueGroup": {
"Type": "AWS::SQS::Queue", "Type": "AWS::SQS::Queue",
"Properties": {"QueueName": "my-queue", "VisibilityTimeout": 60}, "Properties": {"QueueName": q_name, "VisibilityTimeout": 60},
} }
}, },
} }
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=sqs_template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=sqs_template_json)
client = boto3.client("sqs", region_name="us-west-1") client = boto3.client("sqs", region_name="us-west-1")
client.list_queues()["QueueUrls"].should.have.length_of(1) client.list_queues(QueueNamePrefix=q_name)["QueueUrls"].should.have.length_of(1)
sqs_template["Resources"].pop("QueueGroup") sqs_template["Resources"].pop("QueueGroup")
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
cf.update_stack(StackName="test_stack", TemplateBody=sqs_template_json) cf.update_stack(StackName=stack_name, TemplateBody=sqs_template_json)
client.list_queues().shouldnt.have.key( # No queues exist, so the key is not passed through
"QueueUrls" client.list_queues(QueueNamePrefix=q_name).shouldnt.have.key("QueueUrls")
) # No queues exist, so the key is not passed through
@mock_cloudformation @mock_cloudformation
@ -164,22 +182,44 @@ def test_update_stack_and_add_resource():
sqs_template = {"AWSTemplateFormatVersion": "2010-09-09", "Resources": {}} sqs_template = {"AWSTemplateFormatVersion": "2010-09-09", "Resources": {}}
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
q_name = str(uuid4())[0:6]
cf = boto3.client("cloudformation", region_name="us-west-1") cf = boto3.client("cloudformation", region_name="us-west-1")
cf.create_stack(StackName="test_stack", TemplateBody=sqs_template_json) stack_name = str(uuid4())[0:6]
cf.create_stack(StackName=stack_name, TemplateBody=sqs_template_json)
client = boto3.client("sqs", region_name="us-west-1") client = boto3.client("sqs", region_name="us-west-1")
client.list_queues().shouldnt.have.key("QueueUrls") client.list_queues(QueueNamePrefix=q_name).shouldnt.have.key("QueueUrls")
sqs_template = { sqs_template = {
"AWSTemplateFormatVersion": "2010-09-09", "AWSTemplateFormatVersion": "2010-09-09",
"Resources": { "Resources": {
"QueueGroup": { "QueueGroup": {
"Type": "AWS::SQS::Queue", "Type": "AWS::SQS::Queue",
"Properties": {"QueueName": "my-queue", "VisibilityTimeout": 60}, "Properties": {"QueueName": q_name, "VisibilityTimeout": 60},
} }
}, },
} }
sqs_template_json = json.dumps(sqs_template) sqs_template_json = json.dumps(sqs_template)
cf.update_stack(StackName="test_stack", TemplateBody=sqs_template_json) cf.update_stack(StackName=stack_name, TemplateBody=sqs_template_json)
client.list_queues()["QueueUrls"].should.have.length_of(1) client.list_queues(QueueNamePrefix=q_name)["QueueUrls"].should.have.length_of(1)
@mock_sqs
@mock_cloudformation
def test_create_queue_passing_integer_as_name():
"""
Passing the queue name as an Integer in the CloudFormation template
This works in AWS - it simply converts the integer to a string, and treats it as any other name
"""
cf = boto3.client("cloudformation", region_name="us-east-1")
client = boto3.client("sqs", region_name="us-east-1")
stack_name = str(uuid4())[0:6]
q_name = f"{randint(10000000, 99999999)}"
template_body = simple_queue.substitute(q_name=q_name)
cf.create_stack(StackName=stack_name, TemplateBody=template_body)
queue_urls = client.list_queues(QueueNamePrefix=q_name[0:6])["QueueUrls"]
queue_urls.should.have.length_of(1)

View File

@ -4,4 +4,4 @@ export MOTO_PORT=${MOTO_PORT:-5000}
set -e set -e
pip install $(ls /moto/dist/moto*.gz)[server,all] pip install $(ls /moto/dist/moto*.gz)[server,all]
moto_server -H 0.0.0.0 -p ${MOTO_PORT} moto_server -H 0.0.0.0 -p ${MOTO_PORT} > /moto/server_output.log 2>&1