-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests: add integration tests for OCI seccomp and devices support.
Signed-off-by: Ismo Puustinen <[email protected]>
- Loading branch information
Showing
6 changed files
with
422 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
[package] | ||
name = "oci-tests" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
anyhow = { workspace = true } | ||
chrono = { workspace = true } | ||
containerd-shim-wasm = { path = "../../crates/containerd-shim-wasm" } | ||
containerd-shim-wasmedge = { path = "../../crates/containerd-shim-wasmedge" } | ||
containerd-shim-wasmtime = { path = "../../crates/containerd-shim-wasmtime" } | ||
libc = { workspace = true } | ||
oci-spec = { workspace = true } | ||
serde = { workspace = true } | ||
serde_json = { workspace = true } | ||
tempfile = "3.0" | ||
wasmedge-sdk = { version = "0.10.1", features = [ "standalone", "static" ] } | ||
wasmtime = { version = "11.0", default-features = false, features = [ | ||
'cache', | ||
'wat', | ||
'jitdump', | ||
'parallel-compilation', | ||
'cranelift', | ||
'pooling-allocator', | ||
'vtune', | ||
]} | ||
|
||
[dev-dependencies] | ||
tempfile = "3.0" | ||
pretty_assertions = "1" | ||
serial_test = "*" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
use std::fs::{create_dir, read_to_string, File, OpenOptions}; | ||
use std::io::prelude::*; | ||
use std::os::unix::fs::OpenOptionsExt; | ||
use std::path::{Path, PathBuf}; | ||
use std::sync::mpsc::channel; | ||
use std::time::Duration; | ||
|
||
use libc::SIGKILL; | ||
use oci_spec::runtime::Spec; | ||
use serde::{Deserialize, Serialize}; | ||
use tempfile::tempdir; | ||
|
||
use containerd_shim_wasm::sandbox::instance::Wait; | ||
use containerd_shim_wasm::sandbox::{EngineGetter, Error, Instance, InstanceConfig}; | ||
|
||
#[derive(Serialize, Deserialize)] | ||
struct Options { | ||
root: Option<PathBuf>, | ||
} | ||
|
||
pub static WASM_FILENAME: &str = "./file.wasm"; | ||
|
||
pub(crate) fn get_external_wasm_module(name: String) -> Result<Vec<u8>, Error> { | ||
let manifest_dir = env!("CARGO_MANIFEST_DIR"); | ||
let target = Path::new(manifest_dir) | ||
.join("../../target/wasm32-wasi/debug") | ||
.join(name.clone()); | ||
std::fs::read(target).map_err(|e| { | ||
Error::Others(format!( | ||
"failed to read requested Wasm module ({}): {}. Perhaps you need to run 'make test/wasm-modules' first.", | ||
name, e | ||
)) | ||
}) | ||
} | ||
|
||
pub(crate) fn run_test_with_spec<I, E>(spec: &Spec, bytes: &[u8]) -> Result<(String, u32), Error> | ||
where | ||
I: Instance<E = E> + EngineGetter<E = E>, | ||
E: Sync + Send + Clone, | ||
{ | ||
let dir = tempdir().unwrap(); | ||
create_dir(dir.path().join("rootfs"))?; | ||
let rootdir = dir.path().join("runwasi"); | ||
create_dir(&rootdir)?; | ||
let opts = Options { | ||
root: Some(rootdir), | ||
}; | ||
let opts_file = OpenOptions::new() | ||
.read(true) | ||
.create(true) | ||
.truncate(true) | ||
.write(true) | ||
.open(dir.path().join("options.json"))?; | ||
write!(&opts_file, "{}", serde_json::to_string(&opts)?)?; | ||
|
||
let wasm_path = dir.path().join("rootfs").join(WASM_FILENAME); | ||
let mut f = OpenOptions::new() | ||
.write(true) | ||
.create(true) | ||
.truncate(true) | ||
.mode(0o755) | ||
.open(wasm_path)?; | ||
f.write_all(bytes)?; | ||
|
||
let stdout = File::create(dir.path().join("stdout"))?; | ||
drop(stdout); | ||
|
||
spec.save(dir.path().join("config.json"))?; | ||
|
||
let mut cfg = InstanceConfig::new( | ||
I::new_engine()?, | ||
"test_namespace".into(), | ||
"/containerd/address".into(), | ||
); | ||
let cfg = cfg | ||
.set_bundle(dir.path().to_str().unwrap().to_string()) | ||
.set_stdout(dir.path().join("stdout").to_str().unwrap().to_string()); | ||
|
||
let wasi = I::new("test".to_string(), Some(cfg)); | ||
|
||
wasi.start()?; | ||
|
||
let (tx, rx) = channel(); | ||
let waiter = Wait::new(tx); | ||
wasi.wait(&waiter).unwrap(); | ||
|
||
let res = match rx.recv_timeout(Duration::from_secs(600)) { | ||
Ok(res) => res, | ||
Err(e) => { | ||
wasi.kill(SIGKILL as u32).unwrap(); | ||
return Err(Error::Others(format!( | ||
"error waiting for module to finish: {0}", | ||
e | ||
))); | ||
} | ||
}; | ||
wasi.delete()?; | ||
let output = read_to_string(dir.path().join("stdout"))?; | ||
Ok((output, res.0)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use std::borrow::Cow; | ||
use std::path::PathBuf; | ||
|
||
use serde::{Deserialize, Serialize}; | ||
use serial_test::serial; | ||
use oci_spec::runtime::{ProcessBuilder, RootBuilder, SpecBuilder}; | ||
use wasmedge_sdk::Vm as WasmEdgeVm; | ||
use wasmtime::Engine as WasmtimeVm; | ||
|
||
use containerd_shim_wasm::function; | ||
use containerd_shim_wasm::sandbox::testutil::{has_cap_sys_admin, run_test_with_sudo}; | ||
use containerd_shim_wasm::sandbox::Error; | ||
|
||
use containerd_shim_wasmedge::instance::Wasi as WasmEdgeWasi; | ||
use containerd_shim_wasmtime::instance::Wasi as WasmtimeWasi; | ||
|
||
#[derive(Serialize, Deserialize)] | ||
struct Options { | ||
root: Option<PathBuf>, | ||
} | ||
|
||
mod common; | ||
|
||
#[test] | ||
#[serial] | ||
fn test_has_default_devices() -> Result<(), Error> { | ||
if !has_cap_sys_admin() { | ||
println!("running test with sudo: {}", function!()); | ||
return run_test_with_sudo("test_has_default_devices"); | ||
} | ||
|
||
let wasmbytes = common::get_external_wasm_module("has-default-devices.wasm".to_string())?; | ||
|
||
let spec = SpecBuilder::default() | ||
.root(RootBuilder::default().path("rootfs").build()?) | ||
.process( | ||
ProcessBuilder::default() | ||
.cwd("/") | ||
.args(vec![common::WASM_FILENAME.to_string()]) | ||
.build()?, | ||
) | ||
.build()?; | ||
|
||
let bytes = Cow::from(wasmbytes); | ||
|
||
let (output, retval) = common::run_test_with_spec::<WasmtimeWasi, WasmtimeVm>(&spec, &bytes)?; | ||
assert_eq!(retval, 0, "error: {}", output); | ||
|
||
let (output, retval) = common::run_test_with_spec::<WasmEdgeWasi, WasmEdgeVm>(&spec, &bytes)?; | ||
assert_eq!(retval, 0, "error: {}", output); | ||
|
||
Ok(()) | ||
} |
Oops, something went wrong.