allow input in `trvmctl run`
This commit is contained in:
parent
cfe35b3edb
commit
bc41781df0
|
@ -56,6 +56,10 @@ pub enum Commands {
|
|||
},
|
||||
|
||||
/// Run a command in a currently running VM.
|
||||
///
|
||||
/// If standard input is not a terminal, all standard input is collected before invoking the
|
||||
/// program. All standard output is collected before returning from the function. Interactive
|
||||
/// programs are not possible at this time..
|
||||
Run {
|
||||
/// The command to run.
|
||||
command: String,
|
||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -2,13 +2,14 @@
|
|||
|
||||
use clap::Parser;
|
||||
use eyre::WrapErr;
|
||||
use std::io::Write;
|
||||
use std::io::{IsTerminal, Read, Write};
|
||||
|
||||
mod cli;
|
||||
mod vm;
|
||||
|
||||
use vm::{SpawnArguments, VirtualMachine};
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn main() -> eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
||||
|
@ -54,7 +55,7 @@ fn main() -> eyre::Result<()> {
|
|||
.ok_or(eyre::eyre!("no hostname"))?
|
||||
.as_str()
|
||||
.ok_or(eyre::eyre!("hostname is not str"))?;
|
||||
let uptime = vm.run_command("uptime", [])?;
|
||||
let uptime = vm.run_command("uptime", [], None)?;
|
||||
eprintln!("hostname: {hostname}");
|
||||
eprint!("{}", String::from_utf8_lossy(&uptime.0));
|
||||
}
|
||||
|
@ -91,7 +92,24 @@ fn main() -> eyre::Result<()> {
|
|||
cli::Commands::Run { command, args } => {
|
||||
let spawn_arguments = SpawnArguments::default();
|
||||
let mut vm = VirtualMachine::load(spawn_arguments, None)?;
|
||||
let (response, exit_code) = vm.run_command(&command, args)?;
|
||||
|
||||
let mut stdin = std::io::stdin();
|
||||
let buffered_stdin = if stdin.is_terminal() {
|
||||
None
|
||||
} else {
|
||||
let mut bytes = vec![];
|
||||
stdin
|
||||
.read_to_end(&mut bytes)
|
||||
.context(eyre::eyre!("could not read input"))?;
|
||||
if bytes.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(bytes)
|
||||
}
|
||||
};
|
||||
|
||||
let (response, exit_code) =
|
||||
vm.run_command(&command, args, buffered_stdin.as_deref())?;
|
||||
std::io::stdout().write_all(&response)?;
|
||||
std::process::exit(
|
||||
i32::try_from(exit_code).context(eyre::eyre!("bad PID: pid < i32::MAX << 1"))?,
|
||||
|
|
|
@ -574,13 +574,16 @@ impl VirtualMachine {
|
|||
&mut self,
|
||||
command: &str,
|
||||
args: impl IntoIterator<Item = String>,
|
||||
stdin: Option<&[u8]>,
|
||||
) -> Result<(Vec<u8>, u64)> {
|
||||
let args = args.into_iter().collect::<Vec<_>>();
|
||||
let input = stdin.map(|bytes| BASE64_STANDARD.encode(bytes));
|
||||
|
||||
let payload = serde_json::json!({
|
||||
"path": command,
|
||||
"arg": args,
|
||||
"capture-output": true,
|
||||
"input-data": input,
|
||||
});
|
||||
|
||||
let bar = spinner(format!("Running: {command:?} {args:?}"));
|
||||
|
|
Loading…
Reference in New Issue