Merge branch 'master' of https://github.com/spulec/moto into 0.4.1-threadsafe
* 'master' of https://github.com/spulec/moto: (25 commits) Add @zkourouma to authors. 0.4.2 Fix bug where listener certificate was not being saved correctly when creating an elb. Added test to cover that case. [dynamodb2] adds lookup method to Table class Add IAM list_groups and list_groups_for_user. Closes #343. Fix for deleting Route53 record sets with set identifiers. Closes #342. Use dummy date instead of an invalid date Adding support for comments on hosted zones. Add availability zone support to Subnets created via CloudFormation Make availability zone dynamic in Subnet Response templates Add filter "availabilityZone" to DescribeSubnets and add availability zone support too allow starting without reseting Fix bug with empty string for instance vpc_id. Closes #337. Fix default security group description. Update responses.py Add @mrucci to authors. Fix merge conflicts. Add support for ELB attributes. cast to int when doing math. General cleanup. ...
This commit is contained in:
commit
e722b67f36
33 changed files with 1381 additions and 167 deletions
|
|
@ -1149,6 +1149,10 @@ class SecurityGroupBackend(object):
|
|||
def __init__(self):
|
||||
# the key in the dict group is the vpc_id or None (non-vpc)
|
||||
self.groups = defaultdict(dict)
|
||||
|
||||
# Create the default security group
|
||||
self.create_security_group("default", "default group")
|
||||
|
||||
super(SecurityGroupBackend, self).__init__()
|
||||
|
||||
def create_security_group(self, name, description, vpc_id=None, force=False):
|
||||
|
|
@ -1212,11 +1216,6 @@ class SecurityGroupBackend(object):
|
|||
if group.name == name:
|
||||
return group
|
||||
|
||||
if name == 'default':
|
||||
# If the request is for the default group and it does not exist, create it
|
||||
default_group = self.create_security_group("default", "The default security group", vpc_id=vpc_id, force=True)
|
||||
return default_group
|
||||
|
||||
def get_security_group_by_name_or_id(self, group_name_or_id, vpc_id):
|
||||
# try searching by id, fallbacks to name search
|
||||
group = self.get_security_group_from_id(group_name_or_id)
|
||||
|
|
@ -1309,7 +1308,7 @@ class SecurityGroupIngress(object):
|
|||
from_port = properties.get("FromPort")
|
||||
source_security_group_id = properties.get("SourceSecurityGroupId")
|
||||
source_security_group_name = properties.get("SourceSecurityGroupName")
|
||||
source_security_owner_id = properties.get("SourceSecurityGroupOwnerId") # IGNORED AT THE MOMENT
|
||||
# source_security_owner_id = properties.get("SourceSecurityGroupOwnerId") # IGNORED AT THE MOMENT
|
||||
to_port = properties.get("ToPort")
|
||||
|
||||
assert group_id or group_name
|
||||
|
|
@ -1329,7 +1328,6 @@ class SecurityGroupIngress(object):
|
|||
else:
|
||||
ip_ranges = []
|
||||
|
||||
|
||||
if group_id:
|
||||
security_group = ec2_backend.describe_security_groups(group_ids=[group_id])[0]
|
||||
else:
|
||||
|
|
@ -1697,41 +1695,66 @@ class VPCPeeringConnectionBackend(object):
|
|||
|
||||
|
||||
class Subnet(TaggedEC2Resource):
|
||||
def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block):
|
||||
def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block, availability_zone):
|
||||
self.ec2_backend = ec2_backend
|
||||
self.id = subnet_id
|
||||
self.vpc_id = vpc_id
|
||||
self.cidr_block = cidr_block
|
||||
self._availability_zone = availability_zone
|
||||
|
||||
@classmethod
|
||||
def create_from_cloudformation_json(cls, resource_name, cloudformation_json, region_name):
|
||||
properties = cloudformation_json['Properties']
|
||||
|
||||
vpc_id = properties['VpcId']
|
||||
cidr_block = properties['CidrBlock']
|
||||
availability_zone = properties.get('AvailabilityZone')
|
||||
ec2_backend = ec2_backends[region_name]
|
||||
subnet = ec2_backend.create_subnet(
|
||||
vpc_id=vpc_id,
|
||||
cidr_block=properties['CidrBlock']
|
||||
cidr_block=cidr_block,
|
||||
availability_zone=availability_zone,
|
||||
)
|
||||
return subnet
|
||||
|
||||
@property
|
||||
def availability_zone(self):
|
||||
# This could probably be smarter, but there doesn't appear to be a
|
||||
# way to pull AZs for a region in boto
|
||||
return self.ec2_backend.region_name + "a"
|
||||
if self._availability_zone is None:
|
||||
# This could probably be smarter, but there doesn't appear to be a
|
||||
# way to pull AZs for a region in boto
|
||||
return self.ec2_backend.region_name + "a"
|
||||
else:
|
||||
return self._availability_zone
|
||||
|
||||
@property
|
||||
def physical_resource_id(self):
|
||||
return self.id
|
||||
|
||||
def get_filter_value(self, filter_name):
|
||||
"""
|
||||
API Version 2014-10-01 defines the following filters for DescribeSubnets:
|
||||
|
||||
* availabilityZone
|
||||
* available-ip-address-count
|
||||
* cidrBlock
|
||||
* defaultForAz
|
||||
* state
|
||||
* subnet-id
|
||||
* tag:key=value
|
||||
* tag-key
|
||||
* tag-value
|
||||
* vpc-id
|
||||
|
||||
Taken from: http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html
|
||||
"""
|
||||
if filter_name in ['cidr', 'cidrBlock', 'cidr-block']:
|
||||
return self.cidr_block
|
||||
elif filter_name == 'vpc-id':
|
||||
return self.vpc_id
|
||||
elif filter_name == 'subnet-id':
|
||||
return self.id
|
||||
elif filter_name == 'availabilityZone':
|
||||
return self.availability_zone
|
||||
|
||||
filter_value = super(Subnet, self).get_filter_value(filter_name)
|
||||
|
||||
|
|
@ -1758,9 +1781,9 @@ class SubnetBackend(object):
|
|||
raise InvalidSubnetIdError(subnet_id)
|
||||
return subnet
|
||||
|
||||
def create_subnet(self, vpc_id, cidr_block):
|
||||
def create_subnet(self, vpc_id, cidr_block, availability_zone=None):
|
||||
subnet_id = random_subnet_id()
|
||||
subnet = Subnet(self, subnet_id, vpc_id, cidr_block)
|
||||
subnet = Subnet(self, subnet_id, vpc_id, cidr_block, availability_zone)
|
||||
self.get_vpc(vpc_id) # Validate VPC exists
|
||||
|
||||
# AWS associates a new subnet with the default Network ACL
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ CREATE_VOLUME_RESPONSE = """<CreateVolumeResponse xmlns="http://ec2.amazonaws.co
|
|||
<snapshotId/>
|
||||
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
|
||||
<status>creating</status>
|
||||
<createTime>YYYY-MM-DDTHH:MM:SS.000Z</createTime>
|
||||
<createTime>2013-10-04T17:38:53.000Z</createTime>
|
||||
<volumeType>standard</volumeType>
|
||||
</CreateVolumeResponse>"""
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
|
|||
<snapshotId/>
|
||||
<availabilityZone>{{ volume.zone.name }}</availabilityZone>
|
||||
<status>{{ volume.status }}</status>
|
||||
<createTime>YYYY-MM-DDTHH:MM:SS.SSSZ</createTime>
|
||||
<createTime>2013-10-04T17:38:53.000Z</createTime>
|
||||
<attachmentSet>
|
||||
{% if volume.attachment %}
|
||||
<item>
|
||||
|
|
@ -125,7 +125,7 @@ DESCRIBE_VOLUMES_RESPONSE = """<DescribeVolumesResponse xmlns="http://ec2.amazon
|
|||
<instanceId>{{ volume.attachment.instance.id }}</instanceId>
|
||||
<device>{{ volume.attachment.device }}</device>
|
||||
<status>attached</status>
|
||||
<attachTime>YYYY-MM-DDTHH:MM:SS.SSSZ</attachTime>
|
||||
<attachTime>2013-10-04T17:38:53.000Z</attachTime>
|
||||
<deleteOnTermination>false</deleteOnTermination>
|
||||
</item>
|
||||
{% endif %}
|
||||
|
|
@ -157,7 +157,7 @@ ATTACHED_VOLUME_RESPONSE = """<AttachVolumeResponse xmlns="http://ec2.amazonaws.
|
|||
<instanceId>{{ attachment.instance.id }}</instanceId>
|
||||
<device>{{ attachment.device }}</device>
|
||||
<status>attaching</status>
|
||||
<attachTime>YYYY-MM-DDTHH:MM:SS.000Z</attachTime>
|
||||
<attachTime>2013-10-04T17:38:53.000Z</attachTime>
|
||||
</AttachVolumeResponse>"""
|
||||
|
||||
DETATCH_VOLUME_RESPONSE = """<DetachVolumeResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
|
||||
|
|
@ -166,7 +166,7 @@ DETATCH_VOLUME_RESPONSE = """<DetachVolumeResponse xmlns="http://ec2.amazonaws.c
|
|||
<instanceId>{{ attachment.instance.id }}</instanceId>
|
||||
<device>{{ attachment.device }}</device>
|
||||
<status>detaching</status>
|
||||
<attachTime>YYYY-MM-DDTHH:MM:SS.000Z</attachTime>
|
||||
<attachTime>2013-10-04T17:38:53.000Z</attachTime>
|
||||
</DetachVolumeResponse>"""
|
||||
|
||||
CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
|
||||
|
|
@ -174,7 +174,7 @@ CREATE_SNAPSHOT_RESPONSE = """<CreateSnapshotResponse xmlns="http://ec2.amazonaw
|
|||
<snapshotId>{{ snapshot.id }}</snapshotId>
|
||||
<volumeId>{{ snapshot.volume.id }}</volumeId>
|
||||
<status>pending</status>
|
||||
<startTime>YYYY-MM-DDTHH:MM:SS.000Z</startTime>
|
||||
<startTime>2013-10-04T17:38:53.000Z</startTime>
|
||||
<progress>60%</progress>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
|
||||
|
|
@ -189,7 +189,7 @@ DESCRIBE_SNAPSHOTS_RESPONSE = """<DescribeSnapshotsResponse xmlns="http://ec2.am
|
|||
<snapshotId>{{ snapshot.id }}</snapshotId>
|
||||
<volumeId>{{ snapshot.volume.id }}</volumeId>
|
||||
<status>pending</status>
|
||||
<startTime>YYYY-MM-DDTHH:MM:SS.SSSZ</startTime>
|
||||
<startTime>2013-10-04T17:38:53.000Z</startTime>
|
||||
<progress>30%</progress>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<volumeSize>{{ snapshot.volume.size }}</volumeSize>
|
||||
|
|
|
|||
|
|
@ -214,8 +214,10 @@ EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc
|
|||
<state>enabled</state>
|
||||
</monitoring>
|
||||
{% if instance.nics %}
|
||||
<subnetId>{{ instance.nics[0].subnet.id }}</subnetId>
|
||||
<vpcId>{{ instance.nics[0].subnet.vpc_id }}</vpcId>
|
||||
{% if instance.nics[0].subnet %}
|
||||
<subnetId>{{ instance.nics[0].subnet.id }}</subnetId>
|
||||
<vpcId>{{ instance.nics[0].subnet.vpc_id }}</vpcId>
|
||||
{% endif %}
|
||||
<privateIpAddress>{{ instance.private_ip }}</privateIpAddress>
|
||||
{% if instance.public_ip %}
|
||||
<ipAddress>{{ instance.public_ip }}</ipAddress>
|
||||
|
|
@ -245,8 +247,10 @@ EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc
|
|||
{% for nic in instance.nics.values() %}
|
||||
<item>
|
||||
<networkInterfaceId>{{ nic.id }}</networkInterfaceId>
|
||||
<subnetId>{{ nic.subnet.id }}</subnetId>
|
||||
<vpcId>{{ nic.subnet.vpc_id }}</vpcId>
|
||||
{% if nic.subnet %}
|
||||
<subnetId>{{ nic.subnet.id }}</subnetId>
|
||||
<vpcId>{{ nic.subnet.vpc_id }}</vpcId>
|
||||
{% endif %}
|
||||
<description>Primary network interface</description>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<status>in-use</status>
|
||||
|
|
@ -338,8 +342,10 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
|
|||
<state>disabled</state>
|
||||
</monitoring>
|
||||
{% if instance.nics %}
|
||||
<subnetId>{{ instance.nics[0].subnet.id }}</subnetId>
|
||||
<vpcId>{{ instance.nics[0].subnet.vpc_id }}</vpcId>
|
||||
{% if instance.nics[0].subnet %}
|
||||
<subnetId>{{ instance.nics[0].subnet.id }}</subnetId>
|
||||
<vpcId>{{ instance.nics[0].subnet.vpc_id }}</vpcId>
|
||||
{% endif %}
|
||||
<privateIpAddress>{{ instance.private_ip }}</privateIpAddress>
|
||||
{% if instance.nics[0].public_ip %}
|
||||
<ipAddress>{{ instance.nics[0].public_ip }}</ipAddress>
|
||||
|
|
@ -390,8 +396,10 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
|
|||
{% for nic in instance.nics.values() %}
|
||||
<item>
|
||||
<networkInterfaceId>{{ nic.id }}</networkInterfaceId>
|
||||
<subnetId>{{ nic.subnet.id }}</subnetId>
|
||||
<vpcId>{{ nic.subnet.vpc_id }}</vpcId>
|
||||
{% if nic.subnet %}
|
||||
<subnetId>{{ nic.subnet.id }}</subnetId>
|
||||
<vpcId>{{ nic.subnet.vpc_id }}</vpcId>
|
||||
{% endif %}
|
||||
<description>Primary network interface</description>
|
||||
<ownerId>111122223333</ownerId>
|
||||
<status>in-use</status>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,15 @@ class Subnets(BaseResponse):
|
|||
def create_subnet(self):
|
||||
vpc_id = self.querystring.get('VpcId')[0]
|
||||
cidr_block = self.querystring.get('CidrBlock')[0]
|
||||
subnet = self.ec2_backend.create_subnet(vpc_id, cidr_block)
|
||||
if 'AvailabilityZone' in self.querystring:
|
||||
availability_zone = self.querystring['AvailabilityZone'][0]
|
||||
else:
|
||||
availability_zone = None
|
||||
subnet = self.ec2_backend.create_subnet(
|
||||
vpc_id,
|
||||
cidr_block,
|
||||
availability_zone,
|
||||
)
|
||||
template = self.response_template(CREATE_SUBNET_RESPONSE)
|
||||
return template.render(subnet=subnet)
|
||||
|
||||
|
|
@ -33,7 +41,7 @@ CREATE_SUBNET_RESPONSE = """
|
|||
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||
<availableIpAddressCount>251</availableIpAddressCount>
|
||||
<availabilityZone>us-east-1a</availabilityZone>
|
||||
<availabilityZone>{{ subnet.availability_zone }}</availabilityZone>
|
||||
<tagSet>
|
||||
{% for tag in subnet.get_tags() %}
|
||||
<item>
|
||||
|
|
@ -64,7 +72,7 @@ DESCRIBE_SUBNETS_RESPONSE = """
|
|||
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||
<availableIpAddressCount>251</availableIpAddressCount>
|
||||
<availabilityZone>us-east-1a</availabilityZone>
|
||||
<availabilityZone>{{ subnet.availability_zone }}</availabilityZone>
|
||||
<tagSet>
|
||||
{% for tag in subnet.get_tags() %}
|
||||
<item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue