Esempio n. 1
0
def list(obj, output):
    '''List AWS profiles'''

    profile_list = get_profiles(obj['service_url'])
    default = obj['default'] if 'default' in obj else {}

    if 'aliases' in obj:
        alias_list = {(v['account_name'], v['role_name']): alias
                      for alias, v in obj['aliases'].items()}
    else:
        alias_list = {}

    for profile in profile_list:
        if (default and (profile['account_name'], profile['role_name'])
                == (default['account_name'], default['role_name'])):
            profile['default'] = '✓'
        else:
            profile['default'] = ''

        if (profile['account_name'], profile['role_name']) in alias_list:
            profile['alias'] = alias_list[(profile['account_name'],
                                           profile['role_name'])]
        else:
            profile['alias'] = ''

    profile_list.sort(key=lambda r: r['account_name'])

    with OutputFormat(output):
        print_table(
            ['account_id', 'account_name', 'role_name', 'alias', 'default'],
            profile_list)
Esempio n. 2
0
def pull_requests(config, output):
    '''List pull requests'''
    token = config.get('github_access_token')

    repositories = get_repositories()

    rows = []
    for issue in get_my_issues(token):
        pr = issue.get('pull_request')
        if pr:
            repo = repositories.get(issue['repository']['url'])
            if repo:
                r = request(session.get, pr['url'], token)
                pr = r.json()
                issue.update(**pr)
                issue['repository'] = repo['full_name']
                issue['created_time'] = parse_time(issue['created_at'])
                issue['created_by'] = issue['user']['login']
                issue['labels'] = ', '.join(
                    [l['name'] for l in issue['labels']])
                rows.append(issue)

    rows.sort(key=lambda x: (x['repository'], x['number']))
    with OutputFormat(output):
        print_table([
            'repository', 'number', 'title', 'labels', 'mergeable',
            'mergeable_state', 'created_time', 'created_by'
        ], rows)
Esempio n. 3
0
def list_dummy_states(output, watch):
    '''Example for Listings'''
    states = ['ERROR', 'FINE', 'WARNING']
    i = 0
    for _ in watching(watch):
        i += 1
        rows = []
        for y in (1, 2, 3):
            id = i * y - i
            rows.append({
                'id': id,
                'name': 'Column #{}'.format(id),
                'state': states[id % len(states)],
                'creation_time': 1444911300,
                'desc': 'this is a ve' + 'r' * 50 + 'y long description',
                'without_title': 'column without title',
                'missing_column': 'Column are not in output'
            })

        with OutputFormat(output):
            print_table(
                'id name state creation_time desc without_title'.split(),
                rows,
                styles=STYLES,
                titles=TITLES,
                max_column_widths=MAX_COLUMN_WIDTHS)
Esempio n. 4
0
def output(output):
    '''Example for all possible Echo Formats

    You see the message only, if the Output TEXT
    '''
    with OutputFormat(output):
        action('This is a ok:')
        ok()
        action('This is a ok with message:')
        ok('all is fine')
        action('This is a warning:')
        warning('please check this')
        with Action('Start with working..') as act:
            # save_the_world()
            act.progress()
            act.progress()
            act.progress()
            act.progress()
        print_table('id name'.split(), [{
            'id': 1,
            'name': 'Test #1'
        }, {
            'id': 2,
            'name': 'Test #2'
        }])
        info('Only FYI')
        action('This is a error:')
        error('this is wrong, please fix')
        action('This is a fatal error:')
        fatal_error('this is a fuckup')
        info('I\'am not printed, the process a dead')
Esempio n. 5
0
def render_entities(entities, output):
    rows = []
    for e in entities:
        row = e
        s = sorted(e.keys())

        key_values = []

        for k in s:
            if k not in ('id', 'type'):
                if k == 'last_modified':
                    row['last_modified_time'] = (calendar.timegm(
                        time.strptime(row.pop('last_modified'),
                                      LAST_MODIFIED_FMT)))
                else:
                    key_values.append('{}={}'.format(k, e[k]))

        row['data'] = ' '.join(key_values)
        rows.append(row)

    rows.sort(key=lambda r: (r['last_modified_time'], r['id'], r['type']))

    with OutputFormat(output):
        print_table('id type last_modified_time data'.split(),
                    rows,
                    titles={'last_modified_time': 'Modified'})
