def await_resource(conn, resource, status, module): start_time = time.time() wait_timeout = module.params.get('wait_timeout') + start_time check_interval = 5 while wait_timeout > time.time() and resource.status != status: time.sleep(check_interval) if wait_timeout <= time.time(): module.fail_json(msg="Timeout waiting for RDS resource %s" % resource.name) if module.params.get('command') == 'snapshot': # Temporary until all the rds2 commands have their responses parsed if resource.name is None: module.fail_json( msg="There was a problem waiting for RDS snapshot %s" % resource.snapshot) # Back off if we're getting throttled, since we're just waiting anyway resource = AWSRetry.backoff(tries=5, delay=20, backoff=1.5)( conn.get_db_snapshot)(resource.name) else: # Temporary until all the rds2 commands have their responses parsed if resource.name is None: module.fail_json( msg="There was a problem waiting for RDS instance %s" % resource.instance) # Back off if we're getting throttled, since we're just waiting anyway resource = AWSRetry.backoff(tries=5, delay=20, backoff=1.5)( conn.get_db_instance)(resource.name) if resource is None: break # Some RDS resources take much longer than others to be ready. Check # less aggressively for slow ones to avoid throttling. if time.time() > start_time + 90: check_interval = 20 return resource
def get_vpc(module, connection, vpc_id): # wait for vpc to be available try: connection.get_waiter('vpc_available').wait(VpcIds=[vpc_id]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws( e, msg="Unable to wait for VPC {0} to be available.".format(vpc_id)) try: vpc_obj = AWSRetry.backoff( delay=3, tries=8, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.describe_vpcs)(VpcIds=[vpc_id])['Vpcs'][0] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to describe VPCs") try: vpc_obj['ClassicLinkEnabled'] = get_classic_link_with_backoff( connection, vpc_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to describe VPCs") return vpc_obj
def update_vpc_tags(connection, module, vpc_id, tags, name): if tags is None: tags = dict() tags.update({'Name': name}) try: current_tags = dict((t['Key'], t['Value']) for t in connection.describe_tags(Filters=[{'Name': 'resource-id', 'Values': [vpc_id]}])['Tags']) if tags != current_tags: if not module.check_mode: tags = ansible_dict_to_boto3_tag_list(tags) vpc_obj = AWSRetry.backoff( delay=1, tries=5, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.create_tags)(Resources=[vpc_id], Tags=tags) # Wait for tags to be updated expected_tags = boto3_tag_list_to_ansible_dict(tags) filters = [{'Name': 'tag:{0}'.format(key), 'Values': [value]} for key, value in expected_tags.items()] connection.get_waiter('vpc_available').wait(VpcIds=[vpc_id], Filters=filters) return True else: return False except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to update tags")
def update_vpc_tags(connection, module, vpc_id, tags, name): if tags is None: tags = dict() tags.update({'Name': name}) try: current_tags = dict( (t['Key'], t['Value']) for t in connection.describe_tags(Filters=[{ 'Name': 'resource-id', 'Values': [vpc_id] }])['Tags']) if tags != current_tags: if not module.check_mode: tags = ansible_dict_to_boto3_tag_list(tags) vpc_obj = AWSRetry.backoff( delay=1, tries=5, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.create_tags)(Resources=[vpc_id], Tags=tags) return True else: return False except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to update tags")
def run_func(*args, **kwargs): try: result = AWSRetry.backoff(tries=8, delay=5, catch_extra_error_codes=[ 'DirectConnectClientException' ])(f)(*args, **kwargs) except (ClientError, BotoCoreError) as e: raise DirectConnectError(failure_msg, traceback.format_exc(), e) return result
def connection_exists(client, connection_id=None, connection_name=None, verify=True): params = {} if connection_id: params['connectionId'] = connection_id try: response = AWSRetry.backoff(**retry_params)( client.describe_connections)(**params) except (BotoCoreError, ClientError) as e: if connection_id: msg = "Failed to describe DirectConnect ID {0}".format( connection_id) else: msg = "Failed to describe DirectConnect connections" raise DirectConnectError(msg=msg, last_traceback=traceback.format_exc(), exception=e) match = [] connection = [] # look for matching connections if len(response.get('connections', [])) == 1 and connection_id: if response['connections'][0]['connectionState'] != 'deleted': match.append(response['connections'][0]['connectionId']) connection.extend(response['connections']) for conn in response.get('connections', []): if connection_name == conn[ 'connectionName'] and conn['connectionState'] != 'deleted': match.append(conn['connectionId']) connection.append(conn) # verifying if the connections exists; if true, return connection identifier, otherwise return False if verify and len(match) == 1: return match[0] elif verify: return False # not verifying if the connection exists; just return current connection info elif len(connection) == 1: return {'connection': connection[0]} return {'connection': {}}
def create_connection(client, location, bandwidth, name, lag_id): if not name: raise DirectConnectError(msg="Failed to create a Direct Connect connection: name required.") params = { 'location': location, 'bandwidth': bandwidth, 'connectionName': name, } if lag_id: params['lagId'] = lag_id try: connection = AWSRetry.backoff(**retry_params)(client.create_connection)(**params) except (BotoCoreError, ClientError) as e: raise DirectConnectError(msg="Failed to create DirectConnect connection {0}".format(name), last_traceback=traceback.format_exc(), exception=e) return connection['connectionId']
def get_vpc(module, connection, vpc_id): # wait for vpc to be available try: connection.get_waiter('vpc_available').wait(VpcIds=[vpc_id]) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Unable to wait for VPC {0} to be available.".format(vpc_id)) try: vpc_obj = AWSRetry.backoff( delay=3, tries=8, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.describe_vpcs)(VpcIds=[vpc_id])['Vpcs'][0] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to describe VPCs") try: vpc_obj['ClassicLinkEnabled'] = get_classic_link_with_backoff(connection, vpc_id) except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to describe VPCs") return vpc_obj
def list_elbs(self): elb_array, token = [], None get_elb_with_backoff = AWSRetry.backoff(tries=5, delay=5, backoff=2.0)(self.connection.get_all_load_balancers) while True: all_elbs = get_elb_with_backoff(marker=token) token = all_elbs.next_marker if all_elbs: if self.names: for existing_lb in all_elbs: if existing_lb.name in self.names: elb_array.append(existing_lb) else: elb_array.extend(all_elbs) else: break if token is None: break return list(map(self._get_elb_info, elb_array))
def connection_exists(client, connection_id=None, connection_name=None, verify=True): params = {} if connection_id: params['connectionId'] = connection_id try: response = AWSRetry.backoff(**retry_params)(client.describe_connections)(**params) except (BotoCoreError, ClientError) as e: if connection_id: msg = "Failed to describe DirectConnect ID {0}".format(connection_id) else: msg = "Failed to describe DirectConnect connections" raise DirectConnectError(msg=msg, last_traceback=traceback.format_exc(), exception=e) match = [] connection = [] # look for matching connections if len(response.get('connections', [])) == 1 and connection_id: if response['connections'][0]['connectionState'] != 'deleted': match.append(response['connections'][0]['connectionId']) connection.extend(response['connections']) for conn in response.get('connections', []): if connection_name == conn['connectionName'] and conn['connectionState'] != 'deleted': match.append(conn['connectionId']) connection.append(conn) # verifying if the connections exists; if true, return connection identifier, otherwise return False if verify and len(match) == 1: return match[0] elif verify: return False # not verifying if the connection exists; just return current connection info elif len(connection) == 1: return {'connection': connection[0]} return {'connection': {}}
def update_vpc_tags(connection, module, vpc_id, tags, name): if tags is None: tags = dict() tags.update({'Name': name}) tags = dict((k, to_native(v)) for k, v in tags.items()) try: current_tags = dict( (t['Key'], t['Value']) for t in connection.describe_tags(Filters=[{ 'Name': 'resource-id', 'Values': [vpc_id] }])['Tags']) tags_to_update, dummy = compare_aws_tags(current_tags, tags, False) if tags_to_update: if not module.check_mode: tags = ansible_dict_to_boto3_tag_list(tags_to_update) vpc_obj = AWSRetry.backoff( delay=1, tries=5, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.create_tags)(Resources=[vpc_id], Tags=tags) # Wait for tags to be updated expected_tags = boto3_tag_list_to_ansible_dict(tags) filters = [{ 'Name': 'tag:{0}'.format(key), 'Values': [value] } for key, value in expected_tags.items()] connection.get_waiter('vpc_available').wait(VpcIds=[vpc_id], Filters=filters) return True else: return False except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to update tags")
def get_vpc(module, connection, vpc_id): try: vpc_obj = AWSRetry.backoff( delay=1, tries=5, catch_extra_error_codes=['InvalidVpcID.NotFound'], )(connection.describe_vpcs)(VpcIds=[vpc_id])['Vpcs'][0] except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: module.fail_json_aws(e, msg="Failed to describe VPCs") try: classic_link = connection.describe_vpc_classic_link( VpcIds=[vpc_id])['Vpcs'][0].get('ClassicLinkEnabled') vpc_obj['ClassicLinkEnabled'] = classic_link except botocore.exceptions.ClientError as e: if e.response["Error"][ "Message"] == "The functionality you requested is not available in this region.": vpc_obj['ClassicLinkEnabled'] = False else: module.fail_json_aws(e, msg="Failed to describe VPCs") except botocore.exceptions.BotoCoreError as e: module.fail_json_aws(e, msg="Failed to describe VPCs") return vpc_obj
RETURN = '''#''' try: import botocore from botocore.exceptions import BotoCoreError, ClientError except ImportError: pass # handled by AnsibleAWSModule from ansible.module_utils.aws.core import AnsibleAWSModule, is_boto3_error_code from ansible.module_utils.ec2 import boto3_conn, get_aws_connection_info, AWSRetry from ansible.module_utils.ec2 import camel_dict_to_snake_dict, boto3_tag_list_to_ansible_dict # this waits for an IAM role to become fully available, at the cost of # taking a long time to fail when the IAM role/policy really is invalid retry_unavailable_iam_on_put_delivery = AWSRetry.backoff( catch_extra_error_codes=['InsufficientDeliveryPolicyException'], ) def resource_exists(client, module, params): try: channel = client.describe_delivery_channels( DeliveryChannelNames=[params['name']], aws_retry=True, ) return channel['DeliveryChannels'][0] except is_boto3_error_code('NoSuchDeliveryChannelException'): return except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e: # pylint: disable=duplicate-except module.fail_json_aws(e)
def run_func(*args, **kwargs): try: result = AWSRetry.backoff(tries=8, delay=5, catch_extra_error_codes=['DirectConnectClientException'])(f)(*args, **kwargs) except (ClientError, BotoCoreError) as e: raise DirectConnectError(failure_msg, traceback.format_exc(), e) return result