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)
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)
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)
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')
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'})
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)
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' })
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)
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)
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)
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)
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.' })
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)
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' })
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
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
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
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
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' })
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
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})
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)
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)
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)
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' })
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)
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)
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()
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
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)