Esempio n. 6
0
def events(stack_ref, region, w, watch, output):
    '''Show all Cloud Formation events for a single stack'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)
    cf = boto3.client('cloudformation', region)

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region):
            events = cf.describe_stack_events(
                StackName=stack.StackId)['StackEvents']

            for event in events:
                d = event.copy()
                d['stack_name'] = stack.name
                d['version'] = stack.version
                d['resource_type'] = format_resource_type(d['ResourceType'])
                d['event_time'] = calendar.timegm(
                    event['Timestamp'].timetuple())
                rows.append(d)

        rows.sort(key=lambda x: x['event_time'])

        with OutputFormat(output):
            print_table(
                ('stack_name version resource_type LogicalResourceId ' +
                 'ResourceStatus ResourceStatusReason event_time').split(),
                rows,
                styles=STYLES,
                titles=TITLES,
                max_column_widths=MAX_COLUMN_WIDTHS)
Esempio n. 7
0
def image(config, image, output):
    '''List tags that point to this image'''
    token = get_token()

    resp = request(config.get('url'), '/tags/{}'.format(image),
                   token['access_token'])

    if resp.status_code == 404:
        click.echo('Image {} not found'.format(image))
        return

    if resp.status_code == 412:
        click.echo('Prefix {} matches more than one image.'.format(image))
        return

    tags = resp.json()

    with OutputFormat(output):
        print_table(['team', 'artifact', 'name'],
                    tags,
                    titles={
                        'name': 'Tag',
                        'artifact': 'Artifact',
                        'team': 'Team'
                    })
Esempio n. 8
0
def list_stacks(region, stack_ref, all, output, w, watch):
    '''List Cloud Formation stacks'''
    region = get_region(region)
    check_credentials(region)

    stack_refs = get_stack_refs(stack_ref)

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region, all=all):
            rows.append({
                'stack_name':
                stack.name,
                'version':
                stack.version,
                'status':
                stack.StackStatus,
                'creation_time':
                calendar.timegm(stack.CreationTime.timetuple()),
                'description':
                stack.TemplateDescription
            })

        rows.sort(key=lambda x: (x['stack_name'], x['version']))

        with OutputFormat(output):
            print_table(
                'stack_name version status creation_time description'.split(),
                rows,
                styles=STYLES,
                titles=TITLES)
Esempio n. 9
0
File: cli.py Progetto: mindis/senza
def events(stack_ref, region, w, watch, output):
    '''Show all Cloud Formation events for a single stack'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)
    cf = boto.cloudformation.connect_to_region(region)

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region):
            events = cf.describe_stack_events(stack.stack_name)

            for event in events:
                d = event.__dict__
                d['stack_name'] = stack.name
                d['version'] = stack.version
                d['resource_type'] = format_resource_type(d['resource_type'])
                d['event_time'] = calendar.timegm(event.timestamp.timetuple())
                rows.append(d)

        rows.sort(key=lambda x: x['event_time'])

        with OutputFormat(output):
            print_table(
                ('stack_name version resource_type logical_resource_id ' +
                 'resource_status resource_status_reason event_time').split(),
                rows,
                styles=STYLES,
                titles=TITLES,
                max_column_widths=MAX_COLUMN_WIDTHS)
Esempio n. 10
0
def resources(stack_ref, region, w, watch, output):
    '''Show all resources of a single Cloud Formation stack'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)
    cf = boto3.client('cloudformation', region)

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region):
            resources = cf.describe_stack_resources(
                StackName=stack.StackName)['StackResources']

            for resource in resources:
                d = resource.copy()
                d['stack_name'] = stack.name
                d['version'] = stack.version
                d['resource_type'] = format_resource_type(d['ResourceType'])
                d['creation_time'] = calendar.timegm(
                    resource['Timestamp'].timetuple())
                rows.append(d)

        rows.sort(key=lambda x:
                  (x['stack_name'], x['version'], x['LogicalResourceId']))

        with OutputFormat(output):
            print_table(
                'stack_name version LogicalResourceId resource_type ResourceStatus creation_time'
                .split(),
                rows,
                styles=STYLES,
                titles=TITLES)
Esempio n. 11
0
File: cli.py Progetto: mindis/senza
def resources(stack_ref, region, w, watch, output):
    '''Show all resources of a single Cloud Formation stack'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)
    cf = boto.cloudformation.connect_to_region(region)

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region):
            resources = cf.describe_stack_resources(stack.stack_name)

            for resource in resources:
                d = resource.__dict__
                d['stack_name'] = stack.name
                d['version'] = stack.version
                d['resource_type'] = format_resource_type(d['resource_type'])
                d['creation_time'] = calendar.timegm(
                    resource.timestamp.timetuple())
                rows.append(d)

        rows.sort(key=lambda x:
                  (x['stack_name'], x['version'], x['logical_resource_id']))

        with OutputFormat(output):
            print_table(
                'stack_name version logical_resource_id resource_type resource_status creation_time'
                .split(),
                rows,
                styles=STYLES,
                titles=TITLES)
