def update_resource(client, module, params, result):
    current_params = client.describe_delivery_channels(
        DeliveryChannelNames=[params['name']],
        aws_retry=True,
    )

    if params != current_params['DeliveryChannels'][0]:
        try:
            retry_unavailable_iam_on_put_delivery(
                client.put_delivery_channel, )(DeliveryChannel=params, )
            result['changed'] = True
            result['channel'] = camel_dict_to_snake_dict(
                resource_exists(client, module, params))
            return result
        except is_boto3_error_code('InvalidS3KeyPrefixException') as e:
            module.fail_json_aws(
                e,
                msg=
                "The `s3_prefix` parameter was invalid. Try '/' for no prefix")
        except is_boto3_error_code('InsufficientDeliveryPolicyException') as e:  # pylint: disable=duplicate-except
            module.fail_json_aws(
                e,
                msg="The `s3_prefix` or `s3_bucket` parameter is invalid. "
                "Make sure the bucket exists and is available")
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
            module.fail_json_aws(
                e, msg="Couldn't create AWS Config delivery channel")
Beispiel #2
0
def find_address(ec2, module, public_ip, device_id, is_instance=True):
    """ Find an existing Elastic IP address """
    filters = []
    kwargs = {}

    if public_ip:
        kwargs["PublicIps"] = [public_ip]
    elif device_id:
        if is_instance:
            filters.append({"Name": 'instance-id', "Values": [device_id]})
        else:
            filters.append({'Name': 'network-interface-id', "Values": [device_id]})

    if len(filters) > 0:
        kwargs["Filters"] = filters
    elif len(filters) == 0 and public_ip is None:
        return None

    try:
        addresses = ec2.describe_addresses(**kwargs)
    except is_boto3_error_code('InvalidAddress.NotFound') as e:
        # If we're releasing and we can't find it, it's already gone...
        if module.params.get('state') == 'absent':
            module.exit_json(changed=False)
        module.fail_json_aws(e, msg="Couldn't obtain list of existing Elastic IP addresses")

    addresses = addresses["Addresses"]
    if len(addresses) == 1:
        return addresses[0]
    elif len(addresses) > 1:
        msg = "Found more than one address using args {0}".format(kwargs)
        msg += "Addresses found: {0}".format(addresses)
        module.fail_json_aws(botocore.exceptions.ClientError, msg=msg)
