예제 #1
0
def interactive():
    session = PromptSession(
        completer=DshellCompleter.from_nested_dict(nested_dict),
        history=get_history('main', InMemoryHistory()),
        clipboard=PyperclipClipboard(),
        enable_history_search=True,
        enable_suspend=True)

    parser = ArgumentParserRaise(allow_abbrev=False, prog='')
    parser = create_parser(nested_dict, parser)
    while True:
        message = [
            ('class:username', env._username if env._username else "?"),
            ('class:at', '@'),
            ('class:host', env.get("SERVER") if env.get("SERVER") else "?"),
            ('', ':'),
            ('class:path', 'dshell'),
            ('', '> '),
        ]
        try:
            text = session.prompt(message, style=style)
        except KeyboardInterrupt:
            continue  # Control-C pressed. Try again.
        except EOFError:
            exit_dshell()

        if text.startswith('!'):
            subprocess.call(text.lstrip('!'), shell=True)
        else:
            try:
                namespace = parser.parse_args(shlex.split(text))
            except (ValueError, argparse.ArgumentError) as e:
                dprint(e)
                continue
            except SystemExit:
                continue
            except Exception as e:
                dprint(e)
                continue
            else:
                cmd_params = vars(namespace)

            if not text:
                continue
            elif text == 'help':
                parser.print_usage()
            elif text and len(cmd_params) == 0:
                try:
                    parser.parse_args(shlex.split(text) + ['-h'])
                except SystemExit:
                    continue
            else:
                call_func_with_signature(cmd_params)
예제 #2
0
def login(username=None, password=None, save=False):
    try:
        ntwrk.login(username, password)
    except requests.exceptions.ConnectionError as e:
        dprint(
            f"Unable to contact with {environ.get('SCHEME')}://{environ.get('SERVER')}:{environ.get('PORT')}/"
        )
    except Exception as e:
        dprint(str(e))
    else:
        if save:
            save_config_file(os.path.expanduser(env.get('CONFIG_FILE', None)),
                             username=env._username,
                             token=env._refresh_token,
                             server=env.get('SERVER'),
                             port=env.get('PORT'))
예제 #3
0
def get_history(tag, default=None):
    file_history = environ.get('FILE_HISTORY', None)
    if file_history:
        file_history = os.path.expanduser('~/.dshell_history')
        if not os.path.exists(file_history):
            open(file_history, 'w').close()
        history = FileTagHistory(file_history, tag)
    else:
        history = default
    return history
예제 #4
0
def generate_url(view,
                 view_data,
                 ip=None,
                 port=defaults.DEFAULT_PORT,
                 scheme='https'):
    try:
        path = view_path_map[view]
    except KeyError:
        raise RuntimeError(f"'{view}' not set in metadata")
    path = _replace_path_args(path, view_data or {})
    if (env.get('SERVER', ip) or ip) is None:
        raise ValueError('No SERVER specified.')
    return f"{env.get('SCHEME', scheme) or scheme}://" \
           f"{env.get('SERVER', ip) or ip}:" \
           f"{env.get('PORT', port) or port}" \
           f"{path}"
예제 #5
0
def main():
    ch = logging.StreamHandler()
    logger = logging.getLogger('dshell')
    logger.addHandler(ch)

    # parse args
    args = docopt(__doc__,
                  version='dshell version 1.0',
                  options_first=True)

    bootstrap_environ(args)

    # process args
    argv = [args['COMMAND']] + args['ARGS']

    if not ('-h' or '--help') in argv:
        if args['COMMAND'] is None:
            import dimensigon.dshell
            dimensigon.dshell.INTERACTIVE = True
            interactive()
        else:
            if env._refresh_token is None:
                exit('No token specified. Unable to run command')
            if not env.get('SERVER', None):
                exit('No server specified. Unable to run command')
            if args['COMMAND'] in commands:
                parser = create_parser({args['COMMAND']: nested_dict[args['COMMAND']]},
                                       parser=ArgumentParser(prog="dshell"))
                namespace = parser.parse_args(argv)
                if hasattr(namespace, 'func'):
                    call_func_with_signature(vars(namespace))
            elif args['COMMAND'] in batch_commands:
                module = importlib.import_module('.dshell_%s' % args['COMMAND'], 'dimensigon.dshell.batch')
                module.main(argv)
            else:
                exit("%r is not a dshell command. See 'dshell --help'." % args['COMMAND'])
    else:
        parser = create_parser({args['COMMAND']: nested_dict[args['COMMAND']]},
                               parser=ArgumentParser(prog="dshell"))
        parser.parse_args(argv)
