Skip to content

Commit cb8705c

Browse files
committed
cli: Pygments based output in cloudmonkey and new cfg processing
- Pygments based colored output for tabular and normal list outputs - Fix cfg processing as per new cfg paths and ds - Get rid of clint and old way of parsing and color printing Signed-off-by: Rohit Yadav <bhaisaab@apache.org>
1 parent 233c0ad commit cb8705c

2 files changed

Lines changed: 51 additions & 52 deletions

File tree

tools/cli/cloudmonkey/cloudmonkey.py

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
try:
2121
import atexit
2222
import cmd
23-
import clint
2423
import codecs
2524
import json
2625
import logging
@@ -32,14 +31,15 @@
3231
import time
3332
import types
3433

35-
from clint.textui import colored
3634
from ConfigParser import ConfigParser, SafeConfigParser
3735
from urllib2 import HTTPError, URLError
3836
from httplib import BadStatusLine
3937

4038
from prettytable import PrettyTable
41-
from common import __version__, config_file, config_fields
39+
from common import __version__, config_dir, config_file, config_fields
4240
from common import precached_verbs
41+
from lexer import monkeyprint
42+
4343
from marvin.cloudstackConnection import cloudConnection
4444
from marvin.cloudstackException import cloudstackAPIException
4545
from marvin.cloudstackAPI import *
@@ -70,37 +70,47 @@ class CloudMonkeyShell(cmd.Cmd, object):
7070
intro = ("☁ Apache CloudStack 🐵 cloudmonkey " + __version__ +
7171
". Type help or ? to list commands.\n")
7272
ruler = "="
73+
config_dir = config_dir
7374
config_file = config_file
74-
config_fields = config_fields
7575
# datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
7676
cache_verbs = precached_verbs
77+
config_options = []
7778

7879
def __init__(self, pname, verbs):
7980
self.program_name = pname
8081
self.verbs = verbs
82+
global config_fields
83+
first_time = False
84+
if not os.path.exists(self.config_dir):
85+
os.makedirs(self.config_dir)
8186
if os.path.exists(self.config_file):
8287
config = self.read_config()
8388
else:
84-
for key in self.config_fields.keys():
85-
setattr(self, key, self.config_fields[key])
86-
config = self.write_config()
89+
first_time = True
90+
config = self.write_config(first_time)
91+
92+
for section in config_fields.keys():
93+
for key in config_fields[section].keys():
94+
try:
95+
self.config_options.append(key)
96+
setattr(self, key, config.get(section, key))
97+
except Exception:
98+
print "Please fix `%s` in %s" % (key, self.config_file)
99+
sys.exit()
100+
101+
if first_time:
87102
print "Welcome! Using `set` configure the necessary settings:"
88-
print " ".join(sorted(self.config_fields.keys()))
103+
print " ".join(sorted(self.config_options))
89104
print "Config file:", self.config_file
90105
print "For debugging, tail -f", self.log_file, "\n"
91106

92-
for key in self.config_fields.keys():
93-
try:
94-
setattr(self, key, config.get('CLI', key))
95-
self.config_fields[key] = config.get('CLI', key)
96-
except Exception:
97-
print "Please fix `%s` config in %s" % (key, self.config_file)
98-
sys.exit()
99-
100107
self.prompt = self.prompt.strip() + " " # Cosmetic fix for prompt
108+
101109
logging.basicConfig(filename=self.log_file,
102110
level=logging.DEBUG, format=log_fmt)
103-
logger.debug("Loaded config fields:\n%s" % self.config_fields)
111+
logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" %
112+
(x, getattr(self, x)),
113+
self.config_options))
104114

105115
cmd.Cmd.__init__(self)
106116
if not os.path.exists(self.config_file):
@@ -122,11 +132,16 @@ def read_config(self):
122132
self.print_shell("Error: config_file not found", e)
123133
return config
124134

