Esempio n. 1
0
File: cli.py Progetto: pbarron/zign
def list_tokens(output):
    '''List tokens'''
    data = get_tokens()

    rows = []
    for key, val in sorted(data.items()):
        access_token = val.get('access_token')
        rows.append({'name': key,
                     'access_token': access_token,
                     'scope': val.get('scope'),
                     'creation_time': val.get('creation_time'),
                     'expires_in': format_expires(val)})

    with OutputFormat(output):
        print_table('name access_token scope creation_time expires_in'.split(), rows,
                    titles={'creation_time': 'Created'}, max_column_widths={'access_token': 36})
Esempio n. 2
0
def scm_source(config, team, artifact, tag, url, output):
    '''Show SCM source information such as GIT revision'''
    url = set_pierone_url(config, url)
    api = PierOne(url)
    token = get_token()

    tags = get_tags(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:
        image = DockerImage(url, team, artifact, t)
        try:
            scm_source = api.get_scm_source(image)
            row = scm_source
        except ArtifactNotFound:
            row = {}
        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. 3
0
def list_profiles(obj, output):
    '''List profiles'''

    if obj['config']:
        rows = []
        for name, config in obj['config'].items():
            row = {
                'name': name,
                'role': get_role_label(config.get('saml_role')),
                'url': config.get('saml_identity_provider_url'),
                'user': config.get('saml_user')}
            rows.append(row)

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

        with OutputFormat(output):
            print_table(sorted(rows[0].keys()), rows)
Esempio n. 4
0
def scm_source(config, team, artifact, tag, output):
    '''Show SCM source information such as GIT revision'''
    token = get_token()

    tags = get_tags(config.get('url'), team, artifact, token['access_token'])

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

    rows = []
    for t in tag:
        row = request(
            config.get('url'),
            '/teams/{}/artifacts/{}/tags/{}/scm-source'.format(
                team, artifact, t), token['access_token']).json()
        if not row:
            row = {}
        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'] = datetime.datetime.strptime(
                ''.join([d['created'] for d in matching_tag]),
                '%Y-%m-%dT%H:%M:%S.%f%z').timestamp()
        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. 5
0
def cves(config, team, artifact, tag, url, output):
    '''List all CVE's found by Clair service for a specific artifact tag'''
    set_pierone_url(config, url)

    rows = []
    token = get_token()
    for artifact_tag in get_tags(config.get('url'), team, artifact, token):
        if artifact_tag['name'] == tag:
            installed_software = get_clair_features(
                artifact_tag.get('clair_details'), token)
            for software_pkg in installed_software:
                for cve in software_pkg.get('Vulnerabilities', []):
                    rows.append({
                        'cve':
                        cve['Name'],
                        'severity':
                        cve['Severity'].upper(),
                        'affected_feature':
                        '{}:{}'.format(software_pkg['Name'],
                                       software_pkg['Version']),
                        'fixing_feature':
                        cve.get('FixedBy') and '{}:{}'.format(
                            software_pkg['Name'], cve['FixedBy']),
                        'link':
                        cve['Link'],
                    })
    severity_rating = [
        'CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'NEGLIGIBLE', 'UNKNOWN', 'PENDING'
    ]
    rows.sort(key=lambda row: severity_rating.index(row['severity']))
    with OutputFormat(output):
        titles = {
            'cve': 'CVE',
            'severity': 'Severity',
            'affected_feature': 'Affected Feature',
            'fixing_feature': 'Fixing Feature',
            'link': 'Link'
        }
        print_table(
            ['cve', 'severity', 'affected_feature', 'fixing_feature', 'link'],
            rows,
            titles=titles,
            styles=CVE_STYLES)
