Skip to content

Commit

Permalink
Merge pull request #91 from jathanism/display-improvements
Browse files Browse the repository at this point in the history
Improved support for displaying objects via the CLI utility.
  • Loading branch information
vanilladuck committed Mar 16, 2016
2 parents c810872 + 43b3723 commit f3a9ee5
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 21 deletions.
35 changes: 31 additions & 4 deletions pynsot/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import logging
import os
import sys
import textwrap

import pynsot
from . import client
Expand All @@ -25,7 +26,7 @@
__author__ = 'Jathan McCollum'
__maintainer__ = 'Jathan McCollum'
__email__ = 'jathan@dropbox.com'
__copyright__ = 'Copyright (c) 2015 Dropbox, Inc.'
__copyright__ = 'Copyright (c) 2015-2016 Dropbox, Inc.'


# Constants/Globals
Expand Down Expand Up @@ -53,16 +54,17 @@
'devices': ['hostname'],
'networks': ['cidr'],
'attributes': ['name', 'resource_name'],
# 'interfaces': ['name', 'device'],
'interfaces': ['name', 'device'],
}

# Mapping of resource_names to what we want objects to look like when formatted
# to stdout for grep-friendliness. These are string interpolation style.
GREP_FORMATS = {
'devices': '%(hostname)s',
'networks': '%(network_address)s/%(prefix_length)s',
'attributes': '%(name)s:%(resource_name)s',
'attributes': '%(resource_name)s:%(name)s',
'interfaces': '%(device)s:%(name)s',
'sites': '%(name)s',
}


Expand Down Expand Up @@ -306,6 +308,10 @@ def format_field(self, field, field_data):
if field == 'user':
field_data = field_data['email']

# Arbitrarily wrap description field at 20 chars
if field == 'description':
field_data = '\n'.join(textwrap.wrap(field_data, 20))

# If the field is a dict, pretty_dict it!
if isinstance(field_data, dict):
# If this is an inner dict, prettify it, too.
Expand Down Expand Up @@ -360,6 +366,24 @@ def print_grep(self, objects):

click.echo('\n'.join(output))

def print_by_natural_key(self, objects):
"""
Print a list of objects by their natural_key
:param objects:
List of objects
"""
output = []
for obj in objects:
output.append(self.format_object_for_grep(obj))

# Networks results are already sorted, so don't re-sort them,
# because it gets screwed up.
if self.resource_name != 'networks':
output = sorted(output)

click.echo('\n'.join(output))

