pub mod composite;
#[cfg(all(target_os = "linux", feature = "youki-runtime"))]
mod youki;
#[cfg(feature = "docker")]
mod docker;
#[cfg(feature = "wasm")]
mod wasm;
#[cfg(feature = "wasm")]
mod wasm_host;
#[cfg(feature = "wasm")]
mod wasm_http;
#[cfg(feature = "wasm")]
mod wasm_http_interfaces;
#[cfg(feature = "wasm")]
mod wasm_pipeline;
#[cfg(feature = "wasm")]
pub mod wasm_test;
#[cfg(target_os = "macos")]
pub mod macos_sandbox;
#[cfg(target_os = "macos")]
pub mod macos_vm;
#[cfg(target_os = "windows")]
pub mod hcs;
#[cfg(all(target_os = "windows", feature = "wsl"))]
pub mod wsl2_delegate;
#[cfg(target_os = "windows")]
pub use hcs::{HcsConfig, HcsRuntime, IsolationMode};
#[cfg(all(target_os = "linux", feature = "youki-runtime"))]
pub use youki::{YoukiConfig, YoukiRuntime};
#[cfg(target_os = "macos")]
pub use macos_sandbox::SandboxRuntime;
#[cfg(target_os = "macos")]
pub use macos_vm::VmRuntime;
#[cfg(feature = "docker")]
pub use docker::DockerRuntime;
#[cfg(feature = "wasm")]
pub use wasm::{WasmConfig, WasmRuntime};
#[cfg(feature = "wasm")]
pub use wasm_host::{
add_to_linker, add_to_linker_with_capabilities, configure_wasi_ctx_with_capabilities,
DefaultHost, KvError, LogLevel, MetricsStore, ZLayerHost,
};
#[cfg(feature = "wasm")]
pub use wasm_http::{HttpRequest, HttpResponse, PoolStats, WasmHttpError, WasmHttpRuntime};
#[cfg(feature = "wasm")]
pub use wasm_pipeline::WasmPipelineRuntime;
#[cfg(feature = "wasm")]
pub use wasm_http_interfaces::{
duration_to_ns,
ns_to_duration,
CacheDecision,
CacheEntry,
CachingPlugin,
DurationNs,
HttpMethod,
HttpVersion,
ImmediateResponse,
KeyValue,
MessageType,
MiddlewareAction,
MiddlewarePlugin,
PluginRequest,
RedirectInfo,
RequestMetadata,
RouterPlugin,
RoutingDecision,
Timestamp,
UpgradeDecision,
Upstream,
WasmInterfaceError,
WebSocketMessage,
WebSocketPlugin,
};
#[cfg(feature = "wasm")]
pub enum WasmRuntimeKind {
Http(WasmHttpRuntime),
Plugin(WasmPluginConfig),
Pipeline(WasmPipelineConfig),
}
#[cfg(feature = "wasm")]
#[derive(Debug, Clone)]
pub struct WasmPluginConfig {
pub capabilities: zlayer_spec::WasmCapabilities,
pub max_memory: Option<String>,
pub max_fuel: u64,
pub request_timeout: std::time::Duration,
}
#[cfg(feature = "wasm")]
#[derive(Debug, Clone)]
pub struct WasmPipelineConfig {
pub service_type: zlayer_spec::ServiceType,
pub capabilities: zlayer_spec::WasmCapabilities,
pub max_memory: Option<String>,
pub max_fuel: u64,
pub request_timeout: std::time::Duration,
pub min_instances: u32,
pub max_instances: u32,
}
#[cfg(feature = "wasm")]
pub fn create_wasm_runtime_for_service_type(
service_type: zlayer_spec::ServiceType,
wasm_config: &zlayer_spec::WasmConfig,
) -> Result<WasmRuntimeKind, Box<dyn std::error::Error + Send + Sync>> {
use zlayer_spec::ServiceType;
match service_type {
ServiceType::WasmHttp => {
#[allow(deprecated)]
let http_config = zlayer_spec::WasmHttpConfig {
min_instances: wasm_config.min_instances,
max_instances: wasm_config.max_instances,
idle_timeout: wasm_config.idle_timeout,
request_timeout: wasm_config.request_timeout,
};
let capabilities = wasm_config
.capabilities
.clone()
.unwrap_or_else(|| service_type.default_wasm_capabilities().unwrap());
let mut runtime = WasmHttpRuntime::new_with_capabilities(http_config, capabilities)?;
runtime.set_resource_limits(wasm_config);
Ok(WasmRuntimeKind::Http(runtime))
}
ServiceType::WasmPlugin => Ok(WasmRuntimeKind::Plugin(WasmPluginConfig {
capabilities: wasm_config
.capabilities
.clone()
.unwrap_or_else(|| service_type.default_wasm_capabilities().unwrap()),
max_memory: wasm_config.max_memory.clone(),
max_fuel: wasm_config.max_fuel,
request_timeout: wasm_config.request_timeout,
})),
ServiceType::WasmTransformer
| ServiceType::WasmAuthenticator
| ServiceType::WasmRateLimiter
| ServiceType::WasmMiddleware
| ServiceType::WasmRouter => Ok(WasmRuntimeKind::Pipeline(WasmPipelineConfig {
service_type,
capabilities: wasm_config
.capabilities
.clone()
.unwrap_or_else(|| service_type.default_wasm_capabilities().unwrap()),
max_memory: wasm_config.max_memory.clone(),
max_fuel: wasm_config.max_fuel,
request_timeout: wasm_config.request_timeout,
min_instances: wasm_config.min_instances,
max_instances: wasm_config.max_instances,
})),
_ => Err(format!("service type {service_type:?} is not a WASM type").into()),
}
}
use crate::error::{AgentError, Result};
use crate::runtime::Runtime;
use std::sync::Arc;
use zlayer_registry::ImagePuller;
pub async fn create_runtime_for_image(
image: &str,
registry: Arc<ImagePuller>,
) -> Result<Arc<dyn Runtime + Send + Sync>> {
let auth = zlayer_registry::RegistryAuth::Anonymous;
tracing::info!(image = %image, "detecting artifact type for runtime selection");
let (artifact_type, _manifest, _digest) = registry
.detect_artifact_type(image, &auth)
.await
.map_err(|e| AgentError::PullFailed {
image: image.to_string(),
reason: format!("failed to detect artifact type: {e}"),
})?;
match artifact_type {
zlayer_registry::ArtifactType::Wasm { wasi_version } => {
tracing::info!(
image = %image,
wasi_version = %wasi_version,
"detected WASM artifact"
);
#[cfg(feature = "wasm")]
{
let runtime = WasmRuntime::new(WasmConfig::default(), None).await?;
Ok(Arc::new(runtime))
}
#[cfg(not(feature = "wasm"))]
{
Err(AgentError::Configuration(format!(
"Image '{image}' is a WASM artifact (WASI {wasi_version}) but the 'wasm' feature is not enabled. \
Recompile zlayer-agent with --features wasm to run WASM workloads."
)))
}
}
zlayer_registry::ArtifactType::Container => {
tracing::info!(image = %image, "detected container image");
crate::create_runtime(crate::RuntimeConfig::Auto, None).await
}
}
}
pub async fn detect_image_artifact_type(
image: &str,
registry: Arc<ImagePuller>,
) -> Result<zlayer_registry::ArtifactType> {
let auth = zlayer_registry::RegistryAuth::Anonymous;
let (artifact_type, _manifest, _digest) = registry
.detect_artifact_type(image, &auth)
.await
.map_err(|e| AgentError::PullFailed {
image: image.to_string(),
reason: format!("failed to detect artifact type: {e}"),
})?;
Ok(artifact_type)
}