mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-545: Tabularize cloudmonkey's response using filter=<fields,> argument
- Adds new cloudmonkey config field, tabularize - If tabularize is set to true, all the list of dict in response are printed as table - The columns of the tables can be filtered using the filter= argument, for ex: list domains listall=true filter=id,name,path - filter arg will take comma separated values, if they have space put them under quotes - Empty filter argument will cause it to print the whole table - Multiple fields with the same name will cause it to print the column again - In case there is a typo in the field, that column is skipped. It takes an intersection of response dict keys and filter keys provided - Uses opensource prettytable library to pretty print tabular data TODOs: - Handle recursive table printing for nested list of dicts - Colorize table columns if community wants such a feature Signed-off-by: Rohit Yadav <bhaisaab@apache.org>
This commit is contained in:
parent
264a0670a8
commit
8f51c630bd
@ -37,6 +37,7 @@ try:
|
||||
from urllib2 import HTTPError, URLError
|
||||
from httplib import BadStatusLine
|
||||
|
||||
from prettytable import PrettyTable
|
||||
from common import __version__, config_file, config_fields
|
||||
from common import grammar, precached_verbs
|
||||
from marvin.cloudstackConnection import cloudConnection
|
||||
@ -173,29 +174,58 @@ class CloudStackShell(cmd.Cmd, object):
|
||||
except Exception, e:
|
||||
print colored.red("Error: "), e
|
||||
|
||||
def print_result(self, result):
|
||||
def print_result(self, result, result_filter=None):
|
||||
if result is None or len(result) == 0:
|
||||
return
|
||||
|
||||
def print_result_as_dict(result):
|
||||
def printer_helper(printer, toprow):
|
||||
if printer:
|
||||
print printer
|
||||
return PrettyTable(toprow)
|
||||
|
||||
def print_result_tabular(result, result_filter=None):
|
||||
toprow = None
|
||||
printer = None
|
||||
for node in result:
|
||||
if toprow != node.keys():
|
||||
if result_filter is not None and len(result_filter) != 0:
|
||||
commonkeys = filter(lambda x: x in node.keys(),
|
||||
result_filter)
|
||||
if commonkeys != toprow:
|
||||
toprow = commonkeys
|
||||
printer = printer_helper(printer, toprow)
|
||||
else:
|
||||
toprow = node.keys()
|
||||
printer = printer_helper(printer, toprow)
|
||||
row = map(lambda x: node[x], toprow)
|
||||
if printer and row:
|
||||
printer.add_row(row)
|
||||
if printer:
|
||||
print printer
|
||||
|
||||
def print_result_as_dict(result, result_filter=None):
|
||||
for key in result.keys():
|
||||
if not (isinstance(result[key], list) or
|
||||
isinstance(result[key], dict)):
|
||||
self.print_shell("%s = %s" % (key, result[key]))
|
||||
else:
|
||||
self.print_shell(key + ":\n" + len(key) * "=")
|
||||
self.print_result(result[key])
|
||||
self.print_shell(key + ":\n" + len(key) * self.ruler)
|
||||
self.print_result(result[key], result_filter)
|
||||
|
||||
def print_result_as_list(result):
|
||||
def print_result_as_list(result, result_filter=None):
|
||||
for node in result:
|
||||
# Tabular print if it's a list of dict and tabularize is true
|
||||
if isinstance(node, dict) and self.tabularize == 'true':
|
||||
print_result_tabular(result, result_filter)
|
||||
break
|
||||
self.print_result(node)
|
||||
if len(result) > 1:
|
||||
self.print_shell(self.ruler * 80)
|
||||
|
||||
if isinstance(result, dict):
|
||||
print_result_as_dict(result)
|
||||
print_result_as_dict(result, result_filter)
|
||||
elif isinstance(result, list):
|
||||
print_result_as_list(result)
|
||||
print_result_as_list(result, result_filter)
|
||||
elif isinstance(result, str):
|
||||
print result
|
||||
elif not (str(result) is None):
|
||||
@ -281,6 +311,11 @@ class CloudStackShell(cmd.Cmd, object):
|
||||
args_dict = dict(map(lambda x: [x.partition("=")[0],
|
||||
x.partition("=")[2]],
|
||||
args[1:])[x] for x in range(len(args) - 1))
|
||||
field_filter = None
|
||||
if 'filter' in args_dict:
|
||||
field_filter = filter(lambda x: x is not '',
|
||||
map(lambda x: x.strip(),
|
||||
args_dict.pop('filter').split(',')))
|
||||
|
||||
api_cmd_str = "%sCmd" % api_name
|
||||
api_mod = self.get_api_module(api_name, [api_cmd_str])
|
||||
@ -313,7 +348,8 @@ class CloudStackShell(cmd.Cmd, object):
|
||||
return
|
||||
try:
|
||||
# Response is in the key "apiname+response" (lowercase)
|
||||
self.print_result(result[api_name.lower()+'response'])
|
||||
self.print_result(result[api_name.lower() + 'response'],
|
||||
field_filter)
|
||||
print
|
||||
except Exception as e:
|
||||
self.print_shell("🙈 Error on parsing and printing", e)
|
||||
@ -367,6 +403,7 @@ class CloudStackShell(cmd.Cmd, object):
|
||||
self.cache_verbs[verb][subject][1])
|
||||
search_string = text
|
||||
|
||||
autocompletions.append("filter=")
|
||||
return [s for s in autocompletions if s.startswith(search_string)]
|
||||
|
||||
def do_api(self, args):
|
||||
@ -496,7 +533,6 @@ def main():
|
||||
try:
|
||||
args_partition = args.partition(" ")
|
||||
res = self.cache_verbs[rule][args_partition[0]]
|
||||
|
||||
except KeyError, e:
|
||||
self.print_shell("Error: invalid %s api arg" % rule, e)
|
||||
return
|
||||
|
||||
@ -33,6 +33,7 @@ config_fields = {'host': 'localhost', 'port': '8080',
|
||||
'apikey': '', 'secretkey': '',
|
||||
'timeout': '3600', 'asyncblock': 'true',
|
||||
'prompt': '🐵 cloudmonkey>', 'color': 'true',
|
||||
'tabularize': 'false',
|
||||
'log_file':
|
||||
os.path.expanduser('~/.cloudmonkey_log'),
|
||||
'history_file':
|
||||
|
||||
@ -26,7 +26,9 @@ from cloudmonkey import __version__
|
||||
|
||||
name = 'cloudmonkey'
|
||||
version = __version__
|
||||
requires = ['clint>=0.3.0',]
|
||||
requires = ['clint>=0.3.0',
|
||||
'prettytable>=0.5',
|
||||
]
|
||||
|
||||
try:
|
||||
import readline
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user