def _execute_with_retries(conn, function, **kwargs):
    '''
    Retry if we're rate limited by AWS or blocked by another call.
    Give up and return error message if resource not found or argument is invalid.

    conn
        The connection established by the calling method via _get_conn()

    function
        The function to call on conn. i.e. create_stream

    **kwargs
        Any kwargs required by the above function, with their keywords
        i.e. StreamName=stream_name

    Returns:
        The result dict with the HTTP response and JSON data if applicable
        as 'result', or an error as 'error'

    CLI example::

        salt myminion boto_kinesis._execute_with_retries existing_conn function_name function_kwargs

    '''
    r = {}
    max_attempts = 18
    max_retry_delay = 10
    for attempt in range(max_attempts):
        log.info("attempt: %s function: %s", attempt, function)
        try:
            fn = getattr(conn, function)
            r['result'] = fn(**kwargs)
            return r
        except botocore.exceptions.ClientError as e:
            error_code = e.response['Error']['Code']
            if "LimitExceededException" in error_code or "ResourceInUseException" in error_code:
                # could be rate limited by AWS or another command is blocking,
                # retry with exponential backoff
                log.debug("Retrying due to AWS exception", exc_info=True)
                time.sleep(_jittered_backoff(attempt, max_retry_delay))
            else:
                # ResourceNotFoundException or InvalidArgumentException
                r['error'] = e.response['Error']
                log.error(r['error'])
                r['result'] = None
                return r

    r['error'] = "Tried to execute function {0} {1} times, but was unable".format(function, max_attempts)
    log.error(r['error'])
    return r
Retry if we're rate limited by AWS or blocked by another call.
    Give up and return error message if resource not found or argument is invalid.

    conn
        The connection established by the calling method via _get_conn()

    function
        The function to call on conn. i.e. create_stream

    **kwargs
        Any kwargs required by the above function, with their keywords
        i.e. StreamName=stream_name

    Returns:
        The result dict with the HTTP response and JSON data if applicable
        as 'result', or an error as 'error'

    CLI example::

        salt myminion boto_kinesis._execute_with_retries existing_conn function_name function_kwargs