예제 #6
0
def dprint(msg):
    if isinstance(msg, str):
        if msg not in ('\n', None, ''):
            print(msg)
    elif isinstance(msg, Response):
        if msg.code:
            dprint(msg.msg)
        else:
            dprint(msg.exception)
    elif isinstance(msg, Exception):
        if env.get('DEBUG'):
            dprint(format_exception(msg))
        else:
            dprint(str(msg) if str(msg) else msg.__class__.__name__)
    else:
        try:
            tokens = list(
                pygments.lex(json.dumps(msg, indent=2), lexer=JSONLexer()))
        except:
            pprint(msg)
        else:
            print_formatted_text(PygmentsTokens(tokens), end="")
예제 #7
0
def login(username=None, password=None):
    if not username:
        if not env._username:
            try:
                username = prompt("Username: "******"Password: ", is_password=True)
        except KeyboardInterrupt:
            return

    resp = requests.post(generate_url('root.login', {}),
                         json={
                             'username': username,
                             'password': password
                         },
                         verify=False)
    resp.raise_for_status()

    env._username = username
    env._access_token = resp.json()['access_token']
    env._refresh_token = resp.json()['refresh_token']

    file = os.path.expanduser(env.get('CONFIG_FILE', None))
    if file and os.path.exists(file):
        config = configparser.ConfigParser()
        config.read(file)
        if config.has_section('AUTH') and config.has_section('REMOTE'):
            if config['AUTH'].get('username') == env._username:
                from dimensigon.dshell.bootstrap import save_config_file
                del config
                save_config_file(token=env._refresh_token)
예제 #8
0
def request(method,
            url,
            session=None,
            token_refreshed=False,
            login=True,
            **kwargs) -> Response:
    exception = None
    content = None
    status = None
    json_data = None
    headers = {}

    if not session:
        _session = requests.session()
    else:
        _session = session

    raise_on_error = kwargs.pop('raise_on_error', False)

    func = getattr(_session, method.lower())

    if 'auth' not in kwargs:
        if env._access_token is None:
            try:
                refresh_access_token(login_=login)
            except requests.exceptions.ConnectionError as e:
                return Response(exception=ConnectionError(
                    f"Unable to contact with {env.get('SCHEME')}://"
                    f"{env.get('SERVER')}:{env.get('PORT')}/refresh"),
                                url=url)
            except Exception as e:
                return Response(exception=e, url=url)
            else:
                if env._access_token is None:
                    return Response(
                        exception=ValueError("No authentication set"), url=url)
        kwargs['auth'] = HTTPBearerAuth(env._access_token)

    if 'headers' not in kwargs:
        kwargs['headers'] = {}
    kwargs['headers'].update({'D-Securizer': 'plain'})

    kwargs['verify'] = env.get('SSL_VERIFY')

    logger.debug(f"{method.upper()} {url}\n{kwargs}")

    resp = None
    try:
        resp: requests.Response = func(url, **kwargs)
    except (requests.Timeout, ) as e:
        timeout = kwargs.get('timeout', None)
        if isinstance(timeout, tuple):
            timeout = timeout[0] + timeout[1]
        exception = TimeoutError(
            f"Socket timeout reached while trying to connect to {url} "
            f"for {timeout} seconds")
    except requests.ConnectionError as e:
        exception = ConnectionError(f"Unable to contact to {url}")
    except Exception as e:
        exception = e
    finally:
        if session is None and not (getattr(resp, 'status_code', None) == 401
                                    and resp.json().get('msg')
                                    == 'Token has expired'):
            _session.close()
    if exception is None:
        status = resp.status_code
        headers = resp.headers
        if status == 401 and not token_refreshed:
            json_data = resp.json()
            if json_data.get('msg') == 'Token has expired':
                try:
                    refresh_access_token()
                except requests.exceptions.ConnectionError as e:
                    return Response(exception=ConnectionError(
                        f"Unable to contact with {env.get('SCHEME')}://"
                        f"{env.get('SERVER')}:{env.get('PORT')}/refresh"),
                                    url=url)
                kwargs['auth'] = HTTPBearerAuth(env._access_token)
                resp = request(method,
                               url,
                               session=_session,
                               token_refreshed=True,
                               **kwargs)
                if not session:
                    _session.close()
                return resp
        try:
            json_data = resp.json()
        except (ValueError, ):
            content = resp.text

        if json_data is not None:
            # try:
            #     content = unpack_msg(json_data)
            # except NotValidMessage:
            #     content = json_data
            content = json_data
    else:
        if raise_on_error:
            raise exception

    return Response(msg=content,
                    code=status,
                    exception=exception,
                    url=url,
                    headers=headers)