Esempio n. 12
0
def types(config, output):
    '''List violation types'''
    url = config.get('url')
    if not url:
        raise click.ClickException(
            'Missing configuration URL. Please run "stups configure".')

    token = get_token()

    r = request(url, '/api/violation-types', token)
    r.raise_for_status()
    data = r.json()

    rows = []
    for row in data:
        row['created_time'] = parse_time(row['created'])
        rows.append(row)

    rows.sort(key=lambda r: r['id'])

    with OutputFormat(output):
        print_table(['id', 'violation_severity', 'created_time', 'help_text'],
                    rows,
                    titles={
                        'created_time': 'Created',
                        'violation_severity': 'Sev.'
                    })
Esempio n. 13
0
def traffic(stack_name: str,
            stack_version: Optional[str],
            percentage: Optional[int],
            region: Optional[str],
            remote: Optional[str],
            output: Optional[str]):
    '''Manage stack traffic'''
    lizzy = setup_lizzy_client(remote)

    if percentage is None:
        stack_reference = [stack_name]

        with Action('Requesting traffic info..'):
            stack_weights = []
            for stack in lizzy.get_stacks(stack_reference, region=region):
                if stack['status'] in ['CREATE_COMPLETE', 'UPDATE_COMPLETE']:
                    stack_id = '{stack_name}-{version}'.format_map(stack)
                    traffic = lizzy.get_traffic(stack_id, region=region)
                    stack_weights.append({
                        'stack_name': stack_name,
                        'version': stack['version'],
                        'identifier': stack_id,
                        'weight%': traffic['weight']
                    })
        cols = 'stack_name version identifier weight%'.split()
        with OutputFormat(output):
            print_table(cols,
                        sorted(stack_weights, key=lambda x: x['identifier']))
    else:
        with Action('Requesting traffic change..'):
            stack_id = '{stack_name}-{stack_version}'.format_map(locals())
            lizzy.traffic(stack_id, percentage, region=region)
Esempio n. 14
0
def tags(config, team, artifact, output):
    '''List all tags'''
    token = get_token()

    if not artifact:
        artifact = get_artifacts(config.get('url'), team,
                                 token['access_token'])

    rows = []
    for art in artifact:
        r = get_tags(config.get('url'), team, art, token['access_token'])
        rows.extend([{
            'team':
            team,
            'artifact':
            art,
            'tag':
            row['name'],
            'created_by':
            row['created_by'],
            'created_time':
            datetime.datetime.strptime(row['created'],
                                       '%Y-%m-%dT%H:%M:%S.%f%z').timestamp()
        } for row in r])

    rows.sort(key=lambda row: (row['team'], row['artifact'], row['tag']))
    with OutputFormat(output):
        print_table(['team', 'artifact', 'tag', 'created_time', 'created_by'],
                    rows,
                    titles={
                        'created_time': 'Created',
                        'created_by': 'By'
                    })
Esempio n. 15
0
def test_yaml_out(capsys):
    with OutputFormat('yaml'):
        warning('this is a warning')
        print_table('a b'.split(), [{}, {}])
    out, err = capsys.readouterr()
    assert 'a: null\nb: null\n---\na: null\nb: null\n\n' == out
    assert 'this is a warning\n' == err
Esempio n. 16
0
def test_tsv_out(capsys):
    with OutputFormat('tsv'):
        warning('this is a warning')
        print_table('a b'.split(), [{"a": 1}, {"b": 2}])
    out, err = capsys.readouterr()
    assert 'a\tb\n1\t\n\t2\n' == out
    assert 'this is a warning\n' == err
