mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									233c0adcf3
								
							
						
					
					
						commit
						cb8705c756
					
				@ -20,7 +20,6 @@
 | 
			
		||||
try:
 | 
			
		||||
    import atexit
 | 
			
		||||
    import cmd
 | 
			
		||||
    import clint
 | 
			
		||||
    import codecs
 | 
			
		||||
    import json
 | 
			
		||||
    import logging
 | 
			
		||||
@ -32,14 +31,15 @@ try:
 | 
			
		||||
    import time
 | 
			
		||||
    import types
 | 
			
		||||
 | 
			
		||||
    from clint.textui import colored
 | 
			
		||||
    from ConfigParser import ConfigParser, SafeConfigParser
 | 
			
		||||
    from urllib2 import HTTPError, URLError
 | 
			
		||||
    from httplib import BadStatusLine
 | 
			
		||||
 | 
			
		||||
    from prettytable import PrettyTable
 | 
			
		||||
    from common import __version__, config_file, config_fields
 | 
			
		||||
    from common import __version__, config_dir, config_file, config_fields
 | 
			
		||||
    from common import precached_verbs
 | 
			
		||||
    from lexer import monkeyprint
 | 
			
		||||
 | 
			
		||||
    from marvin.cloudstackConnection import cloudConnection
 | 
			
		||||
    from marvin.cloudstackException import cloudstackAPIException
 | 
			
		||||
    from marvin.cloudstackAPI import *
 | 
			
		||||
@ -70,37 +70,47 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
    intro = ("☁ Apache CloudStack 🐵 cloudmonkey " + __version__ +
 | 
			
		||||
             ". Type help or ? to list commands.\n")
 | 
			
		||||
    ruler = "="
 | 
			
		||||
    config_dir = config_dir
 | 
			
		||||
    config_file = config_file
 | 
			
		||||
    config_fields = config_fields
 | 
			
		||||
    # datastructure {'verb': {cmd': ['api', [params], doc, required=[]]}}
 | 
			
		||||
    cache_verbs = precached_verbs
 | 
			
		||||
    config_options = []
 | 
			
		||||
 | 
			
		||||
    def __init__(self, pname, verbs):
 | 
			
		||||
        self.program_name = pname
 | 
			
		||||
        self.verbs = verbs
 | 
			
		||||
        global config_fields
 | 
			
		||||
        first_time = False
 | 
			
		||||
        if not os.path.exists(self.config_dir):
 | 
			
		||||
            os.makedirs(self.config_dir)
 | 
			
		||||
        if os.path.exists(self.config_file):
 | 
			
		||||
            config = self.read_config()
 | 
			
		||||
        else:
 | 
			
		||||
            for key in self.config_fields.keys():
 | 
			
		||||
                setattr(self, key, self.config_fields[key])
 | 
			
		||||
            config = self.write_config()
 | 
			
		||||
            first_time = True
 | 
			
		||||
            config = self.write_config(first_time)
 | 
			
		||||
 | 
			
		||||
        for section in config_fields.keys():
 | 
			
		||||
            for key in config_fields[section].keys():
 | 
			
		||||
                try:
 | 
			
		||||
                    self.config_options.append(key)
 | 
			
		||||
                    setattr(self, key, config.get(section, key))
 | 
			
		||||
                except Exception:
 | 
			
		||||
                    print "Please fix `%s` in %s" % (key, self.config_file)
 | 
			
		||||
                    sys.exit()
 | 
			
		||||
 | 
			
		||||
        if first_time:
 | 
			
		||||
            print "Welcome! Using `set` configure the necessary settings:"
 | 
			
		||||
            print " ".join(sorted(self.config_fields.keys()))
 | 
			
		||||
            print " ".join(sorted(self.config_options))
 | 
			
		||||
            print "Config file:", self.config_file
 | 
			
		||||
            print "For debugging, tail -f", self.log_file, "\n"
 | 
			
		||||
 | 
			
		||||
        for key in self.config_fields.keys():
 | 
			
		||||
            try:
 | 
			
		||||
                setattr(self, key, config.get('CLI', key))
 | 
			
		||||
                self.config_fields[key] = config.get('CLI', key)
 | 
			
		||||
            except Exception:
 | 
			
		||||
                print "Please fix `%s` config in %s" % (key, self.config_file)
 | 
			
		||||
                sys.exit()
 | 
			
		||||
 | 
			
		||||
        self.prompt = self.prompt.strip() + " "  # Cosmetic fix for prompt
 | 
			
		||||
 | 
			
		||||
        logging.basicConfig(filename=self.log_file,
 | 
			
		||||
                            level=logging.DEBUG, format=log_fmt)
 | 
			
		||||
        logger.debug("Loaded config fields:\n%s" % self.config_fields)
 | 
			
		||||
        logger.debug("Loaded config fields:\n%s" % map(lambda x: "%s=%s" %
 | 
			
		||||
                                                       (x, getattr(self, x)),
 | 
			
		||||
                                                       self.config_options))
 | 
			
		||||
 | 
			
		||||
        cmd.Cmd.__init__(self)
 | 
			
		||||
        if not os.path.exists(self.config_file):
 | 
			
		||||