def print_list(self, objects, display_fields):
"""
Print a list of objects in a table format.
Expand Down Expand Up @@ -397,7 +421,7 @@ def print_list(self, objects, display_fields):
table = prettytable.PrettyTable(headers)

# Display table in a frame
table.vrules = prettytable.FRAME
table.vrules = prettytable.prettytable.FRAME

# *or* Display table with row separators
# table.hrules = prettytable.ALL
Expand Down Expand Up @@ -549,6 +573,7 @@ def list(self, data, display_fields=None, resource=None,
obj_id = data.get('id') # If obj_id, it's a single object

grep = data.pop('grep', False)
by_natural_key = data.pop('natural_key', False)

# If a resource object is provided, call it instead, and only rebase if
# we haven't provided our own resource.
Expand Down Expand Up @@ -599,6 +624,8 @@ def list(self, data, display_fields=None, resource=None,
objects = self.get_paginated_results(objects)
if grep:
self.print_grep(objects)
elif by_natural_key:
self.print_by_natural_key(objects)
else:
self.print_list(objects, display_fields)
else:
Expand Down
14 changes: 10 additions & 4 deletions pynsot/commands/cmd_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@
('id', 'ID'),
('name', 'Name'),
('resource_name', 'Resource'),
# ('site_id': 'Site ID'),
('required', 'Required?'),
('display', 'Display?'),
('multi', 'Multi?'),
('description', 'Description'),
)
Expand Down Expand Up @@ -197,6 +195,14 @@ def add(ctx, allow_empty, bulk_add, description, display, multi, name, pattern,
metavar='NAME',
help='Filter to Attribute with this name.',
)
@click.option(
'-N',
'--natural-key',
is_flag=True,
help='Display list results by their natural key',
default=False,
show_default=True,
)
@click.option(
'-o',
'--offset',
Expand Down Expand Up @@ -225,8 +231,8 @@ def add(ctx, allow_empty, bulk_add, description, display, multi, name, pattern,
callback=callbacks.process_site_id,
)
@click.pass_context
def list(ctx, id, display, limit, multi, name, offset, required, resource_name,
site_id):
def list(ctx, id, display, limit, multi, name, natural_key, offset, required,
resource_name, site_id):
"""
List existing Attributes for a Site.
Expand Down
12 changes: 10 additions & 2 deletions pynsot/commands/cmd_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,14 @@ def add(ctx, attributes, bulk_add, hostname, site_id):
type=int,
help='Unique ID of the Device being retrieved.',
)
@click.option(
'-N',
'--natural-key',
is_flag=True,
help='Display list results by their natural key',
default=False,
show_default=True,
)
@click.option(
'-l',
'--limit',
Expand Down Expand Up @@ -171,8 +179,8 @@ def add(ctx, attributes, bulk_add, hostname, site_id):
callback=callbacks.process_site_id,
)
@click.pass_context
def list(ctx, attributes, delimited, grep, hostname, id, limit, offset, query,
site_id):
def list(ctx, attributes, delimited, grep, hostname, id, limit, natural_key,
offset, query, site_id):
"""
List existing Devices for a Site.
Expand Down
12 changes: 10 additions & 2 deletions pynsot/commands/cmd_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def add(ctx, attributes, bulk_add, device_id, name):
@click.option(
'-e',
'--description',
metavar='DESCRIPTOIN',
metavar='DESCRIPTION',
type=str,
help='Filter by Interfaces matching this description.',
)
Expand Down Expand Up @@ -180,6 +180,14 @@ def add(ctx, attributes, bulk_add, device_id, name):
metavar='NAME',
help='Filter to Interfaces matching this name.'
)
@click.option(
'-N',
'--natural-key',
is_flag=True,
help='Display list results by their natural key',
default=False,
show_default=True,
)
@click.option(
'-o',
'--offset',
Expand Down Expand Up @@ -222,7 +230,7 @@ def add(ctx, attributes, bulk_add, device_id, name):
)
@click.pass_context
def list(ctx, attributes, delimited, device, description, grep, id, limit,
name, offset, parent_id, query, site_id, speed, type):
name, natural_key, offset, parent_id, query, site_id, speed, type):
"""
List existing Interfaces for a Site.
Expand Down
12 changes: 10 additions & 2 deletions pynsot/commands/cmd_networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ def add(ctx, attributes, bulk_add, cidr, state, site_id):
metavar='NETWORK',
help='Filter to Networks matching this network address.',
)
@click.option(
'-N',
'--natural-key',
is_flag=True,
help='Display list results by their natural key',
default=False,
show_default=True,
)
@click.option(
'-o',
'--offset',
Expand Down Expand Up @@ -236,8 +244,8 @@ def add(ctx, attributes, bulk_add, cidr, state, site_id):
)
@click.pass_context
def list(ctx, attributes, cidr, delimited, grep, id, include_ips,
include_networks, ip_version, limit, network_address, offset,
prefix_length, query, root_only, state, site_id):
include_networks, ip_version, limit, network_address, natural_key,
offset, prefix_length, query, root_only, state, site_id):
"""
List existing Networks for a Site.
Expand Down
10 changes: 9 additions & 1 deletion pynsot/commands/cmd_sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ def add(ctx, description, name):
metavar='NAME',
help='Filter by Site name.'
)
@click.option(
'-N',
'--natural-key',
is_flag=True,
help='Display list results by their natural key',
default=False,
show_default=True,
)
@click.option(
'-o',
'--offset',
Expand All @@ -110,7 +118,7 @@ def add(ctx, description, name):
help='Skip the first N resources.',
)
@click.pass_context
def list(ctx, id, limit, name, offset):
def list(ctx, id, limit, name, natural_key, offset):
"""
List existing Sites.
Expand Down
2 changes: 1 addition & 1 deletion pynsot/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.19.3'
__version__ = '0.19.4'
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
click==6.2
prettytable==0.7.2
PTable==0.9.2
rcfile==0.1.4
requests==2.5.1
slumber==0.7.1
27 changes: 23 additions & 4 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,21 @@ def test_sites_list(client, site):
assert result.exit_code == 0
assert site['name'] in result.output

# Test -i
# Test -i/--id
result = runner.run('sites list -i %s' % site['id'])
assert result.exit_code == 0
assert site['name'] in result.output

# Test -n
# Test -n/--name
result = runner.run('sites list -n %s' % site['name'])
assert result.exit_code == 0
assert site['name'] in result.output

# Test -N/--natural-key
result = runner.run('sites list -N')
assert result.exit_code == 0
assert site['name'] == result.output.strip()


def test_sites_update(client, site):
"""Test ``nsot sites update``."""
Expand Down Expand Up @@ -127,6 +132,11 @@ def test_attributes_list(site_client):
result = runner.run('attributes list')
assert result.exit_code == 0

# Test -N/--natural-key
result = runner.run('attributes list -N')
assert result.exit_code == 0
assert 'Device:monitored\n' == result.output

# List a single attribute by name
attr = site_client.attributes.get(name='monitored')[0]
name_result = runner.run('attributes list -n monitored')
Expand Down Expand Up @@ -261,6 +271,11 @@ def test_devices_list(site_client):
assert result.exit_code == 0
assert result.output == expected_output

# Test -N/--natural-key
result = runner.run('devices list -N')
assert result.exit_code == 0
assert result.output == expected_output # Same output as above

# Set query display comma-delimited (-d/--delimited)
result = runner.run('devices list -q owner=jathan -d')
expected_output = 'foo-bar1,foo-bar2\n'
Expand Down Expand Up @@ -489,6 +504,11 @@ def test_networks_list(site_client):
assert result.exit_code == 0
assert result.output == expected_output

# Test -N/--natural-key
result = runner.run('networks list -N')
assert result.exit_code == 0
assert result.output == expected_output # Same output as above

# Set query display comma-delimited (-d/--delimited)
result = runner.run('networks list -q owner=jathan -d')
expected_output = '10.0.0.0/8,10.0.0.0/24\n'
Expand Down Expand Up @@ -570,12 +590,11 @@ def test_networks_remove(site_client, network):
assert 'Removed network!' in result.output



##########
# Values #
##########
def test_values_list(site_client):
"""Test ``nsot devices list -n owner -r device``."""
"""Test ``nsot values list``."""
runner = CliRunner(site_client.config)
with runner.isolated_filesystem():
# Create the owner attribute
Expand Down

0 comments on commit f3a9ee5

Please sign in to comment.