Esempio n. 17
0
def test_text_out(capsys):
    with OutputFormat('text'):
        warning('this is a warning')
        print_table('a b'.split(), [{}, {}])
    out, err = capsys.readouterr()
    assert u'A│B\n    \n    \n' == out
    assert 'this is a warning\n' == err
Esempio n. 18
0
def test_json_out(capsys):
    with OutputFormat('json'):
        warning('this is a warning')
        print_table('a b'.split(), [{}, {}])
    out, err = capsys.readouterr()
    assert '[{"a": null, "b": null}, {"a": null, "b": null}]\n' == out
    assert 'this is a warning\n' == err
Esempio n. 19
0
def image(config, image, url, output):
    '''List tags that point to this image'''
    set_pierone_url(config, url)
    token = get_token()

    try:
        resp = request(config.get('url'), '/tags/{}'.format(image), token)
    except requests.HTTPError as error:
        status_code = error.response.status_code
        if status_code == 404:
            click.echo('Image {} not found'.format(image))
        elif status_code == 412:
            click.echo('Prefix {} matches more than one image.'.format(image))
        else:
            raise error
        return

    tags = resp.json()

    with OutputFormat(output):
        print_table(['team', 'artifact', 'name'],
                    tags,
                    titles={
                        'name': 'Tag',
                        'artifact': 'Artifact',
                        'team': 'Team'
                    })
Esempio n. 20
0
def list_stacks(stack_ref: List[str], all: bool, remote: str, region: str,
                watch: int, output: str):
    """List Lizzy stacks"""
    lizzy = setup_lizzy_client(remote)
    stack_references = parse_stack_refs(stack_ref)

    while True:
        rows = []
        for stack in lizzy.get_stacks(stack_references, region=region):
            creation_time = dateutil.parser.parse(stack['creation_time'])
            rows.append({'stack_name': stack['stack_name'],
                         'version': stack['version'],
                         'status': stack['status'],
                         'creation_time': creation_time.timestamp(),
                         'description': stack['description']})

        rows.sort(key=lambda x: (x['stack_name'], x['version']))
        with OutputFormat(output):
            print_table(
                'stack_name version status creation_time description'.split(),
                rows, styles=STYLES, titles=TITLES)

        if watch:  # pragma: no cover
            time.sleep(watch)
            click.clear()
        else:
            break
Esempio n. 21
0
def scm_source(config, team, artifact, tag, url, output):
    '''Show SCM source information such as GIT revision'''
    set_pierone_url(config, url)
    token = get_token()

    tags = get_tags(config.get('url'), team, artifact, token)
    if not tags:
        raise click.UsageError('Artifact or Team does not exist! '
                               'Please double check for spelling mistakes.')

    if not tag:
        tag = [t['name'] for t in tags]

    rows = []
    for t in tag:
        r = request(config.get('url'), '/teams/{}/artifacts/{}/tags/{}/scm-source'.format(team, artifact, t),
                    token, True)
        if r is None:
            row = {}
        else:
            row = r.json()
        row['tag'] = t
        matching_tag = [d for d in tags if d['name'] == t]
        row['created_by'] = ''.join([d['created_by'] for d in matching_tag])
        if matching_tag:
            row['created_time'] = parse_time(''.join([d['created'] for d in matching_tag]))
        rows.append(row)

    rows.sort(key=lambda row: (row['tag'], row.get('created_time')))
    with OutputFormat(output):
        print_table(['tag', 'author', 'url', 'revision', 'status', 'created_time', 'created_by'], rows,
                    titles={'tag': 'Tag', 'created_by': 'By', 'created_time': 'Created',
                            'url': 'URL', 'revision': 'Revision', 'status': 'Status'},
                    max_column_widths={'revision': 10})
Esempio n. 22
0
def artifacts(config, team, url, output):
    """List all team artifacts"""
    url = set_pierone_url(config, url)
    api = PierOne(url)
    result = api.get_artifacts(team)
    rows = [{'team': team, 'artifact': name} for name in sorted(result)]
    with OutputFormat(output):
        print_table(['team', 'artifact'], rows)
Esempio n. 23
0
def artifacts(config, team, output):
    '''List all team artifacts'''
    token = get_token()

    result = get_artifacts(config.get('url'), team, token['access_token'])
    rows = [{'team': team, 'artifact': name} for name in sorted(result)]
    with OutputFormat(output):
        print_table(['team', 'artifact'], rows)
