From 6360e1383333bf12f040adf37bbafab553f2e27c Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Thu, 19 Oct 2023 21:09:51 +0000 Subject: [PATCH] Move away from oci artifact naming Signed-off-by: James Sturtevant --- Makefile | 5 +- README.md | 10 +- .../src/container/context.rs | 36 ++++-- .../src/sandbox/containerd.rs | 104 ++++++++++++------ .../containerd-shim-wasm/src/sandbox/error.rs | 2 + .../containerd-shim-wasm/src/sandbox/oci.rs | 5 +- .../src/sys/unix/container/executor.rs | 19 ++-- .../src/sys/unix/container/instance.rs | 15 ++- .../containerd-shim-wasmedge/src/instance.rs | 6 +- crates/containerd-shim-wasmer/src/instance.rs | 6 +- .../containerd-shim-wasmtime/src/instance.rs | 6 +- crates/oci-tar-builder/README.md | 2 +- crates/oci-tar-builder/src/bin.rs | 11 +- crates/oci-tar-builder/src/lib.rs | 24 +--- crates/wasi-demo-app/build.rs | 13 ++- cross/Dockerfile.gnu | 2 +- cross/Dockerfile.musl | 2 +- test/k8s/Dockerfile.oci | 9 +- 18 files changed, 158 insertions(+), 119 deletions(-) diff --git a/Makefile b/Makefile index 64463b593..6f5e86153 100644 --- a/Makefile +++ b/Makefile @@ -169,8 +169,11 @@ dist/img-oci.tar: target/wasm32-wasi/$(OPT_PROFILE)/img-oci.tar load: dist/img.tar sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< +CTR_VERSION := $(shell sudo ctr version | sed -n -e '/Version/ {s/.*: *//p;q;}') load/oci: dist/img-oci.tar - sudo ../containerd/bin/ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< + @echo $(CTR_VERSION)\\nv1.7.7 | sort -crV || (echo "containerd version must be 1.7.7+ was $(CTR_VERSION)" && exit 1) + @echo using containerd $(CTR_VERSION) + sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< .PHONY: target/wasm32-wasi/$(OPT_PROFILE)/img-oci.tar: target/wasm32-wasi/$(OPT_PROFILE)/wasi-demo-app.wasm diff --git a/README.md b/README.md index 9dc15a9c7..2a2c01986 100644 --- a/README.md +++ b/README.md @@ -323,22 +323,22 @@ To kill the process from demo 2, you can run in other session: `sudo ctr task ki The test binary supports commands for different type of functionality, check [crates/wasi-demo-app/src/main.rs](crates/wasi-demo-app/src/main.rs) to try it out. -## Demo 3 using WASM OCI artifacts +## Demo 3 using OCI Images with custom WASM layers -The previous demos run with an OCI Container image containing the wasm module in the file system. Another option is to provide a cross-platform OCI artifact that that will not have the wasm module or components in the file system of the container that wraps the wasmtime/wasmedge process. This OCI artifact can be run across any platform and provides for de-duplication in the Containerd content store among other benefits. +The previous demos run with an OCI Container image containing the wasm module in the file system. Another option is to provide a cross-platform OCI Image that that will not have the wasm module or components in the file system of the container that wraps the wasmtime/wasmedge process. This OCI Image with custom WASM layers can be run across any platform and provides for de-duplication in the Containerd content store among other benefits. To learn more about this approach checkout the [design document](https://docs.google.com/document/d/11shgC3l6gplBjWF1VJCWvN_9do51otscAm0hBDGSSAc/edit). -> **Note**: This requires containerd components based on https://github.com/containerd/containerd/pull/8699. Both CTR and containerd need to be build with that patch. If you do not have this patch for both `containerd` and `ctr` you will end up with an error message such as `mismatched image rootfs and manifest layers` at the import and run steps +> **Note**: This requires containerd 1.7.7+ and 1.6.25+ (not yet released). If you do not have these patches for both `containerd` and `ctr` you will end up with an error message such as `mismatched image rootfs and manifest layers` at the import and run steps. -Build and import the OCI artifact image: +Build and import the OCI image with WASM layers image: ``` make test-image/oci make load/oci ``` -Run the image with `sudo ctr run --rm --runtime=io.containerd.[ wasmedge | wasmtime | wasmer ].v1 --label application/vnd.bytecodealliance.wasm.module=oci.wasm ghcr.io/containerd/runwasi/wasi-demo-oci:latest testwasmoci` +Run the image with `sudo ctr run --rm --runtime=io.containerd.[ wasmedge | wasmtime | wasmer ].v1 ghcr.io/containerd/runwasi/wasi-demo-oci:latest testwasmoci` ``` sudo ctr run --rm --runtime=io.containerd.wasmtime.v1 ghcr.io/containerd/runwasi/wasi-demo-oci:latest testwasmoci wasi-demo-oci.wasm echo 'hello' diff --git a/crates/containerd-shim-wasm/src/container/context.rs b/crates/containerd-shim-wasm/src/container/context.rs index e9fb982e7..97fea259a 100644 --- a/crates/containerd-shim-wasm/src/container/context.rs +++ b/crates/containerd-shim-wasm/src/container/context.rs @@ -1,8 +1,9 @@ use std::path::{Path, PathBuf}; +use oci_spec::image::Platform; use oci_spec::runtime::Spec; -use crate::sandbox::oci::OciArtifact; +use crate::sandbox::oci::WasmLayer; pub trait RuntimeContext { // ctx.args() returns arguments from the runtime spec process field, including the @@ -23,7 +24,9 @@ pub trait RuntimeContext { // "#init" -> { path: "", func: "init" } fn wasi_entrypoint(&self) -> WasiEntrypoint; - fn oci_artifacts(&self) -> &[OciArtifact]; + fn wasm_layers(&self) -> &[WasmLayer]; + + fn platform(&self) -> &Platform; } pub struct WasiEntrypoint { @@ -33,7 +36,8 @@ pub struct WasiEntrypoint { pub(crate) struct WasiContext<'a> { pub spec: &'a Spec, - pub oci_artifacts: &'a [OciArtifact], + pub wasm_layers: &'a [WasmLayer], + pub platform: &'a Platform, } impl RuntimeContext for WasiContext<'_> { @@ -59,8 +63,12 @@ impl RuntimeContext for WasiContext<'_> { } } - fn oci_artifacts(&self) -> &[OciArtifact] { - self.oci_artifacts + fn wasm_layers(&self) -> &[WasmLayer] { + self.wasm_layers + } + + fn platform(&self) -> &Platform { + self.platform } } @@ -85,7 +93,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let args = ctx.args(); @@ -104,7 +113,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let args = ctx.args(); @@ -131,7 +141,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let args = ctx.args(); @@ -152,7 +163,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let path = ctx.wasi_entrypoint().path; @@ -179,7 +191,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let WasiEntrypoint { path, func } = ctx.wasi_entrypoint(); @@ -207,7 +220,8 @@ mod tests { let ctx = WasiContext { spec: &spec, - oci_artifacts: &[], + wasm_layers: &[], + platform: &Platform::default(), }; let WasiEntrypoint { path, func } = ctx.wasi_entrypoint(); diff --git a/crates/containerd-shim-wasm/src/sandbox/containerd.rs b/crates/containerd-shim-wasm/src/sandbox/containerd.rs index 8c9569957..3168c1dd7 100644 --- a/crates/containerd-shim-wasm/src/sandbox/containerd.rs +++ b/crates/containerd-shim-wasm/src/sandbox/containerd.rs @@ -10,14 +10,14 @@ use containerd_client::services::v1::{GetContainerRequest, GetImageRequest, Read use containerd_client::tonic::transport::Channel; use containerd_client::{tonic, with_namespace}; use futures::TryStreamExt; -use oci_spec::image::{ImageManifest, MediaType}; +use oci_spec::image::{Arch, ImageManifest, MediaType, Platform}; use tokio::runtime::Runtime; use tonic::Request; use crate::sandbox::error::{Error as ShimError, Result}; -use crate::sandbox::oci::{self, OciArtifact, COMPONENT_ARTIFACT_TYPE, MODULE_ARTIFACT_TYPE}; +use crate::sandbox::oci::{self, WasmLayer}; -pub struct Client { +pub(crate) struct Client { inner: Channel, rt: Runtime, namespace: String, @@ -33,7 +33,7 @@ impl Client { let inner = rt .block_on(containerd_client::connect(address)) - .map_err(|err| ShimError::Others(err.to_string()))?; + .map_err(|err| ShimError::Containerd(err.to_string()))?; Ok(Client { inner, @@ -53,12 +53,12 @@ impl Client { ContentClient::new(self.inner.clone()) .read(req) .await - .map_err(|err| ShimError::Others(err.to_string()))? + .map_err(|err| ShimError::Containerd(err.to_string()))? .into_inner() .map_ok(|msg| msg.data) .try_concat() .await - .map_err(|err| ShimError::Others(err.to_string())) + .map_err(|err| ShimError::Containerd(err.to_string())) }) } @@ -70,10 +70,22 @@ impl Client { let digest = ImagesClient::new(self.inner.clone()) .get(req) .await - .map_err(|err| ShimError::Others(err.to_string()))? + .map_err(|err| ShimError::Containerd(err.to_string()))? .into_inner() - .image.ok_or(ShimError::Others(format!("failed to get image content sha for image {}", image_name.to_string())))? - .target.ok_or(ShimError::Others(format!("failed to get image content sha for image {}", image_name.to_string())))? + .image + .ok_or_else(|| { + ShimError::Containerd(format!( + "failed to get image content sha for image {}", + image_name.to_string() + )) + })? + .target + .ok_or_else(|| { + ShimError::Containerd(format!( + "failed to get image content sha for image {}", + image_name.to_string() + )) + })? .digest; Ok(digest) }) @@ -87,50 +99,74 @@ impl Client { let image = ContainersClient::new(self.inner.clone()) .get(req) .await - .map_err(|err| ShimError::Others(err.to_string()))? + .map_err(|err| ShimError::Containerd(err.to_string()))? .into_inner() .container - .ok_or(ShimError::Others(format!("failed to get image for container {}", container_name.to_string())))? + .ok_or_else(|| { + ShimError::Containerd(format!( + "failed to get image for container {}", + container_name.to_string() + )) + })? .image; Ok(image) }) } - // load module will query the containerd store to find an image that has an ArtifactType of WASM OCI Artifact + // load module will query the containerd store to find an image that has an OS of type 'wasm' // If found it continues to parse the manifest and return the layers that contains the WASM modules - // and possibly other configuration artifacts - pub fn load_modules(&self, containerd_id: impl ToString) -> Result> { + // and possibly other configuration layers. + pub fn load_modules( + &self, + containerd_id: impl ToString, + ) -> Result<(Vec, Platform)> { let image_name = self.get_image(containerd_id.to_string())?; let digest = self.get_image_content_sha(image_name)?; let manifest = self.read_content(digest)?; let manifest = manifest.as_slice(); let manifest = ImageManifest::from_reader(manifest)?; - let artifact_type = manifest - .artifact_type() - .as_ref() - .ok_or(ShimError::Others("manifest is not an OCI Artifact".to_string()))?; + let image_config_descriptor = manifest.config(); + let image_config = self.read_content(image_config_descriptor.digest())?; + let image_config = image_config.as_slice(); - match artifact_type { - MediaType::Other(s) if s == COMPONENT_ARTIFACT_TYPE || s == MODULE_ARTIFACT_TYPE => { - log::info!("manifest with OCI Artifact of type {s}"); - } - _ => { - log::info!("manifest is not a known OCI Artifact: {artifact_type}"); - return Ok([].to_vec()); - } - } + // the only part we care about here is the platform values + let platform: Platform = serde_json::from_slice(image_config)?; + let Arch::Wasm = platform.architecture() else { + log::info!("manifest is not in WASM OCI image format"); + return Ok((vec![], platform)); + }; + log::info!("found manifest with WASM OCI image format."); - Ok(manifest + let layers = manifest .layers() .iter() + .filter(|x| !is_image_layer_type(x.media_type())) .map(|config| { - self.read_content(config.digest()) - .map(|module| OciArtifact { - config: config.clone(), - layer: module, - }) + self.read_content(config.digest()).map(|module| WasmLayer { + config: config.clone(), + layer: module, + }) }) - .collect::>>()?) + .collect::>>()?; + Ok((layers, platform)) + } +} + +fn is_image_layer_type(media_type: &MediaType) -> bool { + match media_type { + MediaType::ImageLayer + | MediaType::ImageLayerGzip + | MediaType::ImageLayerNonDistributable + | MediaType::ImageLayerNonDistributableGzip + | MediaType::ImageLayerNonDistributableZstd + | MediaType::ImageLayerZstd => true, + MediaType::Other(s) + if s.as_str() + .starts_with("application/vnd.docker.image.rootfs.") => + { + true + } + _ => false, } } diff --git a/crates/containerd-shim-wasm/src/sandbox/error.rs b/crates/containerd-shim-wasm/src/sandbox/error.rs index 6d072077a..a9a87f0c0 100644 --- a/crates/containerd-shim-wasm/src/sandbox/error.rs +++ b/crates/containerd-shim-wasm/src/sandbox/error.rs @@ -46,6 +46,8 @@ pub enum Error { #[cfg(unix)] #[error("{0}")] Libcontainer(#[from] libcontainer::error::LibcontainerError), + #[error("{0}")] + Containerd(String), } pub type Result = ::std::result::Result; diff --git a/crates/containerd-shim-wasm/src/sandbox/oci.rs b/crates/containerd-shim-wasm/src/sandbox/oci.rs index bc03d9e36..e06f50dec 100644 --- a/crates/containerd-shim-wasm/src/sandbox/oci.rs +++ b/crates/containerd-shim-wasm/src/sandbox/oci.rs @@ -12,11 +12,8 @@ pub use oci_spec::runtime::Spec; use super::error::Result; -pub const COMPONENT_ARTIFACT_TYPE: &str = "application/vnd.bytecodealliance.component.v1+wasm"; -pub const MODULE_ARTIFACT_TYPE: &str = "application/vnd.bytecodealliance.module.v1+wasm"; - #[derive(Clone)] -pub struct OciArtifact { +pub struct WasmLayer { pub config: Descriptor, pub layer: Vec, } diff --git a/crates/containerd-shim-wasm/src/sys/unix/container/executor.rs b/crates/containerd-shim-wasm/src/sys/unix/container/executor.rs index 99598cd5e..287f74d3c 100644 --- a/crates/containerd-shim-wasm/src/sys/unix/container/executor.rs +++ b/crates/containerd-shim-wasm/src/sys/unix/container/executor.rs @@ -10,10 +10,11 @@ use libcontainer::workload::{ Executor as LibcontainerExecutor, ExecutorError as LibcontainerExecutorError, ExecutorValidationError, }; +use oci_spec::image::Platform; use oci_spec::runtime::Spec; use crate::container::{Engine, PathResolve, RuntimeContext, Stdio, WasiContext}; -use crate::sandbox::oci::OciArtifact; +use crate::sandbox::oci::WasmLayer; #[derive(Clone)] enum InnerExecutor { @@ -27,7 +28,8 @@ pub(crate) struct Executor { engine: E, stdio: Stdio, inner: OnceCell, - oci_artifacts: Vec, + wasm_layers: Vec, + platform: Platform, } impl LibcontainerExecutor for Executor { @@ -64,27 +66,30 @@ impl LibcontainerExecutor for Executor { } impl Executor { - pub fn new(engine: E, stdio: Stdio, oci_artifacts: Vec) -> Self { + pub fn new(engine: E, stdio: Stdio, wasm_layers: Vec, platform: Platform) -> Self { Self { engine, stdio, inner: Default::default(), - oci_artifacts, + wasm_layers, + platform, } } fn ctx<'a>(&'a self, spec: &'a Spec) -> WasiContext<'a> { - let oci_artifacts = &self.oci_artifacts; + let wasm_layers = &self.wasm_layers; + let platform = &self.platform; WasiContext { spec, - oci_artifacts, + wasm_layers, + platform, } } fn inner(&self, spec: &Spec) -> &InnerExecutor { self.inner.get_or_init(|| { // if the spec has oci annotations we know it is wasm so short circuit checks - if !self.oci_artifacts.is_empty() { + if !self.wasm_layers.is_empty() { InnerExecutor::Wasm } else if is_linux_container(&self.ctx(spec)).is_ok() { InnerExecutor::Linux diff --git a/crates/containerd-shim-wasm/src/sys/unix/container/instance.rs b/crates/containerd-shim-wasm/src/sys/unix/container/instance.rs index dcc624efc..247bb39b5 100644 --- a/crates/containerd-shim-wasm/src/sys/unix/container/instance.rs +++ b/crates/containerd-shim-wasm/src/sys/unix/container/instance.rs @@ -12,11 +12,14 @@ use libcontainer::syscall::syscall::SyscallType; use nix::errno::Errno; use nix::sys::wait::{waitid, Id as WaitID, WaitPidFlag, WaitStatus}; use nix::unistd::Pid; +use oci_spec::image::Platform; use crate::container::Engine; use crate::sandbox::instance_utils::{determine_rootdir, get_instance_root, instance_exists}; use crate::sandbox::sync::WaitableCell; -use crate::sandbox::{containerd, Error as SandboxError, Instance as SandboxInstance, InstanceConfig, Stdio}; +use crate::sandbox::{ + containerd, Error as SandboxError, Instance as SandboxInstance, InstanceConfig, Stdio, +}; use crate::sys::container::executor::Executor; static DEFAULT_CONTAINER_ROOT_DIR: &str = "/run/containerd"; @@ -40,16 +43,16 @@ impl SandboxInstance for Instance { let rootdir = determine_rootdir(&bundle, &namespace, rootdir)?; let stdio = Stdio::init_from_cfg(cfg)?; - // check if container is OCI artifact and attempt to read the module - let modules = containerd::Client::connect(cfg.get_containerd_address(), &namespace)? + // check if container is OCI image with wasm layers and attempt to read the module + let (modules, platform) = containerd::Client::connect(cfg.get_containerd_address(), &namespace)? .load_modules(&id) .unwrap_or_else(|e| { - log::warn!("Error obtaining wasm layers for container {}. Will attempt to use files inside containerd image. Error: {}", id.clone(), e); - vec![] + log::warn!("Error obtaining wasm layers for container {id}. Will attempt to use files inside container image. Error: {e}"); + (vec![], Platform::default()) }); ContainerBuilder::new(id.clone(), SyscallType::Linux) - .with_executor(Executor::new(engine, stdio, modules)) + .with_executor(Executor::new(engine, stdio, modules, platform)) .with_root_path(rootdir.clone())? .as_init(&bundle) .with_systemd(false) diff --git a/crates/containerd-shim-wasmedge/src/instance.rs b/crates/containerd-shim-wasmedge/src/instance.rs index a42560123..ce723d439 100644 --- a/crates/containerd-shim-wasmedge/src/instance.rs +++ b/crates/containerd-shim-wasmedge/src/instance.rs @@ -57,7 +57,7 @@ impl Engine for WasmEdgeEngine { PluginManager::load(None)?; let vm = vm.auto_detect_plugins()?; - let vm = match ctx.oci_artifacts() { + let vm = match ctx.wasm_layers() { [] => { debug!("loading module from file"); let path = entrypoint_path @@ -69,11 +69,11 @@ impl Engine for WasmEdgeEngine { .context("registering module")? } [module] => { - log::info!("loading module from OCI Artifact"); + log::info!("loading module from wasm OCI layers"); vm.register_module_from_bytes(&mod_name, &module.layer) .context("registering module")? } - [..] => bail!("only a single module is supported when using OCI Artifact"), + [..] => bail!("only a single module is supported when using images with OCI layers"), }; stdio.redirect()?; diff --git a/crates/containerd-shim-wasmer/src/instance.rs b/crates/containerd-shim-wasmer/src/instance.rs index 360d7ed68..7ca35a2ec 100644 --- a/crates/containerd-shim-wasmer/src/instance.rs +++ b/crates/containerd-shim-wasmer/src/instance.rs @@ -31,7 +31,7 @@ impl Engine for WasmerEngine { log::info!("Create a Store"); let mut store = Store::new(self.engine.clone()); - let module = match ctx.oci_artifacts() { + let module = match ctx.wasm_layers() { [] => { log::info!("loading module from file {path:?}"); let path = path @@ -42,10 +42,10 @@ impl Engine for WasmerEngine { Module::from_file(&store, path)? } [module] => { - log::info!("loading module from OCI Artifact"); + log::info!("loading module wasm OCI layers"); Module::from_binary(&store, &module.layer)? } - [..] => bail!("only a single module is supported when using OCI Artifact"), + [..] => bail!("only a single module is supported when using images with OCI layers"), }; let runtime = tokio::runtime::Builder::new_multi_thread() diff --git a/crates/containerd-shim-wasmtime/src/instance.rs b/crates/containerd-shim-wasmtime/src/instance.rs index 057c50fb1..3655a2773 100644 --- a/crates/containerd-shim-wasmtime/src/instance.rs +++ b/crates/containerd-shim-wasmtime/src/instance.rs @@ -37,7 +37,7 @@ impl Engine for WasmtimeEngine { log::info!("wasi context ready"); let WasiEntrypoint { path, func } = ctx.wasi_entrypoint(); - let module = match ctx.oci_artifacts() { + let module = match ctx.wasm_layers() { [] => { log::info!("loading module from file"); let path = path @@ -48,10 +48,10 @@ impl Engine for WasmtimeEngine { Module::from_file(&self.engine, path)? } [module] => { - log::info!("loading module from OCI Artifact"); + log::info!("loading module wasm OCI layers"); Module::from_binary(&self.engine, &module.layer)? } - [..] => bail!("only a single module is supported when using OCI Artifact"), + [..] => bail!("only a single module is supported when using images with OCI layers"), }; let mut linker = Linker::new(&self.engine); diff --git a/crates/oci-tar-builder/README.md b/crates/oci-tar-builder/README.md index fd0911eae..f775f9641 100644 --- a/crates/oci-tar-builder/README.md +++ b/crates/oci-tar-builder/README.md @@ -20,7 +20,7 @@ See [wasi-demo-app build script](../wasi-demo-app/build.rs) for an example. ### Executable usage -There is an experimental executable that uses the library and can package a wasm module as an OCI artifact. This isn't currently usable with containerd/runwasi today. See the [OCI artifacts in containerd](https://docs.google.com/document/d/11shgC3l6gplBjWF1VJCWvN_9do51otscAm0hBDGSSAc) for more information. +There is an experimental executable that uses the library and can package a wasm module as an OCI image with wasm layers. See the [OCI WASM in containerd](https://docs.google.com/document/d/11shgC3l6gplBjWF1VJCWvN_9do51otscAm0hBDGSSAc) for more information. To generate the package and import to a registry using a tool such as [regctl](https://github.com/regclient/regclient/blob/main/docs/regctl.md#image-commands): diff --git a/crates/oci-tar-builder/src/bin.rs b/crates/oci-tar-builder/src/bin.rs index 06575ffdb..0d1ba80b8 100644 --- a/crates/oci-tar-builder/src/bin.rs +++ b/crates/oci-tar-builder/src/bin.rs @@ -4,11 +4,9 @@ use std::{env, fs}; use anyhow::Context; use clap::Parser; -use oci_spec::image as spec; +use oci_spec::image::{self as spec, Arch}; use oci_tar_builder::Builder; -// Following labels and media types must match in ../containerd-shim-wasm/src/sandbox/oci.rs -// not using it here to avoid needing to have all the deps for containerd-shim-wasm pub const WASM_LAYER_MEDIA_TYPE: &str = "application/vnd.bytecodealliance.wasm.component.layer.v0+wasm"; @@ -27,8 +25,6 @@ pub fn main() { let mut builder = Builder::default(); for module_path in args.module.iter() { - builder.as_module_artifact(); - let module_path = PathBuf::from(module_path); builder.add_layer_with_media_type(&module_path, WASM_LAYER_MEDIA_TYPE.to_string()); } @@ -43,7 +39,6 @@ pub fn main() { } if let Some(components_path) = args.components.as_deref() { - builder.as_component_artifact(); let paths = fs::read_dir(components_path).unwrap(); for path in paths { @@ -69,8 +64,8 @@ pub fn main() { let img = spec::ImageConfigurationBuilder::default() .config(config) - .os("wasi") - .architecture("wasm") + .os("wasip1") + .architecture(Arch::Wasm) .rootfs( spec::RootFsBuilder::default() .diff_ids(vec![]) diff --git a/crates/oci-tar-builder/src/lib.rs b/crates/oci-tar-builder/src/lib.rs index 3defdacd5..cabf785a1 100644 --- a/crates/oci-tar-builder/src/lib.rs +++ b/crates/oci-tar-builder/src/lib.rs @@ -11,18 +11,10 @@ use oci_spec::image::{ }; use serde::Serialize; use sha256::{digest, try_digest}; - -// duplicated here to avoid pulling in all of containerd-shim-wasm -// Module is preview1 -// Component is preview2 -const COMPONENT_ARTIFACT_TYPE: &str = "application/vnd.bytecodealliance.component.v1+wasm"; -const MODULE_ARTIFACT_TYPE: &str = "application/vnd.bytecodealliance.module.v1+wasm"; - #[derive(Debug, Default)] pub struct Builder { configs: Vec<(ImageConfiguration, String)>, layers: Vec<(PathBuf, String)>, - artifact_type: Option, } #[derive(Serialize, Debug)] @@ -131,7 +123,7 @@ impl Builder { .build() .context("failed to build descriptor")?; - // add all layer_digests including any OCI artifacts types that are may not be in the rootfs + // add all layer_digests including any OCI WASM types that are may not be in the rootfs let mut layers = Vec::new(); for (_k, v) in layer_digests.iter() { layers.push(v.clone()); @@ -155,14 +147,10 @@ impl Builder { mfst.repo_tags.push(config.1.clone()); annotations.insert("io.containerd.image.name".to_string(), config.1.clone()); - let mut manifest = ImageManifestBuilder::default() + let manifest = ImageManifestBuilder::default() .schema_version(SCHEMA_VERSION) .media_type(MediaType::ImageManifest); - if self.artifact_type.is_some() { - manifest = manifest.artifact_type(self.artifact_type.clone().unwrap().as_str()); - } - let manifest = manifest .layers(layers) .config(desc) @@ -244,12 +232,4 @@ impl Builder { Ok(()) } - - pub fn as_module_artifact(&mut self) { - self.artifact_type = Some(MODULE_ARTIFACT_TYPE.to_string()); - } - - pub fn as_component_artifact(&mut self) { - self.artifact_type = Some(COMPONENT_ARTIFACT_TYPE.to_string()); - } } diff --git a/crates/wasi-demo-app/build.rs b/crates/wasi-demo-app/build.rs index f5b43ed11..70a336691 100644 --- a/crates/wasi-demo-app/build.rs +++ b/crates/wasi-demo-app/build.rs @@ -1,7 +1,12 @@ #[cfg(feature = "oci-v1-tar")] use { - anyhow::Context, oci_spec::image as spec, oci_tar_builder::Builder, sha256::try_digest, - std::env, std::fs::File, std::path::PathBuf, + anyhow::Context, + oci_spec::image::{self as spec, Arch}, + oci_tar_builder::Builder, + sha256::try_digest, + std::env, + std::fs::File, + std::path::PathBuf, }; #[cfg(not(feature = "oci-v1-tar"))] @@ -39,8 +44,8 @@ fn main() { let layer_digest = try_digest(layer_path.as_path()).unwrap(); let img = spec::ImageConfigurationBuilder::default() .config(config) - .os("wasi") - .architecture("wasm") + .os("wasip1") + .architecture(Arch::Wasm) .rootfs( spec::RootFsBuilder::default() .diff_ids(vec!["sha256:".to_owned() + &layer_digest]) diff --git a/cross/Dockerfile.gnu b/cross/Dockerfile.gnu index 54ca2996e..9ba7fb199 100644 --- a/cross/Dockerfile.gnu +++ b/cross/Dockerfile.gnu @@ -5,4 +5,4 @@ FROM $CROSS_BASE_IMAGE ARG CROSS_DEB_ARCH RUN dpkg --add-architecture ${CROSS_DEB_ARCH} && \ apt-get -y update && \ - apt-get install -y pkg-config libseccomp-dev:${CROSS_DEB_ARCH} + apt-get install -y pkg-config protobuf-compiler libseccomp-dev:${CROSS_DEB_ARCH} diff --git a/cross/Dockerfile.musl b/cross/Dockerfile.musl index e359b520c..48dbd6c60 100644 --- a/cross/Dockerfile.musl +++ b/cross/Dockerfile.musl @@ -22,4 +22,4 @@ rustflags = ["-Clink-arg=-lgcc"] EOF RUN apt-get -y update && \ - apt-get install -y pkg-config + apt-get install -y pkg-config protobuf-compiler diff --git a/test/k8s/Dockerfile.oci b/test/k8s/Dockerfile.oci index 4473470a0..2dcbccc9e 100644 --- a/test/k8s/Dockerfile.oci +++ b/test/k8s/Dockerfile.oci @@ -1,13 +1,13 @@ # syntax=docker/dockerfile:1.4 -ARG KIND_NODE_VERSION=v1.23.13 +ARG KIND_NODE_VERSION=v1.27.3@sha256:3966ac761ae0136263ffdb6cfd4db23ef8a83cba8a463690e98317add2c9ba72 ARG RUNTIME=wasmtime -ARG GO_VERSION="1.21.1" +ARG GO_VERSION="1.21.3-bullseye" # modified from https://github.com/kubernetes-sigs/kind/blob/main/images/base/Dockerfile # stage for building containerd FROM golang:${GO_VERSION} as build-containerd -ARG CONTAINERD_VERSION="main" +ARG CONTAINERD_VERSION="v1.7.7" ARG CONTAINERD_CLONE_URL="https://github.com/containerd/containerd" # we don't build with optional snapshotters, we never select any of these # they're not ideal inside kind anyhow, and we save some disk space @@ -28,8 +28,7 @@ RUN apt-get update -y && \ ADD dist/bin/* /usr/local/bin/ ARG RUNTIME -RUN sed -i 's,SystemdCgroup = true,,' /etc/containerd/config.toml && \ - cat <> /etc/containerd/config.toml +RUN cat <> /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.wasm] runtime_type = "io.containerd.${RUNTIME}.v1" EOF \ No newline at end of file