Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

dyn-admin: cluster admin CLI

dyn-admin is the operator-facing CLI that ships alongside dynomited. It is the Dynomite Rust port's answer to Riak's riak-admin tool: a single binary an operator points at one running node and asks structured questions of. The subcommand surface is intentionally narrow in v0; mutating operations land in v1 once the gossip substrate exposes the necessary admin-only DNODE messages.

Connecting

Every subcommand reads from a running node over one of two ports:

PortDefaultUsed by
PBC (Riak Protocol Buffers)127.0.0.1:8087ping, status, ring-status, cluster-list, cluster-join, cluster-leave, cluster-plan, cluster-commit, aae-status
Stats / metrics HTTP127.0.0.1:22222stats, metrics, distribution-dump (and status/ring-status augmentation)

Override the address with --node <host:port> (or --seed for cluster-list). status and ring-status accept --stats-node to reach a stats endpoint that lives on a different host or port, and --no-stats to skip the HTTP fetch entirely.

Subcommands

ping

Sends RpbPingReq and times the round-trip:

$ dyn-admin ping
PONG from 127.0.0.1:8087 (1.234 ms)
$ dyn-admin ping --json | jq .rtt_us
1234

Exit code 0 on success. Non-zero exit and an error printed on stderr otherwise.

status

Reads RpbGetServerInfoResp from the PBC port and combines it with a slice of the /stats JSON snapshot:

$ dyn-admin status
node: 127.0.0.1:8087
server_node: dyniak
server_version: dyniak 0.0.1
engine_source: node-a
engine_version: 0.0.1
datacenter: dc1
rack: r1
uptime_seconds: 7
pool: dyn_o_mite

When the stats endpoint is unreachable, the human formatter notes stats: unavailable (...) and the JSON formatter sets stats: null plus stats_error: "...".

ring-status

Best-effort ring/topology view. The substrate does not yet expose a multi-peer ring map over PBC, so the v0 output is a single-row table for the contacted node:

$ dyn-admin ring-status
Ring status (queried 127.0.0.1:8087)

node                          dc          rack        state   version               token
----------------------------  ----------  ----------  ------  --------------------  --------
node-a                        dc1         r1          up      dyniak 0.0.1        <unset>

token and richer per-vnode state become populated once the substrate gossips a peer table over PBC. Until then the column is present so the output shape is forward-compatible.

stats

Pretty-prints the high-value fields from the /stats JSON snapshot. --json echoes the raw snapshot byte-for-byte so downstream jq filters keep working:

$ dyn-admin stats
engine_source: node-a
engine_version: 0.0.1
datacenter: dc1
rack: r1
uptime_seconds: 7
pool: dyn_o_mite
latency_p99_us: 1234
latency_max_us: 2345
alloc_msgs: 10
free_msgs: 5

$ dyn-admin stats --json | jq '.dyn_o_mite.client_eof'
0

metrics

Forwards the /metrics Prometheus text endpoint verbatim:

$ dyn-admin metrics | head -3
# HELP dynomite_uptime_seconds Uptime in seconds.
# TYPE dynomite_uptime_seconds gauge
dynomite_uptime_seconds 7

A trailing newline is appended when the upstream body lacks one, so the output is always safe to pipe into line-oriented tools.

cluster-list

Reports what the seed knows about itself, plus a note recording the deferred multi-peer discovery. Once peer-list messages land, the loop here grows naturally:

$ dyn-admin cluster-list --seed 127.0.0.1:8087
Cluster (seed 127.0.0.1:8087)

addr                      node                          state   version
------------------------  ----------------------------  ------  --------------------
127.0.0.1:8087            dyniak                      up      dyniak 0.0.1

note: multi-peer discovery deferred: substrate does not yet expose a peer-list message
      over PBC; reporting only the contacted seed

bucket-props

Inspects or updates a bucket's RpbBucketProps over PBC. Two actions:

  • get <bucket> issues an RpbGetBucketReq and pretty-prints the reply.
  • set <bucket> [flags] reads the current properties first, applies the named overrides on top, and submits an RpbSetBucketReq. Fields the operator does not name are sent back unchanged so the update is always a partial overlay.
$ dyn-admin bucket-props get users
Bucket properties for users via 127.0.0.1:8087
  n_val: 3
  keyfun: std
  replication_strategy: successors

$ dyn-admin bucket-props set users --n-val 5 --keyfun bucketonly
Updated bucket properties for users via 127.0.0.1:8087
  n_val: 5
  keyfun: bucketonly
  replication_strategy: successors

$ dyn-admin bucket-props get users --json | jq '.props.n_val'
5

Flags accepted by set:

FlagValuesMeaning
--n-val Nnon-negative integerReplication factor.
--read-consistency Cone, quorum, all, default, integerDefault replica-read quorum (Riak r).
--write-consistency Csame as --read-consistencyDefault replica-write quorum (Riak w).
--keyfun KFstd, bucketonlyPre-hash strategy.
--replication-strategy STRATtopology, successorsReplica-target selection strategy.

The symbolic quorum names map to Riak's published magic uint32 values so a Riak client and dyn-admin agree on the semantics. set rejects an empty flag list with a hard error rather than a no-op round-trip.

See riak.md for the bucket-property semantics and the locations in the registry where the values are stored.

aae-status

Returns a snapshot of the AAE worker's state: per-peer last-exchange wall-clock time, per-peer divergent-key counts since the most recent full sweep, the configured snapshot path, last save / last load wall-clock times, and the local tree shape (time-buckets * segments) plus a memory estimate:

$ dyn-admin aae-status
AAE status (node 127.0.0.1:8087)

 peer  dc          rack             last_exchange    divergent    repaired
-----  ----------  ----------  ----------------  -----------  ----------
    0  dc1         rA               1700000000           12           9
    1  dc1         rB                        0            0           0

snapshot_path: /var/lib/dynomite/aae/tree.snapshot
snapshot_last_save_unix: 1700000300
snapshot_last_load_unix: 0
snapshot_save_total: 5
snapshot_load_total: 0
snapshot_corruption_total: 0
tree: 24 time-buckets * 1024 segments, window 3600s, ~4096 bytes
2 peer(s)

The JSON form returns the same fields as a stable object suitable for jq filters and dashboard pipelines:

$ dyn-admin aae-status --json | jq .snapshot_save_total
5

When the embedding has not wired an AaeStatusProvider (the default dynomited build does not), the response is an empty snapshot; the CLI prints 0 peer(s) and zero values for every counter rather than failing.

Output formats

  • Default: human-readable. One key: value pair per line for the scalar subcommands; bordered tables for ring-status and cluster-list.
  • --json: pretty-printed JSON. The schema is stable across patch releases of the v0 line; breaking changes ship under a major bump and are recorded in docs/journal/.

Exit codes

  • 0: success.
  • 1: any subcommand-level failure (connection refused, timeout, server error, malformed response). The reason is written to stderr as dyn-admin: <error>.
  • 2: bootstrap failure (tokio runtime). Rare.

Deferred subcommands

The following riak-admin mutating commands are listed in docs/riak-compat-plan.md Section 5 but absent in v0:

  • cluster-join
  • cluster-leave
  • cluster-plan
  • cluster-commit

They are not stubbed; clap rejects them as unknown. The journal entry docs/journal/2026-05-24-dyn-admin-v0.md captures the sequencing: each one needs an admin-only DNODE message that the substrate has not yet exposed, plus a confirmation prompt and a dry-run cluster-plan step before any state mutation.