===== Usage ===== For basic usages, please refer to the `Sample Usages <../README.rst#sample-usages>`_ for a quick guide. Here we provide a few more details which may become handy in certain situations. The CLI interface ------------------ Peek can work in both interactive or batch mode. Without an input file, Peek starts in the interactive mode. Otherwise, it runs in batch mode and execute the input file. The input file can be a pipe so that Peek can be used as part of an IO pipeline. In interactive mode, a blank line is normally required to trigger execution of a HTTP call. This is necessary because it is not always possible to tell whether Peek should wait for more payload lines. For an example, the ``PUT _bulk`` API can take a arbitrary number of lines as its payload. In contrast, functions are expected to be a single line and blank line is not needed to trigger their execution. However, the blank line is *not* always required if there are other ways that can mark the end of a HTTP call. For example: .. code-block:: javascript GET _search // no blank line is needed after this line GET / // no blank line is needed after this line as well echo _ // no blank line is needed since function is always single-lined No blank line is needed anywhere in the above code fragment since a following HTTP statement or function statement can just as well signal the end of the previous statement. Peek starts with a default connection which assumes a locally running, unsecured Elasticsearch cluster, i.e. ``http://localhost:9200``. This may not be the typical cluster you want to connect in real use cases. Please run ``peek -h`` to see a list of options to customise the start-up connection. You can also configure the `default connection `_ with ``peekrc`` file to avoid having to specify them each time. Keyboard Shortcuts ------------------ The interactive prompt has most of the features for readline of emacs bindings. So you can expect things like `Ctrl-a`, `Ctrl-e`, `Ctrl-k`, `Ctrl-u`, `Ctrl-r` work as intended. Additionally, Peek also has a few of its own keyboard shortcuts: * ```` - toggle pretty and compact formatting of the input, e.g. JSON payload * ```` - toggle mouse support * ``ESC + Enter`` - (press ``ESC`` then press ``Enter``) immediately trigger execution of current input * ``ESC + c`` - Copy current input to system clipboard (NOTE this requires `full installation `_). * ``ESC + a`` - Go to the beginning of the current input buffer * ``ESC + e`` - Go to the end of the current input buffer The ``peekrc`` File ------------------- The ``peekrc`` file can be used to customise some aspects of the tool. A `default `_ version is provided as part of the project. It can be overriden by users. Peek looks for user provided ``peekrc`` file in its config folder, which is ``$HOME/.config/peek`` on MacOS. The exact location of the config folder can be checked by running ``config`` inside Peek. Useful config options ^^^^^^^^^^^^^^^^^^^^^ * ``swap_colour`` - Peek's default colour scheme works well with terminals using dark theme. For light themed terminals, set this option to ``True`` for better results. * ``mouse_support`` - Mouse is not supported by default because it does not work well with scroll. It can be enabled by set this option to ``True``. Alternatively, it can also be toggled on the fly with key ````. Default Connection ^^^^^^^^^^^^^^^^^^ Peek starts with a default connection to ``http://localhost:9200`` with no credentials. This is likely not suitable for real use cases. Hence it is possible to customise the default connection in the ``peekrc`` file as the follows: .. code-block:: ini [connection] hosts = example.com:9200 username = admin-user use_ssl = True Credentials ^^^^^^^^^^^ It is **not** recommended to put cleartext password in the ``peekrc`` file. Peek also does not store cleartext password in any files. It by default attempts to use the system keyring for password storage. For this, it will ask for permission to use the keyring. By storing password in keyring, it avoids asking for password repetitively. However, you can opt-out this behaviour by setting ``use_keyring = False`` in ``peekrc`` file. Peek also looks for the ``PEEK_PASSWORD`` environmental variable for password and this is another way to avoid having to enter password many times. If both fails, Peek will prompt for password. Note that API keys and tokens are treated differently. They are considered to be more ephemeral and are stored in Peek's ``history`` sqlite file. Connection and Session ---------------------- In a single Peek session, we can have multiple connections to one or more Elasticsearch clusters. Connections can be added or removed for a session on the fly. A connection is created by specify at least the ``hosts`` of the cluster. For secured cluster, relevant credentials are required as well. Note by default, connection creation is purely local and does **not** automatically test the connection. In another word, even if the remote host is down or the credentials are wrong, a connection will still be created successfully. This behaviour is default because Peek always launches with at least one default connection. As a CLI tool, it may be launched and shutdown frequently. If connections are tested every time when they are created, it could add noticeable overhead since HTTP calls could be slow. With above being said, it is possible to opt-in for connection test on creation. This can be ad-hoc for a specific connection by setting ``test=true`` to the ``connect`` function, e.g.: .. code-block:: bash connect hosts='localhost:9200' username='elastic' test=true Alterntaively, this behaviour can also be enabled persistently with ``test_connection = True`` in the ``peekrc`` file. For a single Peek session, we may end up having multiple connections. Sometimes, it is useful if these connections can be restored when peek restarts. By default, peek saves current session information on exit. But it does not restore it by default on start. This can be enabled by setting ``auto_load_session = True``. NOTE if an connection is specified explicitly on launch, session will not be restored even when ``auto_load_session`` is set to ``True``. It is possible to manually load the last auto-saved session with ``session load='__auto__'``. Using the builtin ``session`` management function, multiple sessions can be saved and restored at will. Auto-Completion --------------- Peek's auto-completion feature for Elasticsearch APIs relies on API spec file published by the `Elasticsearch Specification project `_. Peek however does not ship with the spec file. Use the builtin function, ``_download_api_specs``, to download and initialize the spec file from its GitHub official repository. The spec file is saved in Peek's config folder so you only need to run the function once. Legacy auto-completion with Kibana spec files ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prior to v0.3.0, autocompletion uses API spec files published by the `Kibana project `_. This is disabled by default. It can still be enabled (*NOT recommended*) by setting ``prefer_elasticsearch_specification = False``. This also changes the behaviour of ``_download_api_specs`` to download Kibana spec files instead. Functions --------- Builtin functions ^^^^^^^^^^^^^^^^^ Besides HTTP calls to Elasticsearch cluster. Peek also ships with a collection of builtin functions for various things. The single most useful one is likely the ``connect`` function. It takes an array of options and creates a new connection to a cluster: .. code-block:: javascript connect hosts='host1.example.com:9200,host2.example.com:9200' username='elastic' use_ssl=true Note that quotes are required for string values. This is because Peek's CLI actually runs a `mini language `_. The ``hosts`` option takes a comma separated list of ``host:port`` values. These connection options are handed directly to the `Python Elasticsearch client `_ library, where HTTP connection pooling, retry and so on are taken care of. Another useful function is ``run``, which runs an external Peek script file: .. code-block:: javascript run 'my-script.es' // quotes are necessary Any valid statements in the interactive mode can be put into a script for future references. Type ``help`` to see the list of builtin functions. Use ``help FUNCTION_NAME`` to check a bit more details on the specified function. External functions ^^^^^^^^^^^^^^^^^^ Functions are simple Python callables. They can be defined in external files, loaded by Peek and become available. Following is a simple external function of name ``hello` that just prints "hello world" when invoked: .. code-block:: python def hello_world_func(app): return 'hello world' # The EXPORTS variable is where Peek looks for defined functions EXPORTS = { 'hello': hello_world_func } To load the extension, just specify it in the ``peekrc`` file like: .. code-block:: ini extension_path = /path/to/external/extension/file/or/directory Note the external function must accept at least one argument, which is the ``PeekApp`` instance. More sophisticated interactions are made possible with it: .. code-block:: python class HealthFunc: def __call__(self, app, **options) import json conn = options.get('conn', None) app.process_input(f'GET /_cluster/health conn={json.dumps(conn)}') @property def options(self): return { 'conn': None } @property def description(self): return 'Health check for the Elasticsearch cluster' EXPORTS = { 'healthcheck': HealthFunc() } The ``options`` and ``description`` properties are optional. If provided, they will be used to populate auto-completion and help message. Scripting --------- Peek features a mini scripting language which seamlessly integrates the HTTP call syntax. The goal of the language is to make it possible to perform simple repetitive work without leaving the interactive session, e.g. create an API key and authenticate with it, or quickly populate an index with random test data. The following is a EBNF specification of the Peek language: .. code-block:: ebnf prog = { stmt } ; stmt = http_stmt | function_stmt | let_stmt | forin_stmt ; http_stmt = verb, path, { option }, "\n", [ payload ]; func_stmt = name, { funcarg } ; let_stmt = "let", { name, "=", expr } ; forin_stmt = "for", name, "in", expr, "{", { stmt }, "}" ; verb = "GET" | "PUT" | "POST" | "DELETE" ; path = non_blank_characters, { non_blank_characters } ; option = name, "=", expr ; payload = dict, { "\n", dict } ; expr = "true" | "false" | "null" | [ unaryop ], number | string | [ unaryop ], name | list | dict | [ unaryop ], funcall | expr, binop, expr | [ unaryop ], "(", expr, ")" ; number = digit, {digit} ; name = "_" | letter, { "_" | letter | digit } ; string = '"' , { all_characters - '"' }, '"' | "'", { all_characters - "'" }, "'" | '"""' , { all_characters - '"""' }, '"""' | "'''", { all_characters - "'''" }, "'''" ; list = "[", [ expr, { ",", expr }, [ "," ] ], "]" ; dict = "{", [ expr, ":", expr, { ",", expr, ":", expr }, [ "," ] ], "}" ; funcall = expr, "(", [ funcarg, { ",", funcarg } ], ")" ; funcarg = { expr | option | "@", name } unaryop = "-" | "+" ; binop = "+" | "-" | "*" | "/" | "%" | "." ; digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" | "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" ; Due to its simplistic nature, the language is not intended to be `Turing complete `_ and it is not due to lack of conditional control construct, e.g. ``if/else``. For complex scripting requirements, it is recommended to use Peek in batch mode as part of a shell script.