#![warn(missing_docs)]
pub mod proto;
pub use proto as ror_proto;
mod error;
mod ffi;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "macos")]
mod macos;
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
mod other;
mod request;
#[cfg(any(target_os = "macos", test))]
mod shares;
#[cfg(target_os = "linux")]
unsafe extern "C" {
fn ror_nsexec_keep() -> i32;
}
#[cfg(target_os = "linux")]
#[used]
static ROR_NSEXEC_KEEP: unsafe extern "C" fn() -> i32 = ror_nsexec_keep;
pub use error::{Error, ErrorCode};
pub use request::RunRequest;
use std::sync::Arc;
pub type OutputFn = Arc<dyn Fn(u8, &[u8]) + Send + Sync>;
pub fn startup() -> Result<(), Error> {
#[cfg(target_os = "linux")]
{
linux::startup()
}
#[cfg(target_os = "macos")]
{
Ok(())
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
other::startup()
}
}
pub struct Runtime {
_private: (),
}
impl Runtime {
pub fn open() -> Result<Self, Error> {
#[cfg(target_os = "linux")]
{
linux::open()?;
Ok(Self { _private: () })
}
#[cfg(target_os = "macos")]
{
macos::open()?;
Ok(Self { _private: () })
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
let _ = other::startup()?;
Ok(Self { _private: () })
}
}
pub fn run(&self, request: &RunRequest) -> Result<i32, Error> {
self.run_with(request, None)
}
pub fn run_with(
&self,
request: &RunRequest,
on_output: Option<OutputFn>,
) -> Result<i32, Error> {
let prepared = request.prepare()?;
#[cfg(target_os = "linux")]
{
linux::run(&prepared, on_output)
}
#[cfg(target_os = "macos")]
{
macos::run(&prepared, on_output)
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
let _ = (prepared, on_output);
Err(Error::new(
ErrorCode::Unsupported,
"oci-runner is available on Linux and macOS only",
"",
))
}
}
pub fn shutdown(self) -> Result<(), Error> {
#[cfg(target_os = "linux")]
{
linux::shutdown()
}
#[cfg(target_os = "macos")]
{
macos::shutdown()
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
Ok(())
}
}
pub fn diagnose() -> Result<String, Error> {
#[cfg(target_os = "linux")]
{
linux::diagnose()
}
#[cfg(target_os = "macos")]
{
macos::diagnose()
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
other::diagnose()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn startup_does_not_boot_a_guest() {
startup().expect("startup");
}
#[cfg(target_os = "macos")]
#[test]
fn diagnose_without_a_guest_image_is_a_prerequisite_error() {
match Runtime::diagnose() {
Ok(report) => {
assert!(report.contains("status: ready"));
}
Err(err) => {
assert_eq!(err.code(), ErrorCode::Prerequisite);
assert!(err.detail().contains("status: blocked"));
}
}
}
}