feat(cli): ecrou provision bakes a command into a cache entry

prepare_provisioned and persist were sitting there with no consumer:
the machinery for "install once, every later boot carries it" that
one-shot machines cannot do on their own - packages, users, anything
short of a share - and no way to reach it.

ecrou provision IMAGE -- COMMAND is the missing surface. It boots a
machine over a freshly prepared rootfs, runs the command, and
persists the tree into the cache entry, marked provisioned; a marked
entry is extracted as-is on every later call, the command skipped.
A failing command leaves the entry unprovisioned for the next
attempt, and --no-cache re-downloads before re-provisioning.

The engine behind run splits out as vm::run_prepared: the boot half
of run, taking the rootfs the provisioner is about to persist. run
itself is prepare plus that.

One cache fix the provision flow surfaced: a digest refresh replaced
the tarball but left the old .provisioned marker, so a fresh pristine
image would present as provisioned and skip provisioning for good.
The marker now dies with the entry it belonged to.
This commit is contained in:
vhaudiquet committed 2026-10-28 16:20:37 +01:00
1 parent 1fb3f0c076
commit d9f9c79dc4
5 files changed
+117 -9

No files matched your search

+12
View File
@@ -269,6 +269,7 @@ composable. A boot failure leaves the files absent.
```
ecrou run [OPTIONS] <IMAGE> [-- COMMAND...]
ecrou provision [OPTIONS] <IMAGE> [-- COMMAND...]
ecrou probe
```
@@ -283,6 +284,17 @@ ecrou probe
| `--no-cache` | false | Fresh download, ignore the cache |
| `-v, --verbose` | false | Diagnostics; raises the libkrun log level |
`ecrou provision IMAGE -- COMMAND` bakes a command into the image's
cache entry: the command runs in a machine over a freshly prepared
rootfs and the result is persisted, so every later boot of that image
carries what the command installed — packages, users, whatever a
one-shot boot cannot keep. A marked entry is reused as-is (the
command is skipped), `--no-cache` re-downloads and re-provisions, and
a failing command leaves the entry unprovisioned for the next attempt.
The marker dies with the entry: a digest refresh drops it, so a moved
upstream image is provisioned again, never silently served pristine
under an old marker.
`ecrou probe` reports what a run would find: KVM working (open, ioctl
version, nested-virt state), `libkrun.so.1` loadable, the cache
directory writable. It is the confinement diagnostic and the support