Esempio n. 6
0
def list_access_requests(obj, user, odd_host, status, limit, offset, output):
    '''List access requests filtered by user, host and status'''
    config = load_config(obj)

    if user == '*':
        user = None

    if odd_host == '*':
        odd_host = None
    elif odd_host == 'MY-ODD-HOST':
        odd_host = config.get('odd_host')

    token = zign.api.get_existing_token('piu')
    if not token:
        raise click.UsageError('No valid OAuth token named "piu" found.')

    access_token = token.get('access_token')
    params = {
        'username': user,
        'hostname': odd_host,
        'status': status,
        'limit': limit,
        'offset': offset
    }
    r = requests.get(
        config.get('even_url').rstrip('/') + '/access-requests',
        params=params,
        headers={'Authorization': 'Bearer {}'.format(access_token)})
    r.raise_for_status()
    rows = []
    for req in r.json():
        req['created_time'] = datetime.datetime.strptime(
            req['created'], '%Y-%m-%dT%H:%M:%S.%f%z').timestamp()
        rows.append(req)
    rows.sort(key=lambda x: x['created_time'])
    with OutputFormat(output):
        print_table(
            'username hostname remote_host reason lifetime_minutes status status_reason created_time'
            .split(),
            rows,
            styles=STYLES,
            titles=TITLES,
            max_column_widths=MAX_COLUMN_WIDTHS)
Esempio n. 7
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'
        }
        print_table(['team', 'artifact', 'tag', 'created_time', 'created_by'], rows, titles=titles)
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.stack_status,
                         'creation_time': calendar.timegm(stack.creation_time.timetuple()),
                         'description': stack.template_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)
