better argument preparation
This commit is contained in:
parent
245bbfdf9d
commit
f7f8004323
121
src/spawner.rs
121
src/spawner.rs
@ -9,7 +9,7 @@ use std::collections::HashMap;
|
|||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::IntoRawFd;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use nix::unistd;
|
use nix::unistd;
|
||||||
@ -23,6 +23,23 @@ pub struct Spawner<'a> {
|
|||||||
pub trailing: &'a Vec<&'a str>,
|
pub trailing: &'a Vec<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum TriggerData<'a> {
|
||||||
|
/// No data, for example a Startup trigger
|
||||||
|
None,
|
||||||
|
|
||||||
|
/// A string sent across a pipe
|
||||||
|
Pipe(&'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TriggerData<'a> {
|
||||||
|
fn args(&mut self) -> Vec<CString> {
|
||||||
|
match self {
|
||||||
|
TriggerData::None => vec![],
|
||||||
|
TriggerData::Pipe(s) => vec![CString::new(s.to_string()).unwrap()],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Spawner<'a> {
|
impl<'a> Spawner<'a> {
|
||||||
pub fn spawn(&mut self) -> Result<()> {
|
pub fn spawn(&mut self) -> Result<()> {
|
||||||
for (name, entrypoint) in &self.spec.entrypoints {
|
for (name, entrypoint) in &self.spec.entrypoints {
|
||||||
@ -36,7 +53,9 @@ impl<'a> Spawner<'a> {
|
|||||||
builder.mount(binary, "/entrypoint");
|
builder.mount(binary, "/entrypoint");
|
||||||
|
|
||||||
let closure = || {
|
let closure = || {
|
||||||
let args = self.prepare_args(name, &entrypoint.args, None);
|
let args = self
|
||||||
|
.prepare_args(name, &entrypoint.args, &mut TriggerData::None)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
|
if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
|
||||||
.map_err(|e| Error::Nix {
|
.map_err(|e| Error::Nix {
|
||||||
@ -92,7 +111,9 @@ impl<'a> Spawner<'a> {
|
|||||||
let closure =
|
let closure =
|
||||||
|| {
|
|| {
|
||||||
let pipe_trigger = std::str::from_utf8(&buf[0..read_bytes]).unwrap();
|
let pipe_trigger = std::str::from_utf8(&buf[0..read_bytes]).unwrap();
|
||||||
let args = self.prepare_args_ref(name, &spec.args, Some(pipe_trigger));
|
let args = self
|
||||||
|
.prepare_args_ref(name, &spec.args, &mut TriggerData::Pipe(pipe_trigger))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
|
if let Err(e) = unistd::execv(&CString::new("/entrypoint").unwrap(), &args)
|
||||||
.map_err(|e| Error::Nix {
|
.map_err(|e| Error::Nix {
|
||||||
@ -116,67 +137,67 @@ impl<'a> Spawner<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
entrypoint: &str,
|
entrypoint: &str,
|
||||||
args: &[Arg],
|
args: &[Arg],
|
||||||
pipe_trigger: Option<&str>,
|
trigger: &mut TriggerData,
|
||||||
) -> Vec<CString> {
|
) -> Result<Vec<CString>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match arg {
|
out.extend(self.prepare_arg(entrypoint, arg, trigger)?);
|
||||||
Arg::BinaryName => out.push(CString::new(self.binary).unwrap()),
|
|
||||||
Arg::Entrypoint => out.push(CString::new(entrypoint).unwrap()),
|
|
||||||
|
|
||||||
Arg::Pipe(p) => out.push(match p {
|
|
||||||
Pipe::Rx(s) => {
|
|
||||||
let pipe = self.pipes.get_mut(s).unwrap().take_read().unwrap();
|
|
||||||
CString::new(pipe.as_raw_fd().to_string()).unwrap()
|
|
||||||
}
|
}
|
||||||
Pipe::Tx(s) => {
|
Ok(out)
|
||||||
let pipe = self.pipes.get_mut(s).unwrap().take_write().unwrap();
|
|
||||||
CString::new(pipe.as_raw_fd().to_string()).unwrap()
|
|
||||||
}
|
}
|
||||||
}),
|
|
||||||
|
|
||||||
Arg::PipeTrigger => {
|
|
||||||
out.push(CString::new(pipe_trigger.as_ref().unwrap().to_string()).unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
Arg::TcpListener { port: _port } => unimplemented!(),
|
|
||||||
|
|
||||||
Arg::Trailing => {
|
|
||||||
out.extend(self.trailing.iter().map(|s| CString::new(*s).unwrap()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prepare_args_ref(
|
fn prepare_args_ref(
|
||||||
&self,
|
&self,
|
||||||
entrypoint: &str,
|
entrypoint: &str,
|
||||||
args: &[Arg],
|
args: &[Arg],
|
||||||
pipe_trigger: Option<&str>,
|
trigger: &mut TriggerData,
|
||||||
) -> Vec<CString> {
|
) -> Result<Vec<CString>> {
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
out.extend(self.prepare_arg_ref(entrypoint, arg, trigger)?);
|
||||||
|
}
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare_arg(
|
||||||
|
&mut self,
|
||||||
|
entrypoint: &str,
|
||||||
|
arg: &Arg,
|
||||||
|
trigger: &mut TriggerData,
|
||||||
|
) -> Result<Vec<CString>> {
|
||||||
match arg {
|
match arg {
|
||||||
Arg::BinaryName => out.push(CString::new(self.binary).unwrap()),
|
Arg::Pipe(p) => match p {
|
||||||
Arg::Entrypoint => out.push(CString::new(entrypoint).unwrap()),
|
Pipe::Rx(s) => {
|
||||||
|
let pipe = self.pipes.get_mut(s).unwrap().take_read()?;
|
||||||
Arg::Pipe(_) => panic!("can't use pipes with an immutable reference"),
|
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||||
|
}
|
||||||
Arg::PipeTrigger => {
|
Pipe::Tx(s) => {
|
||||||
out.push(CString::new(pipe_trigger.as_ref().unwrap().to_string()).unwrap())
|
let pipe = self.pipes.get_mut(s).unwrap().take_write()?;
|
||||||
|
Ok(vec![CString::new(pipe.into_raw_fd().to_string()).unwrap()])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
a => self.prepare_arg_ref(entrypoint, a, trigger),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn prepare_arg_ref(
|
||||||
|
&self,
|
||||||
|
entrypoint: &str,
|
||||||
|
arg: &Arg,
|
||||||
|
trigger: &mut TriggerData,
|
||||||
|
) -> Result<Vec<CString>> {
|
||||||
|
match arg {
|
||||||
|
Arg::BinaryName => Ok(vec![CString::new(self.binary).unwrap()]),
|
||||||
|
Arg::Entrypoint => Ok(vec![CString::new(entrypoint).unwrap()]),
|
||||||
|
|
||||||
|
Arg::Pipe(p) => Err(Error::BadPipe(p.get_name().to_string())),
|
||||||
|
|
||||||
|
Arg::Trigger => Ok(trigger.args()),
|
||||||
Arg::TcpListener { port: _port } => unimplemented!(),
|
Arg::TcpListener { port: _port } => unimplemented!(),
|
||||||
|
Arg::Trailing => Ok(self
|
||||||
Arg::Trailing => {
|
.trailing
|
||||||
out.extend(self.trailing.iter().map(|s| CString::new(*s).unwrap()))
|
.iter()
|
||||||
|
.map(|s| CString::new(*s).unwrap())
|
||||||
|
.collect()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -46,9 +46,9 @@ pub enum Arg {
|
|||||||
/// A chosen end of a named pipe
|
/// A chosen end of a named pipe
|
||||||
Pipe(Pipe),
|
Pipe(Pipe),
|
||||||
|
|
||||||
/// The value of a pipe trigger
|
/// A value specified by the trigger
|
||||||
/// NOTE: Only valid if the trigger is of type Pipe(...)
|
/// NOTE: Only valid if the trigger is of type Pipe(...)
|
||||||
PipeTrigger,
|
Trigger,
|
||||||
|
|
||||||
/// A TCP Listener
|
/// A TCP Listener
|
||||||
TcpListener { port: u16 },
|
TcpListener { port: u16 },
|
||||||
@ -69,6 +69,15 @@ pub enum Pipe {
|
|||||||
Tx(String),
|
Tx(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Pipe {
|
||||||
|
pub fn get_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Pipe::Rx(n) => n,
|
||||||
|
Pipe::Tx(n) => n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum Permission {
|
pub enum Permission {
|
||||||
Filesystem {
|
Filesystem {
|
||||||
@ -145,7 +154,7 @@ impl Specification {
|
|||||||
|
|
||||||
// validate pipe trigger arguments make sense
|
// validate pipe trigger arguments make sense
|
||||||
for entrypoint in self.entrypoints.values() {
|
for entrypoint in self.entrypoints.values() {
|
||||||
if entrypoint.args.contains(&Arg::PipeTrigger) {
|
if entrypoint.args.contains(&Arg::Trigger) {
|
||||||
match entrypoint.trigger {
|
match entrypoint.trigger {
|
||||||
Trigger::Pipe(_) => {}
|
Trigger::Pipe(_) => {}
|
||||||
_ => return Err(Error::BadTriggerArgument),
|
_ => return Err(Error::BadTriggerArgument),
|
||||||
|
Loading…
Reference in New Issue
Block a user