diff --git a/src/spawner.rs b/src/spawner.rs index ec618f0..95aa768 100644 --- a/src/spawner.rs +++ b/src/spawner.rs @@ -1,6 +1,8 @@ use log::{debug, error, info}; -use super::specification::{Arg, Entrypoint, FileSocket, Pipe, Specification, Trigger}; +use super::specification::{ + Arg, Entrypoint, Environment, FileSocket, Pipe, Specification, Trigger, +}; use super::{PipePair, SocketPair}; use crate::void::VoidBuilder; use crate::{Error, Result}; @@ -63,6 +65,8 @@ impl<'a> Spawner<'a> { let mut builder = VoidBuilder::new(); builder.mount(binary, "/entrypoint"); + self.prepare_env(&mut builder, &entrypoint.environment); + let closure = || { let args = self .prepare_args(name, &entrypoint.args, &mut TriggerData::None) @@ -92,6 +96,8 @@ impl<'a> Spawner<'a> { builder.mount(binary, "/entrypoint"); builder.keep_fd(&pipe); + self.prepare_env(&mut builder, &entrypoint.environment); + let closure = || match self.pipe_trigger(pipe, entrypoint, name) { Ok(()) => std::process::exit(exitcode::OK), Err(e) => { @@ -111,6 +117,8 @@ impl<'a> Spawner<'a> { builder.mount(binary, "/entrypoint"); builder.keep_fd(&socket); + self.prepare_env(&mut builder, &entrypoint.environment); + let closure = || match self.file_socket_trigger(socket, entrypoint, name) { Ok(()) => std::process::exit(exitcode::OK), Err(e) => { @@ -140,6 +148,17 @@ impl<'a> Spawner<'a> { let mut builder = VoidBuilder::new(); builder.mount("/entrypoint", "/entrypoint"); + for env in &spec.environment { + match env { + Environment::Filesystem { + host_path: _host_path, + environment_path, + } => { + builder.mount(environment_path, environment_path); + } + } + } + let closure = || { let pipe_trigger = std::str::from_utf8(&buf[0..read_bytes]).unwrap(); @@ -190,6 +209,17 @@ impl<'a> Spawner<'a> { builder.keep_fd(fd); } + for env in &spec.environment { + match env { + Environment::Filesystem { + host_path: _host_path, + environment_path, + } => { + builder.mount(environment_path, environment_path); + } + } + } + let closure = || { let args = self .prepare_args_ref( @@ -222,6 +252,23 @@ impl<'a> Spawner<'a> { } } + fn prepare_env<'b>( + &self, + builder: &mut VoidBuilder, + environment: impl IntoIterator, + ) { + for env in environment { + match env { + Environment::Filesystem { + host_path, + environment_path, + } => { + builder.mount(host_path, environment_path); + } + } + } + } + fn prepare_args( &mut self, entrypoint: &str, diff --git a/src/specification.rs b/src/specification.rs index 583bfd1..453d37d 100644 --- a/src/specification.rs +++ b/src/specification.rs @@ -21,6 +21,9 @@ pub struct Entrypoint { #[serde(default = "Arg::default_vec")] pub args: Vec, + + #[serde(default)] + pub environment: HashSet, } #[derive(Serialize, Deserialize, Debug)] @@ -106,15 +109,11 @@ impl FileSocket { } #[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug)] -pub enum Permission { +pub enum Environment { Filesystem { host_path: PathBuf, - final_path: PathBuf, + environment_path: PathBuf, }, - Network { - network: Network, - }, - PropagateFiles, } #[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug)] diff --git a/src/void.rs b/src/void.rs index 2c2eaf5..da8247b 100644 --- a/src/void.rs +++ b/src/void.rs @@ -148,13 +148,21 @@ impl VoidBuilder { // mount paths before unmounting old_root for (src, dst) in &self.mounts { - let src = old_root.join(src.strip_prefix("/").unwrap_or(src)); + let mut src = old_root.join(src.strip_prefix("/").unwrap_or(src)); let dst = new_root.join(dst.strip_prefix("/").unwrap_or(dst)); debug!("mounting `{:?}` as `{:?}`", src, dst); // create the target - let src_data = fs::metadata(&src)?; + let mut src_data = fs::symlink_metadata(&src)?; + + if src_data.is_symlink() { + let link = fs::read_link(src)?; + + src = old_root.join(link.strip_prefix("/").unwrap_or(&link)); + src_data = fs::metadata(&src)?; + } + if src_data.is_dir() { fs::create_dir_all(&dst)?; } else {