Updates to create_subnet and describe_subnets responses (#2053)
* Removed Tags field from create_subnet response. * Added DefaultForAz to create_subnet response. * Added MapPublicIpOnLaunch to create_subnet response. * Added OwnerId to create_subnet response. * Added AssignIpv6AddressOnCreation field for create_subnet and describe_subnet and implemented setting it in modify_subnet_attribute. * Added SubnetArn to create_subnet response. * Added AvailabilityZoneId to create_subnet and describe_subnet responses, and error for invalid availability zone. * Added Ipv6CidrBlockAssociationSet to create_subnet response. * Added missing fields to describe_subnets response. * Added myself to list of contributors and marked describe_subnet as implemented. * Fixed linting errors. * Fixed blank line containing a tab. * Fixed accidentally deleted ). * Fixed broken tests.
This commit is contained in:
parent
2386d47fe3
commit
8f53b16b9a
@ -54,5 +54,6 @@ Moto is written by Steve Pulec with contributions from:
|
|||||||
* [William Richard](https://github.com/william-richard)
|
* [William Richard](https://github.com/william-richard)
|
||||||
* [Alex Casalboni](https://github.com/alexcasalboni)
|
* [Alex Casalboni](https://github.com/alexcasalboni)
|
||||||
* [Jon Beilke](https://github.com/jrbeilke)
|
* [Jon Beilke](https://github.com/jrbeilke)
|
||||||
|
* [Bendeguz Acs](https://github.com/acsbendi)
|
||||||
* [Craig Anderson](https://github.com/craiga)
|
* [Craig Anderson](https://github.com/craiga)
|
||||||
* [Robert Lewis](https://github.com/ralewis85)
|
* [Robert Lewis](https://github.com/ralewis85)
|
||||||
|
@ -1473,7 +1473,7 @@
|
|||||||
- [X] describe_spot_instance_requests
|
- [X] describe_spot_instance_requests
|
||||||
- [ ] describe_spot_price_history
|
- [ ] describe_spot_price_history
|
||||||
- [ ] describe_stale_security_groups
|
- [ ] describe_stale_security_groups
|
||||||
- [ ] describe_subnets
|
- [X] describe_subnets
|
||||||
- [X] describe_tags
|
- [X] describe_tags
|
||||||
- [ ] describe_volume_attribute
|
- [ ] describe_volume_attribute
|
||||||
- [ ] describe_volume_status
|
- [ ] describe_volume_status
|
||||||
|
@ -430,6 +430,16 @@ class OperationNotPermitted(EC2ClientError):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidAvailabilityZoneError(EC2ClientError):
|
||||||
|
|
||||||
|
def __init__(self, availability_zone_value, valid_availability_zones):
|
||||||
|
super(InvalidAvailabilityZoneError, self).__init__(
|
||||||
|
"InvalidParameterValue",
|
||||||
|
"Value ({0}) for parameter availabilityZone is invalid. "
|
||||||
|
"Subnets can currently only be created in the following availability zones: {1}.".format(availability_zone_value, valid_availability_zones)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class NetworkAclEntryAlreadyExistsError(EC2ClientError):
|
class NetworkAclEntryAlreadyExistsError(EC2ClientError):
|
||||||
|
|
||||||
def __init__(self, rule_number):
|
def __init__(self, rule_number):
|
||||||
|
@ -36,6 +36,7 @@ from .exceptions import (
|
|||||||
InvalidAMIIdError,
|
InvalidAMIIdError,
|
||||||
InvalidAMIAttributeItemValueError,
|
InvalidAMIAttributeItemValueError,
|
||||||
InvalidAssociationIdError,
|
InvalidAssociationIdError,
|
||||||
|
InvalidAvailabilityZoneError,
|
||||||
InvalidCIDRBlockParameterError,
|
InvalidCIDRBlockParameterError,
|
||||||
InvalidCIDRSubnetError,
|
InvalidCIDRSubnetError,
|
||||||
InvalidCustomerGatewayIdError,
|
InvalidCustomerGatewayIdError,
|
||||||
@ -1288,17 +1289,107 @@ class Region(object):
|
|||||||
|
|
||||||
|
|
||||||
class Zone(object):
|
class Zone(object):
|
||||||
def __init__(self, name, region_name):
|
def __init__(self, name, region_name, zone_id):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.region_name = region_name
|
self.region_name = region_name
|
||||||
|
self.zone_id = zone_id
|
||||||
|
|
||||||
|
|
||||||
class RegionsAndZonesBackend(object):
|
class RegionsAndZonesBackend(object):
|
||||||
regions = [Region(ri.name, ri.endpoint) for ri in boto.ec2.regions()]
|
regions = [Region(ri.name, ri.endpoint) for ri in boto.ec2.regions()]
|
||||||
|
|
||||||
zones = dict(
|
zones = {
|
||||||
(region, [Zone(region + c, region) for c in 'abc'])
|
'ap-south-1': [
|
||||||
for region in [r.name for r in regions])
|
Zone(region_name="ap-south-1", name="ap-south-1a", zone_id="aps1-az1"),
|
||||||
|
Zone(region_name="ap-south-1", name="ap-south-1b", zone_id="aps1-az3")
|
||||||
|
],
|
||||||
|
'eu-west-3': [
|
||||||
|
Zone(region_name="eu-west-3", name="eu-west-3a", zone_id="euw3-az1"),
|
||||||
|
Zone(region_name="eu-west-3", name="eu-west-3b", zone_id="euw3-az2"),
|
||||||
|
Zone(region_name="eu-west-3", name="eu-west-3c", zone_id="euw3-az3")
|
||||||
|
],
|
||||||
|
'eu-north-1': [
|
||||||
|
Zone(region_name="eu-north-1", name="eu-north-1a", zone_id="eun1-az1"),
|
||||||
|
Zone(region_name="eu-north-1", name="eu-north-1b", zone_id="eun1-az2"),
|
||||||
|
Zone(region_name="eu-north-1", name="eu-north-1c", zone_id="eun1-az3")
|
||||||
|
],
|
||||||
|
'eu-west-2': [
|
||||||
|
Zone(region_name="eu-west-2", name="eu-west-2a", zone_id="euw2-az2"),
|
||||||
|
Zone(region_name="eu-west-2", name="eu-west-2b", zone_id="euw2-az3"),
|
||||||
|
Zone(region_name="eu-west-2", name="eu-west-2c", zone_id="euw2-az1")
|
||||||
|
],
|
||||||
|
'eu-west-1': [
|
||||||
|
Zone(region_name="eu-west-1", name="eu-west-1a", zone_id="euw1-az3"),
|
||||||
|
Zone(region_name="eu-west-1", name="eu-west-1b", zone_id="euw1-az1"),
|
||||||
|
Zone(region_name="eu-west-1", name="eu-west-1c", zone_id="euw1-az2")
|
||||||
|
],
|
||||||
|
'ap-northeast-3': [
|
||||||
|
Zone(region_name="ap-northeast-3", name="ap-northeast-2a", zone_id="apne3-az1")
|
||||||
|
],
|
||||||
|
'ap-northeast-2': [
|
||||||
|
Zone(region_name="ap-northeast-2", name="ap-northeast-2a", zone_id="apne2-az1"),
|
||||||
|
Zone(region_name="ap-northeast-2", name="ap-northeast-2c", zone_id="apne2-az3")
|
||||||
|
],
|
||||||
|
'ap-northeast-1': [
|
||||||
|
Zone(region_name="ap-northeast-1", name="ap-northeast-1a", zone_id="apne1-az4"),
|
||||||
|
Zone(region_name="ap-northeast-1", name="ap-northeast-1c", zone_id="apne1-az1"),
|
||||||
|
Zone(region_name="ap-northeast-1", name="ap-northeast-1d", zone_id="apne1-az2")
|
||||||
|
],
|
||||||
|
'sa-east-1': [
|
||||||
|
Zone(region_name="sa-east-1", name="sa-east-1a", zone_id="sae1-az1"),
|
||||||
|
Zone(region_name="sa-east-1", name="sa-east-1c", zone_id="sae1-az3")
|
||||||
|
],
|
||||||
|
'ca-central-1': [
|
||||||
|
Zone(region_name="ca-central-1", name="ca-central-1a", zone_id="cac1-az1"),
|
||||||
|
Zone(region_name="ca-central-1", name="ca-central-1b", zone_id="cac1-az2")
|
||||||
|
],
|
||||||
|
'ap-southeast-1': [
|
||||||
|
Zone(region_name="ap-southeast-1", name="ap-southeast-1a", zone_id="apse1-az1"),
|
||||||
|
Zone(region_name="ap-southeast-1", name="ap-southeast-1b", zone_id="apse1-az2"),
|
||||||
|
Zone(region_name="ap-southeast-1", name="ap-southeast-1c", zone_id="apse1-az3")
|
||||||
|
],
|
||||||
|
'ap-southeast-2': [
|
||||||
|
Zone(region_name="ap-southeast-2", name="ap-southeast-2a", zone_id="apse2-az1"),
|
||||||
|
Zone(region_name="ap-southeast-2", name="ap-southeast-2b", zone_id="apse2-az3"),
|
||||||
|
Zone(region_name="ap-southeast-2", name="ap-southeast-2c", zone_id="apse2-az2")
|
||||||
|
],
|
||||||
|
'eu-central-1': [
|
||||||
|
Zone(region_name="eu-central-1", name="eu-central-1a", zone_id="euc1-az2"),
|
||||||
|
Zone(region_name="eu-central-1", name="eu-central-1b", zone_id="euc1-az3"),
|
||||||
|
Zone(region_name="eu-central-1", name="eu-central-1c", zone_id="euc1-az1")
|
||||||
|
],
|
||||||
|
'us-east-1': [
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1a", zone_id="use1-az6"),
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1b", zone_id="use1-az1"),
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1c", zone_id="use1-az2"),
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1d", zone_id="use1-az4"),
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1e", zone_id="use1-az3"),
|
||||||
|
Zone(region_name="us-east-1", name="us-east-1f", zone_id="use1-az5")
|
||||||
|
],
|
||||||
|
'us-east-2': [
|
||||||
|
Zone(region_name="us-east-2", name="us-east-2a", zone_id="use2-az1"),
|
||||||
|
Zone(region_name="us-east-2", name="us-east-2b", zone_id="use2-az2"),
|
||||||
|
Zone(region_name="us-east-2", name="us-east-2c", zone_id="use2-az3")
|
||||||
|
],
|
||||||
|
'us-west-1': [
|
||||||
|
Zone(region_name="us-west-1", name="us-west-1a", zone_id="usw1-az3"),
|
||||||
|
Zone(region_name="us-west-1", name="us-west-1b", zone_id="usw1-az1")
|
||||||
|
],
|
||||||
|
'us-west-2': [
|
||||||
|
Zone(region_name="us-west-2", name="us-west-2a", zone_id="usw2-az2"),
|
||||||
|
Zone(region_name="us-west-2", name="us-west-2b", zone_id="usw2-az1"),
|
||||||
|
Zone(region_name="us-west-2", name="us-west-2c", zone_id="usw2-az3")
|
||||||
|
],
|
||||||
|
'cn-north-1': [
|
||||||
|
Zone(region_name="cn-north-1", name="cn-north-1a", zone_id="cnn1-az1"),
|
||||||
|
Zone(region_name="cn-north-1", name="cn-north-1b", zone_id="cnn1-az2")
|
||||||
|
],
|
||||||
|
'us-gov-west-1': [
|
||||||
|
Zone(region_name="us-gov-west-1", name="us-gov-west-1a", zone_id="usgw1-az1"),
|
||||||
|
Zone(region_name="us-gov-west-1", name="us-gov-west-1b", zone_id="usgw1-az2"),
|
||||||
|
Zone(region_name="us-gov-west-1", name="us-gov-west-1c", zone_id="usgw1-az3")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
def describe_regions(self, region_names=[]):
|
def describe_regions(self, region_names=[]):
|
||||||
if len(region_names) == 0:
|
if len(region_names) == 0:
|
||||||
@ -2374,7 +2465,7 @@ class VPCPeeringConnectionBackend(object):
|
|||||||
|
|
||||||
class Subnet(TaggedEC2Resource):
|
class Subnet(TaggedEC2Resource):
|
||||||
def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block, availability_zone, default_for_az,
|
def __init__(self, ec2_backend, subnet_id, vpc_id, cidr_block, availability_zone, default_for_az,
|
||||||
map_public_ip_on_launch):
|
map_public_ip_on_launch, owner_id=111122223333, assign_ipv6_address_on_creation=False):
|
||||||
self.ec2_backend = ec2_backend
|
self.ec2_backend = ec2_backend
|
||||||
self.id = subnet_id
|
self.id = subnet_id
|
||||||
self.vpc_id = vpc_id
|
self.vpc_id = vpc_id
|
||||||
@ -2383,6 +2474,9 @@ class Subnet(TaggedEC2Resource):
|
|||||||
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
|
||||||
|
self.owner_id = owner_id
|
||||||
|
self.assign_ipv6_address_on_creation = assign_ipv6_address_on_creation
|
||||||
|
self.ipv6_cidr_block_associations = []
|
||||||
|
|
||||||
# Theory is we assign ip's as we go (as 16,777,214 usable IPs in a /8)
|
# Theory is we assign ip's as we go (as 16,777,214 usable IPs in a /8)
|
||||||
self._subnet_ip_generator = self.cidr.hosts()
|
self._subnet_ip_generator = self.cidr.hosts()
|
||||||
@ -2412,7 +2506,7 @@ class Subnet(TaggedEC2Resource):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def availability_zone(self):
|
def availability_zone(self):
|
||||||
return self._availability_zone
|
return self._availability_zone.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def physical_resource_id(self):
|
def physical_resource_id(self):
|
||||||
@ -2509,7 +2603,7 @@ class SubnetBackend(object):
|
|||||||
return subnets[subnet_id]
|
return subnets[subnet_id]
|
||||||
raise InvalidSubnetIdError(subnet_id)
|
raise InvalidSubnetIdError(subnet_id)
|
||||||
|
|
||||||
def create_subnet(self, vpc_id, cidr_block, availability_zone):
|
def create_subnet(self, vpc_id, cidr_block, availability_zone, context=None):
|
||||||
subnet_id = random_subnet_id()
|
subnet_id = random_subnet_id()
|
||||||
vpc = self.get_vpc(vpc_id) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's
|
vpc = self.get_vpc(vpc_id) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's
|
||||||
vpc_cidr_block = ipaddress.IPv4Network(six.text_type(vpc.cidr_block), strict=False)
|
vpc_cidr_block = ipaddress.IPv4Network(six.text_type(vpc.cidr_block), strict=False)
|
||||||
@ -2529,8 +2623,15 @@ class SubnetBackend(object):
|
|||||||
# consider it the default
|
# consider it the default
|
||||||
default_for_az = str(availability_zone not in self.subnets).lower()
|
default_for_az = str(availability_zone not in self.subnets).lower()
|
||||||
map_public_ip_on_launch = default_for_az
|
map_public_ip_on_launch = default_for_az
|
||||||
subnet = Subnet(self, subnet_id, vpc_id, cidr_block, availability_zone,
|
if availability_zone is None:
|
||||||
default_for_az, map_public_ip_on_launch)
|
availability_zone = 'us-east-1a'
|
||||||
|
try:
|
||||||
|
availability_zone_data = next(zone for zones in RegionsAndZonesBackend.zones.values() for zone in zones if zone.name == availability_zone)
|
||||||
|
except StopIteration:
|
||||||
|
raise InvalidAvailabilityZoneError(availability_zone, ", ".join([zone.name for zones in RegionsAndZonesBackend.zones.values() for zone in zones]))
|
||||||
|
subnet = Subnet(self, subnet_id, vpc_id, cidr_block, availability_zone_data,
|
||||||
|
default_for_az, map_public_ip_on_launch,
|
||||||
|
owner_id=context.get_current_user() if context else '111122223333', assign_ipv6_address_on_creation=False)
|
||||||
|
|
||||||
# AWS associates a new subnet with the default Network ACL
|
# AWS associates a new subnet with the default Network ACL
|
||||||
self.associate_default_network_acl_with_subnet(subnet_id, vpc_id)
|
self.associate_default_network_acl_with_subnet(subnet_id, vpc_id)
|
||||||
@ -2558,11 +2659,12 @@ class SubnetBackend(object):
|
|||||||
return subnets.pop(subnet_id, None)
|
return subnets.pop(subnet_id, None)
|
||||||
raise InvalidSubnetIdError(subnet_id)
|
raise InvalidSubnetIdError(subnet_id)
|
||||||
|
|
||||||
def modify_subnet_attribute(self, subnet_id, map_public_ip):
|
def modify_subnet_attribute(self, subnet_id, attr_name, attr_value):
|
||||||
subnet = self.get_subnet(subnet_id)
|
subnet = self.get_subnet(subnet_id)
|
||||||
if map_public_ip not in ('true', 'false'):
|
if attr_name in ('map_public_ip_on_launch', 'assign_ipv6_address_on_creation'):
|
||||||
raise InvalidParameterValueError(map_public_ip)
|
setattr(subnet, attr_name, attr_value)
|
||||||
subnet.map_public_ip_on_launch = map_public_ip
|
else:
|
||||||
|
raise InvalidParameterValueError(attr_name)
|
||||||
|
|
||||||
|
|
||||||
class SubnetRouteTableAssociation(object):
|
class SubnetRouteTableAssociation(object):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import random
|
import random
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
|
from moto.core.utils import camelcase_to_underscores
|
||||||
from moto.ec2.utils import filters_from_querystring
|
from moto.ec2.utils import filters_from_querystring
|
||||||
|
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ class Subnets(BaseResponse):
|
|||||||
vpc_id,
|
vpc_id,
|
||||||
cidr_block,
|
cidr_block,
|
||||||
availability_zone,
|
availability_zone,
|
||||||
|
context=self,
|
||||||
)
|
)
|
||||||
template = self.response_template(CREATE_SUBNET_RESPONSE)
|
template = self.response_template(CREATE_SUBNET_RESPONSE)
|
||||||
return template.render(subnet=subnet)
|
return template.render(subnet=subnet)
|
||||||
@ -35,9 +37,14 @@ class Subnets(BaseResponse):
|
|||||||
|
|
||||||
def modify_subnet_attribute(self):
|
def modify_subnet_attribute(self):
|
||||||
subnet_id = self._get_param('SubnetId')
|
subnet_id = self._get_param('SubnetId')
|
||||||
map_public_ip = self._get_param('MapPublicIpOnLaunch.Value')
|
|
||||||
self.ec2_backend.modify_subnet_attribute(subnet_id, map_public_ip)
|
for attribute in ('MapPublicIpOnLaunch', 'AssignIpv6AddressOnCreation'):
|
||||||
return MODIFY_SUBNET_ATTRIBUTE_RESPONSE
|
if self.querystring.get('%s.Value' % attribute):
|
||||||
|
attr_name = camelcase_to_underscores(attribute)
|
||||||
|
attr_value = self.querystring.get('%s.Value' % attribute)[0]
|
||||||
|
self.ec2_backend.modify_subnet_attribute(
|
||||||
|
subnet_id, attr_name, attr_value)
|
||||||
|
return MODIFY_SUBNET_ATTRIBUTE_RESPONSE
|
||||||
|
|
||||||
|
|
||||||
CREATE_SUBNET_RESPONSE = """
|
CREATE_SUBNET_RESPONSE = """
|
||||||
@ -49,17 +56,14 @@ CREATE_SUBNET_RESPONSE = """
|
|||||||
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
||||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||||
<availableIpAddressCount>251</availableIpAddressCount>
|
<availableIpAddressCount>251</availableIpAddressCount>
|
||||||
<availabilityZone>{{ subnet.availability_zone }}</availabilityZone>
|
<availabilityZone>{{ subnet._availability_zone.name }}</availabilityZone>
|
||||||
<tagSet>
|
<availabilityZoneId>{{ subnet._availability_zone.zone_id }}</availabilityZoneId>
|
||||||
{% for tag in subnet.get_tags() %}
|
<defaultForAz>{{ subnet.default_for_az }}</defaultForAz>
|
||||||
<item>
|
<mapPublicIpOnLaunch>{{ subnet.map_public_ip_on_launch }}</mapPublicIpOnLaunch>
|
||||||
<resourceId>{{ tag.resource_id }}</resourceId>
|
<ownerId>{{ subnet.owner_id }}</ownerId>
|
||||||
<resourceType>{{ tag.resource_type }}</resourceType>
|
<assignIpv6AddressOnCreation>{{ subnet.assign_ipv6_address_on_creation }}</assignIpv6AddressOnCreation>
|
||||||
<key>{{ tag.key }}</key>
|
<ipv6CidrBlockAssociationSet>{{ subnet.ipv6_cidr_block_associations }}</ipv6CidrBlockAssociationSet>
|
||||||
<value>{{ tag.value }}</value>
|
<subnetArn>arn:aws:ec2:{{ subnet._availability_zone.name[0:-1] }}:{{ subnet.owner_id }}:subnet/{{ subnet.id }}</subnetArn>
|
||||||
</item>
|
|
||||||
{% endfor %}
|
|
||||||
</tagSet>
|
|
||||||
</subnet>
|
</subnet>
|
||||||
</CreateSubnetResponse>"""
|
</CreateSubnetResponse>"""
|
||||||
|
|
||||||
@ -80,19 +84,26 @@ DESCRIBE_SUBNETS_RESPONSE = """
|
|||||||
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
<vpcId>{{ subnet.vpc_id }}</vpcId>
|
||||||
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
<cidrBlock>{{ subnet.cidr_block }}</cidrBlock>
|
||||||
<availableIpAddressCount>251</availableIpAddressCount>
|
<availableIpAddressCount>251</availableIpAddressCount>
|
||||||
<availabilityZone>{{ subnet.availability_zone }}</availabilityZone>
|
<availabilityZone>{{ subnet._availability_zone.name }}</availabilityZone>
|
||||||
|
<availabilityZoneId>{{ subnet._availability_zone.zone_id }}</availabilityZoneId>
|
||||||
<defaultForAz>{{ subnet.default_for_az }}</defaultForAz>
|
<defaultForAz>{{ subnet.default_for_az }}</defaultForAz>
|
||||||
<mapPublicIpOnLaunch>{{ subnet.map_public_ip_on_launch }}</mapPublicIpOnLaunch>
|
<mapPublicIpOnLaunch>{{ subnet.map_public_ip_on_launch }}</mapPublicIpOnLaunch>
|
||||||
<tagSet>
|
<ownerId>{{ subnet.owner_id }}</ownerId>
|
||||||
{% for tag in subnet.get_tags() %}
|
<assignIpv6AddressOnCreation>{{ subnet.assign_ipv6_address_on_creation }}</assignIpv6AddressOnCreation>
|
||||||
<item>
|
<ipv6CidrBlockAssociationSet>{{ subnet.ipv6_cidr_block_associations }}</ipv6CidrBlockAssociationSet>
|
||||||
<resourceId>{{ tag.resource_id }}</resourceId>
|
<subnetArn>arn:aws:ec2:{{ subnet._availability_zone.name[0:-1] }}:{{ subnet.owner_id }}:subnet/{{ subnet.id }}</subnetArn>
|
||||||
<resourceType>{{ tag.resource_type }}</resourceType>
|
{% if subnet.get_tags() %}
|
||||||
<key>{{ tag.key }}</key>
|
<tagSet>
|
||||||
<value>{{ tag.value }}</value>
|
{% for tag in subnet.get_tags() %}
|
||||||
</item>
|
<item>
|
||||||
{% endfor %}
|
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||||
</tagSet>
|
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||||
|
<key>{{ tag.key }}</key>
|
||||||
|
<value>{{ tag.value }}</value>
|
||||||
|
</item>
|
||||||
|
{% endfor %}
|
||||||
|
</tagSet>
|
||||||
|
{% endif %}
|
||||||
</item>
|
</item>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</subnetSet>
|
</subnetSet>
|
||||||
|
@ -30,12 +30,12 @@ def test_new_subnet_associates_with_default_network_acl():
|
|||||||
conn = boto.connect_vpc('the_key', 'the secret')
|
conn = boto.connect_vpc('the_key', 'the secret')
|
||||||
vpc = conn.get_all_vpcs()[0]
|
vpc = conn.get_all_vpcs()[0]
|
||||||
|
|
||||||
subnet = conn.create_subnet(vpc.id, "172.31.48.0/20")
|
subnet = conn.create_subnet(vpc.id, "172.31.112.0/20")
|
||||||
all_network_acls = conn.get_all_network_acls()
|
all_network_acls = conn.get_all_network_acls()
|
||||||
all_network_acls.should.have.length_of(1)
|
all_network_acls.should.have.length_of(1)
|
||||||
|
|
||||||
acl = all_network_acls[0]
|
acl = all_network_acls[0]
|
||||||
acl.associations.should.have.length_of(4)
|
acl.associations.should.have.length_of(7)
|
||||||
[a.subnet_id for a in acl.associations].should.contain(subnet.id)
|
[a.subnet_id for a in acl.associations].should.contain(subnet.id)
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ def test_boto3_non_default_subnet():
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_modify_subnet_attribute():
|
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')
|
||||||
|
|
||||||
@ -145,6 +145,34 @@ def test_modify_subnet_attribute():
|
|||||||
subnet.map_public_ip_on_launch.should.be.ok
|
subnet.map_public_ip_on_launch.should.be.ok
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_modify_subnet_attribute_assign_ipv6_address_on_creation():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
|
client = boto3.client('ec2', region_name='us-west-1')
|
||||||
|
|
||||||
|
# Get the default VPC
|
||||||
|
vpc = list(ec2.vpcs.all())[0]
|
||||||
|
|
||||||
|
subnet = ec2.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='172.31.112.0/20', AvailabilityZone='us-west-1a')
|
||||||
|
|
||||||
|
# 'map_public_ip_on_launch' is set when calling 'DescribeSubnets' action
|
||||||
|
subnet.reload()
|
||||||
|
|
||||||
|
# For non default subnet, attribute value should be 'False'
|
||||||
|
subnet.assign_ipv6_address_on_creation.shouldnt.be.ok
|
||||||
|
|
||||||
|
client.modify_subnet_attribute(
|
||||||
|
SubnetId=subnet.id, AssignIpv6AddressOnCreation={'Value': False})
|
||||||
|
subnet.reload()
|
||||||
|
subnet.assign_ipv6_address_on_creation.shouldnt.be.ok
|
||||||
|
|
||||||
|
client.modify_subnet_attribute(
|
||||||
|
SubnetId=subnet.id, AssignIpv6AddressOnCreation={'Value': True})
|
||||||
|
subnet.reload()
|
||||||
|
subnet.assign_ipv6_address_on_creation.should.be.ok
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_modify_subnet_attribute_validation():
|
def test_modify_subnet_attribute_validation():
|
||||||
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
@ -291,6 +319,84 @@ def test_subnet_tags_through_cloudformation():
|
|||||||
subnet.tags["blah"].should.equal("baz")
|
subnet.tags["blah"].should.equal("baz")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_subnet_response_fields():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
|
client = boto3.client('ec2', region_name='us-west-1')
|
||||||
|
|
||||||
|
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
subnet = client.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-1a')['Subnet']
|
||||||
|
|
||||||
|
subnet.should.have.key('AvailabilityZone')
|
||||||
|
subnet.should.have.key('AvailabilityZoneId')
|
||||||
|
subnet.should.have.key('AvailableIpAddressCount')
|
||||||
|
subnet.should.have.key('CidrBlock')
|
||||||
|
subnet.should.have.key('State')
|
||||||
|
subnet.should.have.key('SubnetId')
|
||||||
|
subnet.should.have.key('VpcId')
|
||||||
|
subnet.shouldnt.have.key('Tags')
|
||||||
|
subnet.should.have.key('DefaultForAz').which.should.equal(False)
|
||||||
|
subnet.should.have.key('MapPublicIpOnLaunch').which.should.equal(False)
|
||||||
|
subnet.should.have.key('OwnerId')
|
||||||
|
subnet.should.have.key('AssignIpv6AddressOnCreation').which.should.equal(False)
|
||||||
|
|
||||||
|
subnet_arn = "arn:aws:ec2:{region}:{owner_id}:subnet/{subnet_id}".format(region=subnet['AvailabilityZone'][0:-1],
|
||||||
|
owner_id=subnet['OwnerId'],
|
||||||
|
subnet_id=subnet['SubnetId'])
|
||||||
|
subnet.should.have.key('SubnetArn').which.should.equal(subnet_arn)
|
||||||
|
subnet.should.have.key('Ipv6CidrBlockAssociationSet').which.should.equal([])
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_describe_subnet_response_fields():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
|
client = boto3.client('ec2', region_name='us-west-1')
|
||||||
|
|
||||||
|
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
subnet_object = ec2.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone='us-west-1a')
|
||||||
|
|
||||||
|
subnets = client.describe_subnets(SubnetIds=[subnet_object.id])['Subnets']
|
||||||
|
subnets.should.have.length_of(1)
|
||||||
|
subnet = subnets[0]
|
||||||
|
|
||||||
|
subnet.should.have.key('AvailabilityZone')
|
||||||
|
subnet.should.have.key('AvailabilityZoneId')
|
||||||
|
subnet.should.have.key('AvailableIpAddressCount')
|
||||||
|
subnet.should.have.key('CidrBlock')
|
||||||
|
subnet.should.have.key('State')
|
||||||
|
subnet.should.have.key('SubnetId')
|
||||||
|
subnet.should.have.key('VpcId')
|
||||||
|
subnet.shouldnt.have.key('Tags')
|
||||||
|
subnet.should.have.key('DefaultForAz').which.should.equal(False)
|
||||||
|
subnet.should.have.key('MapPublicIpOnLaunch').which.should.equal(False)
|
||||||
|
subnet.should.have.key('OwnerId')
|
||||||
|
subnet.should.have.key('AssignIpv6AddressOnCreation').which.should.equal(False)
|
||||||
|
|
||||||
|
subnet_arn = "arn:aws:ec2:{region}:{owner_id}:subnet/{subnet_id}".format(region=subnet['AvailabilityZone'][0:-1],
|
||||||
|
owner_id=subnet['OwnerId'],
|
||||||
|
subnet_id=subnet['SubnetId'])
|
||||||
|
subnet.should.have.key('SubnetArn').which.should.equal(subnet_arn)
|
||||||
|
subnet.should.have.key('Ipv6CidrBlockAssociationSet').which.should.equal([])
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_create_subnet_with_invalid_availability_zone():
|
||||||
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
|
client = boto3.client('ec2', region_name='us-west-1')
|
||||||
|
|
||||||
|
vpc = ec2.create_vpc(CidrBlock='10.0.0.0/16')
|
||||||
|
|
||||||
|
subnet_availability_zone = 'asfasfas'
|
||||||
|
with assert_raises(ClientError) as ex:
|
||||||
|
subnet = client.create_subnet(
|
||||||
|
VpcId=vpc.id, CidrBlock='10.0.0.0/24', AvailabilityZone=subnet_availability_zone)
|
||||||
|
assert str(ex.exception).startswith(
|
||||||
|
"An error occurred (InvalidParameterValue) when calling the CreateSubnet "
|
||||||
|
"operation: Value ({}) for parameter availabilityZone is invalid. Subnets can currently only be created in the following availability zones: ".format(subnet_availability_zone))
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_create_subnet_with_invalid_cidr_range():
|
def test_create_subnet_with_invalid_cidr_range():
|
||||||
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
ec2 = boto3.resource('ec2', region_name='us-west-1')
|
||||||
|
Loading…
Reference in New Issue
Block a user