1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Integration smoke for the v0.2 stable surface:
//!
//! - `Image::start` — one-shot VM
//! - `Vm::write_file` / `Vm::read_file`
//! - `ExecBuilder::output() -> ExecOutcome` with `.timeout()`
//!
//! ## Important: in-process VM cardinality
//!
//! macOS `hv_vm_create` is a process-wide singleton — one
//! embedding process can host **one** Vm at a time. To run
//! many VMs concurrently from a single Rust app, use the CLI's
//! pool (`supermachine-router --workers-per-snapshot N`) which
//! spawns separate worker subprocesses. A future v0.2.x will
//! make `Image::acquire` transparently spawn workers in the
//! same shape, so you'll write the same code and get N VMs.
//!
//! Usage:
//!
//! ```sh
//! supermachine run nginx:1.27-alpine --detach && supermachine run --stop
//! cargo run --release --example v02_surface
//! ```
use std::time::Duration;
use supermachine::{Image, VmConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let snap_path = std::env::args().nth(1).unwrap_or_else(|| {
format!(
"{}/.local/supermachine-snapshots/nginx_1_27-alpine",
std::env::var("HOME").unwrap()
)
});
let image = Image::from_snapshot(&snap_path)?;
println!("=== image.start() + write_file/read_file + timeout ===");
let vm = image.start(&VmConfig::new())?;
// 1. exec with output()
let out = vm
.exec_builder()
.argv(["echo", "hello from start()"])
.timeout(Duration::from_secs(5))
.output()?;
println!(
" echo: status={:?} duration={:?} peak_rss_kib={:?} stdout={:?}",
out.status.code(),
out.duration,
out.peak_rss_kib,
String::from_utf8_lossy(&out.stdout).trim_end()
);
// 2. write_file + read_file round-trip
vm.write_file("/tmp/v02-test.txt", b"v0.2 surface works\n")?;
let bytes = vm.read_file("/tmp/v02-test.txt")?;
println!(
" write/read round-trip: {:?}",
String::from_utf8_lossy(&bytes).trim_end()
);
// 3. timeout fires on a slow command
let out = vm
.exec_builder()
.argv(["sh", "-c", "sleep 10; echo never"])
.timeout(Duration::from_millis(500))
.output()?;
println!(
" timeout: timed_out={} duration={:?} status={:?}",
out.timed_out,
out.duration,
out.status.code()
);
vm.stop()?;
println!("OK");
Ok(())
}