def existing_templates(module):
    ec2 = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff())
    matches = None
    try:
        if module.params.get('template_id'):
            matches = ec2.describe_launch_templates(
                LaunchTemplateIds=[module.params.get('template_id')])
        elif module.params.get('template_name'):
            matches = ec2.describe_launch_templates(
                LaunchTemplateNames=[module.params.get('template_name')])
    except is_boto3_error_code(
            'InvalidLaunchTemplateName.NotFoundException') as e:
        # no named template was found, return nothing/empty versions
        return None, []
    except is_boto3_error_code('InvalidLaunchTemplateId.Malformed') as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(
            e,
            msg=
            'Launch template with ID {0} is not a valid ID. It should start with `lt-....`'
            .format(module.params.get('launch_template_id')))
    except is_boto3_error_code(
            'InvalidLaunchTemplateId.NotFoundException') as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(
            e,
            msg=
            'Launch template with ID {0} could not be found, please supply a name '
            'instead so that a new template can be created'.format(
                module.params.get('launch_template_id')))
    except (ClientError, BotoCoreError, WaiterError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(
            e,
            msg=
            'Could not check existing launch templates. This may be an IAM permission problem.'
        )
    else:
        template = matches['LaunchTemplates'][0]
        template_id, template_version, template_default = template[
            'LaunchTemplateId'], template['LatestVersionNumber'], template[
                'DefaultVersionNumber']
        try:
            return template, ec2.describe_launch_template_versions(
                LaunchTemplateId=template_id)['LaunchTemplateVersions']
        except (ClientError, BotoCoreError, WaiterError) as e:
            module.fail_json_aws(
                e,
                msg='Could not find launch template versions for {0} (ID: {1}).'
                .format(template['LaunchTemplateName'], template_id))
def paginated_versions_list(s3_client, **pagination_params):
    try:
        pg = s3_client.get_paginator('list_object_versions')
        for page in pg.paginate(**pagination_params):
            # We have to merge the Versions and DeleteMarker lists here, as DeleteMarkers can still prevent a bucket deletion
            yield [(data['Key'], data['VersionId'])
                   for data in (page.get('Versions', []) +
                                page.get('DeleteMarkers', []))]
    except is_boto3_error_code('NoSuchBucket'):
        yield []
def resource_exists(client, module, params):
    try:
        aggregator = client.describe_configuration_aggregators(
            ConfigurationAggregatorNames=[params['name']])
        return aggregator['ConfigurationAggregators'][0]
    except is_boto3_error_code('NoSuchConfigurationAggregatorException'):
        return
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e)
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)
Beispiel #7
0
def rule_exists(client, module, params):
    try:
        rule = client.describe_config_rules(
            ConfigRuleNames=[params['ConfigRuleName']],
            aws_retry=True,
        )
        return rule['ConfigRules'][0]
    except is_boto3_error_code('NoSuchConfigRuleException'):
        return
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e)
def get_kms_policies(connection, module, key_id):
    try:
        policies = list_key_policies_with_backoff(connection,
                                                  key_id)['PolicyNames']
        return [
            get_key_policy_with_backoff(connection, key_id, policy)['Policy']
            for policy in policies
        ]
    except is_boto3_error_code('AccessDeniedException'):
        return []
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, msg="Failed to obtain key policies")
Beispiel #9
0
def describe_pipeline(client, name, version, module):
    pipeline = {}
    try:
        if version is not None:
            pipeline = client.get_pipeline(name=name, version=version)
            return pipeline
        else:
            pipeline = client.get_pipeline(name=name)
            return pipeline
    except is_boto3_error_code('PipelineNotFoundException'):
        return pipeline
    except (botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e)
        def _add_tags_for_hosts(connection, hosts, strict):
            for host in hosts:
                if 'DBInstanceArn' in host:
                    resource_arn = host['DBInstanceArn']
                else:
                    resource_arn = host['DBClusterArn']

                try:
                    tags = connection.list_tags_for_resource(ResourceName=resource_arn)['TagList']
                except is_boto3_error_code('AccessDenied') as e:
                    if not strict:
                        tags = []
                    else:
                        raise e
                host['Tags'] = tags
def peer_status(client, module):
    params = dict()
    params['VpcPeeringConnectionIds'] = [module.params.get('peering_id')]
    try:
        vpc_peering_connection = client.describe_vpc_peering_connections(
            **params)
        return vpc_peering_connection['VpcPeeringConnections'][0]['Status'][
            'Code']
    except is_boto3_error_code('InvalidVpcPeeringConnectionId.Malformed') as e:  # pylint: disable=duplicate-except
        module.fail_json(msg='Malformed connection ID: {0}'.format(e),
                         traceback=traceback.format_exc())
    except botocore.exceptions.ClientError as e:  # pylint: disable=duplicate-except
        module.fail_json(
            msg='Error while describing peering connection by peering_id: {0}'.
            format(e),
            traceback=traceback.format_exc())
 def wrapper(f, *args, **kwargs):
     try:
         results = f(*args, **kwargs)
         if 'DBInstances' in results:
             results = results['DBInstances']
         else:
             results = results['DBClusters']
         _add_tags_for_hosts(connection, results, strict)
     except is_boto3_error_code('AccessDenied') as e:  # pylint: disable=duplicate-except
         if not strict:
             results = []
         else:
             raise AnsibleError("Failed to query RDS: {0}".format(to_native(e)))
     except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:  # pylint: disable=duplicate-except
         raise AnsibleError("Failed to query RDS: {0}".format(to_native(e)))
     return results
def common_snapshot_info(module, conn, method, prefix, params):
    paginator = conn.get_paginator(method)
    try:
        results = paginator.paginate(**params).build_full_result()['%ss' % prefix]
    except is_boto3_error_code('%sNotFound' % prefix):
        results = []
    except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, "trying to get snapshot information")

    for snapshot in results:
        try:
            snapshot['Tags'] = boto3_tag_list_to_ansible_dict(conn.list_tags_for_resource(ResourceName=snapshot['%sArn' % prefix],
                                                                                          aws_retry=True)['TagList'])
        except (botocore.exceptions.ClientError, botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, "Couldn't get tags for snapshot %s" % snapshot['%sIdentifier' % prefix])

    return [camel_dict_to_snake_dict(snapshot, ignore_list=['Tags']) for snapshot in results]
