Rename format to mode; remove unsupported --detach option on proc-run

This commit is contained in:
Chip Senkbeil 2021-07-30 21:46:12 -05:00
parent b9cec3399b
commit c7b8db517c
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131
4 changed files with 29 additions and 57 deletions

View File

@ -133,10 +133,6 @@ pub enum RequestPayload {
/// Arguments for the command
args: Vec<String>,
/// Whether or not to detach from the running process without killing it
#[structopt(long)]
detach: bool,
},
/// Kills a process running on the remote machine

View File

@ -8,6 +8,7 @@ use std::{
str::FromStr,
};
use structopt::StructOpt;
use strum::{EnumString, EnumVariantNames, VariantNames};
lazy_static! {
static ref USERNAME: String = whoami::username();
@ -83,34 +84,18 @@ pub enum SessionSubcommand {
Clear,
}
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, IsVariant)]
pub enum ResponseFormat {
/// Output responses in JSON format
#[display(fmt = "json")]
/// Represents the communication medium used for the send command
#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, IsVariant, EnumString, EnumVariantNames)]
#[strum(serialize_all = "snake_case")]
pub enum SendMode {
/// Sends and receives data in JSON format
Json,
/// Output responses in a manner that makes sense from a shell
#[display(fmt = "shell")]
/// Commands are traditional shell commands and output responses are
/// inline with what is expected of a program's output in a shell
Shell,
}
#[derive(Clone, Debug, Display, From, Error, PartialEq, Eq)]
pub enum ResponseFormatParseError {
InvalidVariant(#[error(not(source))] String),
}
impl FromStr for ResponseFormat {
type Err = ResponseFormatParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim() {
"json" => Ok(Self::Json),
"shell" => Ok(Self::Shell),
x => Err(ResponseFormatParseError::InvalidVariant(x.to_string())),
}
}
}
/// Represents subcommand to execute some operation remotely
#[derive(Debug, StructOpt)]
#[structopt(verbatim_doc_comment)]
@ -123,11 +108,11 @@ pub struct SendSubcommand {
#[structopt(
short,
long,
value_name = "json|shell",
default_value = "shell",
possible_values = &["json", "shell"]
case_insensitive = true,
default_value = "Shell",
possible_values = SendMode::VARIANTS
)]
pub format: ResponseFormat,
pub mode: SendMode,
#[structopt(subcommand)]
pub operation: RequestPayload,

View File

@ -37,8 +37,8 @@ pub(super) async fn process(
RequestPayload::Remove { path, force } => remove(path, force).await,
RequestPayload::Copy { src, dst } => copy(src, dst).await,
RequestPayload::Rename { src, dst } => rename(src, dst).await,
RequestPayload::ProcRun { cmd, args, detach } => {
proc_run(client_id, state, tx, cmd, args, detach).await
RequestPayload::ProcRun { cmd, args } => {
proc_run(client_id, state, tx, cmd, args).await
}
RequestPayload::ProcKill { id } => proc_kill(state, id).await,
RequestPayload::ProcStdin { id, data } => proc_stdin(state, id, data).await,
@ -192,7 +192,6 @@ async fn proc_run(
tx: Reply,
cmd: String,
args: Vec<String>,
detach: bool,
) -> Result<ResponsePayload, Box<dyn Error>> {
let id = rand::random();
@ -327,16 +326,13 @@ async fn proc_run(
};
state.lock().await.processes.insert(id, process);
// If we are not detaching from process, we want to associate it with our client
if !detach {
state
.lock()
.await
.client_processes
.entry(client_id)
.or_insert(Vec::new())
.push(id);
}
state
.lock()
.await
.client_processes
.entry(client_id)
.or_insert(Vec::new())
.push(id);
Ok(ResponsePayload::ProcStart { id })
}

View File

@ -1,7 +1,7 @@
use crate::{
data::{Request, RequestPayload, Response, ResponsePayload},
net::{Client, TransportError},
opt::{CommonOpt, ResponseFormat, SendSubcommand},
opt::{CommonOpt, SendMode, SendSubcommand},
utils::{Session, SessionError},
};
use derive_more::{Display, Error, From};
@ -30,11 +30,6 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
// Special conditions for continuing to process responses
let is_proc_req = req.payload.is_proc_run();
let not_detach = if let RequestPayload::ProcRun { detach, .. } = req.payload {
!detach
} else {
false
};
let res = client.send(req).await?;
@ -44,11 +39,11 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
_ => 0,
};
format_response(cmd.format, res)?.print();
format_response(cmd.mode, res)?.print();
// If we are executing a process and not detaching, we want to continue receiving
// responses sent to us
if is_proc_req && not_detach {
if is_proc_req {
let mut stream = client.to_response_stream();
// We also want to spawn a task to handle sending stdin to the remote process
@ -80,7 +75,7 @@ async fn run_async(cmd: SendSubcommand, _opt: CommonOpt) -> Result<(), Error> {
})?;
let done = res.payload.is_proc_done();
format_response(cmd.format, res)?.print();
format_response(cmd.mode, res)?.print();
if done {
break;
@ -134,13 +129,13 @@ impl ResponseOut {
}
}
fn format_response(fmt: ResponseFormat, res: Response) -> io::Result<ResponseOut> {
Ok(match fmt {
ResponseFormat::Json => ResponseOut::Stdout(
fn format_response(mode: SendMode, res: Response) -> io::Result<ResponseOut> {
Ok(match mode {
SendMode::Json => ResponseOut::Stdout(
serde_json::to_string(&res)
.map_err(|x| io::Error::new(io::ErrorKind::InvalidData, x))?,
),
ResponseFormat::Shell => format_shell(res),
SendMode::Shell => format_shell(res),
})
}