From 702972fb10fc3f45a5203f9bd860a04342314e64 Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Fri, 17 Mar 2023 01:35:14 +0800 Subject: [PATCH] Reuse unioned_filesystem() for WCGI --- lib/cli/src/commands/run.rs | 6 +---- lib/vfs/src/webc_fs.rs | 3 +-- lib/wasi/src/runners/wasi.rs | 29 ++++++++++++++++++---- lib/wasi/src/runners/wcgi/handler.rs | 36 ++++------------------------ lib/wasi/src/runners/wcgi/runner.rs | 5 ++-- tests/integration/cli/tests/run2.rs | 7 ++++-- 6 files changed, 38 insertions(+), 48 deletions(-) diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index f16dd7e71..10c9fb9cf 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -409,7 +409,7 @@ impl RunWithPathBuf { .addr(self.wcgi.addr) .envs(self.wasi.env_vars.clone()) .map_directories(self.wasi.mapped_dirs.clone()); - if self.wcgi.forward_host_env { + if self.wasi.forward_host_env { runner.config().forward_host_env(); } if runner.can_run_command(id, command).unwrap_or(false) { @@ -706,16 +706,12 @@ pub(crate) struct WcgiOptions { /// The address to serve on. #[clap(long, short, env, default_value_t = ([127, 0, 0, 1], 8000).into())] pub(crate) addr: SocketAddr, - /// Forward all host env variables to the wcgi task. - #[clap(long)] - pub(crate) forward_host_env: bool, } impl Default for WcgiOptions { fn default() -> Self { Self { addr: ([127, 0, 0, 1], 8000).into(), - forward_host_env: false, } } } diff --git a/lib/vfs/src/webc_fs.rs b/lib/vfs/src/webc_fs.rs index d845a0375..0bb1970cc 100644 --- a/lib/vfs/src/webc_fs.rs +++ b/lib/vfs/src/webc_fs.rs @@ -197,8 +197,7 @@ where let start: usize = self.cursor.try_into().unwrap(); let remaining = &bytes[start..]; let bytes_read = remaining.len().min(buf.remaining()); - let end = start + bytes_read; - let bytes = &bytes[start..end]; + let bytes = &remaining[..bytes_read]; buf.put_slice(bytes); self.cursor += u64::try_from(bytes_read).unwrap(); diff --git a/lib/wasi/src/runners/wasi.rs b/lib/wasi/src/runners/wasi.rs index cf1a8da22..f8dbab035 100644 --- a/lib/wasi/src/runners/wasi.rs +++ b/lib/wasi/src/runners/wasi.rs @@ -132,13 +132,17 @@ impl WasiRunner { container: &WapmContainer, command: &str, ) -> Result { - let root_fs = unioned_filesystem(&self.mapped_dirs, container)?; + let fs = unioned_filesystem(&self.mapped_dirs, container)?; + let fs = container.container_fs(); let mut builder = WasiEnv::builder(command) .args(&self.args) - .fs(Box::new(root_fs)) .preopen_dir("/")?; + preopen(&fs, "/".as_ref(), &mut builder)?; + + builder.set_fs(Box::new(fs)); + if self.forward_host_env { for (k, v) in std::env::vars() { builder.add_env(k, v); @@ -192,7 +196,7 @@ impl crate::runners::Runner for WasiRunner { /// Create a [`FileSystem`] which merges the WAPM container's volumes with any /// directories that were mapped from the host. -fn unioned_filesystem( +pub(crate) fn unioned_filesystem( mapped_dirs: &[MappedDirectory], container: &WapmContainer, ) -> Result { @@ -236,6 +240,19 @@ fn unioned_filesystem( Ok(OverlayFileSystem::new(primary, [container.container_fs()])) } +fn preopen(fs: &dyn FileSystem, path: &Path, builder: &mut WasiEnvBuilder) -> Result<(), Error> { + for result in fs.read_dir(path)? { + let entry = result?; + + if entry.file_type()?.is_dir() { + builder.add_preopen_dir(&entry.path)?; + preopen(fs, &entry.path, builder)?; + } + } + + Ok(()) +} + fn create_dir_all(fs: &(impl FileSystem + ?Sized), path: &Path) -> Result<(), Error> { match fs.metadata(path) { Ok(meta) if meta.is_dir() => return Ok(()), @@ -257,7 +274,6 @@ fn create_dir_all(fs: &(impl FileSystem + ?Sized), path: &Path) -> Result<(), Er mod tests { use tempfile::TempDir; use tokio::io::AsyncReadExt; - use wasmer_vfs::host_fs; use super::*; @@ -313,6 +329,9 @@ mod tests { ] ); let abc = read_file(&fs, "/lib/python3.6/collections/abc.py").await; - assert_eq!(abc, "from _collections_abc import *"); + assert_eq!( + abc, + "from _collections_abc import *\nfrom _collections_abc import __all__\n" + ); } } diff --git a/lib/wasi/src/runners/wcgi/handler.rs b/lib/wasi/src/runners/wcgi/handler.rs index 4b7ac0f2e..278d4302a 100644 --- a/lib/wasi/src/runners/wcgi/handler.rs +++ b/lib/wasi/src/runners/wcgi/handler.rs @@ -23,7 +23,7 @@ use wcgi_host::CgiDialect; use crate::{ capabilities::Capabilities, http::HttpClientCapabilityV1, - runners::{wcgi::Callbacks, MappedDirectory}, + runners::{wcgi::Callbacks, MappedDirectory, WapmContainer}, Pipe, PluggableRuntime, VirtualTaskManager, WasiEnv, }; @@ -134,37 +134,8 @@ impl Handler { Ok(response) } - fn fs(&self) -> Result { - let root_fs = RootFileSystemBuilder::new().build(); - - if !self.mapped_dirs.is_empty() { - let fs_backing: Arc = - Arc::new(PassthruFileSystem::new(crate::default_fs_backing())); - - for MappedDirectory { host, guest } in self.mapped_dirs.iter() { - let guest = match guest.starts_with('/') { - true => PathBuf::from(guest), - false => Path::new("/").join(guest), - }; - tracing::debug!( - host=%host.display(), - guest=%guest.display(), - "mounting host directory", - ); - - root_fs - .mount(guest.clone(), &fs_backing, host.clone()) - .with_context(|| { - format!( - "Unable to mount \"{}\" to \"{}\"", - host.display(), - guest.display() - ) - }) - .unwrap(); - } - } - Ok(root_fs) + fn fs(&self) -> Result { + crate::runners::wasi::unioned_filesystem(&self.mapped_dirs, &self.container) } } @@ -255,6 +226,7 @@ pub(crate) struct SharedState { pub(crate) env: HashMap, pub(crate) args: Vec, pub(crate) mapped_dirs: Vec, + pub(crate) container: WapmContainer, pub(crate) module: Module, pub(crate) dialect: CgiDialect, pub(crate) task_manager: Arc, diff --git a/lib/wasi/src/runners/wcgi/runner.rs b/lib/wasi/src/runners/wcgi/runner.rs index f9b2bd8c9..ad280da05 100644 --- a/lib/wasi/src/runners/wcgi/runner.rs +++ b/lib/wasi/src/runners/wcgi/runner.rs @@ -148,6 +148,7 @@ impl WcgiRunner { .clone() .unwrap_or_else(|| Arc::new(TokioTaskManager::default())), module, + container: ctx.container.clone(), dialect, callbacks: Arc::clone(&self.config.callbacks), }; @@ -225,8 +226,8 @@ impl RunnerContext<'_> { &self.store } - fn volume(&self, _name: &str) -> Option> { - todo!("Implement a read-only filesystem backed by a volume"); + fn container_fs(&self) -> Box { + self.container.container_fs() } fn get_atom(&self, name: &str) -> Option<&[u8]> { diff --git a/tests/integration/cli/tests/run2.rs b/tests/integration/cli/tests/run2.rs index f3bd8b808..efdfe0e21 100644 --- a/tests/integration/cli/tests/run2.rs +++ b/tests/integration/cli/tests/run2.rs @@ -15,6 +15,7 @@ use tempfile::TempDir; use wasmer_integration_tests_cli::get_wasmer_path; const RUST_LOG: &str = "info,wasmer_wasi::runners=debug"; +// const RUST_LOG: &str = "info,wasmer_wasi=trace"; mod webc_on_disk { use super::*; @@ -81,13 +82,15 @@ mod webc_on_disk { let assert = Command::new(get_wasmer_path()) .arg("run2") .arg(fixtures::python()) - .arg("--env") - .arg("SOME_VAR=Hello, World!") + .arg("--env=SOME_VAR=Hello, World!") .arg("--") .arg("-c") .arg("import os; print(os.environ['SOME_VAR'])") + .env("RUST_LOG", RUST_LOG) .assert(); + panic!("{}", String::from_utf8_lossy(&assert.get_output().stderr)); + assert.success().stdout(contains("Hello, World!")); }