Skip to content

feat(kvp): add libazureinit-kvp CLI#309

Merged
cjp256 merged 4 commits into
Azure:mainfrom
peytonr18:probertson-kvp-cli
Jun 18, 2026
Merged

feat(kvp): add libazureinit-kvp CLI#309
cjp256 merged 4 commits into
Azure:mainfrom
peytonr18:probertson-kvp-cli

Conversation

@peytonr18

@peytonr18 peytonr18 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a libazureinit-kvp command-line interface around the existing KVP store APIs, supporting development, debugging, and operational workflows against Azure/Hyper-V KVP pool files. The CLI can inspect pool metadata, read/write/delete records, bulk-load records, clear stale data, and check staleness.

Adds clap (derive) as a direct dependency on libazureinit-kvp.

Usage

The CLI operates on one pool at a time. Defaults: pool guest, safe mode, default Hyper-V KVP directory.

libazureinit-kvp info
libazureinit-kvp --pool guest --dir /var/lib/hyperv info
libazureinit-kvp --pool 1 --unsafe dump

Global options (valid with any command):

  • --pool <POOL>external/0, guest/1, auto/2, auto-external/3, auto-internal/4
  • --dir <PATH> — pool directory
  • --unsafe — use the full wire-format key/value limits instead of the safe profile

Commands

Command Description
info Print store metadata: pool, path, mode, record count, empty/stale state, and key/value size limits.
dump Print every record in insertion order as KEY=VALUE; duplicates preserved.
entries Print one KEY=VALUE per key (last value wins), sorted by key.
read <KEY> Print the last value for a key. Exit 1 if missing.
write [--append] <KEY> <VALUE> Write a record. Replaces existing records for KEY unless --append is set.
load [--file PATH] Replace pool contents from KEY=VALUE lines (file or stdin).
delete <KEY> Delete every record for a key; prints true/false.
clear [--yes] [--if-stale] Clear the pool. Requires --yes unless --if-stale is set.
is-stale Print whether the pool is stale. Exit 0 if stale, 1 if not.

Examples:

libazureinit-kvp write hostname vm-01
libazureinit-kvp write --append history booted
printf 'a=1\nb=2\n' | libazureinit-kvp load
libazureinit-kvp clear --if-stale

Exit codes

  • 0 — success
  • 1 — not found / false status (missing key, is-stale=false)
  • 2 — usage or validation error
  • 3 — I/O error

KVP store validation errors surface as CLI errors on stderr. read of a missing key writes nothing to stderr.

Test Coverage

Filename                      Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
cli.rs                            917                37    95.97%          52                 0   100.00%         510                 0   100.00%           0                 0         -
error.rs                           39                 0   100.00%           3                 0   100.00%          21                 0   100.00%           0                 0         -
main.rs                             3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
store.rs                         4661                51    98.91%         264                 0   100.00%        2142                 0   100.00%           0                 0         -
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                            5620                88    98.43%         320                 0   100.00%        2676                 0   100.00%           0                 0         -

Replace the handwritten libazureinit-kvp argument parser with clap-derived
command and option parsing. Keep existing command behavior, including numeric
pool aliases, while adding generated help output and validation.

Expose the CLI through the library run entrypoint, add a binary main, and expand
CLI integration coverage for help, metadata, read/write/load/delete/clear flows,
stdin loading, missing keys, and validation errors.
@codecov-commenter

codecov-commenter commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.32%. Comparing base (1d4df06) to head (9768a5a).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #309      +/-   ##
==========================================
+ Coverage   94.78%   95.32%   +0.53%     
==========================================
  Files          19       21       +2     
  Lines        6348     7076     +728     
==========================================
+ Hits         6017     6745     +728     
  Misses        331      331              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Some(dir) => KvpPoolStore::new_in(pool, dir, mode),
None => KvpPoolStore::new(pool, mode),
}
.expect("KvpPoolStore construction is currently infallible");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol

@peytonr18 peytonr18 Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had just a simple ? since it can't fail, but that breaks the cargo-llvm coverage since it introduces a new path that we can't actually hit. This was the alternative solution lol

@cjp256 cjp256 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load actually sounds better than populate. maybe we should rename populate too.

i think --yes is overkill for clear. None of this data is sacred and generally overwritten on reboot.

--json will be useful for outputs I think. entries key=value gets awkward if there are newlines unless we encode it, etc.

- Rename KvpPoolStore::populate (and Command::Load) to load.
- Drop --yes from clear; --if-stale unchanged.
- Add global --json flag with machine-readable output for info, dump,
  entries, read, delete, delete-multiple, and is-stale. Adds serde_json.
- Consolidate tests: merge the two clear dispatch tests into one rstest,
  fold --json parse assertions into existing globals/defaults tests, and
  drop redundant JSON tests already covered elsewhere.
@peytonr18

Copy link
Copy Markdown
Contributor Author

load actually sounds better than populate. maybe we should rename populate too.

i think --yes is overkill for clear. None of this data is sacred and generally overwritten on reboot.

--json will be useful for outputs I think. entries key=value gets awkward if there are newlines unless we encode it, etc.

Addressed all of these in the latest commit! I was trying to avoid adding too many dependencies to keep the size minimal but I agree that --json would be super helpful to have.

I also like load() instead of populate() so I went ahead and renamed that function.

@cjp256 cjp256 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@cjp256 cjp256 merged commit a3f512f into Azure:main Jun 18, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants