diff --git a/salt/modules/boto_vpc.py b/salt/modules/boto_vpc.py index 01cfa0e054..549aa57554 100644 --- a/salt/modules/boto_vpc.py +++ b/salt/modules/boto_vpc.py @@ -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 diff --git a/tests/unit/modules/boto_vpc_test.py b/tests/unit/modules/boto_vpc_test.py index 631da94ce4..d242d7bd07 100644 --- a/tests/unit/modules/boto_vpc_test.py +++ b/tests/unit/modules/boto_vpc_test.py @@ -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):