def cli(ctx, amount, index, query, stage):
    """Pull data from Source Service Client"""

    if not ctx.bubble:
        ctx.say_yellow('There is no bubble present, will not pull')
        raise click.Abort()
    STAGE = None
    SRC = None

    if stage in STAGES and stage in ctx.cfg.CFG:
        STAGE = ctx.cfg.CFG[stage]

    if not STAGE:
        ctx.say_red('There is no STAGE in CFG:' + stage)
        ctx.say_yellow('please check configuration in ' +
                       ctx.home + '/config/config.yaml')
        raise click.Abort()

    if 'SOURCE' in STAGE:
        SRC = STAGE.SOURCE
    if not SRC:
        ctx.say_red('There is no SOURCE in stage:' + stage)
        ctx.say_yellow('please check configuration in ' +
                       ctx.home + '/config/config.yaml')
        raise click.Abort()
    gbc = ctx.GLOBALS['gbc']
    src_client = get_client(gbc, SRC.CLIENT, ctx.home)

    # TODO: client get error count?
    # make default counters
    # client.pull(amount,index,counters)
    # counter:#Good Bad Ugly: BUG, counters
    # for this the client must be able to keep stats, or update stats in the pull loop.
    # bug.counters

    try:
        sclient = src_client.BubbleClient(cfg=SRC)
        sclient.set_parent(gbc)
        sclient.set_verbose(ctx.get_verbose())
    except Exception as e:
        ctx.say_red(
            'cannot create bubble client:' + SRC.CLIENT)
        ctx.say_red(str(e))
        raise click.Abort('cannot pull')

    full_data = False
    if amount == -1 and index == -1:
        full_data = True

    try:
        if amount > 0:
            if index < 0:
                index = 0
            pb_label='Pulling %d+%d '% (index,amount)
            src_data_gen = sclient.pull(amount, index)
        else:
            if query:
                pb_label='Querying:%s' % query
                src_data_gen = [sclient.query(query)]
                full_data = False
            else:
                pb_label='Pulling all'
                src_data_gen = sclient.pull()
    except Exception as e:
        ctx.say_red('cannot pull from source client: ' + SRC.CLIENT)
        ctx.say_red(str(e))
        raise click.Abort('cannot pull')
    click.echo()

    # TODO: these actually need to be counted someway.
    # in client,
    # in storage,
    # where else?
    error_count = 0

    with click.progressbar(src_data_gen,
                           label=pb_label,
                           show_pos=True,
                           length=amount,
                           show_eta=True,
                           fill_char='◐') as progress_src_data_gen:
        pfr = bubble_lod_dump(ctx=ctx,
                          step='pulled',
                          stage=stage,
                          full_data=full_data,
                          reset=True,
                          data_gen=progress_src_data_gen)
    ctx.say('pulled [%d] objects' % pfr['total'])


    stats = {}
    stats['pulled_stat_error_count'] = error_count
    stats['pulled_stat_total_count'] = pfr['total']
    update_stats(ctx, stage, stats)

    return True
Pull data from Source Service Client