def determine_iam_role(module, name_or_arn):
    if re.match(r'^arn:aws:iam::\d+:instance-profile/[\w+=/,.@-]+$',
                name_or_arn):
        return name_or_arn
    iam = module.client('iam', retry_decorator=AWSRetry.jittered_backoff())
    try:
        role = iam.get_instance_profile(InstanceProfileName=name_or_arn,
                                        aws_retry=True)
        return {'arn': role['InstanceProfile']['Arn']}
    except is_boto3_error_code('NoSuchEntity') as e:
        module.fail_json_aws(
            e, msg="Could not find instance_role {0}".format(name_or_arn))
    except (BotoCoreError, ClientError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(
            e,
            msg=
            "An error occurred while searching for instance_role {0}. Please try supplying the full ARN."
            .format(name_or_arn))
Beispiel #15
0
def delete_cluster(module, redshift):
    """
    Delete a cluster.

    module: Ansible module object
    redshift: authenticated redshift connection object
    """

    identifier = module.params.get('identifier')
    wait = module.params.get('wait')
    wait_timeout = module.params.get('wait_timeout')

    params = {}
    for p in ('skip_final_cluster_snapshot',
              'final_cluster_snapshot_identifier'):
        if p in module.params:
            # https://github.com/boto/boto3/issues/400
            if module.params.get(p) is not None:
                params[p] = module.params.get(p)

    try:
        redshift.delete_cluster(ClusterIdentifier=identifier,
                                **snake_dict_to_camel_dict(
                                    params, capitalize_first=True))
    except is_boto3_error_code('ClusterNotFound'):
        return (False, {})
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, msg="Failed to delete cluster")

    if wait:
        attempts = wait_timeout // 60
        waiter = redshift.get_waiter('cluster_deleted')
        try:
            waiter.wait(ClusterIdentifier=identifier,
                        WaiterConfig=dict(MaxAttempts=attempts))
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(e, msg="Timeout deleting the cluster")

    return (True, {})