Esempio n. 24
0
def teams(config, output):
    '''List all teams having artifacts in Pier One'''
    token = get_token()

    r = request(config.get('url'), '/teams', token['access_token'])
    rows = [{'name': name} for name in sorted(r.json())]
    with OutputFormat(output):
        print_table(['name'], rows)
Esempio n. 25
0
def list_violations(config, output, since, region, meta, remeta, limit, all,
                    **kwargs):
    '''List violations'''
    url = config.get('url')
    if not url:
        raise click.ClickException(
            'Missing configuration URL. Please run "stups configure".')

    kwargs['accounts'] = kwargs.get('accounts') or config.get('accounts')

    token = get_token()

    params = {'size': limit, 'sort': 'id,DESC'}
    params['from'] = parse_since(since)
    params['application-ids'] = kwargs.get('applications')
    params['application-version-ids'] = kwargs.get('application_versions')
    params.update(kwargs)

    r = request(url, '/api/violations', token, params=params)
    r.raise_for_status()
    data = r.json()['content']

    if (all):
        params['checked'] = 'true'
        r = request(url, '/api/violations', token, params=params)
        r.raise_for_status()
        data.extend(r.json()['content'])

    rows = []
    for row in data:
        if region and row['region'] != region:
            continue
        if meta and not meta_matches(row['meta_info'], meta):
            continue
        if remeta and not meta_matches_re(format_meta_info(row['meta_info']),
                                          remeta):
            continue
        row['violation_type'] = row['violation_type']['id']
        row['created_time'] = parse_time(row['created'])
        row['meta_info'] = format_meta_info(row['meta_info'])
        rows.append(row)

    # we get the newest violations first, but we want to print them in order
    rows.reverse()

    with OutputFormat(output):
        print_table(
            [
                'account_id', 'region', 'id', 'violation_type', 'instance_id',
                'application_id', 'application_version_id', 'meta_info',
                'comment', 'created_time'
            ],
            rows,
            titles={
                'created_time': 'Created',
                'application_id': 'Application',
                'application_version_id': 'Application Version'
            })
