def handle(self, client, parser): auth = parser.add_argument_group('OAuth2.0 Options') auth.add_argument('--description', help='description of the generated OAuth2.0 token', metavar='TEXT') auth.add_argument('--conf.client_id', metavar='TEXT') auth.add_argument('--conf.client_secret', metavar='TEXT') auth.add_argument('--conf.scope', choices=['read', 'write'], default='write') if client.help: self.print_help(parser) raise SystemExit() parsed = parser.parse_known_args()[0] kwargs = { 'client_id': getattr(parsed, 'conf.client_id', None), 'client_secret': getattr(parsed, 'conf.client_secret', None), 'scope': getattr(parsed, 'conf.scope', None), } if getattr(parsed, 'description', None): kwargs['description'] = parsed.description try: token = api.Api().get_oauth2_token(**kwargs) except Exception as e: self.print_help(parser) cprint( 'Error retrieving an OAuth2.0 token ({}).'.format(e.__class__), 'red') else: fmt = client.get_config('format') if fmt == 'human': print('export CONTROLLER_OAUTH_TOKEN={}'.format(token)) else: print(to_str(FORMATTERS[fmt]({'token': token}, '.')).strip())
def handle(self, client, parser): auth = parser.add_argument_group('OAuth2.0 Options') auth.add_argument('--conf.client_id', metavar='TEXT') auth.add_argument('--conf.client_secret', metavar='TEXT') auth.add_argument('--conf.scope', choices=['read', 'write'], default='write') if client.help: self.print_help(parser) raise SystemExit() parsed = parser.parse_known_args()[0] kwargs = { 'client_id': getattr(parsed, 'conf.client_id', None), 'client_secret': getattr(parsed, 'conf.client_secret', None), 'scope': getattr(parsed, 'conf.scope', None), } try: token = api.Api().get_oauth2_token(**kwargs) except Exception as e: self.print_help(parser) cprint( 'Error retrieving an OAuth2.0 token ({}).'.format(e.__class__), 'red') else: print('export TOWER_TOKEN={}'.format(token))
def run(stdout=sys.stdout, stderr=sys.stderr, argv=[]): cli = CLI(stdout=stdout, stderr=stderr) try: cli.parse_args(argv or sys.argv) cli.connect() cli.parse_resource() except KeyboardInterrupt: sys.exit(1) except ConnectionError as e: cli.parser.print_help() msg = ( '\nThere was a network error of some kind trying to reach ' '{}.\nYou might need to specify (or double-check) ' '--conf.host'.format(cli.get_config('host')) ) if isinstance(e, SSLError): msg = ( '\nCould not establish a secure connection. ' '\nPlease add your server to your certificate authority.' '\nYou can also run this command by specifying ' '-k or --conf.insecure' ) cprint(msg + '\n', 'red', file=stderr) cprint(e, 'red', file=stderr) sys.exit(1) except Unauthorized as e: cli.parser.print_help() msg = '\nValid credentials were not provided.\n$ awx login --help' cprint(msg + '\n', 'red', file=stderr) if cli.verbose: cprint(e.__class__, 'red', file=stderr) sys.exit(1) except Common as e: if cli.verbose: print(traceback.format_exc(), sys.stderr) if cli.get_config('format') == 'json': json.dump(e.msg, sys.stdout) print('') elif cli.get_config('format') == 'yaml': sys.stdout.write(to_str( yaml.safe_dump( e.msg, default_flow_style=False, encoding='utf-8', allow_unicode=True ) )) elif cli.get_config('format') == 'human': sys.stdout.write(e.__class__.__name__) print('') sys.exit(1) except Exception as e: if cli.verbose: e = traceback.format_exc() cprint(e, 'red', file=stderr) sys.exit(1)
def parse_action(self, page, from_sphinx=False): """Perform an HTTP OPTIONS request This method performs an HTTP OPTIONS request to build a list of valid actions, and (if provided) runs the code for the action specified on the CLI :param page: a awxkit.api.pages.TentativePage object representing the top-level resource in question (e.g., /api/v2/jobs) :param from_sphinx: a flag specified by our sphinx plugin, which allows us to walk API OPTIONS using this function _without_ triggering a SystemExit (argparse's behavior if required arguments are missing) """ subparsers = self.subparsers[self.resource].add_subparsers( dest='action', metavar='action') subparsers.required = True # parse the action from OPTIONS parser = ResourceOptionsParser(self.v2, page, self.resource, subparsers) if from_sphinx: # Our Sphinx plugin runs `parse_action` for *every* available # resource + action in the API so that it can generate usage # strings for automatic doc generation. # # Because of this behavior, we want to silently ignore the # `SystemExit` argparse will raise when you're missing required # positional arguments (which some actions have). try: self.parser.parse_known_args(self.argv)[0] except SystemExit: pass else: self.parser.parse_known_args()[0] # parse any action arguments if self.resource != 'settings': for method in ('list', 'modify', 'create'): parser.build_query_arguments( method, 'GET' if method == 'list' else 'POST') if from_sphinx: parsed, extra = self.parser.parse_known_args(self.argv) else: parsed, extra = self.parser.parse_known_args() if extra and self.verbose: # If extraneous arguments were provided, warn the user cprint('{}: unrecognized arguments: {}'.format( self.parser.prog, ' '.join(extra)), 'yellow', file=self.stdout) # build a dictionary of all of the _valid_ flags specified on the # command line so we can pass them on to the underlying awxkit call # we ignore special global flags like `--help` and `--conf.xyz`, and # the positional resource argument (i.e., "jobs") # everything else is a flag used as a query argument for the HTTP # request we'll make (e.g., --username="******", --verbosity=3) parsed = parsed.__dict__ parsed = dict((k, v) for k, v in parsed.items() if (v is not None and k not in ( 'help', 'resource') and not k.startswith('conf.'))) # if `id` is one of the arguments, it's a detail view if 'id' in parsed: page.endpoint += '{}/'.format(str(parsed.pop('id'))) # determine the awxkit method to call action = self.original_action = parsed.pop('action') page, action = handle_custom_actions(self.resource, action, page) self.method = { 'list': 'get', 'modify': 'patch', }.get(action, action) if self.method == 'patch' and not parsed: # If we're doing an HTTP PATCH with an empty payload, # just print the help message (it's a no-op anyways) parser.parser.choices['modify'].print_help() return if self.help: # If --help is specified on a subarg parser, bail out # and print its help text parser.parser.choices[self.original_action].print_help() return if self.original_action == 'create': return page.post(parsed) return getattr(page, self.method)(**parsed)