Esempio n. 9
0
def instances(stack_ref, all, terminated, region, output, w, watch):
    '''List the stack's EC2 instances'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)

    conn = boto.ec2.connect_to_region(region)
    elb = boto.ec2.elb.connect_to_region(region)

    if all:
        filters = None
    else:
        # filter out instances not part of any stack
        filters = {'tag-key': 'aws:cloudformation:stack-name'}

    for _ in watching(w, watch):
        rows = []

        for instance in conn.get_only_instances(filters=filters):
            cf_stack_name = instance.tags.get('aws:cloudformation:stack-name')
            stack_name = instance.tags.get('StackName')
            stack_version = instance.tags.get('StackVersion')
            if not stack_refs or matches_any(cf_stack_name, stack_refs):
                instance_health = get_instance_health(elb, cf_stack_name)
                if instance.state.upper() != 'TERMINATED' or terminated:
                    rows.append({'stack_name': stack_name or '',
                                 'version': stack_version or '',
                                 'resource_id': instance.tags.get('aws:cloudformation:logical-id'),
                                 'instance_id': instance.id,
                                 'public_ip': instance.ip_address,
                                 'private_ip': instance.private_ip_address,
                                 'state': instance.state.upper().replace('-', '_'),
                                 'lb_status': instance_health.get(instance.id),
                                 'launch_time': parse_time(instance.launch_time)})

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

        with OutputFormat(output):
            print_table(('stack_name version resource_id instance_id public_ip ' +
                         'private_ip state lb_status launch_time').split(), rows, styles=STYLES, titles=TITLES)
Esempio n. 10
0
def list_access_requests(config_file, user, odd_host, status, limit, offset,
                         output, region):
    '''List access requests filtered by user, host and status'''
    config = load_config(config_file)

    if user == '*':
        user = None

    if odd_host == '*':
        odd_host = None
    elif odd_host is None:
        odd_host = piu.utils.find_odd_host(region) or config.get('odd_host')

    access_token = zign.api.get_token('piu', ['piu'])

    params = {
        'username': user,
        'hostname': odd_host,
        'status': status,
        'limit': limit,
        'offset': offset
    }
    r = requests.get(
        config.get('even_url').rstrip('/') + '/access-requests',
        params=params,
        headers={'Authorization': 'Bearer {}'.format(access_token)})
    r.raise_for_status()
    rows = []
    for req in r.json():
        req['created_time'] = parse_time(req['created'])
        rows.append(req)
    rows.sort(key=lambda x: x['created_time'])
    with OutputFormat(output):
        print_table(
            'username hostname remote_host reason lifetime_minutes status status_reason created_time'
            .split(),
            rows,
            styles=STYLES,
            titles=TITLES,
            max_column_widths=MAX_COLUMN_WIDTHS)
Esempio n. 11
0
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. 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 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. 14
0
def issues(config, output):
    '''List open issues'''
    token = config.get('github_access_token')

    repositories = get_repositories()

    rows = []
    for issue in get_my_issues(token):
        if not issue.get('pull_request'):
            repo = repositories.get(issue['repository']['url'])
            if repo:
                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', 'created_time',
            'created_by'
        ], rows)
Esempio n. 15
0
def repositories(config, show_issues, output):
    '''List repositories'''
    token = config.get('github_access_token')

    repositories = get_repositories()

    if show_issues:
        for issue in get_my_issues(token):
            repo = repositories.get(issue['repository']['url'])
            if repo:
                repo['open_issues'] = repo.get('open_issues', 0) + 1
                if issue.get('pull_request'):
                    repo['open_pull_requests'] = repo.get(
                        'open_pull_requests', 0) + 1

    rows = []
    for url, repo in sorted(repositories.items()):
        rows.append(repo)

    with OutputFormat(output):
        columns = ['full_name', 'stargazers_count', 'forks_count']
        if show_issues:
            columns += ['open_issues', 'open_pull_requests']
        print_table(columns, rows)
Esempio n. 16
0
def if_vpc_empty(account: AccountData, region: str):
    ec2 = account.session.resource('ec2', region)
    ec2c = account.session.client('ec2', region)

    def instance_state(instance_id):
        if instance_id:
            return ec2.Instance(id=instance_id).state.get('Name')

    def if_stups_tool(ni: dict):
        instance_id = ni.get('Attachment', {}).get('InstanceId')
        if instance_id:
            instance = ec2.Instance(id=instance_id)
            availability_zones = get_az_names(account.session, region)
            stups_names = ('Odd (SSH Bastion Host)',) + tuple(['NAT {}'.format(x) for x in availability_zones])
            if get_tag(instance.tags, 'Name') in stups_names:
                return True
            if get_tag(instance.tags, 'aws:cloudformation:logical-id') == 'OddServerInstance':
                return True
        allocation_id = ni.get('Association', {}).get('AllocationId')
        if allocation_id:
            for gateway in ec2c.describe_nat_gateways()['NatGateways']:
                if gateway.get('NatGatewayAddresses', {})[0].get('AllocationId') == allocation_id:
                    return True
        return False

    account_is_free = True
    rows = []
    for ni in ec2c.describe_network_interfaces()['NetworkInterfaces']:
        can_remove = if_stups_tool(ni)
        if not can_remove:
            account_is_free = False
        # print(' '.join([str(ni), str(ni.groups), str(ni.attachment), ni.description]))
        rows.append({'network_id': ni.get('NetworkInterfaceId'),
                     'group_name': ', '.join([group['GroupName'] for group in ni.get('Groups')]),
                     'description': ni.get('Description'),
                     'status': ni.get('Attachment', {}).get('Status'),
                     'instance_owner_id': ni.get('Attachment', {}).get('InstanceOwnerId'),
                     'instance_id': ni.get('Attachment', {}).get('InstanceId', ''),
                     'state': instance_state(ni.get('Attachment', {}).get('InstanceId')),
                     'allocation_id': ni.get('Association', {}).get('AllocationId'),
                     'account_name': account.name,
                     'can_remove': '✔' if can_remove else '✘'

                     })
    rows.sort(key=lambda x: (x['account_name'], x['group_name'], x['instance_id']))
    with OutputFormat('text'):
        print_table('''
                    can_remove
                    account_name
                    network_id
                    allocation_id
                    description
                    group_name
                    status
                    instance_owner_id
                    instance_id state
                    '''.split(),
                    rows,
                    styles={
                                'running': {'fg': 'green'},
                                'stopped': {'fg': 'red', 'bold': True},
                                '✔': {'bg': 'green'},
                                '✘': {'bg': 'red', 'bold': True},
                            })

    return account_is_free
Esempio n. 17
0
def inspect_contents(config, team, artifact, tag, url, output, limit):
    '''List image contents (files in tar layers)'''
    set_pierone_url(config, url)
    token = get_token()

    tags = get_tags(config.get('url'), team, artifact, token)

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

    CHUNK_SIZE = 8192
    TYPES = {b'5': 'D', b'0': ' '}

    rows = []
    for t in tag:
        row = request(config.get('url'),
                      '/v2/{}/{}/manifests/{}'.format(team, artifact,
                                                      t), token).json()
        if row.get('layers'):
            layers = reversed([lay.get('digest') for lay in row.get('layers')])
        else:
            layers = [lay.get('blobSum') for lay in row.get('fsLayers')]
        if layers:
            found = 0
            for i, layer in enumerate(layers):
                layer_id = layer
                if layer_id:
                    response = request(
                        config.get('url'),
                        '/v2/{}/{}/blobs/{}'.format(team, artifact,
                                                    layer_id), token)
                    with tempfile.NamedTemporaryFile(prefix='tmp-layer-',
                                                     suffix='.tar') as fd:
                        for chunk in response.iter_content(CHUNK_SIZE):
                            fd.write(chunk)
                        fd.flush()
                        with tarfile.open(fd.name) as archive:
                            has_member = False
                            for member in archive.getmembers():
                                rows.append({
                                    'layer_index': i,
                                    'layer_id': layer_id,
                                    'type': TYPES.get(member.type),
                                    'mode': oct(member.mode)[-4:],
                                    'name': member.name,
                                    'size': member.size,
                                    'created_time': member.mtime
                                })
                                has_member = True
                            if has_member:
                                found += 1
                if found >= limit:
                    break

    rows.sort(key=lambda row: (row['layer_index'], row['name']))
    with OutputFormat(output):
        print_table([
            'layer_index', 'layer_id', 'mode', 'name', 'size', 'created_time'
        ],
                    rows,
                    titles={
                        'created_time': 'Created',
                        'layer_index': 'Idx'
                    },
                    max_column_widths={'layer_id': 16})
Esempio n. 18
0
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 = boto3.resource('cloudformation', region)

    records_by_name = {}

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

            for res in cf.Stack(stack.StackId).resource_summaries.all():
                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]
                        for rec in get_records(zone_name):
                            records_by_name[(rec['Name'].rstrip('.'),
                                             rec.get('SetIdentifier'))] = rec
                    record = records_by_name.get(
                        (name, stack.StackName)) or records_by_name.get(
                            (name, None))
                    row = {
                        'stack_name':
                        stack.name,
                        'version':
                        stack.version,
                        'resource_id':
                        res.logical_id,
                        'domain':
                        res.physical_resource_id,
                        'weight':
                        None,
                        'type':
                        None,
                        'value':
                        None,
                        'create_time':
                        calendar.timegm(res.last_updated_timestamp.timetuple())
                    }
                    if record:
                        row.update({
                            'weight':
                            str(record.get('Weight', '')),
                            'type':
                            record.get('Type'),
                            'value':
                            ','.join([
                                r['Value']
                                for r in record.get('ResourceRecords')
                            ])
                        })
                    rows.append(row)

        with OutputFormat(output):
            print_table(
                'stack_name version resource_id domain weight type value create_time'
                .split(),
                rows,
                styles=STYLES,
                titles=TITLES)
Esempio n. 19
0
def main_list(local):
    ssh_agent_setup.setup()

    repo_path = pygit2.discover_repository(os.getcwd())
    repo = pygit2.Repository(repo_path)

    prune = False  # havn't got the cred callback working

    if prune:
        with Action("Pruning old remotes...") as action:
            for remote in repo.remotes:
                remote.fetch(prune=pygit2.GIT_FETCH_PRUNE,
                             callbacks=SSHAgentCallbacks())
                action.progress()
        # end
    # end

    print(repo.describe())

    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 = []

    for name in info.keys():
        data = info[name]

        if local and not data.local:
            continue

        rows.append({
            "flags":
            "{}{}{}{}.".format(
                "*" if data.head else " ",
                "M" if data.up2date or data.merged else ".",
                "P" if data.pushed else ".",
                "D" if data.gone else ".",
            ),
            "local":
            "local" if data.local else ".....",
            "remote":
            "remote" if data.remote else "......",
            "name":
            name,
            "log":
            first_line(repo[data.target].message),
        })
    # end

    max_width, _ = os.get_terminal_size(0)

    used = 5 + 1 + 5 + 1 + 6 + 1 + 30 + 1
    remaining = max_width - 1 - used

    WIDTHS = {
        "flags": 5,
        "local": 5,
        "remote": 6,
        "name": 30,
        "log": remaining
    }

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

    click.secho(" " * (max_width - 1), fg="black", bg="white")
    print("* = current checkout, M = branch is merged into master")
    print(
        "P = local has been pushed into it's remote, D = No matching upstream branch for local"
    )
Esempio n. 20
0
def instances(stack_ref, all, terminated, docker_image, piu, odd_host, region,
              output, w, watch):
    '''List the stack's EC2 instances'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)

    ec2 = boto3.resource('ec2', region)
    elb = boto3.client('elb', region)

    if all:
        filters = []
    else:
        # filter out instances not part of any stack
        filters = [{
            'Name': 'tag-key',
            'Values': ['aws:cloudformation:stack-name']
        }]

    opt_docker_column = ' docker_source' if docker_image else ''

    for _ in watching(w, watch):
        rows = []

        for instance in ec2.instances.filter(Filters=filters):
            cf_stack_name = get_tag(instance.tags,
                                    'aws:cloudformation:stack-name')
            stack_name = get_tag(instance.tags, 'StackName')
            stack_version = get_tag(instance.tags, 'StackVersion')
            if not stack_refs or matches_any(cf_stack_name, stack_refs):
                instance_health = get_instance_health(elb, cf_stack_name)
                if instance.state['Name'].upper(
                ) != 'TERMINATED' or terminated:

                    docker_source = get_instance_docker_image_source(
                        instance) if docker_image else ''

                    rows.append({
                        'stack_name':
                        stack_name or '',
                        'version':
                        stack_version or '',
                        'resource_id':
                        get_tag(instance.tags,
                                'aws:cloudformation:logical-id'),
                        'instance_id':
                        instance.id,
                        'public_ip':
                        instance.public_ip_address,
                        'private_ip':
                        instance.private_ip_address,
                        'state':
                        instance.state['Name'].upper().replace('-', '_'),
                        'lb_status':
                        instance_health.get(instance.id),
                        'docker_source':
                        docker_source,
                        'launch_time':
                        instance.launch_time.timestamp()
                    })

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

        with OutputFormat(output):
            print_table(
                ('stack_name version resource_id instance_id public_ip ' +
                 'private_ip state lb_status{} launch_time'.format(
                     opt_docker_column)).split(),
                rows,
                styles=STYLES,
                titles=TITLES)

        if piu is not None:
            for row in rows:
                if row['private_ip'] is not None:
                    call([
                        'piu', 'request-access', row['private_ip'],
                        '{} via senza'.format(piu), '-O', odd_host
                    ])