125-
def write_config(self):
135+
def write_config(self, first_time=False):
136+
global config_fields
126137
config = ConfigParser()
127-
config.add_section('CLI')
128-
for key in self.config_fields.keys():
129-
config.set('CLI', key, getattr(self, key))
138+
for section in config_fields.keys():
139+
config.add_section(section)
140+
for key in config_fields[section].keys():
141+
if first_time:
142+
config.set(section, key, config_fields[section][key])
143+
else:
144+
config.set(section, key, getattr(self, key))
130145
with open(self.config_file, 'w') as cfg:
131146
config.write(cfg)
132147
return config
@@ -144,43 +159,27 @@ def cmdloop(self, intro=None):
144159
print("^C")
145160

146161
def print_shell(self, *args):
162+
output = ""
147163
try:
148164
for arg in args:
149165
arg = str(arg)
150166
if isinstance(type(args), types.NoneType):
151167
continue
152-
if self.color == 'true':
153-
if str(arg).count(self.ruler) == len(str(arg)):
154-
print colored.green(arg),
155-
elif 'Error' in arg:
156-
print colored.red(arg),
157-
elif ":\n=" in arg:
158-
print colored.red(arg),
159-
elif ':' in arg:
160-
print colored.blue(arg),
161-
elif 'type' in arg:
162-
print colored.green(arg),
163-
elif 'state' in arg or 'count' in arg:
164-
print colored.magenta(arg),
165-
elif 'id =' in arg:
166-
print colored.yellow(arg),
167-
elif 'name =' in arg:
168-
print colored.cyan(arg),
169-
else:
170-
print arg,
171-
else:
172-
print arg,
173-
print
168+
output += arg
169+
if self.color == 'true':
170+
monkeyprint(output)
171+
else:
172+
print output
174173
except Exception, e:
175-
print colored.red("Error: "), e
174+
self.print_shell("Error: " + e)
176175

177176
def print_result(self, result, result_filter=None):
178177
if result is None or len(result) == 0:
179178
return
180179

181180
def printer_helper(printer, toprow):
182181
if printer:
183-
print printer
182+
self.print_shell(printer)
184183
return PrettyTable(toprow)
185184

186185
def print_result_tabular(result, result_filter=None):
@@ -201,16 +200,16 @@ def print_result_tabular(result, result_filter=None):
201200
if printer and row:
202201
printer.add_row(row)
203202
if printer:
204-
print printer
203+
self.print_shell(printer)
205204

206205
def print_result_as_dict(result, result_filter=None):
207-
for key in sorted(result.keys(),
208-
key=lambda x: x != 'id' and x != 'count' and x):
206+
for key in sorted(result.keys(), key=lambda x:
207+
x not in ['id', 'count', 'name'] and x):
209208
if not (isinstance(result[key], list) or
210209
isinstance(result[key], dict)):
211210
self.print_shell("%s = %s" % (key, result[key]))
212211
else:
213-
self.print_shell(key + ":\n" + len(key) * self.ruler)
212+
self.print_shell(key + ":")
214213
self.print_result(result[key], result_filter)
215214

216215
def print_result_as_list(result, result_filter=None):
@@ -360,7 +359,7 @@ def default(self, args):
360359
command.required)
361360

362361
if len(missing_args) > 0:
363-
self.print_shell("Missing arguments:", ' '.join(missing_args))
362+
self.print_shell("Missing arguments: ", ' '.join(missing_args))
364363
return
365364

366365
isAsync = False
@@ -441,7 +440,7 @@ def do_set(self, args):
441440
def complete_set(self, text, line, begidx, endidx):
442441
mline = line.partition(" ")[2]
443442
offs = len(mline) - len(text)
444-
return [s[offs:] for s in self.config_fields.keys()
443+
return [s[offs:] for s in self.config_options
445444
if s.startswith(mline)]
446445

447446
def do_shell(self, args):

tools/cli/cloudmonkey/lexer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def get_colorscheme():
5151

5252

5353
class MonkeyLexer(RegexLexer):
54-
keywords = ['[a-z]*id', '[a-zA-Z]*:']
54+
keywords = ['[a-z]*id', '^[a-z A-Z]*:']
5555
attributes = ['[Tt]rue', '[Ff]alse']
5656
params = ['[a-z]*[Nn]ame', 'type', '[Ss]tate']
5757

0 commit comments

Comments
 (0)