diff --git a/Cargo.lock b/Cargo.lock index b1da41ce..5068f5bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,37 +275,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - [[package]] name = "dyn-clone" version = "1.0.11" @@ -448,18 +417,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -901,19 +858,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "oci-spec" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9421b067205c68dc80af7c68599a9c1eb113f975aafeb874cea7f4d5d41ce3fb" -dependencies = [ - "derive_builder", - "getset", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "once_cell" version = "1.18.0" @@ -1056,30 +1000,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.66" @@ -1576,14 +1496,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utils" -version = "0.9.0" -dependencies = [ - "anyhow", - "oci-spec", -] - [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index f36a9f3c..1bb4f574 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,5 @@ homepage = "https://github.com/deislabs/containerd-wasm-shims" [workspace] resolver = "2" members = [ - "utils", "tests" ] \ No newline at end of file diff --git a/containerd-shim-lunatic-v1/Cargo.lock b/containerd-shim-lunatic-v1/Cargo.lock index 78df7af5..0a697cb8 100644 --- a/containerd-shim-lunatic-v1/Cargo.lock +++ b/containerd-shim-lunatic-v1/Cargo.lock @@ -587,21 +587,13 @@ dependencies = [ "clap", "containerd-shim", "containerd-shim-wasm", - "libc", - "libcontainer", "log", "lunatic-distributed", "lunatic-process", "lunatic-process-api", "lunatic-runtime", - "nix 0.26.4", - "oci-spec", "openssl", - "serde", - "serde_json", - "thiserror", "tokio", - "utils", ] [[package]] @@ -618,7 +610,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -637,6 +629,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -1713,8 +1706,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libcgroups" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" dependencies = [ "fixedbitset 0.4.2", "nix 0.26.4", @@ -1727,8 +1721,9 @@ dependencies = [ [[package]] name = "libcontainer" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" dependencies = [ "bitflags 2.4.0", "caps", @@ -3843,14 +3838,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "utils" -version = "0.9.1" -dependencies = [ - "anyhow", - "oci-spec", -] - [[package]] name = "uuid" version = "1.4.1" diff --git a/containerd-shim-lunatic-v1/Cargo.toml b/containerd-shim-lunatic-v1/Cargo.toml index 159c5daf..5cface33 100644 --- a/containerd-shim-lunatic-v1/Cargo.toml +++ b/containerd-shim-lunatic-v1/Cargo.toml @@ -7,14 +7,8 @@ edition = "2021" [dependencies] containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } -libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } -nix = "0.26.2" -serde = "1.0.183" -serde_json = "1.0.104" -thiserror = "1.0.44" +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } log = "~0.4" -libc = "0.2.147" anyhow = "1.0.72" chrono = { version = "0.4.26", features = ["std"] } lunatic-process = { git = "https://github.com/lunatic-solutions/lunatic", tag = "v0.13.2"} @@ -23,8 +17,7 @@ lunatic-distributed = { git = "https://github.com/lunatic-solutions/lunatic", ta lunatic-runtime = { git = "https://github.com/lunatic-solutions/lunatic", tag = "v0.13.2"} clap = { version = "4.0", features = ["cargo", "derive"] } tokio = "1.30.0" -oci-spec = "0.6.2" -utils = { path = "../utils" } + # https://github.com/sfackler/rust-openssl/issues/603#issuecomment-822619837 openssl = { version = "0.10", features = ["vendored"] } diff --git a/containerd-shim-lunatic-v1/src/engine.rs b/containerd-shim-lunatic-v1/src/engine.rs new file mode 100644 index 00000000..c5d6c331 --- /dev/null +++ b/containerd-shim-lunatic-v1/src/engine.rs @@ -0,0 +1,68 @@ +use anyhow::{Context, Result}; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::runtime::Runtime; + +use containerd_shim_wasm::container::{Engine, RuntimeContext, Stdio}; +use lunatic_process::{ + env::{Environments, LunaticEnvironments}, + runtimes, +}; + +use crate::common::{run_wasm, RunWasm}; + +#[derive(Clone, Default)] +pub struct LunaticEngine; + +impl Engine for LunaticEngine { + fn name() -> &'static str { + "lunatic" + } + + fn run_wasi(&self, ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; + let cmd = ctx.entrypoint().context("no cmd provided")?; + let rt = Runtime::new().context("failed to create runtime")?; + rt.block_on(exec(cmd.to_owned()))?; + Ok(0) + } +} + +async fn exec(cmd: PathBuf) -> Result<()> { + log::info!(" >>> lunatic wasm binary: {:?}", cmd); + // Create wasmtime runtime + let wasmtime_config = runtimes::wasmtime::default_config(); + let runtime = runtimes::wasmtime::WasmtimeRuntime::new(&wasmtime_config)?; + let envs = Arc::new(LunaticEnvironments::default()); + + let env = envs.create(1).await; + run_wasm(RunWasm { + path: cmd, + wasm_args: vec![], + dir: vec![], + runtime, + envs, + env, + distributed: None, + }) + .await +} + +#[cfg(test)] +mod tests { + use crate::engine::exec; + + #[tokio::test] + async fn test() { + if let Err(error) = exec( + "../images/lunatic/target/wasm32-wasi/release/wasi-hello-world.wasm" + .to_string() + .into(), + ) + .await + { + panic!("Problem opening the file: {:?}", error) + } + } +} diff --git a/containerd-shim-lunatic-v1/src/executor.rs b/containerd-shim-lunatic-v1/src/executor.rs deleted file mode 100644 index 65326389..00000000 --- a/containerd-shim-lunatic-v1/src/executor.rs +++ /dev/null @@ -1,93 +0,0 @@ -use anyhow::{Context, Result}; -use std::path::PathBuf; -use std::sync::Arc; -use tokio::runtime::Runtime; - -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; -use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use lunatic_process::{ - env::{Environments, LunaticEnvironments}, - runtimes, -}; -use oci_spec::runtime::Spec; -use utils::{get_args, is_linux_executable}; - -use crate::common::{run_wasm, RunWasm}; - -#[derive(Clone)] -pub struct LunaticExecutor { - stdio: Stdio, -} - -impl LunaticExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } - } - - fn wasm_exec(&self, spec: &Spec) -> anyhow::Result<()> { - self.stdio - .take() - .redirect() - .context("failed to redirect stdio")?; - let cmd = get_args(spec).first().context("no cmd provided")?.clone(); - let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(async { - log::info!(" >>> building lunatic application"); - crate::executor::exec(cmd).await - }) - } -} - -impl Executor for LunaticExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(e) = self.wasm_exec(spec) { - log::error!(" >>> error: {:?}", e); - std::process::exit(137); - } - std::process::exit(0); - } - } - - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) - } -} - -pub async fn exec(cmd: String) -> Result<()> { - log::info!(" >>> lunatic wasm binary: {:?}", cmd); - // Create wasmtime runtime - let wasmtime_config = runtimes::wasmtime::default_config(); - let runtime = runtimes::wasmtime::WasmtimeRuntime::new(&wasmtime_config)?; - let envs = Arc::new(LunaticEnvironments::default()); - - let env = envs.create(1).await; - run_wasm(RunWasm { - path: PathBuf::from(cmd), - wasm_args: vec![], - dir: vec![], - runtime, - envs, - env, - distributed: None, - }) - .await -} - -#[cfg(test)] -mod tests { - #[tokio::test] - async fn test() { - if let Err(error) = crate::executor::exec( - "../images/lunatic/target/wasm32-wasi/release/wasi-hello-world.wasm".to_string(), - ) - .await - { - panic!("Problem opening the file: {:?}", error) - } - } -} diff --git a/containerd-shim-lunatic-v1/src/main.rs b/containerd-shim-lunatic-v1/src/main.rs index 248fc06c..db162c72 100644 --- a/containerd-shim-lunatic-v1/src/main.rs +++ b/containerd-shim-lunatic-v1/src/main.rs @@ -1,85 +1,15 @@ -use std::{ - env, - path::PathBuf, - sync::{Arc, Condvar, Mutex}, -}; +use std::env; use containerd_shim::{parse, run}; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::{ - libcontainer_instance::LibcontainerInstance, - sandbox::{instance::ExitCode, Error, InstanceConfig, ShimCli}, -}; -use libcontainer::container::{builder::ContainerBuilder, Container}; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; -use anyhow::Result; +use engine::LunaticEngine; -use crate::executor::LunaticExecutor; +type LunaticInstance = Instance; mod common; -mod executor; - -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/lunatic"; - -pub struct Wasi { - id: String, - exit_code: ExitCode, - bundle: String, - rootdir: PathBuf, - stdio: Stdio, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - - Wasi { - id, - exit_code: Arc::new((Mutex::new(None), Condvar::new())), - rootdir: determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(), - bundle, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> Result { - log::info!("Building container"); - - let err_msg = |err| format!("failed to create container: {}", err); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(LunaticExecutor::new(self.stdio.take())) - .with_root_path(self.rootdir.clone()) - .map_err(|err| Error::Others(err_msg(err)))? - .as_init(&self.bundle) - .with_systemd(false) - .build() - .map_err(|err| Error::Others(err_msg(err)))?; - log::info!(">>> Container built."); - Ok(container) - } -} +mod engine; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -96,5 +26,5 @@ fn parse_version() { fn main() { parse_version(); - run::>("io.containerd.lunatic.v1", None); + run::>("io.containerd.lunatic.v1", None); } diff --git a/containerd-shim-slight-v1/Cargo.lock b/containerd-shim-slight-v1/Cargo.lock index 07b2b78d..af70a195 100644 --- a/containerd-shim-slight-v1/Cargo.lock +++ b/containerd-shim-slight-v1/Cargo.lock @@ -1450,35 +1450,21 @@ name = "containerd-shim-slight-v1" version = "0.9.1" dependencies = [ "anyhow", - "chrono", - "clap", "containerd-shim", "containerd-shim-wasm", "curl", "isahc 1.7.2", - "libc", - "libcontainer", "log", - "nix 0.26.4", - "oci-spec", "openssl", "openssl-sys", - "serde", - "serde_json", "slight", "tokio", - "tokio-util", - "toml 0.7.6", - "tracing", - "tracing-subscriber", - "utils", - "wasmtime", ] [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -1497,6 +1483,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -3006,8 +2993,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libcgroups" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" dependencies = [ "fixedbitset 0.4.2", "nix 0.26.4", @@ -3020,8 +3008,9 @@ dependencies = [ [[package]] name = "libcontainer" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" dependencies = [ "bitflags 2.4.0", "caps", @@ -5968,14 +5957,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "utils" -version = "0.9.1" -dependencies = [ - "anyhow", - "oci-spec", -] - [[package]] name = "uuid" version = "1.4.1" diff --git a/containerd-shim-slight-v1/Cargo.toml b/containerd-shim-slight-v1/Cargo.toml index 8ce1bbee..a059d494 100644 --- a/containerd-shim-slight-v1/Cargo.toml +++ b/containerd-shim-slight-v1/Cargo.toml @@ -11,27 +11,14 @@ Containerd shim for running Slight workloads. """ [dependencies] -chrono = "0.4" -clap = { version = "4.1", features = ["derive", "env"] } containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } -libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } log = "0.4" tokio = { version = "1", features = [ "full" ] } -tokio-util = { version = "0.7", features = [ "codec" ]} -wasmtime = "10.0" -toml = "0.7" -tracing-subscriber = { version = "0.3", features = ["env-filter"] } -tracing = { version = "0.1", features = ["log"] } slight = { git = "https://github.com/deislabs/spiderlightning", version = "0.5.1" } openssl = { version = "0.10", features = ["vendored"] } -oci-spec = "0.6.2" -libc = "0.2.147" -nix = "0.26.2" anyhow = "1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -utils = { path = "../utils" } + [dependencies.openssl-sys] features = ["vendored"] diff --git a/containerd-shim-slight-v1/src/engine.rs b/containerd-shim-slight-v1/src/engine.rs new file mode 100644 index 00000000..a4578cc6 --- /dev/null +++ b/containerd-shim-slight-v1/src/engine.rs @@ -0,0 +1,36 @@ +use anyhow::{Context, Result}; +use std::path::PathBuf; +use tokio::runtime::Runtime; + +use containerd_shim_wasm::container::{Engine, RuntimeContext, Stdio}; +use slight_lib::commands::run::{handle_run, RunArgs}; + +#[derive(Clone, Default)] +pub struct SlightEngine; + +impl Engine for SlightEngine { + fn name() -> &'static str { + "slight" + } + + fn run_wasi(&self, _ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; + let mod_path = PathBuf::from("/slightfile.toml"); + let wasm_path = PathBuf::from("/app.wasm"); + let rt = Runtime::new().context("failed to create runtime")?; + let args = RunArgs { + module: wasm_path, + slightfile: mod_path, + io_redirects: None, + link_all_capabilities: true, + }; + + rt.block_on(handle_run(args))?; + Ok(0) + } + + fn can_handle(&self, _ctx: &impl RuntimeContext) -> Result<()> { + Ok(()) + } +} diff --git a/containerd-shim-slight-v1/src/executor.rs b/containerd-shim-slight-v1/src/executor.rs deleted file mode 100644 index 30680e49..00000000 --- a/containerd-shim-slight-v1/src/executor.rs +++ /dev/null @@ -1,58 +0,0 @@ -use anyhow::{Context, Result}; -use std::path::PathBuf; -use tokio::runtime::Runtime; - -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; -use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; -use slight_lib::commands::run::{handle_run, RunArgs}; -use utils::is_linux_executable; - -#[derive(Clone)] -pub struct SlightExecutor { - stdio: Stdio, -} - -impl SlightExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } - } - - fn wasm_exec(&self) -> anyhow::Result<()> { - self.stdio - .take() - .redirect() - .context("failed to redirect stdio")?; - let mod_path = PathBuf::from("/slightfile.toml"); - let wasm_path = PathBuf::from("/app.wasm"); - let rt = Runtime::new().context("failed to create runtime")?; - let args = RunArgs { - module: wasm_path, - slightfile: mod_path, - io_redirects: None, - link_all_capabilities: true, - }; - rt.block_on(handle_run(args)) - } -} - -impl Executor for SlightExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec() { - log::error!(" >>> error: {:?}", err); - std::process::exit(137); - } - log::info!(" >>> slight shut down: exiting"); - std::process::exit(0); - } - } - - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { - Ok(()) - } -} diff --git a/containerd-shim-slight-v1/src/main.rs b/containerd-shim-slight-v1/src/main.rs index 08efa0f5..bd581b1e 100644 --- a/containerd-shim-slight-v1/src/main.rs +++ b/containerd-shim-slight-v1/src/main.rs @@ -1,78 +1,12 @@ use std::env; -use std::option::Option; -use std::path::PathBuf; use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::SlightExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::{container::Instance, sandbox::ShimCli}; +use engine::SlightEngine; -mod executor; +mod engine; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/slight"; - -pub struct Wasi { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - log::info!(">>> new instance"); - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Wasi { - exit_code: Default::default(), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle, - rootdir, - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let slight_executor = SlightExecutor::new(self.stdio.take()); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(slight_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} +type SlightInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -89,5 +23,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.slight.v1", None); + shim::run::>("io.containerd.slight.v1", None); } diff --git a/containerd-shim-spin-v1/Cargo.lock b/containerd-shim-spin-v1/Cargo.lock index c646b887..047adcde 100644 --- a/containerd-shim-spin-v1/Cargo.lock +++ b/containerd-shim-spin-v1/Cargo.lock @@ -96,54 +96,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - [[package]] name = "anyhow" version = "1.0.75" @@ -242,7 +194,7 @@ dependencies = [ "rustc_version", "serde", "serde_json", - "time 0.3.28", + "time", "url", "uuid", ] @@ -263,7 +215,7 @@ dependencies = [ "serde_json", "sha2 0.10.7", "thiserror", - "time 0.3.28", + "time", "url", "uuid", ] @@ -365,7 +317,7 @@ dependencies = [ "sled", "tempfile", "thiserror", - "time 0.3.28", + "time", "tokio", "tokio-stream", "tokio-tar", @@ -571,11 +523,8 @@ checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "time 0.1.45", - "wasm-bindgen", "windows-targets 0.48.5", ] @@ -607,8 +556,8 @@ checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", "bitflags 1.3.2", - "clap_derive 3.2.25", - "clap_lex 0.2.4", + "clap_derive", + "clap_lex", "indexmap 1.9.3", "once_cell", "strsim", @@ -616,29 +565,6 @@ dependencies = [ "textwrap", ] -[[package]] -name = "clap" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27" -dependencies = [ - "clap_builder", - "clap_derive 4.4.0", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d" -dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.5.1", - "strsim", -] - [[package]] name = "clap_derive" version = "3.2.25" @@ -652,18 +578,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "clap_derive" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "syn 2.0.29", -] - [[package]] name = "clap_lex" version = "0.2.4" @@ -673,12 +587,6 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "clap_lex" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" - [[package]] name = "clone3" version = "0.2.3" @@ -698,12 +606,6 @@ dependencies = [ "cc", ] -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "combine" version = "4.6.6" @@ -762,7 +664,7 @@ dependencies = [ "serde_json", "signal-hook", "thiserror", - "time 0.3.28", + "time", "windows-sys 0.48.0", ] @@ -782,38 +684,26 @@ name = "containerd-shim-spin-v1" version = "0.9.1" dependencies = [ "anyhow", - "async-trait", - "chrono", - "clap 4.4.1", "containerd-shim", "containerd-shim-wasm", - "libc", - "libcontainer", "log", - "nix 0.26.4", - "oci-spec", "openssl", - "reqwest", "serde", "serde_json", - "spin-app", - "spin-core", "spin-loader", "spin-manifest", "spin-redis-engine", "spin-trigger", "spin-trigger-http", "tokio", - "tokio-util 0.7.8", "url", - "utils", "wasmtime", ] [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -832,6 +722,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -2262,8 +2153,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libcgroups" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" dependencies = [ "fixedbitset 0.4.2", "nix 0.26.4", @@ -2276,8 +2168,9 @@ dependencies = [ [[package]] name = "libcontainer" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" dependencies = [ "bitflags 2.4.0", "caps", @@ -4095,7 +3988,7 @@ dependencies = [ "num-bigint", "num-traits", "thiserror", - "time 0.3.28", + "time", ] [[package]] @@ -4426,7 +4319,7 @@ source = "git+https://github.com/fermyon/spin?tag=v1.4.1#e0bd9115fa51399e106681a dependencies = [ "anyhow", "async-trait", - "clap 3.2.25", + "clap", "ctrlc", "dirs 4.0.0", "futures", @@ -4468,7 +4361,7 @@ source = "git+https://github.com/fermyon/spin?tag=v1.4.1#e0bd9115fa51399e106681a dependencies = [ "anyhow", "async-trait", - "clap 3.2.25", + "clap", "futures", "futures-util", "http", @@ -4699,17 +4592,6 @@ dependencies = [ "syn 2.0.29", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.28" @@ -5136,20 +5018,6 @@ dependencies = [ "serde", ] -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "utils" -version = "0.9.1" -dependencies = [ - "anyhow", - "oci-spec", -] - [[package]] name = "uuid" version = "1.4.1" @@ -5222,12 +5090,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/containerd-shim-spin-v1/Cargo.toml b/containerd-shim-spin-v1/Cargo.toml index 88ac3381..2dde4c6e 100644 --- a/containerd-shim-spin-v1/Cargo.toml +++ b/containerd-shim-spin-v1/Cargo.toml @@ -11,32 +11,20 @@ Containerd shim for running Spin workloads. """ [dependencies] -chrono = "0.4" -clap = { version = "4.3", features = ["derive", "env"] } containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } -libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } log = "0.4" spin-trigger = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } -spin-app = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } -spin-core = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } spin-trigger-http = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } spin-redis-engine = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } -spin-loader = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } spin-manifest = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } +spin-loader = { git = "https://github.com/fermyon/spin", tag = "v1.4.1" } wasmtime = "10.0.1" tokio = { version = "1", features = ["rt"] } -tokio-util = { version = "0.7", features = ["codec"] } openssl = { version = "*", features = ["vendored"] } -serde = { version = "1.0", features = ["derive"] } +serde = "1.0" serde_json = "1.0" url = "2.3" -reqwest = { version = "0.11", features = ["stream"] } anyhow = "1.0" -async-trait = "0.1" -oci-spec = "0.6.2" -libc = "0.2.147" -nix = "0.26.2" -utils = { path = "../utils" } [workspace] diff --git a/containerd-shim-spin-v1/src/executor.rs b/containerd-shim-spin-v1/src/engine.rs similarity index 69% rename from containerd-shim-spin-v1/src/executor.rs rename to containerd-shim-spin-v1/src/engine.rs index e2c6001f..90d724bf 100644 --- a/containerd-shim-spin-v1/src/executor.rs +++ b/containerd-shim-spin-v1/src/engine.rs @@ -1,35 +1,24 @@ use anyhow::{anyhow, Context, Result}; +use std::net::SocketAddr; +use std::net::ToSocketAddrs; +use std::path::PathBuf; + +use containerd_shim_wasm::container::{Engine, RuntimeContext, Stdio}; use log::info; use spin_manifest::Application; use spin_redis_engine::RedisTrigger; use spin_trigger::{loader, RuntimeConfig, TriggerExecutor, TriggerExecutorBuilder}; use spin_trigger_http::HttpTrigger; -use std::path::PathBuf; - use tokio::runtime::Runtime; use url::Url; use wasmtime::OptLevel; -use containerd_shim_wasm::libcontainer_instance::LinuxContainerExecutor; -use containerd_shim_wasm::sandbox::Stdio; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; -use utils::is_linux_executable; - -use crate::{parse_addr, SPIN_ADDR}; - -#[derive(Clone)] -pub struct SpinExecutor { - stdio: Stdio, -} +const SPIN_ADDR: &str = "0.0.0.0:80"; -impl SpinExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } - } -} +#[derive(Clone, Default)] +pub struct SpinEngine; -impl SpinExecutor { +impl SpinEngine { async fn build_spin_application( mod_path: PathBuf, working_dir: PathBuf, @@ -65,16 +54,10 @@ impl SpinExecutor { Ok(executor) } - fn wasm_exec(&self, _spec: &Spec) -> Result<()> { - log::info!("executing spin container"); - let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(self.wasm_exec_async()) - } - async fn wasm_exec_async(&self) -> Result<()> { info!(" >>> building spin application"); let app = - SpinExecutor::build_spin_application(PathBuf::from("/spin.toml"), PathBuf::from("/")) + SpinEngine::build_spin_application(PathBuf::from("/spin.toml"), PathBuf::from("/")) .await .context("failed to build spin application")?; @@ -84,7 +67,7 @@ impl SpinExecutor { let f = match trigger { spin_manifest::ApplicationTrigger::Http(_config) => { let http_trigger: HttpTrigger = - SpinExecutor::build_spin_trigger(PathBuf::from("/"), app) + SpinEngine::build_spin_trigger(PathBuf::from("/"), app) .await .context("failed to build spin trigger")?; info!(" >>> running spin trigger"); @@ -96,7 +79,7 @@ impl SpinExecutor { } spin_manifest::ApplicationTrigger::Redis(_config) => { let redis_trigger: RedisTrigger = - SpinExecutor::build_spin_trigger(PathBuf::from("/"), app) + SpinEngine::build_spin_trigger(PathBuf::from("/"), app) .await .context("failed to build spin trigger")?; @@ -111,22 +94,41 @@ impl SpinExecutor { } } -impl Executor for SpinExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec(spec) { - log::info!(" >>> server shut down due to error: {err}"); - std::process::exit(137); - } - log::info!(" >>> server shut down: exiting"); - std::process::exit(0); - } +impl Engine for SpinEngine { + fn name() -> &'static str { + "spin" + } + + fn run_wasi(&self, _ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; + let rt = Runtime::new().context("failed to create runtime")?; + + rt.block_on(self.wasm_exec_async())?; + Ok(0) } - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { + fn can_handle(&self, _ctx: &impl RuntimeContext) -> Result<()> { Ok(()) } } + +fn parse_addr(addr: &str) -> Result { + let addrs: SocketAddr = addr + .to_socket_addrs()? + .next() + .ok_or_else(|| anyhow!("could not parse address: {}", addr))?; + Ok(addrs) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_parse_spin_address() { + let parsed = parse_addr(SPIN_ADDR).unwrap(); + assert_eq!(parsed.clone().port(), 80); + assert_eq!(parsed.ip().to_string(), "0.0.0.0"); + } +} diff --git a/containerd-shim-spin-v1/src/main.rs b/containerd-shim-spin-v1/src/main.rs index b51c8c2e..d9f1c7a2 100644 --- a/containerd-shim-spin-v1/src/main.rs +++ b/containerd-shim-spin-v1/src/main.rs @@ -1,91 +1,13 @@ use std::env; -use std::net::SocketAddr; -use std::net::ToSocketAddrs; -use std::option::Option; -use std::path::PathBuf; -use std::sync::{Arc, Condvar, Mutex}; -use anyhow::{anyhow, Result}; use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::stdio::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::SpinExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; +use engine::SpinEngine; -mod executor; +mod engine; -const SPIN_ADDR: &str = "0.0.0.0:80"; -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/spin"; - -pub struct Wasi { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -impl LibcontainerInstance for Wasi { - type Engine = (); - - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Wasi { - exit_code: Arc::new((Mutex::new(None), Condvar::new())), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle: cfg.get_bundle().unwrap_or_default(), - rootdir, - } - } - - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } - - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let spin_executor = SpinExecutor::new(self.stdio.take()); - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(spin_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} - -fn parse_addr(addr: &str) -> Result { - let addrs: SocketAddr = addr - .to_socket_addrs()? - .next() - .ok_or_else(|| anyhow!("could not parse address: {}", addr))?; - Ok(addrs) -} +pub type SpinInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -101,17 +23,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.spin.v1", None); -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn can_parse_spin_address() { - let parsed = parse_addr(SPIN_ADDR).unwrap(); - assert_eq!(parsed.clone().port(), 80); - assert_eq!(parsed.ip().to_string(), "0.0.0.0"); - } + shim::run::>("io.containerd.spin.v1", None); } diff --git a/containerd-shim-wws-v1/Cargo.lock b/containerd-shim-wws-v1/Cargo.lock index 937ef89d..f2e55c86 100644 --- a/containerd-shim-wws-v1/Cargo.lock +++ b/containerd-shim-wws-v1/Cargo.lock @@ -188,7 +188,7 @@ dependencies = [ "serde_urlencoded", "smallvec", "socket2 0.5.3", - "time 0.3.28", + "time", "url", ] @@ -628,11 +628,8 @@ checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "time 0.1.45", - "wasm-bindgen", "windows-targets 0.48.5", ] @@ -753,7 +750,7 @@ dependencies = [ "serde_json", "signal-hook", "thiserror", - "time 0.3.28", + "time", "windows-sys 0.48.0", ] @@ -771,7 +768,7 @@ dependencies = [ [[package]] name = "containerd-shim-wasm" version = "0.2.1" -source = "git+https://github.com/containerd/runwasi?rev=7e978edeaf34b54efb895738357c805cf888b76d#7e978edeaf34b54efb895738357c805cf888b76d" +source = "git+https://github.com/containerd/runwasi?rev=4d212b968d24d42a27952e8b04979382b543a613#4d212b968d24d42a27952e8b04979382b543a613" dependencies = [ "anyhow", "caps", @@ -790,6 +787,7 @@ dependencies = [ "serde_json", "thiserror", "ttrpc", + "wat", "windows-sys 0.48.0", ] @@ -798,20 +796,11 @@ name = "containerd-shim-wws-v1" version = "0.9.1" dependencies = [ "anyhow", - "chrono", "containerd-shim", "containerd-shim-wasm", - "libc", - "libcontainer", "log", - "nix 0.26.4", - "oci-spec", "openssl", - "serde", - "serde_json", "tokio", - "tokio-util", - "utils", "wasm-workers-server", ] @@ -828,7 +817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.28", + "time", "version_check", ] @@ -1572,7 +1561,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1998,8 +1987,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libcgroups" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc75981724e1f7e065582ddfb1ef41bbe82c2d3afa130777fc41d75f386a0c6" dependencies = [ "fixedbitset 0.4.2", "nix 0.26.4", @@ -2012,8 +2002,9 @@ dependencies = [ [[package]] name = "libcontainer" -version = "0.1.0" -source = "git+https://github.com/containers/youki?rev=09e67372a892f22a89eeef62ff429c3cbcac6d41#09e67372a892f22a89eeef62ff429c3cbcac6d41" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a122c3ce58c5a705d3e71809816ab6726dfd37621d8e55bfd5f33dac213c713" dependencies = [ "bitflags 2.4.0", "caps", @@ -2243,7 +2234,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -3447,17 +3438,6 @@ dependencies = [ "syn 2.0.31", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "time" version = "0.3.28" @@ -3784,14 +3764,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "utils" -version = "0.9.1" -dependencies = [ - "anyhow", - "oci-spec", -] - [[package]] name = "utoipa" version = "3.5.0" @@ -3854,12 +3826,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/containerd-shim-wws-v1/Cargo.toml b/containerd-shim-wws-v1/Cargo.toml index 2b2950c7..c55357ff 100644 --- a/containerd-shim-wws-v1/Cargo.toml +++ b/containerd-shim-wws-v1/Cargo.toml @@ -13,21 +13,12 @@ Containerd shim for running Wasm Workers Server workloads. # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0" containerd-shim = "0.5.0" -containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "7e978edeaf34b54efb895738357c805cf888b76d", features = ["cgroupsv2"] } -libcontainer = { git = "https://github.com/containers/youki", rev = "09e67372a892f22a89eeef62ff429c3cbcac6d41", features = ["v1","v2"], default-features = false } +containerd-shim-wasm = { git = "https://github.com/containerd/runwasi", rev = "4d212b968d24d42a27952e8b04979382b543a613", features = ["cgroupsv2"] } wasm-workers-server = { git = "https://github.com/vmware-labs/wasm-workers-server", tag = "v1.5.0" } log = "0.4" tokio = { version = "1", features = [ "full" ] } -tokio-util = { version = "0.7", features = [ "codec" ]} -chrono = "0.4" -oci-spec = "0.6.2" -libc = "0.2.147" -nix = "0.26.2" -anyhow = "1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -utils = { path = "../utils" } [target.x86_64-unknown-linux-musl.dependencies] openssl = { version = "=0.10.48", features = ["vendored"] } diff --git a/containerd-shim-wws-v1/src/executor.rs b/containerd-shim-wws-v1/src/engine.rs similarity index 54% rename from containerd-shim-wws-v1/src/executor.rs rename to containerd-shim-wws-v1/src/engine.rs index 05e50415..b824b9c0 100644 --- a/containerd-shim-wws-v1/src/executor.rs +++ b/containerd-shim-wws-v1/src/engine.rs @@ -3,10 +3,7 @@ use log::{error, info}; use std::path::Path; use tokio::runtime::Runtime; -use containerd_shim_wasm::{libcontainer_instance::LinuxContainerExecutor, sandbox::Stdio}; -use libcontainer::workload::{Executor, ExecutorError, ExecutorValidationError}; -use oci_spec::runtime::Spec; -use utils::is_linux_executable; +use containerd_shim_wasm::container::{Engine, RuntimeContext, Stdio}; use wasm_workers_server::{ wws_config::Config, wws_router::Routes, @@ -17,20 +14,33 @@ use wasm_workers_server::{ const WWS_ADDR: &str = "0.0.0.0"; const WWS_PORT: u16 = 3000; -#[derive(Clone)] -pub struct WwsExecutor { - pub stdio: Stdio, -} +#[derive(Clone, Default)] +pub struct WwsEngine; -impl WwsExecutor { - pub fn new(stdio: Stdio) -> Self { - Self { stdio } +impl WwsEngine { + async fn wasm_exec_async(&self, root: &Path, routes: Routes) -> Result<()> { + let server = serve(ServeOptions { + root_path: root.to_path_buf(), + base_routes: routes, + hostname: WWS_ADDR.to_string(), + port: WWS_PORT, + panel: Panel::Disabled, + cors_origins: None, + }) + .await?; + info!(" >>> notifying main thread we are about to start"); + Ok(server.await?) } +} - fn wasm_exec(&self, _spec: &Spec) -> anyhow::Result<()> { - let stderr = self.stdio.take().stderr; - stderr.redirect().context("redirecting stdio")?; +impl Engine for WwsEngine { + fn name() -> &'static str { + "wws" + } + fn run_wasi(&self, _ctx: &impl RuntimeContext, stdio: Stdio) -> Result { + log::info!("setting up wasi"); + stdio.redirect()?; let path = Path::new("/"); let config = Config::load(path).unwrap_or_else(|err| { @@ -48,39 +58,12 @@ impl WwsExecutor { let routes = Routes::new(path, "", Vec::new(), &config); let rt = Runtime::new().context("failed to create runtime")?; - rt.block_on(self.wasm_exec_async(path, routes)) - } - async fn wasm_exec_async(&self, root: &Path, routes: Routes) -> Result<()> { - let server = serve(ServeOptions { - root_path: root.to_path_buf(), - base_routes: routes, - hostname: WWS_ADDR.to_string(), - port: WWS_PORT, - panel: Panel::Disabled, - cors_origins: None, - }).await?; - info!(" >>> notifying main thread we are about to start"); - Ok(server.await?) - } -} - -impl Executor for WwsExecutor { - fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { - if is_linux_executable(spec).is_ok() { - log::info!("executing linux container"); - LinuxContainerExecutor::new(self.stdio.clone()).exec(spec) - } else { - if let Err(err) = self.wasm_exec(spec) { - log::info!(" >>> server shut down due to error: {err}"); - std::process::exit(137); - } - log::info!(" >>> server shut down: exiting"); - std::process::exit(0); - } + rt.block_on(self.wasm_exec_async(path, routes))?; + Ok(0) } - fn validate(&self, _spec: &Spec) -> Result<(), ExecutorValidationError> { + fn can_handle(&self, _ctx: &impl RuntimeContext) -> Result<()> { Ok(()) } } diff --git a/containerd-shim-wws-v1/src/main.rs b/containerd-shim-wws-v1/src/main.rs index 3db75c12..555c10e1 100644 --- a/containerd-shim-wws-v1/src/main.rs +++ b/containerd-shim-wws-v1/src/main.rs @@ -1,79 +1,13 @@ -use containerd_shim as shim; -use containerd_shim_wasm::libcontainer_instance::LibcontainerInstance; -use containerd_shim_wasm::sandbox::instance::ExitCode; -use containerd_shim_wasm::sandbox::instance_utils::determine_rootdir; -use containerd_shim_wasm::sandbox::Stdio; -use containerd_shim_wasm::sandbox::{error::Error, InstanceConfig, ShimCli}; -use executor::WwsExecutor; -use libcontainer::container::builder::ContainerBuilder; -use libcontainer::container::Container; -use libcontainer::syscall::syscall::SyscallType; use std::env; -use std::option::Option; -use std::path::PathBuf; - -mod executor; - -static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd/wws"; - -pub struct Workers { - exit_code: ExitCode, - id: String, - stdio: Stdio, - bundle: String, - rootdir: PathBuf, -} - -/// Implement the "default" interface from runwasi -impl LibcontainerInstance for Workers { - type Engine = (); - fn new_libcontainer(id: String, cfg: Option<&InstanceConfig>) -> Self { - log::info!("[wws] new instance"); - let cfg = cfg.unwrap(); - let bundle = cfg.get_bundle().unwrap_or_default(); - let rootdir = determine_rootdir( - bundle.as_str(), - cfg.get_namespace().as_str(), - DEFAULT_CONTAINER_ROOT_DIR, - ) - .unwrap(); - Workers { - exit_code: Default::default(), - id, - stdio: Stdio::init_from_cfg(cfg).expect("failed to open stdio"), - bundle, - rootdir, - } - } - fn get_exit_code(&self) -> ExitCode { - self.exit_code.clone() - } - - fn get_id(&self) -> String { - self.id.clone() - } - - fn get_root_dir(&self) -> std::result::Result { - Ok(self.rootdir.clone()) - } +use containerd_shim as shim; +use containerd_shim_wasm::container::Instance; +use containerd_shim_wasm::sandbox::ShimCli; +use engine::WwsEngine; - fn build_container(&self) -> std::result::Result { - let err_others = |err| Error::Others(format!("failed to create container: {}", err)); - let wws_executor = WwsExecutor::new(self.stdio.take()); +mod engine; - let container = ContainerBuilder::new(self.id.clone(), SyscallType::Linux) - .with_executor(wws_executor) - .with_root_path(self.rootdir.clone()) - .map_err(err_others)? - .as_init(&self.bundle) - .with_systemd(false) - .with_detach(true) - .build() - .map_err(err_others)?; - Ok(container) - } -} +pub type WwsInstance = Instance; fn parse_version() { let os_args: Vec<_> = env::args_os().collect(); @@ -90,5 +24,5 @@ fn parse_version() { fn main() { parse_version(); - shim::run::>("io.containerd.wws.v1", None); + shim::run::>("io.containerd.wws.v1", None); } diff --git a/utils/Cargo.toml b/utils/Cargo.toml deleted file mode 100644 index 9e04699c..00000000 --- a/utils/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "utils" -version.workspace = true -edition.workspace = true -license.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1" -oci-spec = "0.6.2" \ No newline at end of file diff --git a/utils/src/lib.rs b/utils/src/lib.rs deleted file mode 100644 index 8ecc537f..00000000 --- a/utils/src/lib.rs +++ /dev/null @@ -1,62 +0,0 @@ -use anyhow::{bail, ensure, Context}; -use oci_spec::runtime::Spec; -use std::fs::File; -use std::io::Read; -use std::os::unix::fs::PermissionsExt; - -pub fn get_args(spec: &Spec) -> Vec { - let p = match spec.process() { - None => return vec![], - Some(p) => p, - }; - - match p.args() { - None => vec![], - Some(args) => args.as_slice().to_vec(), - } -} - -pub fn is_linux_executable(spec: &Spec) -> anyhow::Result<()> { - let args = get_args(spec).to_vec(); - - let executable = args.first().context("no executable provided")?; - ensure!(!executable.is_empty(), "executable is empty"); - let cwd = std::env::current_dir()?; - - let executable = if executable.contains('/') { - let path = cwd.join(executable); - ensure!(path.is_file(), "file not found"); - path - } else { - spec.process() - .as_ref() - .and_then(|p| p.env().clone()) - .unwrap_or_default() - .into_iter() - .map(|v| match v.split_once('=') { - None => (v, "".to_string()), - Some((k, v)) => (k.to_string(), v.to_string()), - }) - .find(|(key, _)| key == "PATH") - .context("PATH not defined")? - .1 - .split(':') - .map(|p| cwd.join(p).join(executable)) - .find(|p| p.is_file()) - .context("file not found")? - }; - - let mode = executable.metadata()?.permissions().mode(); - ensure!(mode & 0o001 != 0, "entrypoint is not a executable"); - - // check the shebang and ELF magic number - // https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header - let mut buffer = [0; 4]; - File::open(&executable)?.read_exact(&mut buffer)?; - - match buffer { - [0x7f, 0x45, 0x4c, 0x46] => Ok(()), // ELF magic number - [0x23, 0x21, ..] => Ok(()), // shebang - _ => bail!("{executable:?} is not a valid script or elf file"), - } -}