moved argument processing to main.rs
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing

This commit is contained in:
Jake Hillion 2022-05-04 10:48:44 +01:00
parent 763fab12d8
commit 05fe72e733
4 changed files with 78 additions and 52 deletions

View File

@ -13,47 +13,23 @@ use specification::Specification;
use std::collections::HashMap;
use std::fs::File;
use std::os::unix::io::FromRawFd;
use std::path::Path;
use clap::{App, AppSettings};
use nix::fcntl::OFlag;
use nix::sys::socket;
use nix::unistd;
pub fn run() -> Result<()> {
// process arguments
let matches = App::new("clone-shim")
.version(env!("GIT_HASH"))
.author("Jake Hillion <jake@hillion.co.uk>")
.about("Launch a multi entrypoint app, cloning as requested by an external specification or the ELF.")
.arg(clap::Arg::new("spec").long("specification").short('s').help("Provide the specification as an external JSON file.").takes_value(true))
.setting(AppSettings::TrailingVarArg)
.arg(clap::Arg::new("verbose").long("verbose").short('v').help("Use verbose logging.").takes_value(false))
.arg(clap::Arg::new("debug").long("debug").short('d').help("Stop each spawned application process so that it can be attached to.").takes_value(false))
.arg(clap::Arg::new("binary").index(1).help("Binary and arguments to launch with the shim").required(true).multiple_values(true))
.get_matches();
pub struct RunArgs<'a> {
pub spec: Option<&'a Path>,
pub debug: bool,
let (binary, trailing) = {
let mut argv = matches.values_of("binary").unwrap();
let binary = argv.next().unwrap();
let trailing: Vec<&str> = argv.collect();
(binary, trailing)
};
// setup logging
let env = env_logger::Env::new().filter_or(
"LOG",
if matches.is_present("verbose") {
"debug"
} else {
"warn"
},
);
env_logger::init_from_env(env);
pub binary: &'a Path,
pub binary_args: Vec<&'a str>,
}
pub fn run(args: &RunArgs) -> Result<()> {
// parse the specification
let spec: Specification = if let Some(m) = matches.value_of("spec") {
let spec: Specification = if let Some(m) = args.spec {
if m.ends_with(".json") {
let f = std::fs::File::open(m)?;
Ok(serde_json::from_reader(f)?)
@ -75,13 +51,11 @@ pub fn run() -> Result<()> {
let sockets = create_sockets(sockets)?;
// spawn all processes
let debug = matches.is_present("debug");
Spawner {
spec: &spec,
binary,
trailing: &trailing,
debug,
binary: args.binary,
binary_args: &args.binary_args,
debug: args.debug,
pipes,
sockets,

View File

@ -1,16 +1,63 @@
use log::{error, info};
use clone_shim::run;
use clone_shim::{run, RunArgs};
use std::path::Path;
use clap::{App, AppSettings};
fn main() {
std::process::exit(match run() {
Ok(_) => {
info!("launched successfully");
exitcode::OK
}
Err(e) => {
error!("error: {}", e);
-1
// process arguments
let matches = App::new("clone-shim")
.version(env!("GIT_HASH"))
.author("Jake Hillion <jake@hillion.co.uk>")
.about("Launch a multi entrypoint app, cloning as requested by an external specification or the ELF.")
.arg(clap::Arg::new("spec").long("specification").short('s').help("Provide the specification as an external JSON file.").takes_value(true))
.setting(AppSettings::TrailingVarArg)
.arg(clap::Arg::new("verbose").long("verbose").short('v').help("Use verbose logging.").takes_value(false))
.arg(clap::Arg::new("debug").long("debug").short('d').help("Stop each spawned application process so that it can be attached to.").takes_value(false))
.arg(clap::Arg::new("binary").index(1).help("Binary and arguments to launch with the shim").required(true).multiple_values(true))
.get_matches();
// setup logging
let env = env_logger::Env::new().filter_or(
"LOG",
if matches.is_present("verbose") {
"debug"
} else {
"warn"
},
);
env_logger::init_from_env(env);
// launch process
// execute shimmed process
std::process::exit({
let (binary, binary_args) = {
let mut argv = matches.values_of("binary").unwrap();
let binary = Path::new(argv.next().expect("one value is required"));
let binary_args: Vec<&str> = argv.collect();
(binary, binary_args)
};
let args = RunArgs {
spec: matches.value_of("spec").map(Path::new),
debug: matches.is_present("debug"),
binary,
binary_args,
};
match run(&args) {
Ok(_) => {
info!("launched successfully");
exitcode::OK
}
Err(e) => {
error!("error: {}", e);
-1
}
}
})
}

View File

@ -6,6 +6,7 @@ use crate::{Error, Result};
use std::ffi::CString;
use std::fs::File;
use std::net::TcpListener;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::IntoRawFd;
pub struct PreparedArgs(Vec<PreparedArg>);
@ -162,7 +163,11 @@ impl PreparedArg {
trigger: &mut TriggerData,
) -> Result<Vec<CString>> {
match self {
PreparedArg::BinaryName => Ok(vec![CString::new(spawner.binary).unwrap()]),
PreparedArg::BinaryName => {
Ok(vec![
CString::new(spawner.binary.as_os_str().as_bytes()).unwrap()
])
}
PreparedArg::Entrypoint => Ok(vec![CString::new(entrypoint).unwrap()]),
PreparedArg::Pipe(p) => Ok(vec![CString::new(p.into_raw_fd().to_string()).unwrap()]),
@ -179,7 +184,7 @@ impl PreparedArg {
}
PreparedArg::Trailing => Ok(spawner
.trailing
.binary_args
.iter()
.map(|s| CString::new(*s).unwrap())
.collect()),

View File

@ -14,7 +14,7 @@ use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use nix::sys::signal::{kill, Signal};
use nix::sys::socket::{recvmsg, ControlMessageOwned, MsgFlags};
@ -24,8 +24,8 @@ const BUFFER_SIZE: usize = 1024;
pub struct Spawner<'a> {
pub spec: &'a Specification,
pub binary: &'a str,
pub trailing: &'a Vec<&'a str>,
pub binary: &'a Path,
pub binary_args: &'a Vec<&'a str>,
pub debug: bool,
pub pipes: HashMap<String, PipePair>,