Ejemplo n.º 1
0
 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())
Ejemplo n.º 2
0
    def parse_resource(self, skip_deprecated=False):
        """Attempt to parse the <resource> (e.g., jobs) specified on the CLI

        If a valid resource is discovered, the user will be authenticated
        (either via an OAuth2.0 token or session-based auth) and the remaining
        CLI arguments will be processed (to determine the requested action
        e.g., list, create, delete)

        :param skip_deprecated: when False (the default), deprecated resource
                                names from the open source tower-cli project
                                will be allowed
        """
        self.resource = parse_resource(self, skip_deprecated=skip_deprecated)
        if self.resource:
            self.authenticate()
            resource = getattr(self.v2, self.resource)
            if is_control_resource(self.resource):
                # control resources are special endpoints that you can only
                # do an HTTP GET to, and which return plain JSON metadata
                # examples are `/api/v2/ping/`, `/api/v2/config/`, etc...
                if self.help:
                    self.subparsers[self.resource].print_help()
                    raise SystemExit()
                self.method = 'get'
                response = getattr(resource, self.method)()
            else:
                response = self.parse_action(resource)

            _filter = self.get_config('filter')

            # human format for metrics, settings is special
            if self.resource in ('metrics', 'settings'
                                 ) and self.get_config('format') == 'human':
                response.json = {
                    'count':
                    len(response.json),
                    'results': [{
                        'key': k,
                        'value': v
                    } for k, v in response.json.items()]
                }
                _filter = 'key, value'

            if self.get_config(
                    'format'
            ) == 'human' and _filter == '.' and self.resource in UNIQUENESS_RULES:
                _filter = ', '.join(UNIQUENESS_RULES[self.resource])

            formatted = format_response(response,
                                        fmt=self.get_config('format'),
                                        filter=_filter,
                                        changed=self.original_action
                                        in ('modify', 'create', 'associate',
                                            'disassociate'))
            if formatted:
                print(utils.to_str(formatted), file=self.stdout)
            if hasattr(response, 'rc'):
                raise SystemExit(response.rc)
        else:
            self.parser.print_help()
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
 def fetch(next_line):
     for result in events(**payload).json.results:
         if result['start_line'] != next_line:
             # If this event is a line from _later_ in the stdout,
             # it means that the events didn't arrive in order;
             # skip it for now and wait until the prior lines arrive and are
             # printed
             continue
         stdout = to_str(result.get('stdout'))
         if stdout and print_stdout:
             print(stdout)
         next_line = result['end_line']
     return next_line
Ejemplo n.º 5
0
Archivo: client.py Proyecto: lpasha/awx
    def parse_resource(self, skip_deprecated=False):
        """Attempt to parse the <resource> (e.g., jobs) specified on the CLI

        If a valid resource is discovered, the user will be authenticated
        (either via an OAuth2.0 token or session-based auth) and the remaining
        CLI arguments will be processed (to determine the requested action
        e.g., list, create, delete)

        :param skip_deprecated: when False (the default), deprecated resource
                                names from the open source tower-cli project
                                will be allowed
        """
        self.resource = parse_resource(self, skip_deprecated=skip_deprecated)
        if self.resource:
            self.authenticate()
            resource = getattr(self.v2, self.resource)
            if is_control_resource(self.resource):
                # control resources are special endpoints that you can only
                # do an HTTP GET to, and which return plain JSON metadata
                # examples are `/api/v2/ping/`, `/api/v2/config/`, etc...
                if self.help:
                    self.subparsers[self.resource].print_help()
                    raise SystemExit()
                self.method = 'get'
                response = getattr(resource, self.method)()
            else:
                response = self.parse_action(resource)
            formatted = format_response(
                response,
                fmt=self.get_config('format'),
                filter=self.get_config('filter'),
                changed=self.original_action in (
                    'modify', 'create', 'associate', 'disassociate'
                )
            )
            if formatted:
                print(utils.to_str(formatted), file=self.stdout)
        else:
            self.parser.print_help()

            if six.PY2 and not self.help:
                # Unfortunately, argparse behavior between py2 and py3
                # changed in a notable way when required subparsers
                # have invalid (or missing) arguments specified
                # see: https://github.com/python/cpython/commit/f97c59aaba2d93e48cbc6d25f7ff9f9c87f8d0b2
                print('\nargument resource: invalid choice')
                raise SystemExit(2)
Ejemplo n.º 6
0
    def fetch(seen):
        results = response.connection.get('/api/v2/unified_jobs',
                                          payload).json()['results']

        # erase lines we've previously printed
        if print_stdout and sys.stdout.isatty():
            for _ in seen:
                sys.stdout.write('\x1b[1A')
                sys.stdout.write('\x1b[2K')

        for result in results:
            result['name'] = to_str(result['name'])
            if print_stdout:
                print(' ↳ {id} - {name} '.format(**result), end='')
                status = result['status']
                if color_enabled():
                    color = STATUS_COLORS.get(status, 'white')
                    cprint(status, color)
                else:
                    print(status)
                seen.add(result['id'])
Ejemplo n.º 7
0
def monitor_workflow(response,
                     session,
                     print_stdout=True,
                     timeout=None,
                     interval=0.25):
    get = response.url.get
    payload = {
        'order_by': 'finished',
        'unified_job_node__workflow_job': response.id,
    }

    def fetch(seen):
        results = response.connection.get('/api/v2/unified_jobs',
                                          payload).json()['results']

        # erase lines we've previously printed
        if print_stdout and sys.stdout.isatty():
            for _ in seen:
                sys.stdout.write('\x1b[1A')
                sys.stdout.write('\x1b[2K')

        for result in results:
            result['name'] = to_str(result['name'])
            if print_stdout:
                print(' ↳ {id} - {name} '.format(**result), end='')
                status = result['status']
                if color_enabled():
                    color = STATUS_COLORS.get(status, 'white')
                    cprint(status, color)
                else:
                    print(status)
                seen.add(result['id'])

    if print_stdout:
        cprint('------Starting Standard Out Stream------', 'red')

    if print_stdout:
        print('Launching {}...'.format(to_str(get().json.name)))

    started = time.time()
    seen = set()
    while True:
        if timeout and time.time() - started > timeout:
            if print_stdout:
                cprint('Monitoring aborted due to timeout.', 'red')
            break

        if sys.stdout.isatty():
            # if this is a tty-like device, we can send ANSI codes
            # to draw an auto-updating view
            # otherwise, just wait for the job to finish and print it *once*
            # all at the end
            fetch(seen)

        time.sleep(0.25)
        json = get().json
        if json.finished:
            fetch(seen)
            break
    if print_stdout:
        cprint('------End of Standard Out Stream--------\n', 'red')
    return get().json.status
Ejemplo n.º 8
0
 def __init__(self, endpoint, connection):
     self.endpoint = to_str(endpoint)
     self.connection = connection
Ejemplo n.º 9
0
 def __new__(cls, endpoint, connection):
     return super(TentativePage, cls).__new__(cls, to_str(endpoint))