def get_kms_tags(connection, module, key_id):
    # Handle pagination here as list_resource_tags does not have
    # a paginator
    kwargs = {}
    tags = []
    more = True
    while more:
        try:
            tag_response = get_kms_tags_with_backoff(connection, key_id,
                                                     **kwargs)
            tags.extend(tag_response['Tags'])
        except is_boto3_error_code('AccessDeniedException'):
            tag_response = {}
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
            module.fail_json_aws(e, msg="Failed to obtain key tags")
        if tag_response.get('NextMarker'):
            kwargs['Marker'] = tag_response['NextMarker']
        else:
            more = False
    return tags
 def _list_topic_subscriptions(self):
     try:
         return self._list_topic_subscriptions_with_backoff()
     except is_boto3_error_code('AuthorizationError'):
         try:
             # potentially AuthorizationError when listing subscriptions for third party topic
             return [
                 sub for sub in self._list_subscriptions_with_backoff()
                 if sub['TopicArn'] == self.topic_arn
             ]
         except (botocore.exceptions.ClientError,
                 botocore.exceptions.BotoCoreError) as e:
             self.module.fail_json_aws(
                 e,
                 msg="Couldn't get subscriptions list for topic %s" %
                 self.topic_arn)
     except (botocore.exceptions.ClientError,
             botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
         self.module.fail_json_aws(
             e,
             msg="Couldn't get subscriptions list for topic %s" %
             self.topic_arn)
def create_vgw(client, module):
    params = dict()
    params['Type'] = module.params.get('type')
    if module.params.get('asn'):
        params['AmazonSideAsn'] = module.params.get('asn')

    try:
        response = client.create_vpn_gateway(**params)
        get_waiter(
            client, 'vpn_gateway_exists'
        ).wait(
            VpnGatewayIds=[response['VpnGateway']['VpnGatewayId']]
        )
    except botocore.exceptions.WaiterError as e:
        module.fail_json(msg="Failed to wait for Vpn Gateway {0} to be available".format(response['VpnGateway']['VpnGatewayId']),
                         exception=traceback.format_exc())
    except is_boto3_error_code('VpnGatewayLimitExceeded'):
        module.fail_json(msg="Too many VPN gateways exist in this account.", exception=traceback.format_exc())
    except botocore.exceptions.ClientError as e:  # pylint: disable=duplicate-except
        module.fail_json(msg=to_native(e), exception=traceback.format_exc())

    result = response
    return result
Beispiel #19
0
def instance_info(module, conn):
    instance_name = module.params.get('db_instance_identifier')
    filters = module.params.get('filters')

    params = dict()
    if instance_name:
        params['DBInstanceIdentifier'] = instance_name
    if filters:
        params['Filters'] = ansible_dict_to_boto3_filter_list(filters)

    paginator = conn.get_paginator('describe_db_instances')
    try:
        results = paginator.paginate(
            **params).build_full_result()['DBInstances']
    except is_boto3_error_code('DBInstanceNotFound'):
        results = []
    except (botocore.exceptions.ClientError,
            botocore.exceptions.BotoCoreError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, "Couldn't get instance information")

    for instance in results:
        try:
            instance['Tags'] = boto3_tag_list_to_ansible_dict(
                conn.list_tags_for_resource(
                    ResourceName=instance['DBInstanceArn'],
                    aws_retry=True)['TagList'])
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(
                e, "Couldn't get tags for instance %s" %
                instance['DBInstanceIdentifier'])

    return dict(changed=False,
                instances=[
                    camel_dict_to_snake_dict(instance, ignore_list=['Tags'])
                    for instance in results
                ])
Beispiel #20
0
def describe_eni_with_backoff(ec2, module, device_id):
    try:
        return ec2.describe_network_interfaces(NetworkInterfaceIds=[device_id])
    except is_boto3_error_code('InvalidNetworkInterfaceID.NotFound') as e:
        module.fail_json_aws(e, msg="Couldn't get list of network interfaces.")
Beispiel #21
0
def create_cluster(module, redshift):
    """
    Create a new cluster

    module: AnsibleModule object
    redshift: authenticated redshift connection object

    Returns:
    """

    identifier = module.params.get('identifier')
    node_type = module.params.get('node_type')
    username = module.params.get('username')
    password = module.params.get('password')
    d_b_name = module.params.get('db_name')
    wait = module.params.get('wait')
    wait_timeout = module.params.get('wait_timeout')

    changed = True
    # Package up the optional parameters
    params = {}
    for p in ('cluster_type', 'cluster_security_groups',
              'vpc_security_group_ids', 'cluster_subnet_group_name',
              'availability_zone', 'preferred_maintenance_window',
              'cluster_parameter_group_name',
              'automated_snapshot_retention_period', 'port', 'cluster_version',
              'allow_version_upgrade', 'number_of_nodes',
              'publicly_accessible', 'encrypted', 'elastic_ip',
              'enhanced_vpc_routing'):
        # https://github.com/boto/boto3/issues/400
        if module.params.get(p) is not None:
            params[p] = module.params.get(p)

    if d_b_name:
        params['d_b_name'] = d_b_name

    try:
        redshift.describe_clusters(ClusterIdentifier=identifier)['Clusters'][0]
        changed = False
    except is_boto3_error_code('ClusterNotFound'):
        try:
            redshift.create_cluster(ClusterIdentifier=identifier,
                                    NodeType=node_type,
                                    MasterUsername=username,
                                    MasterUserPassword=password,
                                    **snake_dict_to_camel_dict(
                                        params, capitalize_first=True))
        except (botocore.exceptions.BotoCoreError,
                botocore.exceptions.ClientError) as e:
            module.fail_json_aws(e, msg="Failed to create cluster")
    except (botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError) as e:  # pylint: disable=duplicate-except
        module.fail_json_aws(e, msg="Failed to describe cluster")
    if wait:
        attempts = wait_timeout // 60
        waiter = redshift.get_waiter('cluster_available')
        try:
            waiter.wait(ClusterIdentifier=identifier,
                        WaiterConfig=dict(MaxAttempts=attempts))
        except (botocore.exceptions.ClientError,
                botocore.exceptions.BotoCoreError) as e:
            module.fail_json_aws(
                e, msg="Timeout waiting for the cluster creation")
    try:
        resource = redshift.describe_clusters(
            ClusterIdentifier=identifier)['Clusters'][0]
    except (botocore.exceptions.BotoCoreError,
            botocore.exceptions.ClientError) as e:
        module.fail_json_aws(e, msg="Failed to describe cluster")

    return (changed, _collect_facts(resource))