osapi is a small, general-purpose CLI for talking to any OpenSearch REST endpoint with robust
retry behaviour.
It behaves like a resilient curl for OpenSearch: bounded or unlimited retry with configurable
backoff, optional insecure-TLS, and status-code-based success/terminal classification — in a single
binary that can reach any endpoint. The response body is written to stdout (pipe it to jq);
diagnostics and per-attempt retry detail go to stderr.
go build -o osapi ./cmd/osapi
# or
make buildosapi sends one request per invocation — the command itself is the request
(there is no request subcommand). osapi --version prints the version.
# Cluster health, pretty-printed
osapi --endpoint https://localhost:9200 -k -u admin --path _cluster/health | jq .
# PUT a policy from a file, retrying up to 5 times but stopping immediately on 400
osapi -X PUT --path _plugins/_ism/policies/my-policy \
--body @policy.json --retry 5 --abort-on 400
# Read the body from stdin
echo '{"query":{"match_all":{}}}' | osapi -X POST --path my-index/_search -d @-| Flag | Default | Description |
|---|---|---|
--endpoint |
OpenSearch endpoint URL, e.g. https://localhost:9200 |
|
-u, --username |
username for basic authentication | |
--password |
password for basic authentication (see the caveat below) | |
--ca-cert |
path to a CA certificate bundle (PEM) used to verify TLS | |
-k, --insecure |
skip TLS certificate verification | |
--env-file |
path to a dotenv file providing the environment variables below | |
-v, --verbose |
print per-attempt retry detail to stderr | |
-X, --method |
GET |
HTTP method |
--path |
required | request path, e.g. _cluster/health |
-d, --body |
request body: literal string, @file, or @- for stdin |
|
-q, --query |
query parameter as key=value (repeatable) |
|
-H, --header |
request header as "Key: Value" (repeatable) |
|
--retry |
0 |
number of retries (0 = none; -1 = unlimited) |
--abort-on |
status codes that stop retrying (comma-separated) | |
--backoff |
linear |
backoff strategy: constant, linear, or exponential |
--backoff-initial |
2s |
initial backoff delay |
--backoff-max |
30s |
maximum backoff delay |
--backoff-jitter |
0 |
backoff jitter as a fraction in [0,1) |
Each connection setting is resolved as:
explicit flag > --env-file > process environment > default
Recognised environment variables (also valid inside an --env-file dotenv file):
| Setting | Variable |
|---|---|
| endpoint | OPENSEARCH_URL |
| username | OPENSEARCH_USERNAME |
| password | OPENSEARCH_PASSWORD |
Values in an --env-file take precedence over the process environment, so a file can override
whatever is exported in the shell.
--retry Nperforms1 + Nattempts.--retry 0(the default) makes a single attempt with no retry;--retry -1retries until the request succeeds or hits an--abort-onstatus.- Any
2xxresponse is a success: the body is printed to stdout and the exit code is0. - A status listed in
--abort-onstops retrying immediately (terminal failure). - Any other non-
2xxresponse, or a transport error, is retried until the retry budget is exhausted. - On any non-success outcome the exit code is
1; a Ctrl-C (interrupt) exits with130. - The response body is always printed to stdout, including for failing responses, so you can
inspect
4xx/5xxpayloads.
Prefer OPENSEARCH_PASSWORD, an --env-file, or the interactive masked prompt over --password.
A password passed on the command line is visible in the process list (ps) and your shell history.
When a username is set on an interactive terminal and no password is supplied, osapi prompts for
one; on a non-interactive terminal it fails instead of hanging.
-k, --insecuredisables TLS certificate verification entirely — use it only against hosts you trust.--queryand--headervalues are sent as given and are not redacted in verbose output, so avoid placing secrets in them.
make test # go test ./...
make lint # golangci-lint run
make build # build the osapi binary