mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 00:55:19 +00:00
[WIP] refactor boto_vpc execution module
This commit is contained in:
parent
5376a13ca9
commit
6f9434cb10
@ -4,6 +4,11 @@ Connection module for Amazon VPC
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
.. versionchanged:: Beryllium
|
||||
When boto raises a BotoServerError, this module now raises CommandExecutionError
|
||||
instead of returning False.
|
||||
|
||||
|
||||
:configuration: This module accepts explicit VPC credentials but can also
|
||||
utilize IAM roles assigned to the instance trough Instance Profiles.
|
||||
Dynamic credentials are then automatically obtained from AWS API and no
|
||||
@ -110,8 +115,8 @@ def _get_profile(service, region, key, keyid, profile):
|
||||
|
||||
|
||||
def _cache_id(name, sub_resource=None, resource_id=None,
|
||||
invalidate=False, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
invalidate=False, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
# TODO: Move this to a common utils module
|
||||
'''
|
||||
Cache, invalidate, or retrieve an AWS resource id keyed by name.
|
||||
@ -146,8 +151,6 @@ def _check_vpc(vpc_id, vpc_name, region, key, keyid, profile):
|
||||
'''
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
if vpc_name:
|
||||
vpc_id = get_id(name=vpc_name, region=region, key=key, keyid=keyid,
|
||||
@ -166,8 +169,8 @@ def _check_vpc(vpc_id, vpc_name, region, key, keyid, profile):
|
||||
return vpc_id
|
||||
|
||||
|
||||
def _create_resource(resource, name, tags, region, key, keyid,
|
||||
profile, **kwargs):
|
||||
def _create_resource(resource, name=None, tags=None, region=None, key=None,
|
||||
keyid=None, profile=None, **kwargs):
|
||||
'''
|
||||
Create a VPC resource. Returns the resource id if created, or False
|
||||
if not created.
|
||||
@ -211,11 +214,11 @@ def _create_resource(resource, name, tags, region, key, keyid,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def _delete_resource(resource, name, resource_id, region,
|
||||
key, keyid, profile, **kwargs):
|
||||
def _delete_resource(resource, name=None, resource_id=None, region=None,
|
||||
key=None, keyid=None, profile=None, **kwargs):
|
||||
'''
|
||||
Delete a VPC resource. Returns True if succesful, otherwise False.
|
||||
'''
|
||||
@ -252,26 +255,50 @@ def _delete_resource(resource, name, resource_id, region,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def _get_resource(resource, name=None, resource_id=None, region=None,
|
||||
key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Get a VPC resource based on resource type and name or id.
|
||||
Cache the id if name was provided.
|
||||
'''
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
|
||||
def _get_resource(resource, name, conn):
|
||||
try:
|
||||
get_resources = getattr(conn, 'get_all_{0}s'.format(resource))
|
||||
r = get_resources(filters={'tag:Name': name})
|
||||
filter_parameters = {}
|
||||
if name:
|
||||
filter_parameters['filters'] = {'tag:Name': name}
|
||||
if resource_id:
|
||||
filter_parameters['_ids'.format(resource)] = resource_id
|
||||
if not filter_parameters:
|
||||
return False
|
||||
|
||||
r = get_resources(**filter_parameters)
|
||||
|
||||
if r:
|
||||
if len(r) == 1:
|
||||
if name:
|
||||
_cache_id(name, sub_resource=resource,
|
||||
resource_id=r[0].id,
|
||||
region=region,
|
||||
key=key, keyid=keyid,
|
||||
profile=profile)
|
||||
return r[0]
|
||||
else:
|
||||
raise CommandExecutionError('Found more than one '
|
||||
'{0} named "{1}"'.format(
|
||||
resource, name))
|
||||
log.warning('Found more than one {0} named '
|
||||
'"{1}"'.format(resource, name))
|
||||
return False
|
||||
else:
|
||||
return None
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def resource_exists(resource, name, region=None,
|
||||
@ -316,33 +343,13 @@ def get_resource_id(resource, name, region=None,
|
||||
if _id:
|
||||
return _id
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return None
|
||||
r = _get_resource(resource, name=name, region=region, key=key,
|
||||
keyid=keyid, profile=profile)
|
||||
|
||||
try:
|
||||
f = getattr(conn, 'get_all_{0}s'.format(resource))
|
||||
r = f(filters={'tag:Name': name})
|
||||
|
||||
if r:
|
||||
if len(r) == 1:
|
||||
_id = r[0].id
|
||||
_cache_id(name, sub_resource=resource,
|
||||
resource_id=_id,
|
||||
region=region,
|
||||
key=key, keyid=keyid,
|
||||
profile=profile)
|
||||
return r[0].id
|
||||
else:
|
||||
raise CommandExecutionError('Found more than one '
|
||||
'{0} named "{1}"'.format(
|
||||
resource, name))
|
||||
else:
|
||||
log.warning('No {0} named "{1}"'.format(resource, name))
|
||||
return None
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
if r:
|
||||
return r.id
|
||||
else:
|
||||
return r
|
||||
|
||||
|
||||
def get_subnet_association(subnets, region=None, key=None, keyid=None,
|
||||
@ -373,8 +380,8 @@ def get_subnet_association(subnets, region=None, key=None, keyid=None,
|
||||
# subnet_ids=subnets can accept either a string or a list
|
||||
subnets = conn.get_all_subnets(subnet_ids=subnets)
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.debug(exc)
|
||||
return False
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
# using a set to store vpc_ids - the use of set prevents duplicate
|
||||
# vpc_id values
|
||||
vpc_ids = set()
|
||||
@ -399,8 +406,6 @@ def _find_vpc(vpc_id=None, name=None, cidr=None, tags=None, conn=None):
|
||||
Given VPC properties, find and return matching VPC_IDs
|
||||
|
||||
'''
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
if not vpc_id and not name and not tags and not cidr:
|
||||
raise SaltInvocationError('At least one of the following must be specified: vpc id, name, cidr or tags.')
|
||||
@ -430,7 +435,7 @@ def _find_vpc(vpc_id=None, name=None, cidr=None, tags=None, conn=None):
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def get_id(name=None, cidr=None, tags=None, region=None, key=None, keyid=None,
|
||||
@ -455,8 +460,6 @@ def get_id(name=None, cidr=None, tags=None, region=None, key=None, keyid=None,
|
||||
return vpc_id
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return None
|
||||
|
||||
vpcs_id = _find_vpc(name=name, cidr=cidr, tags=tags, conn=conn)
|
||||
if vpcs_id:
|
||||
@ -543,7 +546,7 @@ def create(cidr_block, instance_tenancy=None, vpc_name=None,
|
||||
log.warning('VPC was not created')
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def delete(vpc_id=None, name=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -587,7 +590,7 @@ def delete(vpc_id=None, name=None, tags=None, region=None, key=None, keyid=None,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def _find_subnets(subnet_name=None, vpc_id=None, cidr=None, tags=None, conn=None):
|
||||
@ -627,7 +630,7 @@ def _find_subnets(subnet_name=None, vpc_id=None, cidr=None, tags=None, conn=None
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_subnet(vpc_id=None, cidr_block=None, vpc_name=None,
|
||||
@ -653,16 +656,12 @@ def create_subnet(vpc_id=None, cidr_block=None, vpc_name=None,
|
||||
subnet_name='mysubnet', cidr_block='10.0.0.0/25'
|
||||
'''
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
vpc_id = _check_vpc(vpc_id, vpc_name, region, key, keyid, profile)
|
||||
if not vpc_id:
|
||||
log.warning('Refusing to create subnet for non-existent VPC')
|
||||
return False
|
||||
|
||||
vpc_subnet = _create_resource('subnet', subnet_name, tags=tags,
|
||||
vpc_subnet = _create_resource('subnet', name=subnet_name, tags=tags,
|
||||
vpc_id=vpc_id, cidr_block=cidr_block,
|
||||
region=region, key=key, keyid=keyid,
|
||||
profile=profile)
|
||||
@ -692,31 +691,9 @@ def delete_subnet(subnet_id=None, subnet_name=None, region=None, key=None,
|
||||
|
||||
'''
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
if subnet_name:
|
||||
ids = _find_subnets(subnet_name=subnet_name, conn=conn)
|
||||
if ids and len(ids) > 1:
|
||||
log.warning('multiple subnets found '
|
||||
'named "{0}"'.format(subnet_name))
|
||||
return False
|
||||
elif ids:
|
||||
subnet_id = ids[0]
|
||||
|
||||
try:
|
||||
if conn.delete_subnet(subnet_id):
|
||||
log.debug('Subnet {0} was deleted.'.format(subnet_id))
|
||||
|
||||
return True
|
||||
else:
|
||||
log.debug('Subnet {0} was not deleted.'.format(subnet_id))
|
||||
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
return _delete_resource(resource='subnet', name=subnet_name,
|
||||
resource_id=subnet_id, region=region, key=key,
|
||||
keyid=keyid, profile=profile)
|
||||
|
||||
|
||||
def subnet_exists(subnet_id=None, name=None, subnet_name=None, cidr=None,
|
||||
@ -781,7 +758,7 @@ def subnet_exists(subnet_id=None, name=None, subnet_name=None, cidr=None,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_internet_gateway(internet_gateway_name=None, vpc_id=None,
|
||||
@ -791,7 +768,7 @@ def create_internet_gateway(internet_gateway_name=None, vpc_id=None,
|
||||
Create an Internet Gateway, optionally attaching it to an existing VPC.
|
||||
|
||||
Returns the internet gateway id if the internet gateway was created and
|
||||
returns False if the internet gateways as not created.
|
||||
returns False if the internet gateways was not created.
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
CLI example::
|
||||
@ -807,13 +784,11 @@ def create_internet_gateway(internet_gateway_name=None, vpc_id=None,
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
vpc_id = _check_vpc(vpc_id, vpc_name, region, key, keyid, profile)
|
||||
if not vpc_id:
|
||||
log.warning('Refusing to create internet for non-existent VPC')
|
||||
return False
|
||||
|
||||
igw = _create_resource('internet_gateway', internet_gateway_name,
|
||||
tags, region, key, keyid, profile)
|
||||
vpc_id = vpc_id or get_id(name=vpc_name, region=region, key=key,
|
||||
keyid=keyid, profile=profile)
|
||||
igw = _create_resource('internet_gateway', name=internet_gateway_name,
|
||||
tags=tags, region=region, key=key, keyid=keyid,
|
||||
profile=profile)
|
||||
if igw:
|
||||
if vpc_id:
|
||||
try:
|
||||
@ -822,7 +797,7 @@ def create_internet_gateway(internet_gateway_name=None, vpc_id=None,
|
||||
'VPC {1}'.format(igw.id, (vpc_name or vpc_id)))
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
return igw.id
|
||||
return False
|
||||
|
||||
@ -874,10 +849,12 @@ def delete_internet_gateway(internet_gateway_id=None,
|
||||
return True
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
return False
|
||||
|
||||
|
||||
def create_customer_gateway(vpn_connection_type, ip_address, bgp_asn, customer_gateway_name=None, tags=None,
|
||||
def create_customer_gateway(vpn_connection_type, ip_address, bgp_asn,
|
||||
customer_gateway_name=None, tags=None,
|
||||
region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Given a valid VPN connection type, a static IP address and a customer
|
||||
@ -895,25 +872,14 @@ def create_customer_gateway(vpn_connection_type, ip_address, bgp_asn, customer_g
|
||||
|
||||
'''
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
try:
|
||||
customer_gateway = conn.create_customer_gateway(vpn_connection_type, ip_address, bgp_asn)
|
||||
if customer_gateway:
|
||||
log.info('A customer gateway with id {0} was created'.format(customer_gateway.id))
|
||||
|
||||
_maybe_set_name_tag(customer_gateway_name, customer_gateway)
|
||||
_maybe_set_tags(tags, customer_gateway)
|
||||
|
||||
return customer_gateway.id
|
||||
else:
|
||||
log.warning('A customer gateway was not created')
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
customer_gateway = _create_resource('customer_gateway', customer_gateway_name,
|
||||
vpn_connection_type=vpn_connection_type,
|
||||
ip_address=ip_address, bgp_asn=bgp_asn,
|
||||
tags=tags, region=region, key=key,
|
||||
keyid=keyid, profile=profile)
|
||||
if customer_gateway:
|
||||
return customer_gateway.id
|
||||
return False
|
||||
|
||||
|
||||
def delete_customer_gateway(customer_gateway_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -945,7 +911,7 @@ def delete_customer_gateway(customer_gateway_id, region=None, key=None, keyid=No
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def customer_gateway_exists(customer_gateway_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -976,7 +942,7 @@ def customer_gateway_exists(customer_gateway_id, region=None, key=None, keyid=No
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_dhcp_options(domain_name=None, domain_name_servers=None, ntp_servers=None,
|
||||
@ -1014,7 +980,7 @@ def create_dhcp_options(domain_name=None, domain_name_servers=None, ntp_servers=
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def associate_dhcp_options_to_vpc(dhcp_options_id, vpc_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1043,7 +1009,7 @@ def associate_dhcp_options_to_vpc(dhcp_options_id, vpc_id, region=None, key=None
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def associate_new_dhcp_options_to_vpc(vpc_id, domain_name=None, domain_name_servers=None, ntp_servers=None,
|
||||
@ -1073,7 +1039,8 @@ def associate_new_dhcp_options_to_vpc(vpc_id, domain_name=None, domain_name_serv
|
||||
return dhcp_options.id
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise exc
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def dhcp_options_exists(dhcp_options_id=None, name=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1121,7 +1088,7 @@ def dhcp_options_exists(dhcp_options_id=None, name=None, tags=None, region=None,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_network_acl(vpc_id, network_acl_name=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1153,7 +1120,7 @@ def create_network_acl(vpc_id, network_acl_name=None, tags=None, region=None, ke
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def delete_network_acl(network_acl_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1182,7 +1149,7 @@ def delete_network_acl(network_acl_id, region=None, key=None, keyid=None, profil
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def network_acl_exists(network_acl_id=None, name=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1227,7 +1194,7 @@ def network_acl_exists(network_acl_id=None, name=None, tags=None, region=None, k
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def associate_network_acl_to_subnet(network_acl_id, subnet_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1257,7 +1224,7 @@ def associate_network_acl_to_subnet(network_acl_id, subnet_id, region=None, key=
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def associate_new_network_acl_to_subnet(vpc_id, subnet_id, network_acl_name=None, tags=None,
|
||||
@ -1297,7 +1264,7 @@ def associate_new_network_acl_to_subnet(vpc_id, subnet_id, network_acl_name=None
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def disassociate_network_acl(subnet_id, vpc_id=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1319,7 +1286,7 @@ def disassociate_network_acl(subnet_id, vpc_id=None, region=None, key=None, keyi
|
||||
return conn.disassociate_network_acl(subnet_id, vpc_id=vpc_id)
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress=None,
|
||||
@ -1352,8 +1319,74 @@ def create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress=None,
|
||||
icmp_code=None, icmp_type=None, port_range_from=None, port_range_to=None,
|
||||
region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Creates a network acl entry.
|
||||
|
||||
CLI Example::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_vpc.create_network_acl_entry 'acl-5fb85d36' '32767' '-1' 'deny' '0.0.0.0/0'
|
||||
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
try:
|
||||
network_acl_entry = conn.create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action,
|
||||
cidr_block,
|
||||
egress=egress, icmp_code=icmp_code, icmp_type=icmp_type,
|
||||
port_range_from=port_range_from, port_range_to=port_range_to)
|
||||
if network_acl_entry:
|
||||
log.info('Network ACL entry was created')
|
||||
return True
|
||||
else:
|
||||
log.warning('Network ACL entry was not created')
|
||||
return False
|
||||
except boto.exception as exc:
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress=None,
|
||||
icmp_code=None, icmp_type=None, port_range_from=None, port_range_to=None,
|
||||
region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Creates a network acl entry.
|
||||
|
||||
CLI Example::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_vpc.create_network_acl_entry 'acl-5fb85d36' '32767' '-1' 'deny' '0.0.0.0/0'
|
||||
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
try:
|
||||
network_acl_entry = conn.create_network_acl_entry(network_acl_id, rule_number, protocol, rule_action,
|
||||
cidr_block,
|
||||
egress=egress, icmp_code=icmp_code, icmp_type=icmp_type,
|
||||
port_range_from=port_range_from, port_range_to=port_range_to)
|
||||
if network_acl_entry:
|
||||
log.info('Network ACL entry was created')
|
||||
return True
|
||||
else:
|
||||
log.warning('Network ACL entry was not created')
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def replace_network_acl_entry(network_acl_id, rule_number, protocol, rule_action, cidr_block, egress=None,
|
||||
icmp_code=None, icmp_type=None, port_range_from=None, port_range_to=None,
|
||||
@ -1386,7 +1419,7 @@ def replace_network_acl_entry(network_acl_id, rule_number, protocol, rule_action
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def delete_network_acl_entry(network_acl_id, rule_number, egress=None, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1414,7 +1447,7 @@ def delete_network_acl_entry(network_acl_id, rule_number, egress=None, region=No
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_route_table(vpc_id=None, vpc_name=None, route_table_name=None,
|
||||
@ -1464,17 +1497,13 @@ def delete_route_table(route_table_id=None, route_table_name=None,
|
||||
salt myminion boto_vpc.delete_route_table route_table_name='myroutetable'
|
||||
|
||||
'''
|
||||
try:
|
||||
if _delete_resource(resource='route_table', name=route_table_name,
|
||||
return _delete_resource(resource='route_table', name=route_table_name,
|
||||
resource_id=route_table_id, region=region, key=key,
|
||||
keyid=keyid, profile=profile):
|
||||
return True
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
keyid=keyid, profile=profile)
|
||||
|
||||
|
||||
def route_table_exists(route_table_id=None, name=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
def route_table_exists(route_table_id=None, name=None, route_table_name=None,
|
||||
tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Checks if a route table exists.
|
||||
|
||||
@ -1485,12 +1514,18 @@ def route_table_exists(route_table_id=None, name=None, tags=None, region=None, k
|
||||
salt myminion boto_vpc.route_table_exists route_table_id='rtb-1f382e7d'
|
||||
|
||||
'''
|
||||
if name:
|
||||
log.warning('boto_vpc.route_table_exists: name parameter is deprecated '
|
||||
'use route_table_name instead.')
|
||||
route_table_name = name
|
||||
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
if not route_table_id and not name and not tags:
|
||||
raise SaltInvocationError('At least one of the following must be specified: route table id, name or tags.')
|
||||
if not route_table_id and not route_table_name and not tags:
|
||||
raise SaltInvocationError('At least one of the following must be specified: '
|
||||
'router_table_id, route_table_name or tags.')
|
||||
|
||||
try:
|
||||
filter_parameters = {'filters': {}}
|
||||
@ -1498,8 +1533,8 @@ def route_table_exists(route_table_id=None, name=None, tags=None, region=None, k
|
||||
if route_table_id:
|
||||
filter_parameters['route_table_ids'] = [route_table_id]
|
||||
|
||||
if name:
|
||||
filter_parameters['filters']['tag:Name'] = name
|
||||
if route_table_name:
|
||||
filter_parameters['filters']['tag:Name'] = route_table_name
|
||||
|
||||
if tags:
|
||||
for tag_name, tag_value in six.iteritems(tags):
|
||||
@ -1516,13 +1551,14 @@ def route_table_exists(route_table_id=None, name=None, tags=None, region=None, k
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def route_exists(destination_cidr_block, route_table_name=None, route_table_id=None, gateway_id=None, instance_id=None,
|
||||
interface_id=None, tags=None, region=None, key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Checks if a route exists.
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
CLI Example::
|
||||
@ -1562,10 +1598,10 @@ def route_exists(destination_cidr_block, route_table_name=None, route_table_id=N
|
||||
raise SaltInvocationError('Found more than one route table.')
|
||||
|
||||
route_check = {'destination_cidr_block': destination_cidr_block,
|
||||
'gateway_id': gateway_id,
|
||||
'instance_id': instance_id,
|
||||
'interface_id': interface_id
|
||||
}
|
||||
'gateway_id': gateway_id,
|
||||
'instance_id': instance_id,
|
||||
'interface_id': interface_id
|
||||
}
|
||||
|
||||
for route_match in route_tables[0].routes:
|
||||
|
||||
@ -1583,7 +1619,7 @@ def route_exists(destination_cidr_block, route_table_name=None, route_table_id=N
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def associate_route_table(route_table_id, subnet_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1608,7 +1644,7 @@ def associate_route_table(route_table_id, subnet_id, region=None, key=None, keyi
|
||||
return association_id
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def disassociate_route_table(association_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1640,7 +1676,7 @@ def disassociate_route_table(association_id, region=None, key=None, keyid=None,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def replace_route_table_association(association_id, route_table_id, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1665,7 +1701,7 @@ def replace_route_table_association(association_id, route_table_id, region=None,
|
||||
return association_id
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def create_route(route_table_id, destination_cidr_block, gateway_id=None, instance_id=None, interface_id=None,
|
||||
@ -1697,7 +1733,7 @@ def create_route(route_table_id, destination_cidr_block, gateway_id=None, instan
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def delete_route(route_table_id, destination_cidr_block, region=None, key=None, keyid=None, profile=None):
|
||||
@ -1727,7 +1763,7 @@ def delete_route(route_table_id, destination_cidr_block, region=None, key=None,
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def replace_route(route_table_id, destination_cidr_block, gateway_id=None, instance_id=None, interface_id=None,
|
||||
@ -1747,46 +1783,48 @@ def replace_route(route_table_id, destination_cidr_block, gateway_id=None, insta
|
||||
return False
|
||||
|
||||
try:
|
||||
if conn.replace_route(route_table_id, destination_cidr_block, gateway_id=gateway_id, instance_id=instance_id,
|
||||
if conn.replace_route(route_table_id, destination_cidr_block,
|
||||
gateway_id=gateway_id, instance_id=instance_id,
|
||||
interface_id=interface_id):
|
||||
log.info('Route with cider block {0} on route table {1} was replaced'.format(route_table_id,
|
||||
destination_cidr_block))
|
||||
|
||||
log.info('Route with cider block {0} on route table {1} was '
|
||||
'replaced'.format(route_table_id, destination_cidr_block))
|
||||
return True
|
||||
else:
|
||||
log.warning('Route with cider block {0} on route table {1} was not replaced'.format(route_table_id,
|
||||
destination_cidr_block))
|
||||
destination_cidr_block))
|
||||
return False
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def describe(vpc_id=None, region=None, key=None, keyid=None, profile=None):
|
||||
def describe(vpc_id=None, vpc_name=None, region=None, key=None,
|
||||
keyid=None, profile=None):
|
||||
'''
|
||||
Given a VPC ID describe it's properties.
|
||||
Given a VPC ID describe its properties.
|
||||
|
||||
Returns a dictionary of interesting properties.
|
||||
|
||||
.. versionchanged Beryllium
|
||||
Added vpc_name argument
|
||||
|
||||
CLI example::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_vpc.describe vpc_id=vpc-123456
|
||||
salt myminion boto_vpc.describe vpc_name=myvpc
|
||||
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
_ret = dict(cidr_block=None,
|
||||
is_default=None,
|
||||
state=None,
|
||||
tags=None,
|
||||
dhcp_options_id=None,
|
||||
instance_tenancy=None)
|
||||
|
||||
if not conn:
|
||||
return False
|
||||
if not any((vpc_id, vpc_name)):
|
||||
raise SaltInvocationError('A valid vpc id or name needs to be specified.')
|
||||
|
||||
vpc_id = _check_vpc(vpc_id, vpc_name, region, key, keyid, profile)
|
||||
|
||||
if not vpc_id:
|
||||
raise SaltInvocationError('VPC ID needs to be specified.')
|
||||
return None
|
||||
|
||||
try:
|
||||
filter_parameters = {'vpc_ids': vpc_id}
|
||||
@ -1796,13 +1834,14 @@ def describe(vpc_id=None, region=None, key=None, keyid=None, profile=None):
|
||||
if vpcs:
|
||||
vpc = vpcs[0] # Found!
|
||||
log.debug('Found VPC: {0}'.format(vpc.id))
|
||||
for k in six.iterkeys(_ret):
|
||||
_ret[k] = getattr(vpc, k)
|
||||
return _ret
|
||||
|
||||
keys = ('id', 'cidr_block', 'is_default', 'state', 'tags',
|
||||
'dhcp_options_id', 'instance_tenancy')
|
||||
return dict([(k, getattr(vpc, k)) for k in keys])
|
||||
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def describe_vpcs(vpc_id=None, name=None, cidr=None, tags=None,
|
||||
@ -1811,6 +1850,9 @@ def describe_vpcs(vpc_id=None, name=None, cidr=None, tags=None,
|
||||
Describe all VPCs, matching the filter criteria if provided.
|
||||
|
||||
Returns a a list of dictionaries with interesting properties.
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
CLI example::
|
||||
|
||||
.. code-block:: bash
|
||||
@ -1819,13 +1861,13 @@ def describe_vpcs(vpc_id=None, name=None, cidr=None, tags=None,
|
||||
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
items = ('id',
|
||||
'cidr_block',
|
||||
'is_default',
|
||||
'state',
|
||||
'tags',
|
||||
'dhcp_options_id',
|
||||
'instance_tenancy')
|
||||
keys = ('id',
|
||||
'cidr_block',
|
||||
'is_default',
|
||||
'state',
|
||||
'tags',
|
||||
'dhcp_options_id',
|
||||
'instance_tenancy')
|
||||
|
||||
if not conn:
|
||||
return False
|
||||
@ -1851,55 +1893,43 @@ def describe_vpcs(vpc_id=None, name=None, cidr=None, tags=None,
|
||||
if vpcs:
|
||||
ret = []
|
||||
for vpc in vpcs:
|
||||
ret.append(dict((k, getattr(vpc, k)) for k in items))
|
||||
ret.append(dict((k, getattr(vpc, k)) for k in keys))
|
||||
return ret
|
||||
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def describe_subnet(subnet_id=None, region=None, key=None, keyid=None, profile=None):
|
||||
def describe_subnet(subnet_id=None, subnet_name=None, region=None,
|
||||
key=None, keyid=None, profile=None):
|
||||
'''
|
||||
Given a subnet id, describe it's properties.
|
||||
Given a subnet id or name, describe its properties.
|
||||
|
||||
Returns a dictionary of interesting properties.
|
||||
CLI example::
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
CLI examples::
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt myminion boto_vpc.describe_subnet subnet_id=subnet-123456
|
||||
salt myminion boto_vpc.describe_subnet subnet_name=mysubnet
|
||||
|
||||
'''
|
||||
conn = _get_conn(region, key, keyid, profile)
|
||||
_ret = dict(cidr_block=None,
|
||||
availability_zone=None,
|
||||
state=None,
|
||||
vpc_id=None,
|
||||
tags=None)
|
||||
|
||||
if not conn:
|
||||
return False
|
||||
|
||||
if not subnet_id:
|
||||
raise SaltInvocationError('subnet id needs to be specified.')
|
||||
subnet = _get_resource('subnet', subnet_name=subnet_name, region=region,
|
||||
key=key, keyid=keyid, profile=profile)
|
||||
if not subnet:
|
||||
return subnet
|
||||
log.debug('Found subnet: {0}'.format(subnet.id))
|
||||
|
||||
try:
|
||||
filter_parameters = {'subnet_ids': subnet_id}
|
||||
|
||||
subnets = conn.get_all_subnets(**filter_parameters)
|
||||
|
||||
if subnets:
|
||||
subnet = subnets[0] # Found!
|
||||
log.debug('Found subnet: {0}'.format(subnet.id))
|
||||
for k in six.iterkeys(_ret):
|
||||
_ret[k] = getattr(subnet, k)
|
||||
_ret['subnet_id'] = subnet.id
|
||||
return _ret
|
||||
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
keys = ('id', 'cidr_block', 'availability_zone', 'tags')
|
||||
return [getattr(subnet, k) for k in keys]
|
||||
|
||||
|
||||
def describe_subnets(subnet_ids=None, vpc_id=None, cidr=None, region=None, key=None,
|
||||
@ -1907,9 +1937,11 @@ def describe_subnets(subnet_ids=None, vpc_id=None, cidr=None, region=None, key=N
|
||||
'''
|
||||
Given a VPC ID or subnet CIDR, returns a list of associated subnets and
|
||||
their details. Return all subnets if VPC ID or CIDR are not provided.
|
||||
If a subnet CIDR is provided, only it's associated subnet details will be
|
||||
If a subnet id or CIDR is provided, only its associated subnet details will be
|
||||
returned.
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
CLI Examples::
|
||||
|
||||
.. code-block:: bash
|
||||
@ -1950,7 +1982,7 @@ def describe_subnets(subnet_ids=None, vpc_id=None, cidr=None, region=None, key=N
|
||||
return False
|
||||
|
||||
subnets_list = []
|
||||
keys = ['id', 'cidr_block', 'availability_zone', 'tags']
|
||||
keys = ('id', 'cidr_block', 'availability_zone', 'tags')
|
||||
for item in subnets:
|
||||
subnet = {}
|
||||
for key in keys:
|
||||
@ -1961,13 +1993,15 @@ def describe_subnets(subnet_ids=None, vpc_id=None, cidr=None, region=None, key=N
|
||||
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.debug(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def describe_route_table(route_table_id=None, route_table_name=None, tags=None, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
def describe_route_tables(route_table_id=None, route_table_name=None, tags=None, region=None, key=None, keyid=None,
|
||||
profile=None):
|
||||
'''
|
||||
Given route table properties, return route table details if exists.
|
||||
Given route table properties, return route table details if matching table(s) exist.
|
||||
|
||||
.. versionadded:: Beryllium
|
||||
|
||||
CLI Example::
|
||||
|
||||
@ -2002,7 +2036,7 @@ def describe_route_table(route_table_id=None, route_table_name=None, tags=None,
|
||||
return False
|
||||
|
||||
route_table = {}
|
||||
keys = ['id', 'vpc_id', 'tags', 'routes']
|
||||
keys = ('id', 'vpc_id', 'tags', 'routes')
|
||||
route_keys = ['destination_cidr_block', 'gateway_id', 'instance_id', 'interface_id']
|
||||
for item in route_tables:
|
||||
routes_list = []
|
||||
@ -2021,7 +2055,7 @@ def describe_route_table(route_table_id=None, route_table_name=None, tags=None,
|
||||
|
||||
except boto.exception.BotoServerError as exc:
|
||||
log.error(exc)
|
||||
return False
|
||||
raise CommandExecutionError(exc.reason)
|
||||
|
||||
|
||||
def _create_dhcp_options(conn, domain_name=None, domain_name_servers=None, ntp_servers=None, netbios_name_servers=None,
|
||||
@ -2073,9 +2107,10 @@ def _get_conn(region, key, keyid, profile):
|
||||
conn = svc_mod.connect_to_region(region, aws_access_key_id=keyid,
|
||||
aws_secret_access_key=key)
|
||||
except boto.exception.NoAuthHandlerFound:
|
||||
log.error('No authentication credentials found when '
|
||||
'attempting to make boto {0} connection to '
|
||||
'region "{1}".'.format(service, region))
|
||||
return None
|
||||
message = ('No authentication credentials found when '
|
||||
'attempting to make boto {0} connection to '
|
||||
'region "{1}".'.format(service, region))
|
||||
log.error(message)
|
||||
raise CommandExecutionError(message)
|
||||
__context__[cxkey] = conn
|
||||
return conn
|
||||
|
@ -62,7 +62,7 @@ dhcp_options_parameters = {'domain_name': 'example.com', 'domain_name_servers':
|
||||
network_acl_entry_parameters = ('fake', 100, -1, 'allow', cidr_block)
|
||||
dhcp_options_parameters.update(conn_parameters)
|
||||
|
||||
boto_vpc.__context__ = {}
|
||||
#boto_vpc.__context__ = {}
|
||||
|
||||
|
||||
def _has_required_boto():
|
||||
@ -96,6 +96,9 @@ def _has_required_moto():
|
||||
class BotoVpcTestCaseBase(TestCase):
|
||||
conn = None
|
||||
|
||||
def setUp(self):
|
||||
boto_vpc.__context__ = {}
|
||||
|
||||
def _create_vpc(self, name=None, tags=None):
|
||||
'''
|
||||
Helper function to create a test vpc
|
||||
@ -409,9 +412,8 @@ class BotoVpcTestCase(BotoVpcTestCaseBase):
|
||||
tests False VPC not created.
|
||||
'''
|
||||
with patch('moto.ec2.models.VPCBackend.create_vpc', side_effect=BotoServerError(400, 'Mocked error')):
|
||||
vpc_creation_result = boto_vpc.create(cidr_block, **conn_parameters)
|
||||
|
||||
self.assertFalse(vpc_creation_result)
|
||||
with self.assertRaisesRegexp(CommandExecutionError, 'Mocked error'):
|
||||
vpc_creation_result = boto_vpc.create(cidr_block, **conn_parameters)
|
||||
|
||||
@mock_ec2
|
||||
def test_that_when_deleting_an_existing_vpc_the_delete_vpc_method_returns_true(self):
|
||||
@ -442,10 +444,11 @@ class BotoVpcTestCase(BotoVpcTestCaseBase):
|
||||
|
||||
describe_vpc = boto_vpc.describe(vpc_id=vpc.id, **conn_parameters)
|
||||
|
||||
vpc_properties = dict(cidr_block=six.text_type(cidr_block),
|
||||
vpc_properties = dict(id=vpc.id,
|
||||
cidr_block=six.text_type(cidr_block),
|
||||
is_default=None,
|
||||
state=u'available',
|
||||
tags={'Name': 'test', 'test': 'testvalue'},
|
||||
tags={u'Name': u'test', u'test': u'testvalue'},
|
||||
dhcp_options_id=u'dopt-7a8b9c2d',
|
||||
instance_tenancy=u'default')
|
||||
|
||||
@ -463,7 +466,7 @@ class BotoVpcTestCase(BotoVpcTestCaseBase):
|
||||
self.assertFalse(describe_vpc)
|
||||
|
||||
@mock_ec2
|
||||
def test_that_when_describing_vpc_by_id_on_connection_error_it_returns_returns_false(self):
|
||||
def test_that_when_describing_vpc_by_id_on_connection_error_it_raises_execution_error(self):
|
||||
'''
|
||||
Tests describing parameters failure
|
||||
'''
|
||||
@ -471,9 +474,10 @@ class BotoVpcTestCase(BotoVpcTestCaseBase):
|
||||
|
||||
with patch('moto.ec2.models.VPCBackend.get_all_vpcs',
|
||||
side_effect=BotoServerError(400, 'Mocked error')):
|
||||
describe_vpc = boto_vpc.describe(vpc_id=vpc.id, **conn_parameters)
|
||||
|
||||
self.assertFalse(describe_vpc)
|
||||
with self.assertRaisesRegexp(CommandExecutionError,
|
||||
'Mocked error'):
|
||||
describe_vpc = boto_vpc.describe(vpc_id=vpc.id, **conn_parameters)
|
||||
self.assertEqual(describe_vpc, True)
|
||||
|
||||
@mock_ec2
|
||||
def test_that_when_describing_vpc_but_providing_no_vpc_id_the_describe_method_raises_a_salt_invocation_error(self):
|
||||
@ -481,7 +485,7 @@ class BotoVpcTestCase(BotoVpcTestCaseBase):
|
||||
Tests describing vpc without vpc id
|
||||
'''
|
||||
with self.assertRaisesRegexp(SaltInvocationError,
|
||||
'VPC ID needs to be specified.'):
|
||||
'A valid vpc id or name needs to be specified.'):
|
||||
boto_vpc.describe(vpc_id=None, **conn_parameters)
|
||||
|
||||
|
||||
@ -574,9 +578,8 @@ class BotoVpcSubnetsTestCase(BotoVpcTestCaseBase):
|
||||
vpc = self._create_vpc()
|
||||
|
||||
with patch('moto.ec2.models.SubnetBackend.create_subnet', side_effect=BotoServerError(400, 'Mocked error')):
|
||||
subnet_creation_result = boto_vpc.create_subnet(vpc.id, '10.0.0.0/24', **conn_parameters)
|
||||
|
||||
self.assertFalse(subnet_creation_result)
|
||||
with self.assertRaisesRegexp(CommandExecutionError, 'Mocked error'):
|
||||
subnet_creation_result = boto_vpc.create_subnet(vpc.id, '10.0.0.0/24', **conn_parameters)
|
||||
|
||||
@mock_ec2
|
||||
def test_that_when_deleting_an_existing_subnet_the_delete_subnet_method_returns_true(self):
|
||||
|
Loading…
Reference in New Issue
Block a user