# Elasticli Logo [![Rust](https://github.com/giufus/elasticli.rs/actions/workflows/rust.yml/badge.svg)](https://github.com/giufus/elasticli.rs/actions/workflows/rust.yml) The missing Command Line Interface to interact with Elasticsearch (or yet another one). Even if elasticsearch APIs are super easy to invoke and very well documented, I always forget the basic commands and methods to do indexing or searches, so I decided to write my own CLI. I hope you find it useful, it is a work in progress. ### Features Written in Rust 🦀, it uses the following crates: - [clap](https://crates.io/crates/clap) for arguments parsing - [hydroconf](https://crates.io/crates/hydroconf) for configuration management - [reqwest](https://crates.io/crates/reqwest) for http requests toward elasticsearch If opportunely configured, the command can run inside an SSH tunnel (with auto close after a number of seconds). Currently, you can use `elasticli` to: - get info about the target elasticsearch version; - create, read, ~~update~~, delete an index; - create, read, update, delete a document; ### Changelog 0.1.2: cross platform building 0.1.1: basic authentication 0.1.0: first release ### Build & Run #### Option 1 - Build it for your platform with `cargo build --release` (or just type `make`), then go to `target/release` and run the binary `elasticli`. #### Option 2 - Alternatively, download the pre-built binary for your platform in the [releases](https://github.com/giufus/elasticli.rs/releases) page. The executable is available for the following targets: - **x86_64-unknown-linux-gnu** -> 64-bit Linux (kernel 3.2+, glibc 2.17+) # CROSS BUILD - **x86_64-pc-windows-msvc** -> 64-bit MSVC (Windows 7+) # BUILT ON WINDOWS ** *** - **x86_64-apple-darwin** -> 64-bit macOS (10.7+, Lion+) # BUILT ON MAC x86_64 ** - **aarch64-unknown-linux-gnu** -> ARM64 Linux (kernel 4.1, glibc 2.17+) # CROSS BUILD - **aarch64-apple-darwin** -> ARM64 macOS (11.0+, Big Sur+) # BUILT ON MAC aarch64 **: `cross` uses docker images to cross compile, unfortunately windows and apple images are not available at the moment. ***: on windows, apart from [install rust](https://www.rust-lang.org/tools/install), you may need to [install perl](https://strawberryperl.com/) to build `elasticli`. You can get the complete list of rust targets with: `rustc --print target-list` Your platform is shown in the `host` property of the output of: `rustc -vV` #### Option 3 If you want to experience the cross-compilation, install [cross](https://github.com/cross-rs/cross) (you may need other dependencies), grab a beer, then run: `make ` where the target is one of the outputs of `rustc --print target-list`. Anyway, I have already cross-compiled [some of them]([relases](https://github.com/giufus/elasticli.rs/releases)) for you. #### Other - If you want to run unit tests run `cargo test`. - If you want to build and run directly from sources `cargo run -- `. ### Configuration - Every command can use the `hydroconf` features to override default configurations. For example you can override some defaults passing environment name as env var to the command line: `ENV_FOR_HYDRO=production elasticli info` or per single prop, specifying it as an env var to the command line: `HYDRO_ELASTIC__PASSWORD="an even stronger password" elasticli info` Look at the [hydroconf doc](https://github.com/rubik/hydroconf) for major details. - You pass the config root directory with `-c` option before one of the commands (info, index, document). The directory must contain the configuration files (look in the `default` folder for the latest version): [.secrets.toml](samples%2Fdefault%2F.secrets.toml) environment based _sensitive_ configurations (tipically elastic user and password). ``` [default] elastic.username = 'elastic' elastic.password = 'secure_password' [production] elastic.username = 'elastic' elastic.password = 'changeme' ``` [settings.toml](samples%2Fdefault%2Fsettings.toml) environment based configurations ``` [default] # your target elasticsearch host, port, protocol and version elastic.host = 'otherhost' elastic.port = 9200 elastic.protocol = 'http' elastic.version = '8.8.0' # if enabled, the main command will be executed inside an ssh tunnel. It is the same as running ### ssh -i @ :: sleep ### ssh -i .ssh/some_id_rsa centos@bastion-host 9200:remote-es.server.es:9200 sleep 3 # but rust does it for you proxy.enabled = false proxy.host = 'proxyhost' proxy.port = 9201 proxy.protocol = 'http' proxy.user = 'ec2-user' proxy.remote_user = 'ec2-remote-user' proxy.key = 'path to ssh key' proxy.timeout = 3 ``` ## Commands Showcase Learn from examples! Here a few sample commands (and sometimes the output). I hope it is understandable enough. ### General #### - Get help about the command, options and subcommand `elasticli --help` `elasticli --help` ### Info #### - Get basic info about elasticsearch `elasticli info` ``` { "cluster_name": "docker-cluster", "cluster_uuid": "b9c-xKsSRs2HQAvZ8wGsIw", "name": "aecf011cca00", "tagline": "You Know, for Search", "version": { "build_date": "2023-05-23T17:16:07.179039820Z", "build_flavor": "default", "build_hash": "c01029875a091076ed42cdb3a41c10b1a9a5a20f", "build_snapshot": false, "build_type": "docker", "lucene_version": "9.6.0", "minimum_index_compatibility_version": "7.0.0", "minimum_wire_compatibility_version": "7.17.0", "number": "8.8.0" } } ``` ### Index #### - Get index, same operation, multiple ways (it is Clap's magic) `elasticli index -i test1` `elasticli index -i=test1` `elasticli index --index-name=test1` `elasticli index -o read --index-name=test1` #### - Get indexes ('_all' and '*' are Elasticsearch wildcards) `elasticli index -i _all` `elasticli index --index-name='*'` #### - Create index `elasticli index -o create --index-name='pippo'` `elasticli index -o create --index-name='pippo_2' -b '{"settings": { "index": { "number_of_shards": 3, "number_of_replicas": 2 } } }'` ``` { "acknowledged": true, "index": "pippo", "shards_acknowledged": true } ``` #### - Update Index ``` NOT YET IMPLEMENTED ``` #### - Delete Index `elasticli index -o delete -i 'pippo2'` `elasticli -c ./samples/default index -o delete --index-name='pippo2'` ### Document #### - Create a document in `test1` `elasticli document -o create -i test1 -b '{"name":"giufus", "language": "rust"}'` ``` { "_id": "5Lms-YgBu6r1vXY7vPX_", "_index": "test1", "_primary_term": 3, "_seq_no": 2, "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_version": 1, "result": "created" } ``` #### - Update an existing document (you need to put your updates in 'doc') `elasticli document -o update -i test1 -b '{"doc": { "language": "zig"} }' --id 5Lms-YgBu6r1vXY7vPX_` ``` { "_id": "5Lms-YgBu6r1vXY7vPX_", "_index": "test1", "_primary_term": 3, "_seq_no": 3, "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_version": 2, "result": "updated" } ``` #### - Search all docs in test1 index `elasticli document -o read -i test1` #### - Search all docs in test1 with an Elasticsearch query `elasticli document -o read -i test1 -b '{ "query": { "term": { "name": "giufus" } }}'` #### - Delete an existing document `elasticli document -o delete -i test1 --id 5rm3-YgBu6r1vXY7S_Xb` ``` { "_id": "5Lms-YgBu6r1vXY7vPX_", "_index": "test1", "_primary_term": 3, "_seq_no": 9, "_shards": { "failed": 0, "successful": 1, "total": 2 }, "_version": 3, "result": "deleted" } ``` ### Defaults There are some defaults in the code in case you don't specify them: - `http` as protocol - `127.0.0.1` as host - `9200` as port - `_doc` as type (used in document deletion) - `read` as operation - `8.8.0` as es version ### To do - write better documentation - handle elasticsearch versions (e.g. providing multiple implementations of the trait) - integration tests (maybe using something like [testcontainers](https://crates.io/crates/testcontainers)) ### Run elasticsearch locally with docker and no security `docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:8.8.0` ### Run elasticsearch locally with docker and basic authentication `docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=true" -e "ELASTIC_PASSWORD=changeme" elasticsearch:8.8.0`