Querying resources
Reading data uses two verbs: list (many) and get (one), refined by four flags —
--filter (server-side narrowing), --fields (fewer fields per object), --limit (fewer
objects), and --jmespath (client-side reshaping). They compose freely.
Listing
list always returns the complete result set, not just the first page. There is no
--page/--page-size flag and no partial-results footgun where "list all customers" silently
shows only the first 10.
Under the hood, every list endpoint reports its total via an X-Result-Count response header;
list fetches pages of up to 300 (Waldur's maximum) and keeps going until it has everything,
then merges them into one array before rendering.
1 2 | |
If a page fails partway through a long fetch, the command errors — it never returns a
partial list as if it were complete — and reports how far it got, e.g. fetched 300 of 1200
item(s) before this failed.
Streaming large lists
--format ndjson prints one compact JSON object per line, and for list prints each page as
it arrives instead of fetching the complete result set first. For a large collection, the
first line appears after the first page (up to 300 items) rather than after the whole thing --
lower memory, and a consumer processing output line-by-line (an agent, jq, a shell loop)
can start before the fetch finishes:
1 2 3 4 5 | |
It composes with everything above: --filter/--fields still narrow what's fetched, and
--limit still stops early (mid-page, if needed) without fetching further pages.
The one exception is --jmespath: since a JMESPath expression can reshape or aggregate across
the entire array (sort, slice, count, ...), --format ndjson --jmespath ... falls back to
fetching the complete result first -- same as json/toon -- then prints the (possibly
already-reshaped) result one object per line. Everything still comes out as valid NDJSON; it
just isn't streamed in that combination.
Piping into something that stops reading early (| head) is safe -- the command notices and
stops fetching further pages, rather than continuing to pull data nobody will read.
get/create/update under --format ndjson print their single result object as one
compact line, same shape as json without the pretty-printing. delete and bodyless
action verbs print one such line per UUID -- see
batch operations for running them over several
UUIDs (or a piped-in list --format ndjson) at once.
--filter KEY=VALUE — narrow server-side
--filter (repeatable) filters on the server, so only matching rows come back over the wire.
It replaces having a dedicated flag per field — some resources have 20+ filterable fields —
with one uniform, discoverable flag:
1 2 | |
Each key is validated before any request is made, against the resource's real filter fields and their types (string / bool / int). A typo or a bad value fails locally with the list of valid keys, rather than a wasted round trip — or worse, Waldur silently ignoring an unrecognized filter and returning everything:
1 2 3 4 5 | |
Repeat a key to pass multiple values for a list-valued filter (they're OR'd server-side):
1 | |
Ambient project scope
If you've set a current project, it's
applied automatically as project_uuid to every list that supports it — no --filter
project_uuid= needed. An explicit --filter project_uuid=<other> still overrides it.
Full-text search
Many resources have a query field for full-text search. It's reached through
--filter query=<text> (not a separate flag):
1 | |
--fields — fetch fewer fields
--fields uuid,name tells the server to return only those fields, avoiding the cost of
transferring the complete object when you only need a few keys:
1 | |
table/tsv already do this automatically for their curated columns (they never fetch more
than they display). json/toon fetch the complete object by default; --fields narrows
them, and always overrides the table default when given explicitly.
Like --filter, --fields is validated locally against the field names each resource
accepts (also shown in its --help). This matters because Waldur silently ignores unknown
field names rather than rejecting them — an all-invalid --fields list would quietly fall
back to the complete object — so a typo fails loudly here instead of silently doing the wrong
thing.
--order FIELD — sort server-side
Not every resource supports server-side ordering (--help shows --order only where it
does), but where it's there, it sorts the complete result set before pagination -- unlike
--jmespath, which only reorders whatever page(s) already got fetched:
1 2 3 | |
Where the resource's --order is validated against a known set of fields (most are), an
unrecognized one is rejected locally with the valid list, the same as --filter/--fields.
--order used to only be reachable as --filter o=cores -- that's gone now in favor of this
dedicated flag, since it's easy to miss that ordering was ever a --filter key at all, and
--prefixed values need allow_hyphen_values to parse correctly as a value rather than an
unrecognized short flag (which a raw --filter string never got).
--limit N — fetch fewer objects
--limit caps the number of items, for when a resource has far more results than you need:
1 | |
Beyond convenience, --limit bounds two things: how long a huge fetch takes, and the blast
radius if a page fails mid-fetch — a smaller limit means fewer requests, so a failure on a
page you never needed simply never happens.
--jmespath EXPR — reshape client-side
--jmespath runs a JMESPath expression over the already-fetched
result, client-side, before rendering — Amazon CLI's --query by another name. Use it to
project, filter, or restructure output without a separate jq step:
1 2 3 4 5 6 7 8 9 10 11 | |
--filter vs --jmespath: --filter reduces what's fetched (server-side, fewer bytes
over the wire); --jmespath reshapes what's already fetched (client-side, arbitrary
transforms). They're complementary — filter to cut the data down, then JMESPath to shape it:
1 2 3 | |
(Note: --jmespath, not --query — several resources have their own query filter field,
reached via --filter query=..., so the client-side flag is named distinctly to avoid
shadowing it.)
Getting one resource
get fetches a single resource by UUID and prints the complete object:
1 2 | |
--filter, --fields, --limit, and --jmespath are list-only. To pull specific fields
out of a single object, pipe --format json to jq, or (when you know the UUID from a list)
use list with a uuid filter and --jmespath:
1 | |
Opening a resource in the browser: get --web
Resources with a page in Waldur's web UI (HomePort) get a --web flag on get -- prints and
opens the resource's HomePort URL instead of the object itself, in the style of gh pr view
--web/glab issue view --web:
1 2 | |
Not every resource has a HomePort route, so --web only appears on get --help where it
does -- currently team project/team customer, marketplace resource/marketplace order,
and openstack tenant/instance/volume (the latter three go through the generic
marketplace resource-details page, since OpenStack resources have no dedicated route of their
own).
HomePort's base URL is discovered automatically from Waldur's /api/configuration/ endpoint,
falling back to the API URL itself if that deployment doesn't set it (HomePort and the API are
conventionally served from the same origin). If that's wrong for your deployment, override it
with --homeport-url or the WALDUR_HOMEPORT_URL env var.
Opening a browser is best-effort: over SSH or in any headless environment there's nothing to open, so the URL is always printed first regardless of whether a browser actually launches.