@ -122,11 +132,16 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
            self.print_shell("Error: config_file not found", e)
 | 
			
		||||
        return config
 | 
			
		||||
 | 
			
		||||
    def write_config(self):
 | 
			
		||||
    def write_config(self, first_time=False):
 | 
			
		||||
        global config_fields
 | 
			
		||||
        config = ConfigParser()
 | 
			
		||||
        config.add_section('CLI')
 | 
			
		||||
        for key in self.config_fields.keys():
 | 
			
		||||
            config.set('CLI', key, getattr(self, key))
 | 
			
		||||
        for section in config_fields.keys():
 | 
			
		||||
            config.add_section(section)
 | 
			
		||||
            for key in config_fields[section].keys():
 | 
			
		||||
                if first_time:
 | 
			
		||||
                    config.set(section, key, config_fields[section][key])
 | 
			
		||||
                else:
 | 
			
		||||
                    config.set(section, key, getattr(self, key))
 | 
			
		||||
        with open(self.config_file, 'w') as cfg:
 | 
			
		||||
            config.write(cfg)
 | 
			
		||||
        return config
 | 
			
		||||
@ -144,35 +159,19 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
                print("^C")
 | 
			
		||||
 | 
			
		||||
    def print_shell(self, *args):
 | 
			
		||||
        output = ""
 | 
			
		||||
        try:
 | 
			
		||||
            for arg in args:
 | 
			
		||||
                arg = str(arg)
 | 
			
		||||
                if isinstance(type(args), types.NoneType):
 | 
			
		||||
                    continue
 | 
			
		||||
                if self.color == 'true':
 | 
			
		||||
                    if str(arg).count(self.ruler) == len(str(arg)):
 | 
			
		||||
                        print colored.green(arg),
 | 
			
		||||
                    elif 'Error' in arg:
 | 
			
		||||
                        print colored.red(arg),
 | 
			
		||||
                    elif ":\n=" in arg:
 | 
			
		||||
                        print colored.red(arg),
 | 
			
		||||
                    elif ':' in arg:
 | 
			
		||||
                        print colored.blue(arg),
 | 
			
		||||
                    elif 'type' in arg:
 | 
			
		||||
                        print colored.green(arg),
 | 
			
		||||
                    elif 'state' in arg or 'count' in arg:
 | 
			
		||||
                        print colored.magenta(arg),
 | 
			
		||||
                    elif 'id =' in arg:
 | 
			
		||||
                        print colored.yellow(arg),
 | 
			
		||||
                    elif 'name =' in arg:
 | 
			
		||||
                        print colored.cyan(arg),
 | 
			
		||||
                    else:
 | 
			
		||||
                        print arg,
 | 
			
		||||
                else:
 | 
			
		||||
                    print arg,
 | 
			
		||||
            print
 | 
			
		||||
                output += arg
 | 
			
		||||
            if self.color == 'true':
 | 
			
		||||
                monkeyprint(output)
 | 
			
		||||
            else:
 | 
			
		||||
                print output
 | 
			
		||||
        except Exception, e:
 | 
			
		||||
            print colored.red("Error: "), e
 | 
			
		||||
            self.print_shell("Error: " + e)
 | 
			
		||||
 | 
			
		||||
    def print_result(self, result, result_filter=None):
 | 
			
		||||
        if result is None or len(result) == 0:
 | 
			
		||||
@ -180,7 +179,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
 | 
			
		||||
        def printer_helper(printer, toprow):
 | 
			
		||||
            if printer:
 | 
			
		||||
                print printer
 | 
			
		||||
                self.print_shell(printer)
 | 
			
		||||
            return PrettyTable(toprow)
 | 
			
		||||
 | 
			
		||||
        def print_result_tabular(result, result_filter=None):
 | 
			
		||||
@ -201,16 +200,16 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
                if printer and row:
 | 
			
		||||
                    printer.add_row(row)
 | 
			
		||||
            if printer:
 | 
			
		||||
                print printer
 | 
			
		||||
                self.print_shell(printer)
 | 
			
		||||
 | 
			
		||||
        def print_result_as_dict(result, result_filter=None):
 | 
			
		||||
            for key in sorted(result.keys(),
 | 
			
		||||
                              key=lambda x: x != 'id' and x != 'count' and x):
 | 
			
		||||
            for key in sorted(result.keys(), key=lambda x:
 | 
			
		||||
                              x not in ['id', 'count', 'name'] and x):
 | 
			
		||||
                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.ruler)
 | 
			
		||||
                    self.print_shell(key + ":")
 | 
			
		||||
                    self.print_result(result[key], result_filter)
 | 
			
		||||
 | 
			
		||||
        def print_result_as_list(result, result_filter=None):
 | 
			
		||||
@ -360,7 +359,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
                              command.required)
 | 
			
		||||
 | 
			
		||||
        if len(missing_args) > 0:
 | 
			
		||||
            self.print_shell("Missing arguments:", ' '.join(missing_args))
 | 
			
		||||
            self.print_shell("Missing arguments: ", ' '.join(missing_args))
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        isAsync = False
 | 
			
		||||
@ -441,7 +440,7 @@ class CloudMonkeyShell(cmd.Cmd, object):
 | 
			
		||||
    def complete_set(self, text, line, begidx, endidx):
 | 
			
		||||
        mline = line.partition(" ")[2]
 | 
			
		||||
        offs = len(mline) - len(text)
 | 
			
		||||
        return [s[offs:] for s in self.config_fields.keys()
 | 
			
		||||
        return [s[offs:] for s in self.config_options
 | 
			
		||||
                if s.startswith(mline)]
 | 
			
		||||
 | 
			
		||||
    def do_shell(self, args):
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ def get_colorscheme():
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MonkeyLexer(RegexLexer):
 | 
			
		||||
    keywords = ['[a-z]*id', '[a-zA-Z]*:']
 | 
			
		||||
    keywords = ['[a-z]*id', '^[a-z A-Z]*:']
 | 
			
		||||
    attributes = ['[Tt]rue', '[Ff]alse']
 | 
			
		||||
    params = ['[a-z]*[Nn]ame', 'type', '[Ss]tate']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user