diff options
| author | Dean Troyer <dtroyer@gmail.com> | 2012-04-25 16:48:19 -0500 |
|---|---|---|
| committer | Dean Troyer <dtroyer@gmail.com> | 2012-04-25 16:48:19 -0500 |
| commit | 4ceef3b693613eb4968c1e1909165a7c75eb930e (patch) | |
| tree | ad39547484ca90f13d714dd08b55575eb5c93511 /openstackclient/shell.py | |
| parent | 06f82305b56015df6496bf9a2d40ef4f93726454 (diff) | |
| download | python-openstackclient-4ceef3b693613eb4968c1e1909165a7c75eb930e.tar.gz | |
Use cliff
Diffstat (limited to 'openstackclient/shell.py')
| -rw-r--r-- | openstackclient/shell.py | 271 |
1 files changed, 55 insertions, 216 deletions
diff --git a/openstackclient/shell.py b/openstackclient/shell.py index 29ff854f..0aac3646 100644 --- a/openstackclient/shell.py +++ b/openstackclient/shell.py @@ -16,17 +16,23 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 """ -Command-line interface to the OpenStack Identity, Compute and Storage APIs +Command-line interface to the OpenStack APIs """ -import argparse -import httplib2 +import logging +import optparse import os import sys +from cliff.app import App +from cliff.commandmanager import CommandManager + from openstackclient.common import utils +VERSION = '0.1' + + def env(*vars, **kwargs): """Search for the first defined of possibly many env vars @@ -41,265 +47,98 @@ def env(*vars, **kwargs): return kwargs.get('default', '') -class OpenStackShell(object): - - def _find_actions(self, subparsers, actions_module): - if self.debug: - print "_find_actions(module: %s)" % actions_module - for attr in (a for a in dir(actions_module) if a.startswith('do_')): - # I prefer to be hypen-separated instead of underscores. - command = attr[3:].replace('_', '-') - cmd = command.split('-', 1) - action = cmd[0] - if len(cmd) > 1: - subject = cmd[1] - else: - subject = '' - callback = getattr(actions_module, attr) - desc = callback.__doc__ or '' - help = desc.strip().split('\n')[0] - arguments = getattr(callback, 'arguments', []) - - if self.debug: - print " command: %s" % command - print " action: %s" % action - print " subject: %s" % subject - print " arguments: %s" % arguments - - subparser = subparsers.add_parser(command, - help=help, - description=desc, - add_help=False, - formatter_class=OpenStackHelpFormatter +class OpenStackShell(App): + + log = logging.getLogger(__name__) + + def __init__(self): + super(OpenStackShell, self).__init__( + description=__doc__.strip(), + version=VERSION, + command_manager=CommandManager('openstack.cli'), ) - subparser.add_argument('-h', '--help', - action='help', - help=argparse.SUPPRESS, + + def build_option_parser(self, description, version): + parser = super(OpenStackShell, self).build_option_parser( + description, + version, ) - self.subcommands[command] = subparser - for (args, kwargs) in arguments: - subparser.add_argument(*args, **kwargs) - subparser.set_defaults(func=callback) - - @utils.arg('command', metavar='<subcommand>', nargs='?', - help='Display help for <subcommand>') - def do_help(self, args): - """ - Display help about this program or one of its subcommands. - """ - if getattr(args, 'command', None): - if args.command in self.subcommands: - self.subcommands[args.command].print_help() - else: - raise exc.CommandError("'%s' is not a valid subcommand" % - args.command) - else: - self.parser.print_help() - - def get_base_parser(self): - parser = argparse.ArgumentParser( - prog='stack', - description=__doc__.strip(), - epilog='See "stack help COMMAND" ' - 'for help on a specific command.', - add_help=False, - formatter_class=OpenStackHelpFormatter, - ) # Global arguments - parser.add_argument('-h', '--help', - action='store_true', - help=argparse.SUPPRESS, - ) - - parser.add_argument('--os-auth-url', metavar='<auth-url>', + parser.add_option('--os-auth-url', metavar='<auth-url>', default=env('OS_AUTH_URL'), help='Authentication URL (Env: OS_AUTH_URL)') - parser.add_argument('--os-tenant-name', metavar='<auth-tenant-name>', + parser.add_option('--os-tenant-name', metavar='<auth-tenant-name>', default=env('OS_TENANT_NAME'), help='Authentication tenant name (Env: OS_TENANT_NAME)') - parser.add_argument('--os-tenant-id', metavar='<auth-tenant-id>', + parser.add_option('--os-tenant-id', metavar='<auth-tenant-id>', default=env('OS_TENANT_ID'), help='Authentication tenant ID (Env: OS_TENANT_ID)') - parser.add_argument('--os-username', metavar='<auth-username>', + parser.add_option('--os-username', metavar='<auth-username>', default=utils.env('OS_USERNAME'), help='Authentication username (Env: OS_USERNAME)') - parser.add_argument('--os-password', metavar='<auth-password>', + parser.add_option('--os-password', metavar='<auth-password>', default=utils.env('OS_PASSWORD'), help='Authentication password (Env: OS_PASSWORD)') - parser.add_argument('--os-region-name', metavar='<auth-region-name>', + parser.add_option('--os-region-name', metavar='<auth-region-name>', default=env('OS_REGION_NAME'), help='Authentication region name (Env: OS_REGION_NAME)') - parser.add_argument('--debug', - default=False, - action='store_true', - help=argparse.SUPPRESS) - - parser.add_argument('--os-identity-api-version', + parser.add_option('--os-identity-api-version', metavar='<identity-api-version>', default=env('OS_IDENTITY_API_VERSION', default='2.0'), help='Identity API version, default=2.0 (Env: OS_IDENTITY_API_VERSION)') - parser.add_argument('--os-compute-api-version', + parser.add_option('--os-compute-api-version', metavar='<compute-api-version>', default=env('OS_COMPUTE_API_VERSION', default='2'), help='Compute API version, default=2.0 (Env: OS_COMPUTE_API_VERSION)') - parser.add_argument('--os-image-api-version', + parser.add_option('--os-image-api-version', metavar='<image-api-version>', default=env('OS_IMAGE_API_VERSION', default='1.0'), help='Image API version, default=1.0 (Env: OS_IMAGE_API_VERSION)') - parser.add_argument('--service-token', metavar='<service-token>', + parser.add_option('--service-token', metavar='<service-token>', default=env('SERVICE_TOKEN'), - help=argparse.SUPPRESS) + help='deprecated') - parser.add_argument('--service-endpoint', metavar='<service-endpoint>', + parser.add_option('--service-endpoint', metavar='<service-endpoint>', default=env('SERVICE_ENDPOINT'), - help=argparse.SUPPRESS) - - parser.add_argument('action', metavar='<action>', - default='help', - help=argparse.SUPPRESS) - - parser.add_argument('subject', metavar='<subject>', - default='', nargs='?', - help=argparse.SUPPRESS) + help='deprecated') return parser - def get_subcommand_parser(self, cmd_subject): - parser = self.get_base_parser() - - self.subcommands = {} - subparsers = parser.add_subparsers(metavar='<subcommand>') - - if cmd_subject is None or cmd_subject == '': - # TODO(dtroyer): iterate over all known subjects to produce - # the complete help list - print "Get all subjects here - exit" - exit(1) - - (module, version) = self._map_subject(cmd_subject) - if module is None or cmd_subject is None: - print "Module %s not found - exit" % cmd_subject - exit(1) - if self.debug: - print "module: %s" % module - exec("from %s.v%s import %s as cmd" % (module, self.api_version[module], cmd_subject)) - self._find_actions(subparsers, cmd) - - self._find_actions(subparsers, self) - - return parser - - def _map_subject(self, cmd_subject): - '''Convert from subject to the module that implements it''' - COMPUTE = ['server'] - IDENTITY = ['key'] - IMAGE = ['image'] - if cmd_subject in COMPUTE: - version = self.api_version['compute'].replace('.', '_') - return ('compute', version) - elif cmd_subject in IDENTITY: - version = self.api_version['identity'].replace('.', '_') - return ('identity', version) - elif cmd_subject in IMAGE: - version = self.api_version['imade'].replace('.', '_') - return ('image', version) - else: - return None - - def main(self, argv): - ''' - - get api version - - get version command set - - import version-subject module - - is verb-subject supported? - ''' - # Parse global args to find version - parser = self.get_base_parser() - (options, args) = parser.parse_known_args(argv) + def prepare_to_run_command(self, cmd): + """Set up auth and API versions""" + self.log.debug('prepare_to_run_command %s', cmd.__class__.__name__) # stash selected API versions for later # TODO(dtroyer): how do extenstions add their version requirements? self.api_version = { - 'compute': options.os_compute_api_version, - 'identity': options.os_identity_api_version, - 'image': options.os_image_api_version, + 'compute': self.options.os_compute_api_version, + 'identity': self.options.os_identity_api_version, + 'image': self.options.os_image_api_version, } - # Setup debugging - if getattr(options, 'debug', None): - self.debug = 1 - else: - self.debug = 0 - - if self.debug: + if self.options.debug: print "API: Identity=%s Compute=%s Image=%s" % (self.api_version['identity'], self.api_version['compute'], self.api_version['image']) - print "Action: %s" % options.action - print "subject: %s" % getattr(options, 'subject', '') - print "args: %s" % args - - # Handle top-level --help/-h before attempting to parse - # a command off the command line - if getattr(options, 'help', None) or getattr(options, 'action', None) == 'help': - print "top-level help" - # Build available subcommands - self.parser = self.get_subcommand_parser(options.subject) - self.do_help(options) - return 0 - - # Build selected subcommands - self.parser = self.get_subcommand_parser(options.subject) - - # Parse args again and call whatever callback was selected - args.insert(0, '%s-%s' % (options.action, options.subject)) - if self.debug: - print "args: %s" % args - args = self.parser.parse_args(args) - - if self.debug: - print "Testing command parsing" - print "Auth username: %s" % options.os_username - #print "Action: %s" % options.action - #print "Subject: %s" % options.subject - print "args: %s" % args - -class OpenStackHelpFormatter(argparse.HelpFormatter): - def start_section(self, heading): - # Title-case the headings - heading = '%s%s' % (heading[0].upper(), heading[1:]) - super(OpenStackHelpFormatter, self).start_section(heading) - - -def main(): - try: - OpenStackShell().main(sys.argv[1:]) - - except Exception, e: - if httplib2.debuglevel == 1: - raise # dump stack. - else: - print >> sys.stderr, e - sys.exit(1) - -def test_main(argv): - # The argparse/optparse/cmd2 modules muck about with sys.argv - # so we save it and restore at the end to let the tests - # run repeatedly without concatenating the args on each run - save_argv = sys.argv - - main() - - # Put it back so the next test has a clean copy - sys.argv = save_argv + print "cmd: %s" % cmd + + def clean_up(self, cmd, result, err): + self.log.debug('clean_up %s', cmd.__class__.__name__) + if err: + self.log.debug('got an error: %s', err) + + +def main(argv=sys.argv[1:]): + return OpenStackShell().run(argv) + if __name__ == "__main__": - main() + sys.exit(main(sys.argv[1:])) |
