mirror of
https://github.com/vhaudiquet/ecrou.git
synced 2026-11-12 22:22:44 +00:00
docs(cli): rewrite the command help
Each command keeps a crisp one-liner in the command list and carries its contract in the long help: how an image reference resolves, what provision's two shapes do, why pull exists (run never contacts a registry on a cache hit), and what probe checks. Flag help states the real constraints instead of the shortest noun phrase: the guest path of a share must be absolute, the host environment is never inherited, --capture is refused with --tty, --quiet silences engine and kernel messages.
This commit is contained in:
1 parent
4aadc5d28a
commit
3d999b7be0
1 file changed
+55
-41
+55
-41
@@ -6,71 +6,83 @@ use clap::{Args, Parser, Subcommand};
|
|||||||
#[command(
|
#[command(
|
||||||
name = "ecrou",
|
name = "ecrou",
|
||||||
version,
|
version,
|
||||||
about = "One-shot microVM environments on libkrun",
|
about = "Run commands in disposable microVMs on libkrun",
|
||||||
after_help = "Examples:\n ecrou run -it alpine a shell in the machine\n ecrou run ./rootfs.tar.gz -- uname -a boot a local rootfs archive\n ecrou run -v $PWD:/workspace ubuntu -- make"
|
after_help = "Examples:\n ecrou run -it alpine a shell in the machine\n ecrou run ubuntu -- uname -a one command; its exit code propagates\n ecrou run -v $PWD:/src ubuntu -- make share the working tree into the machine\n ecrou pull alpine fetch or refresh the cache entry\n ecrou probe report what a run would find on this host"
|
||||||
)]
|
)]
|
||||||
pub struct Cli {
|
pub struct Cli {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: Command,
|
pub command: Command,
|
||||||
/// Print diagnostic messages
|
/// Print diagnostics, including engine messages
|
||||||
#[arg(long, global = true)]
|
#[arg(long, global = true)]
|
||||||
pub verbose: bool,
|
pub verbose: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
/// Run a command in a fresh microVM from an image
|
/// Run a command in a fresh microVM
|
||||||
|
///
|
||||||
|
/// IMAGE is a distro name (alpine, ubuntu:noble), an OCI image
|
||||||
|
/// reference (ghcr.io/org/image:tag, ubuntu@sha256:...), or a
|
||||||
|
/// local rootfs archive (a path: ./rootfs.tar.gz). The machine
|
||||||
|
/// boots once for the command, streams its stdio, and the run
|
||||||
|
/// exits with the command's exit code; the machine is thrown
|
||||||
|
/// away. Persistence crosses a --volume share or it does not
|
||||||
|
/// happen.
|
||||||
Run(RunArgs),
|
Run(RunArgs),
|
||||||
/// Bake a command into an image's cache entry: the command runs in
|
/// Bake a provisioned layer over a base image
|
||||||
/// a machine over a freshly prepared rootfs, and the result is
|
///
|
||||||
/// persisted, so every later boot of the image carries what the
|
/// Two shapes. --spec FILE describes the layer in checked-in YAML
|
||||||
/// command installed. Cached entries are reused as-is; --no-cache
|
/// (base, packages, run); the layer is keyed by the file's
|
||||||
/// re-downloads and re-provisions.
|
/// content, so the same spec never provisions twice and a changed
|
||||||
|
/// spec never reuses an old layer, and --layer NAME names it for
|
||||||
|
/// `run --layer NAME`. `provision IMAGE -- COMMAND` bakes the
|
||||||
|
/// command into the image's cache entry itself: every later boot
|
||||||
|
/// of that image carries what the command installed.
|
||||||
Provision {
|
Provision {
|
||||||
/// Distribution name or OCI image reference; the spec's `base`
|
/// Base image: distro name or OCI reference; not needed when
|
||||||
/// when omitted and the spec carries one
|
/// the spec carries a base
|
||||||
image: Option<String>,
|
image: Option<String>,
|
||||||
/// A provisioning spec file (YAML: base, packages, run) — the
|
/// Provisioning spec file (YAML: base, packages, run); the
|
||||||
/// layer it describes is keyed by the file's content, so the
|
/// layer it describes is keyed by the file's content
|
||||||
/// same spec never provisions twice and a changed spec never
|
|
||||||
/// reuses an old layer
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
spec: Option<std::path::PathBuf>,
|
spec: Option<std::path::PathBuf>,
|
||||||
/// Name the provisioned layer, so runs can boot it by name
|
/// Name the provisioned layer, so `run --layer NAME` boots it
|
||||||
/// (`run --layer NAME`) without re-deriving anything
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
layer: Option<String>,
|
layer: Option<String>,
|
||||||
/// Ignore the cache: re-download the base and re-provision
|
/// Ignore the cache: re-download the base and re-provision
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
no_cache: bool,
|
no_cache: bool,
|
||||||
/// The provisioning command. An argument vector after `--` is
|
/// Provisioning command, baked into the image's cache entry
|
||||||
/// taken literally; a single quoted line runs through the
|
/// (use with IMAGE, without --spec)
|
||||||
/// image's shell.
|
|
||||||
#[arg(last = true)]
|
#[arg(last = true)]
|
||||||
command: Vec<String>,
|
command: Vec<String>,
|
||||||
},
|
},
|
||||||
/// Fetch or refresh an image's cache entry without booting it:
|
/// Fetch or refresh an image's cache entry without booting it
|
||||||
/// re-checks unpinned OCI tags against the registry and floating
|
///
|
||||||
/// distro aliases against the distro, downloading only when the
|
/// Unpinned OCI tags are re-checked against the registry digest
|
||||||
/// entry is absent or has moved. `run` never contacts the
|
/// and floating distro aliases (latest, lts, edge) re-resolved;
|
||||||
/// registry on a cached image — this is the refresh operation.
|
/// only an absent or moved entry is downloaded. `run` never
|
||||||
|
/// contacts a registry on a cached image: this is the freshness
|
||||||
|
/// operation, docker-pull semantics.
|
||||||
Pull {
|
Pull {
|
||||||
/// Distribution name or OCI image reference
|
/// Distribution name or OCI image reference
|
||||||
image: String,
|
image: String,
|
||||||
/// Ignore the cache: re-download even when the entry is
|
/// Re-download even when the entry is present and current
|
||||||
/// present and current
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
no_cache: bool,
|
no_cache: bool,
|
||||||
},
|
},
|
||||||
/// Report what a run would find on this host
|
/// Report what a run would find on this host
|
||||||
|
///
|
||||||
|
/// KVM working (device, API version, nested-virt state), the
|
||||||
|
/// engine (libkrun.so.1) loadable, and the image cache usable.
|
||||||
|
/// The support tool and the confinement diagnostic.
|
||||||
Probe,
|
Probe,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct RunArgs {
|
pub struct RunArgs {
|
||||||
/// Distribution name, OCI image reference, or a local rootfs
|
/// Distro name, OCI image reference, or a local rootfs archive
|
||||||
/// archive (a path: ./rootfs.tar.gz, /tmp/rootfs.tar); not needed
|
/// path (./rootfs.tar.gz); not needed with --layer
|
||||||
/// with `--layer`, which boots a provisioned cache entry
|
|
||||||
#[arg(required_unless_present = "layer")]
|
#[arg(required_unless_present = "layer")]
|
||||||
pub image: Option<String>,
|
pub image: Option<String>,
|
||||||
/// Keep the machine's stdin open: the host's stdin feeds the
|
/// Keep the machine's stdin open: the host's stdin feeds the
|
||||||
@@ -83,33 +95,35 @@ pub struct RunArgs {
|
|||||||
pub tty: bool,
|
pub tty: bool,
|
||||||
/// Command to run in the machine; the image's default shell when
|
/// Command to run in the machine; the image's default shell when
|
||||||
/// omitted. An argument vector after `--` is taken literally; a
|
/// omitted. An argument vector after `--` is taken literally; a
|
||||||
/// single quoted line runs through the image's shell.
|
/// single quoted line runs through the image's shell as `sh -c`.
|
||||||
#[arg(last = true)]
|
#[arg(last = true)]
|
||||||
pub command: Vec<String>,
|
pub command: Vec<String>,
|
||||||
/// Directory to share into the machine as HOST:GUEST[:ro] (repeatable)
|
/// Share a host directory into the machine as HOST:GUEST[:ro]
|
||||||
|
/// (repeatable; the guest path must be absolute)
|
||||||
#[arg(short = 'v', long = "volume")]
|
#[arg(short = 'v', long = "volume")]
|
||||||
pub volumes: Vec<String>,
|
pub volumes: Vec<String>,
|
||||||
/// Guest memory size
|
/// Guest memory size (bytes, or with a K/M/G suffix)
|
||||||
#[arg(short = 'm', long, default_value = "1G")]
|
#[arg(short = 'm', long, default_value = "1G")]
|
||||||
pub memory: String,
|
pub memory: String,
|
||||||
/// Guest working directory
|
/// Working directory inside the machine
|
||||||
#[arg(short = 'w', long, default_value = "/")]
|
#[arg(short = 'w', long, default_value = "/")]
|
||||||
pub workdir: String,
|
pub workdir: String,
|
||||||
/// Guest environment KEY=VALUE (repeatable)
|
/// Guest environment KEY=VALUE (repeatable; the host environment
|
||||||
|
/// is never inherited)
|
||||||
#[arg(short = 'e', long = "env")]
|
#[arg(short = 'e', long = "env")]
|
||||||
pub env: Vec<String>,
|
pub env: Vec<String>,
|
||||||
/// Suppress console noise
|
/// Silence engine and kernel messages on the console
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub quiet: bool,
|
pub quiet: bool,
|
||||||
/// Capture the payload's stdout and stderr into files in this
|
/// Capture the payload's stdout and stderr into DIR/stdout and
|
||||||
/// directory: DIR/stdout and DIR/stderr. Created when missing.
|
/// DIR/stderr (incompatible with --tty; created when missing)
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub capture: Option<std::path::PathBuf>,
|
pub capture: Option<std::path::PathBuf>,
|
||||||
/// Ignore the cache and download a fresh image
|
/// Ignore the cache: download the image fresh
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub no_cache: bool,
|
pub no_cache: bool,
|
||||||
/// Boot a named provisioned layer (see `provision --layer`)
|
/// Boot a named provisioned layer (see provision --layer)
|
||||||
/// instead of resolving an image
|
/// instead of an image
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub layer: Option<String>,
|
pub layer: Option<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user