Fix conflict with subnet/network ACL association during subnet creation.

This commit is contained in:
Tyler Sanders 2014-11-17 09:37:38 -06:00
commit 2a6c4c89bf
54 changed files with 616 additions and 303 deletions

View file

@ -1,7 +1,10 @@
from __future__ import unicode_literals
from .models import ec2_backends, ec2_backend
from .models import ec2_backends
from ..core.models import MockAWS
ec2_backend = ec2_backends['us-east-1']
def mock_ec2(func=None):
if func:
return MockAWS(ec2_backends)(func)

View file

@ -171,7 +171,7 @@ class InvalidSnapshotIdError(EC2ClientError):
def __init__(self, snapshot_id):
super(InvalidSnapshotIdError, self).__init__(
"InvalidSnapshot.NotFound",
"") # Note: AWS returns empty message for this, as of 2014.08.22.
"") # Note: AWS returns empty message for this, as of 2014.08.22.
class InvalidVolumeIdError(EC2ClientError):

View file

@ -1,16 +1,17 @@
from __future__ import unicode_literals
import copy
import itertools
from collections import defaultdict
import copy
from datetime import datetime
import itertools
import re
import six
import boto
from boto.ec2.instance import Instance as BotoInstance, Reservation
from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
from boto.ec2.spotinstancerequest import SpotInstanceRequest as BotoSpotRequest
from boto.ec2.launchspecification import LaunchSpecification
import six
from moto.core import BaseBackend
from moto.core.models import Model
@ -103,6 +104,7 @@ class InstanceState(object):
self.name = name
self.code = code
class StateReason(object):
def __init__(self, message="", code=""):
self.message = message
@ -134,7 +136,7 @@ class TaggedEC2Resource(object):
class NetworkInterface(object):
def __init__(self, ec2_backend, subnet, private_ip_address, device_index=0,
public_ip_auto_assign=True, group_ids=None):
public_ip_auto_assign=True, group_ids=None):
self.ec2_backend = ec2_backend
self.id = random_eni_id()
self.device_index = device_index
@ -165,12 +167,13 @@ class NetworkInterface(object):
self._group_set.append(group)
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
security_group_ids = properties.get('SecurityGroups', [])
subnet_id = properties['SubnetId']
ec2_backend = ec2_backends[region_name]
subnet = ec2_backend.get_subnet(subnet_id)
private_ip_address = properties.get('PrivateIpAddress', None)
@ -242,12 +245,11 @@ class NetworkInterfaceBackend(object):
for (_filter, _filter_value) in filters.items():
if _filter == 'network-interface-id':
_filter = 'id'
enis = [ eni for eni in enis if getattr(eni, _filter) in _filter_value ]
enis = [eni for eni in enis if getattr(eni, _filter) in _filter_value]
elif _filter == 'group-id':
original_enis = enis
enis = []
for eni in original_enis:
group_ids = []
for group in eni.group_set:
if group.id in _filter_value:
enis.append(eni)
@ -320,14 +322,15 @@ class Instance(BotoInstance, TaggedEC2Resource):
self.vpc_id = subnet.vpc_id
self.prep_nics(kwargs.get("nics", {}),
subnet_id=kwargs.get("subnet_id",None),
private_ip=kwargs.get("private_ip",None),
associate_public_ip=kwargs.get("associate_public_ip",None))
subnet_id=kwargs.get("subnet_id"),
private_ip=kwargs.get("private_ip"),
associate_public_ip=kwargs.get("associate_public_ip"))
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
ec2_backend = ec2_backends[region_name]
security_group_ids = properties.get('SecurityGroups', [])
group_names = [ec2_backend.get_security_group_from_id(group_id).name for group_id in security_group_ids]
@ -385,10 +388,6 @@ class Instance(BotoInstance, TaggedEC2Resource):
self._reason = ""
self._state_reason = StateReason()
def get_tags(self):
tags = self.ec2_backend.describe_tags(filters={'resource-id': [self.id]})
return tags
@property
def dynamic_group_list(self):
if self.nics:
@ -407,7 +406,7 @@ class Instance(BotoInstance, TaggedEC2Resource):
primary_nic = {'SubnetId': subnet_id,
'PrivateIpAddress': private_ip,
'AssociatePublicIpAddress': associate_public_ip}
primary_nic = dict((k,v) for k, v in primary_nic.items() if v)
primary_nic = dict((k, v) for k, v in primary_nic.items() if v)
# If empty NIC spec but primary NIC values provided, create NIC from them.
if primary_nic and not nic_spec:
@ -416,12 +415,9 @@ class Instance(BotoInstance, TaggedEC2Resource):
# Flesh out data structures and associations
for nic in nic_spec.values():
use_eni = None
security_group_ids = []
device_index = int(nic.get('DeviceIndex'))
nic_id = nic.get('NetworkInterfaceId', None)
nic_id = nic.get('NetworkInterfaceId')
if nic_id:
# If existing NIC found, use it.
use_nic = self.ec2_backend.get_network_interface(nic_id)
@ -435,13 +431,13 @@ class Instance(BotoInstance, TaggedEC2Resource):
subnet = self.ec2_backend.get_subnet(nic['SubnetId'])
group_id = nic.get('SecurityGroupId',None)
group_id = nic.get('SecurityGroupId')
group_ids = [group_id] if group_id else []
use_nic = self.ec2_backend.create_network_interface(subnet,
nic.get('PrivateIpAddress',None),
nic.get('PrivateIpAddress'),
device_index=device_index,
public_ip_auto_assign=nic.get('AssociatePublicIpAddress',False),
public_ip_auto_assign=nic.get('AssociatePublicIpAddress', False),
group_ids=group_ids)
self.attach_eni(use_nic, device_index)
@ -450,14 +446,14 @@ class Instance(BotoInstance, TaggedEC2Resource):
device_index = int(device_index)
self.nics[device_index] = eni
eni.instance = self # This is used upon associate/disassociate public IP.
eni.instance = self # This is used upon associate/disassociate public IP.
eni.attachment_id = random_eni_attach_id()
eni.device_index = device_index
return eni.attachment_id
def detach_eni(self, eni):
self.nics.pop(eni.device_index,None)
self.nics.pop(eni.device_index, None)
eni.instance = None
eni.attachment_id = None
eni.device_index = None
@ -717,7 +713,7 @@ class TagBackend(object):
resource_id_filters = []
resource_type_filters = []
value_filters = []
if not filters is None:
if filters is not None:
for tag_filter in filters:
if tag_filter in self.VALID_TAG_FILTERS:
if tag_filter == 'key':
@ -776,7 +772,7 @@ class TagBackend(object):
'key': key,
'value': value,
'resource_type': EC2_PREFIX_TO_RESOURCE[get_prefix(resource_id)],
}
}
results.append(result)
return results
@ -823,7 +819,7 @@ class Ami(TaggedEC2Resource):
elif filter_name == 'kernel-id':
return self.kernel_id
elif filter_name in ['architecture', 'platform']:
return getattr(self,filter_name)
return getattr(self, filter_name)
elif filter_name == 'image-id':
return self.id
elif filter_name == 'state':
@ -862,7 +858,6 @@ class AmiBackend(object):
def describe_images(self, ami_ids=(), filters=None):
if filters:
images = self.amis.values()
return generic_filter(filters, images)
else:
images = []
@ -984,9 +979,10 @@ class SecurityGroup(object):
self.vpc_id = vpc_id
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
ec2_backend = ec2_backends[region_name]
vpc_id = properties.get('VpcId')
security_group = ec2_backend.create_security_group(
name=resource_name,
@ -1014,10 +1010,7 @@ class SecurityGroup(object):
def physical_resource_id(self):
return self.id
def matches_filter(self, key, filter_value):
result = True
def to_attr(filter_name):
attr = None
@ -1037,7 +1030,7 @@ class SecurityGroup(object):
ingress_attr = to_attr(match.groups()[0])
for ingress in self.ingress_rules:
if getattr(ingress, ingress_attr) in filters[key]:
if getattr(ingress, ingress_attr) in filter_value:
return True
else:
attr_name = to_attr(key)
@ -1215,12 +1208,13 @@ class VolumeAttachment(object):
self.device = device
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
instance_id = properties['InstanceId']
volume_id = properties['VolumeId']
ec2_backend = ec2_backends[region_name]
attachment = ec2_backend.attach_volume(
volume_id=volume_id,
instance_id=instance_id,
@ -1229,17 +1223,19 @@ class VolumeAttachment(object):
return attachment
class Volume(object):
def __init__(self, volume_id, size, zone):
class Volume(TaggedEC2Resource):
def __init__(self, ec2_backend, volume_id, size, zone):
self.id = volume_id
self.size = size
self.zone = zone
self.attachment = None
self.ec2_backend = ec2_backend
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
ec2_backend = ec2_backends[region_name]
volume = ec2_backend.create_volume(
size=properties.get('Size'),
zone_name=properties.get('AvailabilityZone'),
@ -1258,12 +1254,13 @@ class Volume(object):
return 'available'
class Snapshot(object):
def __init__(self, snapshot_id, volume, description):
class Snapshot(TaggedEC2Resource):
def __init__(self, ec2_backend, snapshot_id, volume, description):
self.id = snapshot_id
self.volume = volume
self.description = description
self.create_volume_permission_groups = set()
self.ec2_backend = ec2_backend
class EBSBackend(object):
@ -1276,7 +1273,7 @@ class EBSBackend(object):
def create_volume(self, size, zone_name):
volume_id = random_volume_id()
zone = self.get_zone_by_name(zone_name)
volume = Volume(volume_id, size, zone)
volume = Volume(self, volume_id, size, zone)
self.volumes[volume_id] = volume
return volume
@ -1306,7 +1303,7 @@ class EBSBackend(object):
def detach_volume(self, volume_id, instance_id, device_path):
volume = self.get_volume(volume_id)
instance = self.get_instance(instance_id)
self.get_instance(instance_id)
old_attachment = volume.attachment
if not old_attachment:
@ -1318,7 +1315,7 @@ class EBSBackend(object):
def create_snapshot(self, volume_id, description):
snapshot_id = random_snapshot_id()
volume = self.get_volume(volume_id)
snapshot = Snapshot(snapshot_id, volume, description)
snapshot = Snapshot(self, snapshot_id, volume, description)
self.snapshots[snapshot_id] = snapshot
return snapshot
@ -1370,9 +1367,10 @@ class VPC(TaggedEC2Resource):
self.state = 'available'
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
ec2_backend = ec2_backends[region_name]
vpc = ec2_backend.create_vpc(
cidr_block=properties['CidrBlock'],
)
@ -1410,7 +1408,7 @@ class VPCBackend(object):
self.vpcs[vpc_id] = vpc
# AWS creates a default main route table and security group.
main_route_table = self.create_route_table(vpc_id, main=True)
self.create_route_table(vpc_id, main=True)
# AWS creates a default Network ACL
default_network_acl = self.create_network_acl(vpc_id, default=True)
@ -1436,7 +1434,7 @@ class VPCBackend(object):
def delete_vpc(self, vpc_id):
# Delete route table if only main route table remains.
route_tables = self.get_all_route_tables(filters={'vpc-id':vpc_id})
route_tables = self.get_all_route_tables(filters={'vpc-id': vpc_id})
if len(route_tables) > 1:
raise DependencyViolationError(
"The vpc {0} has dependencies and cannot be deleted."
@ -1492,11 +1490,12 @@ class VPCPeeringConnection(TaggedEC2Resource):
self._status = VPCPeeringConnectionStatus()
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
vpc = get_vpc(properties['VpcId'])
peer_vpc = get_vpc(properties['PeerVpcId'])
ec2_backend = ec2_backends[region_name]
vpc = ec2_backend.get_vpc(properties['VpcId'])
peer_vpc = ec2_backend.get_vpc(properties['PeerVpcId'])
vpc_pcx = ec2_backend.create_vpc_peering_connection(vpc, peer_vpc)
@ -1556,10 +1555,11 @@ class Subnet(TaggedEC2Resource):
self.cidr_block = cidr_block
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
vpc_id = properties['VpcId']
ec2_backend = ec2_backends[region_name]
subnet = ec2_backend.create_subnet(
vpc_id=vpc_id,
cidr_block=properties['CidrBlock']
@ -1606,11 +1606,10 @@ class SubnetBackend(object):
def create_subnet(self, vpc_id, cidr_block):
subnet_id = random_subnet_id()
subnet = Subnet(self, subnet_id, vpc_id, cidr_block)
vpc = self.get_vpc(vpc_id) # Validate VPC exists
self.get_vpc(vpc_id) # Validate VPC exists
# AWS associates a new subnet with the default Network ACL
self.associate_default_network_acl_with_subnet(subnet_id)
self.subnets[subnet_id] = subnet
return subnet
@ -1632,12 +1631,13 @@ class SubnetRouteTableAssociation(object):
self.subnet_id = subnet_id
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
route_table_id = properties['RouteTableId']
subnet_id = properties['SubnetId']
ec2_backend = ec2_backends[region_name]
subnet_association = ec2_backend.create_subnet_association(
route_table_id=route_table_id,
subnet_id=subnet_id,
@ -1666,10 +1666,11 @@ class RouteTable(TaggedEC2Resource):
self.routes = {}
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
vpc_id = properties['VpcId']
ec2_backend = ec2_backends[region_name]
route_table = ec2_backend.create_route_table(
vpc_id=vpc_id,
)
@ -1711,7 +1712,7 @@ class RouteTableBackend(object):
def create_route_table(self, vpc_id, main=False):
route_table_id = random_route_table_id()
vpc = self.get_vpc(vpc_id) # Validate VPC exists
vpc = self.get_vpc(vpc_id) # Validate VPC exists
route_table = RouteTable(self, route_table_id, vpc_id, main=main)
self.route_tables[route_table_id] = route_table
@ -1730,7 +1731,7 @@ class RouteTableBackend(object):
route_tables = self.route_tables.values()
if route_table_ids:
route_tables = [ route_table for route_table in route_tables if route_table.id in route_table_ids ]
route_tables = [route_table for route_table in route_tables if route_table.id in route_table_ids]
if len(route_tables) != len(route_table_ids):
invalid_id = list(set(route_table_ids).difference(set([route_table.id for route_table in route_tables])))[0]
raise InvalidRouteTableIdError(invalid_id)
@ -1749,15 +1750,15 @@ class RouteTableBackend(object):
def associate_route_table(self, route_table_id, subnet_id):
# Idempotent if association already exists.
route_tables_by_subnet = self.get_all_route_tables(filters={'association.subnet-id':[subnet_id]})
route_tables_by_subnet = self.get_all_route_tables(filters={'association.subnet-id': [subnet_id]})
if route_tables_by_subnet:
for association_id,check_subnet_id in route_tables_by_subnet[0].associations.items():
for association_id, check_subnet_id in route_tables_by_subnet[0].associations.items():
if subnet_id == check_subnet_id:
return association_id
# Association does not yet exist, so create it.
route_table = self.get_route_table(route_table_id)
subnet = self.get_subnet(subnet_id) # Validate subnet exists
self.get_subnet(subnet_id) # Validate subnet exists
association_id = random_subnet_association_id()
route_table.associations[association_id] = subnet_id
return association_id
@ -1775,13 +1776,13 @@ class RouteTableBackend(object):
return association_id
# Find route table which currently has the association, error if none.
route_tables_by_association_id = self.get_all_route_tables(filters={'association.route-table-association-id':[association_id]})
route_tables_by_association_id = self.get_all_route_tables(filters={'association.route-table-association-id': [association_id]})
if not route_tables_by_association_id:
raise InvalidAssociationIdError(association_id)
# Remove existing association, create new one.
previous_route_table = route_tables_by_association_id[0]
subnet_id = previous_route_table.associations.pop(association_id,None)
subnet_id = previous_route_table.associations.pop(association_id, None)
return self.associate_route_table(route_table_id, subnet_id)
@ -1798,7 +1799,7 @@ class Route(object):
self.vpc_pcx = vpc_pcx
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
gateway_id = properties.get('GatewayId')
@ -1807,6 +1808,7 @@ class Route(object):
pcx_id = properties.get('VpcPeeringConnectionId')
route_table_id = properties['RouteTableId']
ec2_backend = ec2_backends[region_name]
route_table = ec2_backend.create_route(
route_table_id=route_table_id,
destination_cidr_block=properties['DestinationCidrBlock'],
@ -1877,7 +1879,8 @@ class InternetGateway(TaggedEC2Resource):
self.vpc = None
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
ec2_backend = ec2_backends[region_name]
return ec2_backend.create_internet_gateway()
@property
@ -1952,9 +1955,10 @@ class VPCGatewayAttachment(object):
self.vpc_id = vpc_id
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
properties = cloudformation_json['Properties']
ec2_backend = ec2_backends[region_name]
return ec2_backend.create_vpc_gateway_attachment(
gateway_id=properties['InternetGatewayId'],
vpc_id=properties['VpcId'],
@ -2045,8 +2049,7 @@ class SpotRequestBackend(object):
spot_request_id, price, image_id, type, valid_from, valid_until,
launch_group, availability_zone_group, key_name, security_groups,
user_data, instance_type, placement, kernel_id, ramdisk_id,
monitoring_enabled, subnet_id
)
monitoring_enabled, subnet_id)
self.spot_instance_requests[spot_request_id] = request
requests.append(request)
return requests
@ -2074,11 +2077,13 @@ class ElasticAddress(object):
self.association_id = None
@classmethod
def create_from_cloudformation_json(cls, resource_name, cloudformation_json):
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
ec2_backend = ec2_backends[region_name]
properties = cloudformation_json.get('Properties')
instance_id = None
if properties:
domain=properties.get('Domain')
domain = properties.get('Domain')
eip = ec2_backend.allocate_address(
domain=domain if domain else 'standard')
instance_id = properties.get('InstanceId')
@ -2474,5 +2479,3 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
ec2_backends = {}
for region in boto.ec2.regions():
ec2_backends[region.name] = EC2Backend()
ec2_backend = ec2_backends['us-east-1']

View file

@ -35,12 +35,12 @@ class ElasticBlockStore(BaseResponse):
def delete_snapshot(self):
snapshot_id = self.querystring.get('SnapshotId')[0]
success = self.ec2_backend.delete_snapshot(snapshot_id)
self.ec2_backend.delete_snapshot(snapshot_id)
return DELETE_SNAPSHOT_RESPONSE
def delete_volume(self):
volume_id = self.querystring.get('VolumeId')[0]
success = self.ec2_backend.delete_volume(volume_id)
self.ec2_backend.delete_volume(volume_id)
return DELETE_VOLUME_RESPONSE
def describe_snapshots(self):
@ -132,6 +132,16 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
</item>
{% endif %}
</attachmentSet>
<tagSet>
{% for tag in volume.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
<volumeType>standard</volumeType>
</item>
{% endfor %}
@ -187,6 +197,14 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
<description>{{ snapshot.description }}</description>
<tagSet>
{% for tag in snapshot.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</item>
{% endfor %}

View file

@ -59,9 +59,9 @@ class ElasticIPAddresses(BaseResponse):
def disassociate_address(self):
if "PublicIp" in self.querystring:
disassociated = self.ec2_backend.disassociate_address(address=self.querystring['PublicIp'][0])
self.ec2_backend.disassociate_address(address=self.querystring['PublicIp'][0])
elif "AssociationId" in self.querystring:
disassociated = self.ec2_backend.disassociate_address(association_id=self.querystring['AssociationId'][0])
self.ec2_backend.disassociate_address(association_id=self.querystring['AssociationId'][0])
else:
self.ec2_backend.raise_error("MissingParameter", "Invalid request, expect PublicIp/AssociationId parameter.")
@ -69,9 +69,9 @@ class ElasticIPAddresses(BaseResponse):
def release_address(self):
if "PublicIp" in self.querystring:
released = self.ec2_backend.release_address(address=self.querystring['PublicIp'][0])
self.ec2_backend.release_address(address=self.querystring['PublicIp'][0])
elif "AllocationId" in self.querystring:
released = self.ec2_backend.release_address(allocation_id=self.querystring['AllocationId'][0])
self.ec2_backend.release_address(allocation_id=self.querystring['AllocationId'][0])
else:
self.ec2_backend.raise_error("MissingParameter", "Invalid request, expect PublicIp/AllocationId parameter.")

View file

@ -25,7 +25,7 @@ class ElasticNetworkInterfaces(BaseResponse):
raise NotImplementedError('ElasticNetworkInterfaces(AmazonVPC).describe_network_interface_attribute is not yet implemented')
def describe_network_interfaces(self):
#Partially implemented. Supports only network-interface-id and group-id filters
# Partially implemented. Supports only network-interface-id and group-id filters
filters = filters_from_querystring(self.querystring)
enis = self.ec2_backend.describe_network_interfaces(filters)
template = Template(DESCRIBE_NETWORK_INTERFACES_RESPONSE)
@ -46,7 +46,7 @@ class ElasticNetworkInterfaces(BaseResponse):
return template.render()
def modify_network_interface_attribute(self):
#Currently supports modifying one and only one security group
# Currently supports modifying one and only one security group
eni_id = self.querystring.get('NetworkInterfaceId')[0]
group_id = self.querystring.get('SecurityGroupId.1')[0]
self.ec2_backend.modify_network_interface_attribute(eni_id, group_id)

View file

@ -112,4 +112,3 @@ DETACH_INTERNET_GATEWAY_RESPONSE = u"""<DetachInternetGatewayResponse xmlns="htt
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<return>true</return>
</DetachInternetGatewayResponse>"""

View file

@ -22,11 +22,11 @@ class RouteTables(BaseResponse):
interface_id = optional_from_querystring('NetworkInterfaceId', self.querystring)
pcx_id = optional_from_querystring('VpcPeeringConnectionId', self.querystring)
route = self.ec2_backend.create_route(route_table_id, destination_cidr_block,
gateway_id=internet_gateway_id,
instance_id=instance_id,
interface_id=interface_id,
vpc_peering_connection_id=pcx_id)
self.ec2_backend.create_route(route_table_id, destination_cidr_block,
gateway_id=internet_gateway_id,
instance_id=instance_id,
interface_id=interface_id,
vpc_peering_connection_id=pcx_id)
template = Template(CREATE_ROUTE_RESPONSE)
return template.render()
@ -72,11 +72,11 @@ class RouteTables(BaseResponse):
interface_id = optional_from_querystring('NetworkInterfaceId', self.querystring)
pcx_id = optional_from_querystring('VpcPeeringConnectionId', self.querystring)
route = self.ec2_backend.replace_route(route_table_id, destination_cidr_block,
gateway_id=internet_gateway_id,
instance_id=instance_id,
interface_id=interface_id,
vpc_peering_connection_id=pcx_id)
self.ec2_backend.replace_route(route_table_id, destination_cidr_block,
gateway_id=internet_gateway_id,
instance_id=instance_id,
interface_id=interface_id,
vpc_peering_connection_id=pcx_id)
template = Template(REPLACE_ROUTE_RESPONSE)
return template.render()

View file

@ -31,7 +31,7 @@ class VPCPeeringConnections(BaseResponse):
def reject_vpc_peering_connection(self):
vpc_pcx_id = self.querystring.get('VpcPeeringConnectionId')[0]
vpc_pcx = self.ec2_backend.reject_vpc_peering_connection(vpc_pcx_id)
self.ec2_backend.reject_vpc_peering_connection(vpc_pcx_id)
template = Template(REJECT_VPC_PEERING_CONNECTION_RESPONSE)
return template.render()
@ -125,4 +125,3 @@ REJECT_VPC_PEERING_CONNECTION_RESPONSE = """
<return>true</return>
</RejectVpcPeeringConnectionResponse>
"""

View file

@ -139,7 +139,7 @@ def generate_route_id(route_table_id, cidr_block):
def split_route_id(route_id):
values = string.split(route_id, '~')
values = route_id.split('~')
return values[0], values[1]
@ -407,8 +407,8 @@ def generic_filter(filters, objects):
def simple_aws_filter_to_re(filter_string):
import fnmatch
tmp_filter = filter_string.replace('\?','[?]')
tmp_filter = tmp_filter.replace('\*','[*]')
tmp_filter = filter_string.replace('\?', '[?]')
tmp_filter = tmp_filter.replace('\*', '[*]')
tmp_filter = fnmatch.translate(tmp_filter)
return tmp_filter
@ -442,7 +442,7 @@ def get_prefix(resource_id):
if resource_id_prefix == EC2_RESOURCE_TO_PREFIX['network-interface']:
if after.startswith('attach'):
resource_id_prefix = EC2_RESOURCE_TO_PREFIX['network-interface-attachment']
if not resource_id_prefix in EC2_RESOURCE_TO_PREFIX.values():
if resource_id_prefix not in EC2_RESOURCE_TO_PREFIX.values():
uuid4hex = re.compile('[0-9a-f]{12}4[0-9a-f]{3}[89ab][0-9a-f]{15}\Z', re.I)
if uuid4hex.match(resource_id) is not None:
resource_id_prefix = EC2_RESOURCE_TO_PREFIX['reserved-instance']
@ -454,7 +454,7 @@ def get_prefix(resource_id):
def is_valid_resource_id(resource_id):
valid_prefixes = EC2_RESOURCE_TO_PREFIX.values()
resource_id_prefix = get_prefix(resource_id)
if not resource_id_prefix in valid_prefixes:
if resource_id_prefix not in valid_prefixes:
return False
resource_id_pattern = resource_id_prefix + '-[0-9a-f]{8}'
resource_pattern_re = re.compile(resource_id_pattern)