def create_parser(self, command_name=None, parent_usage=None): """ Create an instance of option parser :rtype: OptionParser """ parser = OptionParser(option_class=KatelloOption) self.setup_parser(parser) parser.set_usage(self.usage(command_name, parent_usage)) return parser
def setup_parser(self): """ Add options to the command line parser. @note: this method may be overridden to define new options """ self.parser = OptionParser() self.parser.disable_interspersed_args() self.parser.set_usage(self.usage) credentials = OptionGroup(self.parser, _('Katello User Account Credentials')) credentials.add_option('-u', '--username', dest='username', default=None, help=_('account username')) credentials.add_option('-p', '--password', dest='password', default=None, help=_('account password')) credentials.add_option('--cert-file', dest='certfile', default=None, help=SUPPRESS_HELP) credentials.add_option('--key-file', dest='keyfile', default=None, help=SUPPRESS_HELP) self.parser.add_option_group(credentials) server = OptionGroup(self.parser, _('Katello Server Information')) host = Config.parser.get('server', 'host') or 'localhost.localdomain' server.add_option('--host', dest='host', default=host, help=_('katello server host name (default: %s)') % host) port = Config.parser.get('server', 'port') or '443' server.add_option('--port', dest='port', default=port, help=SUPPRESS_HELP) scheme = Config.parser.get('server', 'scheme') or 'https' server.add_option('--scheme', dest='scheme', default=scheme, help=SUPPRESS_HELP) path = Config.parser.get('server', 'path') or '/katello/api' server.add_option('--path', dest='path', default=path, help=SUPPRESS_HELP) self.parser.add_option_group(server)
def process_options(self, args): self.parser = OptionParser(option_class=KatelloOption) self.parser.disable_interspersed_args() self.parser.set_usage(self.usage) if not args: self.parser.error(_('no action given: please see --help')) self.parser.parse_args(args)
def create_parser(self): parser = OptionParser(option_class=KatelloOption) parser.add_option("-g", dest="grep", action="store_true", help=_("grep friendly output")) parser.add_option("-v", dest="verbose", action="store_true", help=_("verbose, more structured output")) parser.add_option( "-d", dest="delimiter", default="", help=_("column delimiter in grep friendly output, works only with option -g"), ) self.setup_parser(parser) return parser
class KatelloOptionTestCase(TestCase): failureException = ColoredAssertionError def setup_parser(self): self.parser = OptionParser(option_class=KatelloOption) self.parser.error = Mock() self.parser.error.side_effect = OptionParserExitError() return self.parser def assert_args_valid(self, cli_arguments): cli_arguments = self.__ensure_iterable(cli_arguments) try: self.opts, self.args = self.parser.parse_args(cli_arguments) except OptionParserExitError, opee: self.fail("The option parser should accept arguments [ %s ]" % ", ".join(cli_arguments) )
class KatelloOptionTestCase(TestCase): failureException = ColoredAssertionError def setup_parser(self): self.parser = OptionParser(option_class=KatelloOption) self.parser.error = Mock() self.parser.error.side_effect = OptionParserExitError() return self.parser def assert_args_valid(self, cli_arguments): cli_arguments = self.__ensure_iterable(cli_arguments) try: self.opts, self.args = self.parser.parse_args(cli_arguments) except OptionParserExitError, opee: self.fail("The option parser should accept arguments [ %s ]" % ", ".join(cli_arguments))
def __init__(self): self.cmd = None self.name = None self.opts = None self.args = None self.optErrors = [] self.printer = None self.parser = OptionParser(option_class=KatelloOption) self.parser.add_option('-g', dest='grep', action="store_true", help=_("grep friendly output")) self.parser.add_option('-v', dest='verbose', action="store_true", help=_("verbose, more structured output")) self.parser.add_option('-d', dest='delimiter', default="", help=_("grep friendly output column delimiter")) self.setup_parser()
def setup_parser(self): self.parser = OptionParser(option_class=KatelloOption) self.parser.error = Mock() self.parser.error.side_effect = OptionParserExitError() return self.parser
def setup_parser(self, accepted_options): parser = OptionParser() for opt in accepted_options: parser.add_option('--' + opt, dest=opt, action="store_true") return parser
class Command(object): """ Command class representing a katello cli command @ivar name: command's name @ivar parser: optparse.OptionParser instance @ivar username: username credential @ivar password: password credential @ivar cert_file: certificate file credential @ivar key_file: private key file credential """ def __init__(self): """ @type actions: None or tuple/list of str's @param actoins: list of actions to expose, uses _default_actions if None """ self.cli = None self.name = None self._actions = {} self._action_order = [] @property def usage(self): """ Return a string showing the command's usage """ lines = ["Usage: %s <options> %s <action> <options>" % (self.cli.name, self.name), "Supported Actions:"] for name in self._action_order: action = self._actions[name] lines += self.__build_action_usage_lines(action) return "\n".join(lines) def __build_action_usage_lines(self, action): lines = [] desc_lines = action.description.split("\n") lines.append("\t%-14s %s" % (action.name, desc_lines.pop(0))) for l in desc_lines: lines.append("\t%-14s %s" % (" ", l)) return lines @property def description(self): """ Return a string showing the command's description """ return _("no description available") def add_action(self, name, action): """ Add an action to this command @note: actions are displayed in the order they are added @type name: str @param name: name to associate with the action @type action: L{Action} instance @param action: action to add """ action.cmd = self action.name = name self._action_order.append(name) self._actions[name] = action def action_names(self): return self._actions.keys() def get_action(self, name): return self._actions.get(name, None) def create_parser(self): self.parser = OptionParser(option_class=KatelloOption) self.parser.disable_interspersed_args() self.parser.set_usage(self.usage) return self.parser def process_options(self, parser, args): if not args: parser.error(_("no action given: please see --help")) parser.parse_args(args) def extract_action(self, args): action = self._actions.get(args[0], None) if action is None: self.parser.error(_("invalid action: please see --help")) return action def main(self, args): """ Main execution of a katello cli command This method parses options sent to the command itself, looks up the corresponding action, and calls that action's main() @warning: this method should only be overridden with care @type args: list of str's @param args: command line arguments to parse """ if type(args) == str: args = parse_tokens(args) try: parser = self.create_parser() self.process_options(parser, args) action = self.extract_action(args) return action.main(args[1:]) except OptionParserExitError, opee: return opee.args[0]
def create_parser(self): self.parser = OptionParser(option_class=KatelloOption) self.parser.disable_interspersed_args() self.parser.set_usage(self.usage) return self.parser
class Action(object): """ Action class representing a single action for a cli command @ivar name: action's name @ivar parser: optparse.OptionParser instance @ivar opts: options returned from parsing command line @ivar args: arguments returned from parsing command line """ def __init__(self): self.cmd = None self.name = None self.opts = None self.args = None self.optErrors = [] self.printer = None self.parser = OptionParser(option_class=KatelloOption) self.parser.add_option('-g', dest='grep', action="store_true", help=_("grep friendly output")) self.parser.add_option('-v', dest='verbose', action="store_true", help=_("verbose, more structured output")) self.parser.add_option('-d', dest='delimiter', default="", help=_("grep friendly output column delimiter")) self.setup_parser() @property def usage(self): """ Return a string for this action's usage """ if self.cmd: data = (self.cmd.cli.name, self.cmd.name, self.name) else: data = (os.path.basename(sys.argv[0]), self.name, "") return '%s <options> %s %s <options>' % data @property def description(self): """ Return a string for this action's description """ return _('no description available') def get_option(self, opt_dest): """ Get an option from opts or from the config file Options from opts take precedence. @type opt: str @param opt: name of option to get @return: value of the option or None if the option is no present """ attr = getattr(self.opts, opt_dest, None) if not attr: option = self.parser.get_option_by_dest(opt_dest) if option != None: opt_name = option.get_name() if Config.parser.has_option('options', opt_name): attr = Config.parser.get('options', opt_name) return u_obj(attr) def has_option(self, opt): """ Check if option is present @type opt: str @param opt: name of option to check @return True if the option was set, otherwise False """ return self.get_option(opt) != None def get_option_string(self, opt_dest): opt = self.parser.get_option_by_dest(opt_dest) if opt != None: flag = opt.get_opt_string() else: flag = '--' + opt_dest return flag def require_option(self, opt_dest): """ Add option error if an option is not present. @type opt_dest: str @param opt: name of option or option destination to check """ if (not self.option_specified(opt_dest)): flag = self.get_option_string(opt_dest) self.add_option_error(_('Option %s is required; please see --help') % flag) return def require_one_of_options(self, *opt_dests): """ Add option error if one of the options is not present. @type opt_dests: str @param opt_dests: name of option or option destination to check """ flags = [] param_count = 0 for opt_dest in opt_dests: if self.option_specified(opt_dest): param_count += 1 flag = self.get_option_string(opt_dest) flags.append(flag) if not param_count == 1: self.add_option_error(_('One of %s is required; please see --help') % ', '.join(flags)) return def option_specified(self, opt): return self.has_option(opt) and self.get_option(opt) != "" def add_option_error(self, errorMsg): """ Add option error to the error stack @type errorMsg: str @param errorMsg: error message """ self.optErrors.append(errorMsg) def setup_parser(self): """ Add custom options to the parser @note: this method should be overridden to add per-action options """ self.parser.set_usage(self.usage) def run(self): """ Action's functionality @note: override this method to implement the actoin's functionality @raise NotImplementedError: if this method is not overridden """ raise NotImplementedError('Base class method called') def check_options(self): """ Add custom option requirements @note: this method should be overridden to check for required options """ return def output_mode(self): if (self.has_option('grep') or (Config.parser.has_option('interface', 'force_grep_friendly') and Config.parser.get('interface', 'force_grep_friendly').lower() == 'true')): return Printer.OUTPUT_FORCE_GREP elif (self.has_option('verbose') or (Config.parser.has_option('interface', 'force_verbose') and Config.parser.get('interface', 'force_verbose').lower() == 'true')): return Printer.OUTPUT_FORCE_VERBOSE else: return Printer.OUTPUT_FORCE_NONE def process_options(self, args): """ This method setups up the parser, parses the arguments, checks options and prints argument errors. """ self.opts, self.args = self.parser.parse_args(args) self.printer = Printer(self.output_mode(), self.get_option('delimiter')) self.optErrors = [] self.check_options() if len(self.optErrors) > 0: if len(self.optErrors) == 1: self.parser.error(self.optErrors[0]) else: self.parser.error(self.optErrors) # this method exists so that an action can run like a command # it supports having single name actions (e.g. katello shell) def extract_action(self, args): pass def require_credentials(self): """ if True, credentials are required when calling the command. @note: this method should be overriden, if credentials should not be checked for action """ return True def error(self, errorMsg): errorMsg = u_str(errorMsg) _log.error("error: %s" % errorMsg) if errorMsg == '': msg = _('error: operation failed') else: msg = errorMsg print >> sys.stderr, msg def main(self, args): """ Main execution of the action This method setups up the parser, parses the arguments, and calls run() in a try/except block, handling RestlibExceptions and general errors @warning: this method should only be overridden with care """ try: self.process_options(args) return self.run() except SSL.Checker.WrongHost, wh: print _("ERROR: The server hostname you have configured in /etc/katello/client.conf does not match the") print _("hostname returned from the katello server you are connecting to. ") print "" print _("You have: [%s] configured but got: [%s] from the server.") % (wh.expectedHost, wh.actualHost) print "" print _("Please correct the host in the /etc/katello/client.conf file") sys.exit(1) except ServerRequestError, re: try: if "displayMessage" in re.args[1]: msg = re.args[1]["displayMessage"] else: msg = ", ".join(re.args[1]["errors"]) except: msg = re.args[1] if re.args[0] == 401: msg = _("Invalid credentials or unable to authenticate") self.error(msg) return re.args[0]
def create_parser(self, command_name=None, parent_usage=None): parser = OptionParser(option_class=KatelloOption) self.setup_parser(parser) parser.set_usage(self.usage(command_name, parent_usage)) return parser
class KatelloCLI(object): """ Katello command line tool class. """ def __init__(self): self.name = os.path.basename(sys.argv[0]) self.opts = None self._server = None self._commands = {} self.usage_line = 'Usage: %s <options> <command>' % self.name self._username = None self._password = None self._certfile = None self._keyfile = None @property def usage(self): """ Usage string. @rtype: str @return: command's usage string """ lines = [self.usage_line, 'Supported Commands:'] for name, command in sorted(self._commands.items()): lines += self.__build_command_usage_lines(command) return '\n'.join(lines) def __build_command_usage_lines(self, command): lines = [] desc_lines = command.description.split("\n") lines.append('\t%-14s %s' % (command.name, desc_lines.pop(0)) ) for l in desc_lines: lines.append('\t%-14s %s' % (" ", l) ) return lines def add_command(self, name, command): """ Add a command to this command line tool @type name: str @param name: name to associate with the command @type command: L{katello.client.core.base.Command} instance @param command: command to add """ command.cli = self command.name = name self._commands[name] = command def remove_command(self, name): del self._commands[name] def setup_parser(self): """ Add options to the command line parser. @note: this method may be overridden to define new options """ self.parser = OptionParser() self.parser.disable_interspersed_args() self.parser.set_usage(self.usage) credentials = OptionGroup(self.parser, _('Katello User Account Credentials')) credentials.add_option('-u', '--username', dest='username', default=None, help=_('account username')) credentials.add_option('-p', '--password', dest='password', default=None, help=_('account password')) credentials.add_option('--cert-file', dest='certfile', default=None, help=SUPPRESS_HELP) credentials.add_option('--key-file', dest='keyfile', default=None, help=SUPPRESS_HELP) self.parser.add_option_group(credentials) server = OptionGroup(self.parser, _('Katello Server Information')) host = Config.parser.get('server', 'host') or 'localhost.localdomain' server.add_option('--host', dest='host', default=host, help=_('katello server host name (default: %s)') % host) port = Config.parser.get('server', 'port') or '443' server.add_option('--port', dest='port', default=port, help=SUPPRESS_HELP) scheme = Config.parser.get('server', 'scheme') or 'https' server.add_option('--scheme', dest='scheme', default=scheme, help=SUPPRESS_HELP) path = Config.parser.get('server', 'path') or '/katello/api' server.add_option('--path', dest='path', default=path, help=SUPPRESS_HELP) self.parser.add_option_group(server) def setup_server(self): """ Setup the active server connection. """ host = self.opts.host port = self.opts.port scheme = self.opts.scheme path = self.opts.path #print >> sys.stderr, 'server information: %s, %s, %s, %s' % \ # (host, port, scheme, path) self._server = server.KatelloServer(host, int(port), scheme, path) server.set_active_server(self._server) def setup_credentials(self): """ Setup up request credentials with the active server. """ try: self._username = self._username or self.opts.username self._password = self._password or self.opts.password self._certfile = self._certfile or self.opts.certfile self._keyfile = self._keyfile or self.opts.keyfile if None not in (self._username, self._password): self._server.set_basic_auth_credentials(self._username, self._password) elif None not in (self.opts.certfile, self.opts.keyfile): self._server.set_ssl_credentials(self.opts.certfile, self.opts.keyfile) else: self._server.set_kerberos_auth() except GSSError, e: raise KatelloError("Missing credentials and unable to authenticate using Kerberos", e) except Exception, e: raise KatelloError("Invalid credentials or unable to authenticate", e)