1 unstable release
0.1.0 | Jul 7, 2023 |
---|
#1712 in Command line utilities
44KB
436 lines
Elasticli
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 for arguments parsing
- hydroconf for configuration management
- 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 typemake
), then go totarget/release
and run the binaryelasticli
.
Option 2
-
Alternatively, download the pre-built binary for your platform in the 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, you may need to install perl 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 (you may need other dependencies), grab a beer, then run:
make <YOUR-TARGET>
where the target is one of the outputs of rustc --print target-list
. Anyway, I have already cross-compiled some of them 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 -- <your elasticli options and command here>
.
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 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 thedefault
folder for the latest version):
.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 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 <proxy.key> <proxy.remote_user>@<proxy.host> <elastic.port>:<elastic.host>:<elastic.port> sleep <proxy.timeout>
### 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 <info | index | document> --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 protocol127.0.0.1
as host9200
as port_doc
as type (used in document deletion)read
as operation8.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)
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
Dependencies
~12–27MB
~448K SLoC