Esempio n. 21
0
def status(stack_ref, region, output, w, watch):
    '''Show stack status information'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)

    ec2 = boto3.resource('ec2', region)
    elb = boto3.client('elb', region)
    cf = boto3.resource('cloudformation', region)

    for _ in watching(w, watch):
        rows = []
        for stack in sorted(get_stacks(stack_refs, region)):
            instance_health = get_instance_health(elb, stack.StackName)

            main_dns_resolves = False
            http_status = None
            for res in cf.Stack(stack.StackId).resource_summaries.all():
                if res.resource_type == 'AWS::Route53::RecordSet':
                    name = res.physical_resource_id
                    if not name:
                        # physical resource ID will be empty during stack creation
                        continue
                    if 'version' in res.logical_id.lower():
                        try:
                            requests.get('https://{}/'.format(name), timeout=2)
                            http_status = 'OK'
                        except:
                            http_status = 'ERROR'
                    else:
                        try:
                            answers = dns.resolver.query(name, 'CNAME')
                        except:
                            answers = []
                        for answer in answers:
                            if answer.target.to_text().startswith('{}-'.format(
                                    stack.StackName)):
                                main_dns_resolves = True

            instances = list(
                ec2.instances.filter(Filters=[{
                    'Name': 'tag:aws:cloudformation:stack-id',
                    'Values': [stack.StackId]
                }]))
            rows.append({
                'stack_name':
                stack.name,
                'version':
                stack.version,
                'status':
                stack.StackStatus,
                'total_instances':
                len(instances),
                'running_instances':
                len([i for i in instances if i.state['Name'] == 'running']),
                'healthy_instances':
                len([i for i in instance_health.values()
                     if i == 'IN_SERVICE']),
                'lb_status':
                ','.join(set(instance_health.values())),
                'main_dns':
                main_dns_resolves,
                'http_status':
                http_status
            })

        with OutputFormat(output):
            print_table((
                'stack_name version status total_instances running_instances healthy_instances '
                + 'lb_status http_status main_dns').split(),
                        rows,
                        styles=STYLES,
                        titles=TITLES)
Esempio n. 22
0
def images(stack_ref, region, output, hide_older_than, show_instances):
    '''Show all used AMIs and available Taupage AMIs'''
    stack_refs = get_stack_refs(stack_ref)
    region = get_region(region)
    check_credentials(region)

    ec2 = boto3.resource('ec2', region)

    instances_by_image = collections.defaultdict(list)
    for inst in ec2.instances.all():
        if inst.state['Name'] == 'terminated':
            # do not count TERMINATED EC2 instances
            continue
        stack_name = get_tag(inst.tags, 'aws:cloudformation:stack-name')
        if not stack_refs or matches_any(stack_name, stack_refs):
            instances_by_image[inst.image_id].append(inst)

    images = {}
    for image in ec2.images.filter(ImageIds=list(instances_by_image.keys())):
        images[image.id] = image
    if not stack_refs:
        filters = [{
            'Name': 'name',
            'Values': ['*Taupage-*']
        }, {
            'Name': 'state',
            'Values': ['available']
        }]
        for image in ec2.images.filter(Filters=filters):
            images[image.id] = image
    rows = []
    cutoff = datetime.datetime.now() - datetime.timedelta(days=hide_older_than)
    for image in images.values():
        row = image.meta.data.copy()
        creation_time = parse_time(image.creation_date)
        row['creation_time'] = creation_time
        row['instances'] = ', '.join(
            sorted(i.id for i in instances_by_image[image.id]))
        row['total_instances'] = len(instances_by_image[image.id])
        stacks = set()
        for instance in instances_by_image[image.id]:
            stack_name = get_tag(instance.tags,
                                 'aws:cloudformation:stack-name')
            # EC2 instance might not be part of a CF stack
            if stack_name:
                stacks.add(stack_name)
        row['stacks'] = ', '.join(sorted(stacks))

        #
        if creation_time > cutoff.timestamp() or row['total_instances']:
            rows.append(row)

    rows.sort(key=lambda x: x.get('Name'))
    with OutputFormat(output):
        cols = 'ImageId Name OwnerId Description stacks total_instances creation_time'
        if show_instances:
            cols = cols.replace('total_instances', 'instances')
        print_table(cols.split(),
                    rows,
                    titles=TITLES,
                    max_column_widths=MAX_COLUMN_WIDTHS)