Skip to content

Recipes & tips

Worked examples that combine the pieces from the previous pages, followed by a grab-bag of things worth knowing.

Recipes

Switch between environments safely

Set up a profile per instance once, then pin one for a whole terminal session so you can't fire a command at the wrong place:

1
2
3
4
5
6
7
waldur-cli login --profile prod    --api-url https://waldur.example.com  --token ...
waldur-cli login --profile staging --api-url https://staging.example.com --token ...

# in a given terminal:
export WALDUR_PROFILE=staging
waldur-cli whoami            # confirm before doing anything
waldur-cli team customer list

Build a report from a shell loop

--format tsv is made for while read loops — no jq, no header to skip:

1
2
3
waldur-cli team customer list --format tsv | while IFS=$'\t' read -r uuid name abbr state; do
    printf '%-40s %s\n' "$name" "$uuid"
done

For anything structured, --format json piped to jq — or --jmespath to skip jq entirely:

1
2
3
# projects per customer, as CSV
waldur-cli team project list --format json \
  --jmespath '[].[customer_name, name]' | jq -r '.[] | @csv'

Provision a VPC end-to-end

A complete, CLI-only lifecycle for an OpenStack tenant (VPC):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. find the tenant offering + its plan + your project
OFFERING=$(waldur-cli marketplace offering list \
  --filter type=OpenStack.Tenant --filter name_exact="Demo OpenStack" \
  --format json --jmespath '[0].url')
PLAN=$(waldur-cli marketplace offering list \
  --filter name_exact="Demo OpenStack" \
  --format json --jmespath '[0].plans[0].url')
PROJECT=$(waldur-cli team project list \
  --filter name_exact="My Project" --format json --jmespath '[0].url')

# 2. provision (waits for the order to complete, prints the resource)
waldur-cli openstack tenant provision --request "$(cat <<JSON
{
  "offering": $OFFERING, "project": $PROJECT, "plan": $PLAN,
  "attributes": {"name": "my-vpc"},
  "limits": {"cores": 8, "ram": 16384, "storage": 102400},
  "accepting_terms_of_service": true
}
JSON
)" --format json --jmespath '{name: name, tenant: resource_uuid, mrid: uuid}'

# 3. later, tear it down by its marketplace_resource_uuid (the `mrid`/`uuid` above)
waldur-cli openstack tenant terminate <marketplace_resource_uuid>

Instances need a few things a VPC doesn't

An instance order references a flavor, an image, and a subnet, which live inside a tenant. The CLI can provision the instance and list/get the tenant's networks, subnets, and security groups — but it doesn't expose flavor/image browsing or network creation, so those URLs come from the API or the Waldur UI. Provision a tenant without the skip_creation_of_default_* attributes to get a default network + subnet you can point an instance at.

Feed live inventory to an LLM

Minimise tokens: fetch only the fields that matter, and render as TOON.

1
2
3
waldur-cli openstack instance list \
  --fields uuid,name,state,project_name \
  --format toon

Tips & tricks

  • --generate-skeleton is the fastest way to learn a request body. Before writing any create/update/provision JSON, generate the skeleton — it lists every writable field with a typed placeholder, straight from the live schema.

  • Filter on the server, shape on the client. --filter cuts bytes over the wire; --jmespath restructures what's left. Reach for --filter first (it's cheaper), then --jmespath for the exact shape.

  • --fields speeds up big lists. For a resource with large objects, --fields uuid,name can dramatically cut transfer time — the server sends only what you ask for.

  • --format ndjson for big lists. It streams -- printing each page as it arrives -- so a large list starts producing output immediately instead of going quiet until every page is fetched. Pipes straight into jq -c, a shell while read loop, or an agent processing results incrementally.

  • --filter query=<text> is full-text search. On resources that support it (customers, projects, users, …), the query filter searches across fields, unlike the exact-match field filters.

  • schema emits an OpenAPI-for-the-CLI. If you're building an LLM agent that drives waldur-cli, parsing --help text is fragile. waldur-cli schema outputs a complete JSON description of the command surface — paths, parameters, typed filter keys, and request skeletons — that frameworks can directly ingest as a tool specification. Use --compact if you have a tight context budget and only need paths and descriptions.

  • whoami before anything destructive. One command confirms which instance and identity your credentials currently resolve to — cheap insurance before a delete/terminate.

  • --dry-run before a mutation you're unsure of. It validates and prints the exact request (with any defaults filled in) without sending it — see Managing resources. Great for building up a create/provision body iteratively, or confirming a scripted delete targets what you think it does.

  • --debug shows the actual requests. One line per HTTP call (method, URL, status, timing) on stderr, regardless of --format — invaluable for understanding what a command does or diagnosing a server-side rejection. See Troubleshooting.

  • stdout is always clean. Errors and --debug go to stderr; stdout only ever carries successful output. So ... 2>/dev/null or ... > out.json always gives you exactly the result, and a failed command never pollutes a pipe with half a result.

  • Install shell completions. Tab-completion for groups, resources, verbs, and flags makes the three-level command tree far quicker to navigate — see Troubleshooting.

  • Update easily. Run waldur-cli update to seamlessly download and install the latest release from GitHub, avoiding manual un-tarring or re-running installer scripts.

  • --no-wait for fire-and-forget provisioning. Submitting many orders? --no-wait returns each order immediately; marketplace order wait <uuid> --jmespath "state=='done'" (or any resource's own wait) picks up the polling later, from the same script or a different one entirely -- see Waiting on anything, not just orders.