| e0918b88 Andy McCall |
1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
use std::process::Command; |
| 6 |
|
| 7 |
#[test] |
| 8 |
fn a_pipeline_runs_isolated_in_microvms() { |
| 9 |
let (Some(home), Some(rootfs)) = (std::env::var_os("FLOW_TEST_HOME"), std::env::var("FLOW_TEST_ROOTFS").ok()) else { |
| 10 |
eprintln!("skipped: set FLOW_TEST_HOME and FLOW_TEST_ROOTFS to boot microVMs"); |
| 11 |
return; |
| 12 |
}; |
| 13 |
let dir = tempfile::tempdir().unwrap(); |
| 14 |
std::fs::create_dir_all(dir.path().join(".flow")).unwrap(); |
| 15 |
std::fs::write( |
| 16 |
dir.path().join(".flow/pipeline.kdl"), |
| 17 |
format!( |
| 18 |
r#"schema-version 1 |
| 19 |
sandbox "alpine" {{ |
| 20 |
rootfs "cas://blob/{rootfs}" |
| 21 |
memory-limit "256MiB" |
| 22 |
}} |
| 23 |
job "literal" {{ |
| 24 |
sandbox "alpine" |
| 25 |
exec "echo" "a; touch /src/pwned && $(id) | `id`" |
| 26 |
}} |
| 27 |
job "isolated" {{ |
| 28 |
sandbox "alpine" |
| 29 |
exec "sh" "-c" "cat /proc/net/dev | tail -n +3 | cut -d: -f1 | tr -d ' '; wget -q -T 2 -O /dev/null http://1.1.1.1 && echo NETWORK || echo no-network" |
| 30 |
}} |
| 31 |
job "readonly" {{ |
| 32 |
sandbox "alpine" |
| 33 |
exec "sh" "-c" "touch /etc/x 2>/dev/null && echo ROOTFS-WRITABLE; echo ok > /src/w && cat /src/w; id -u" |
| 34 |
}} |
| 35 |
job "fails" {{ |
| 36 |
sandbox "alpine" |
| 37 |
exec "false" |
| 38 |
}} |
| 39 |
job "after-failure" {{ |
| 40 |
sandbox "alpine" |
| 41 |
depends-on "fails" |
| 42 |
exec "echo" "SHOULD-NOT-RUN" |
| 43 |
}} |
| 44 |
"# |
| 45 |
), |
| 46 |
) |
| 47 |
.unwrap(); |
| 48 |
let out = Command::new(env!("CARGO_BIN_EXE_flow")).arg("--home").arg(&home).arg("run").current_dir(dir.path()).output().unwrap(); |
| 49 |
let stdout = String::from_utf8_lossy(&out.stdout); |
| 50 |
assert!(!out.status.success(), "a failed job fails the run"); |
| 51 |
assert!(stdout.contains(" a; touch /src/pwned && $(id) | `id`\n"), "argv is literal: {stdout}"); |
| 52 |
assert!(!dir.path().join("pwned").exists()); |
| 53 |
assert!(stdout.contains(" lo\n") && stdout.contains("no-network") && !stdout.contains(" NETWORK\n"), "only loopback: {stdout}"); |
| 54 |
assert!(stdout.contains(" ok\n") && !stdout.contains(" ROOTFS-WRITABLE\n"), "rootfs read-only, workspace writable: {stdout}"); |
| 55 |
assert!(!stdout.contains(" 0\n"), "the job never runs as root: {stdout}"); |
| 56 |
assert!(stdout.contains("── fails failed (exit 1)"), "{stdout}"); |
| 57 |
assert!(stdout.contains("── after-failure skipped: fails failed") && !stdout.contains(" SHOULD-NOT-RUN\n"), "{stdout}"); |
| 58 |
} |