diff --git a/README.md b/README.md index 2d6313f..5f3f3b1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This repository contains the following crates: | --- | --- | | [containerd-shim-protos](crates/shim-protos) | TTRPC bindings to shim interfaces | | [containerd-shim-logging](crates/logging) | Shim logger | -| [containerd-shim](crates/shim) | Runtime v2 shim wrapper | +| [containerd-shim](crates/shim) | 🚧 Runtime v2 shim wrapper | ## How to build The build process as easy as: diff --git a/crates/shim/README.md b/crates/shim/README.md index eca605a..8c577a8 100644 --- a/crates/shim/README.md +++ b/crates/shim/README.md @@ -1 +1,54 @@ -# shim +# containerd shim + +Rust crate to ease runtime v2 shim implementation. + +It replicates same [shim.Run](https://github.com/containerd/containerd/blob/dbef1d56d7ebc05bc4553d72c419ed5ce025b05d/runtime/v2/example/cmd/main.go) +API offered by containerd's shim v2 runtime implementation written in Go. + +## Look and feel + +The API is very similar to the one offered by Go version: + +```rust +struct Service; + +impl shim::Shim for Service { + fn new(_id: &str, _namespace: &str, _config: &mut shim::Config) -> Self { + Service {} + } + + fn start_shim(&mut self, opts: StartOpts) -> Result> { + let address = shim::spawn(opts)?; + Ok(address) + } + + fn delete_shim(&mut self) -> Result> { + todo!() + } +} + +impl shim::Task for Service { + fn create( + &self, + ctx: &TtrpcContext, + req: api::CreateTaskRequest, + ) -> ::ttrpc::Result { + debug!("Create"); + Ok(api::CreateTaskResponse::default()) + } +} + +fn main() { + shim::run::("io.containerd.empty.v1") +} +``` + +## How to use + +Runtime binary has to be [named in a special way](https://github.com/containerd/containerd/blob/main/runtime/v2/README.md#binary-naming) to be recognized by containerd: + +```bash +$ cargo build --example empty-shim +$ sudo cp ./target/debug/examples/empty-shim /usr/local/bin/containerd-shim-empty-v2 +$ sudo ctr run --rm --runtime io.containerd.empty.v2 -t docker.io/library/hello-world:latest hello +``` diff --git a/crates/shim/examples/empty-shim.rs b/crates/shim/examples/empty-shim.rs index d8eaff7..c09b920 100644 --- a/crates/shim/examples/empty-shim.rs +++ b/crates/shim/examples/empty-shim.rs @@ -1,37 +1,24 @@ -use std::error::Error; - use containerd_shim as shim; -use shim::protos; +use shim::{api, TtrpcContext, TtrpcResult}; -use shim::api::DeleteResponse; -use shim::StartOpts; - -use log::debug; +use log::info; struct Service; impl shim::Shim for Service { fn new(_id: &str, _namespace: &str, _config: &mut shim::Config) -> Self { - todo!() - } - - fn start_shim(&mut self, _opts: StartOpts) -> Result> { - todo!() - } - - fn cleanup(&mut self) -> Result> { - todo!() + Service {} } } impl shim::Task for Service { - fn state( + fn create( &self, - _ctx: &shim::Context, - _request: shim::api::StateRequest, - ) -> protos::ttrpc::Result { - debug!("Get state"); - Ok(shim::api::StateResponse::default()) + _ctx: &TtrpcContext, + _req: api::CreateTaskRequest, + ) -> TtrpcResult { + info!("Create"); + Ok(api::CreateTaskResponse::default()) } } diff --git a/crates/shim/src/lib.rs b/crates/shim/src/lib.rs index 7361628..8d57469 100644 --- a/crates/shim/src/lib.rs +++ b/crates/shim/src/lib.rs @@ -22,8 +22,10 @@ mod reap; pub use protos::shim::shim as api; pub use protos::shim::shim_ttrpc::Task; + pub use protos::ttrpc; -pub use protos::ttrpc::TtrpcContext as Context; +pub use protos::ttrpc::Result as TtrpcResult; +pub use protos::ttrpc::TtrpcContext; /// Config of shim binary options provided by shim implementations #[derive(Debug, Default)] @@ -59,7 +61,7 @@ pub trait Shim: Task { Ok(address) } - fn cleanup(&mut self) -> Result> { + fn delete_shim(&mut self) -> Result> { Ok(DeleteResponse::default()) } } @@ -108,7 +110,7 @@ where Ok(()) } "delete" => { - let response = shim.cleanup().map_err(Error::Cleanup)?; + let response = shim.delete_shim().map_err(Error::Cleanup)?; let stdout = io::stdout(); let mut locked = stdout.lock(); @@ -122,12 +124,18 @@ where } let task_service = create_task(Arc::new(Box::new(shim))); + let mut server = Server::new() - .bind(&flags.socket)? - .register_service(task_service); + .register_service(task_service) + .bind(format!("unix://{}", flags.socket).as_str())?; server.start()?; + // TODO: define exit criteria here. + std::thread::sleep(std::time::Duration::from_secs(360)); + + server.shutdown(); + Ok(()) } } @@ -170,10 +178,12 @@ pub fn socket_address(socket_path: &str, namespace: &str, id: &str) -> String { hasher.finish() }; - format!("unix://{}/{:x}.sock", SOCKET_ROOT, hash) + format!("{}/{:x}.sock", SOCKET_ROOT, hash) } -fn spawn(opts: StartOpts) -> Result { +/// Spawn is a helper func to launch shim process. +/// Typically this expected to be called from `StartShim`. +pub fn spawn(opts: StartOpts) -> Result { let socket_address = socket_address(&opts.address, &opts.namespace, &opts.id); Command::new(env::current_exe()?)