Esempio n. 26
0
File: cli.py Progetto: mindis/senza
def domains(stack_ref, region, output, w, watch):
    '''List the stack's Route53 domains'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)

    cf = boto.cloudformation.connect_to_region(region)
    route53 = boto.route53.connect_to_region(region)

    records_by_name = {}

    for _ in watching(w, watch):
        rows = []
        for stack in get_stacks(stack_refs, region):
            if stack.stack_status == 'ROLLBACK_COMPLETE':
                # performance optimization: do not call EC2 API for "dead" stacks
                continue

            resources = cf.describe_stack_resources(stack.stack_id)
            for res in resources:
                if res.resource_type == 'AWS::Route53::RecordSet':
                    name = res.physical_resource_id
                    if name not in records_by_name:
                        zone_name = name.split('.', 1)[1]
                        zone = route53.get_zone(zone_name)
                        for rec in zone.get_records():
                            records_by_name[(rec.name.rstrip('.'),
                                             rec.identifier)] = rec
                    record = records_by_name.get(
                        (name, stack.stack_name)) or records_by_name.get(
                            (name, None))
                    rows.append({
                        'stack_name':
                        stack.name,
                        'version':
                        stack.version,
                        'resource_id':
                        res.logical_resource_id,
                        'domain':
                        res.physical_resource_id,
                        'weight':
                        record.weight if record else None,
                        'type':
                        record.type if record else None,
                        'value':
                        ','.join(record.resource_records) if record else None,
                        'create_time':
                        calendar.timegm(res.timestamp.timetuple())
                    })

        with OutputFormat(output):
            print_table(
                'stack_name version resource_id domain weight type value create_time'
                .split(),
                rows,
                styles=STYLES,
                titles=TITLES)
Esempio n. 27
0
def artifacts(config, team, url, output):
    '''List all team artifacts'''
    set_pierone_url(config, url)
    token = get_token()

    result = get_artifacts(config.get('url'), team, token)
    rows = [{'team': team, 'artifact': name} for name in sorted(result)]
    with OutputFormat(output):
        print_table(['team', 'artifact'], rows)
Esempio n. 28
0
def main_clean(delete):
    repo_path = pygit2.discover_repository(os.getcwd())
    repo = pygit2.Repository(repo_path)

    info = {}

    fill_branch_info(info, repo.branches, islocal=True)
    fill_branch_info(info, repo.branches, islocal=False)

    fill_merged_info(info, isremote=False)
    fill_merged_info(info, isremote=True)

    rows = []
    issafe = True

    for name in info.keys():
        data = info[name]
        if not data.gone:
            continue

        rows.append({
            "flags": "{}local".format("*" if data.head else " "),
            "name": name,
            "log": first_line(repo[data.target].message),
        })
        if data.head:
            issafe = False
    # end

    if not rows:
        print("No work to be done")
        return

    max_width, _ = os.get_terminal_size(0)

    used = 6 + 1 + 40 + 1
    remaining = max_width - 1 - used

    WIDTHS = {"flags": 6, "name": 40, "log": remaining}

    with OutputFormat("text"):
        print_table(["flags", "name", "log"], rows, max_column_widths=WIDTHS)

    if delete:
        print("Deleting local branches...")
        if not issafe:
            print("Current checkout includes a branch to be deleted.")
            return

        click.confirm("Do you want to continue?", abort=True)

        for name in info.keys():
            data = info[name]
            if not data.gone:
                continue

            repo.branches[data.key].delete()
Esempio n. 29
0
def list_stacks(stack_ref: str, all: bool, watch: int, output: str):
    """List Lizzy stacks"""

    config = Configuration()

    access_token = fetch_token(config.token_url, config.scopes,
                               config.credentials_dir)

    lizzy = Lizzy(config.lizzy_url, access_token)

    repeat = True

    while repeat:
        try:
            all_stacks = lizzy.get_stacks()
        except requests.RequestException as e:
            fatal_error('Failed to get stacks: {}'.format(e))

        if all:
            stacks = all_stacks
        else:
            stacks = [
                stack for stack in all_stacks
                if stack['status'] not in ['LIZZY:REMOVED']
            ]

        if stack_ref:
            stacks = [
                stack for stack in stacks if stack['stack_name'] in stack_ref
            ]

        rows = []
        for stack in stacks:
            creation_time = dateutil.parser.parse(stack['creation_time'])
            rows.append({
                'stack_name': stack['stack_name'],
                'version': stack['stack_version'],
                'image_version': stack['image_version'],
                'status': stack['status'],
                'creation_time': creation_time.timestamp()
            })

        rows.sort(key=lambda x: (x['stack_name'], x['version']))
        with OutputFormat(output):
            print_table(
                'stack_name version image_version status creation_time'.split(
                ),
                rows,
                styles=STYLES,
                titles=TITLES)

        if watch:  # pragma: no cover
            time.sleep(watch)
            click.clear()
        else:
            repeat = False
Esempio n. 30
0
def tags(config, team: str, artifact, url, output, limit):
    '''List all tags for a given team'''
    set_pierone_url(config, url)
    token = get_token()

    if limit is None:
        # show 20 rows if artifact was given, else show only 3
        limit = 20 if artifact else 3

    if not artifact:
        artifact = get_artifacts(config.get('url'), team, token)
        if not artifact:
            raise click.UsageError(
                'The Team you are looking for does not exist or '
                'we could not find any artifacts registered in Pierone! '
                'Please double check for spelling mistakes.')

    registry = config.get('url')
    if registry.startswith('https://'):
        registry = registry[8:]

    slice_from = -limit

    rows = []
    for art in artifact:
        image = DockerImage(registry=registry,
                            team=team,
                            artifact=art,
                            tag=None)
        try:
            tags = get_image_tags(image, token)
        except Unauthorized as e:
            raise click.ClickException(str(e))
        else:
            if not tags:
                raise click.UsageError(
                    'Artifact or Team does not exist! '
                    'Please double check for spelling mistakes.')
            rows.extend(tags[slice_from:])

    # sorts are guaranteed to be stable, i.e. tags will be sorted by time (as returned from REST service)
    rows.sort(key=lambda row: (row['team'], row['artifact']))
    with OutputFormat(output):
        titles = {
            'created_time': 'Created',
            'created_by': 'By',
            'severity_fix_available': 'Fixable CVE Severity',
            'severity_no_fix_available': 'Unfixable CVE Severity'
        }
        print_table([
            'team', 'artifact', 'tag', 'created_time', 'created_by',
            'severity_fix_available', 'severity_no_fix_available'
        ],
                    rows,
                    titles=titles,
                    styles=CVE_STYLES)