Update shim README

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
This commit is contained in:
Maksym Pavlenko 2021-07-24 11:04:19 -07:00
parent 099cd2a838
commit 3f41003493
4 changed files with 81 additions and 31 deletions

View File

@ -10,7 +10,7 @@ This repository contains the following crates:
| --- | --- | | --- | --- |
| [containerd-shim-protos](crates/shim-protos) | TTRPC bindings to shim interfaces | | [containerd-shim-protos](crates/shim-protos) | TTRPC bindings to shim interfaces |
| [containerd-shim-logging](crates/logging) | Shim logger | | [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 ## How to build
The build process as easy as: The build process as easy as:

View File

@ -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<String, Box<dyn Error>> {
let address = shim::spawn(opts)?;
Ok(address)
}
fn delete_shim(&mut self) -> Result<api::DeleteResponse, Box<dyn Error>> {
todo!()
}
}
impl shim::Task for Service {
fn create(
&self,
ctx: &TtrpcContext,
req: api::CreateTaskRequest,
) -> ::ttrpc::Result<api::CreateTaskResponse> {
debug!("Create");
Ok(api::CreateTaskResponse::default())
}
}
fn main() {
shim::run::<Service>("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
```

View File

@ -1,37 +1,24 @@
use std::error::Error;
use containerd_shim as shim; use containerd_shim as shim;
use shim::protos; use shim::{api, TtrpcContext, TtrpcResult};
use shim::api::DeleteResponse; use log::info;
use shim::StartOpts;
use log::debug;
struct Service; struct Service;
impl shim::Shim for Service { impl shim::Shim for Service {
fn new(_id: &str, _namespace: &str, _config: &mut shim::Config) -> Self { fn new(_id: &str, _namespace: &str, _config: &mut shim::Config) -> Self {
todo!() Service {}
}
fn start_shim(&mut self, _opts: StartOpts) -> Result<String, Box<dyn Error>> {
todo!()
}
fn cleanup(&mut self) -> Result<DeleteResponse, Box<dyn Error>> {
todo!()
} }
} }
impl shim::Task for Service { impl shim::Task for Service {
fn state( fn create(
&self, &self,
_ctx: &shim::Context, _ctx: &TtrpcContext,
_request: shim::api::StateRequest, _req: api::CreateTaskRequest,
) -> protos::ttrpc::Result<shim::api::StateResponse> { ) -> TtrpcResult<api::CreateTaskResponse> {
debug!("Get state"); info!("Create");
Ok(shim::api::StateResponse::default()) Ok(api::CreateTaskResponse::default())
} }
} }

View File

@ -22,8 +22,10 @@ mod reap;
pub use protos::shim::shim as api; pub use protos::shim::shim as api;
pub use protos::shim::shim_ttrpc::Task; pub use protos::shim::shim_ttrpc::Task;
pub use protos::ttrpc; 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 /// Config of shim binary options provided by shim implementations
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -59,7 +61,7 @@ pub trait Shim: Task {
Ok(address) Ok(address)
} }
fn cleanup(&mut self) -> Result<DeleteResponse, Box<dyn error::Error>> { fn delete_shim(&mut self) -> Result<DeleteResponse, Box<dyn error::Error>> {
Ok(DeleteResponse::default()) Ok(DeleteResponse::default())
} }
} }
@ -108,7 +110,7 @@ where
Ok(()) Ok(())
} }
"delete" => { "delete" => {
let response = shim.cleanup().map_err(Error::Cleanup)?; let response = shim.delete_shim().map_err(Error::Cleanup)?;
let stdout = io::stdout(); let stdout = io::stdout();
let mut locked = stdout.lock(); let mut locked = stdout.lock();
@ -122,12 +124,18 @@ where
} }
let task_service = create_task(Arc::new(Box::new(shim))); let task_service = create_task(Arc::new(Box::new(shim)));
let mut server = Server::new() 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()?; server.start()?;
// TODO: define exit criteria here.
std::thread::sleep(std::time::Duration::from_secs(360));
server.shutdown();
Ok(()) Ok(())
} }
} }
@ -170,10 +178,12 @@ pub fn socket_address(socket_path: &str, namespace: &str, id: &str) -> String {
hasher.finish() hasher.finish()
}; };
format!("unix://{}/{:x}.sock", SOCKET_ROOT, hash) format!("{}/{:x}.sock", SOCKET_ROOT, hash)
} }
fn spawn(opts: StartOpts) -> Result<String, Error> { /// Spawn is a helper func to launch shim process.
/// Typically this expected to be called from `StartShim`.
pub fn spawn(opts: StartOpts) -> Result<String, Error> {
let socket_address = socket_address(&opts.address, &opts.namespace, &opts.id); let socket_address = socket_address(&opts.address, &opts.namespace, &opts.id);
Command::new(env::current_exe()?) Command::new(env::current_exe()?)