From f0b638063d27242c3c32df4bdc3a24182938ca46 Mon Sep 17 00:00:00 2001 From: Jonathan Rothberg Date: Tue, 24 Sep 2019 20:42:18 -0700 Subject: [PATCH] Transfered Docker to a plugin instead of a Command. --- Cargo.toml | 4 ++ debian/install | 1 + src/cli.rs | 2 +- src/commands.rs | 4 +- src/commands/docker.rs | 116 --------------------------------------- src/plugins/docker.rs | 120 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 128 insertions(+), 119 deletions(-) delete mode 100644 src/commands/docker.rs create mode 100644 src/plugins/docker.rs diff --git a/Cargo.toml b/Cargo.toml index e81bc0ee69..e28674d7be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -158,6 +158,10 @@ name = "nu_plugin_textview" path = "src/plugins/textview.rs" required-features = ["textview"] +[[bin]] +name = "nu_plugin_docker" +path = "src/plugins/docker.rs" + [[bin]] name = "nu" path = "src/main.rs" diff --git a/debian/install b/debian/install index 75cf2844d9..e9ebfc1232 100644 --- a/debian/install +++ b/debian/install @@ -8,3 +8,4 @@ target/release/nu_plugin_sum usr/bin target/release/nu_plugin_sys usr/bin target/release/nu_plugin_textview usr/bin target/release/nu_plugin_tree usr/bin +target/release/nu_plugin_docker usr/bin diff --git a/src/cli.rs b/src/cli.rs index 3bef636b2c..82413ec9a6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -248,7 +248,7 @@ pub async fn cli() -> Result<(), Box> { whole_stream_command(Next), whole_stream_command(Previous), whole_stream_command(Debug), - whole_stream_command(Docker), + // whole_stream_command(Docker), whole_stream_command(Lines), whole_stream_command(Shells), whole_stream_command(SplitColumn), diff --git a/src/commands.rs b/src/commands.rs index cc23cb7d19..5e4287c0af 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -11,7 +11,7 @@ pub(crate) mod config; pub(crate) mod cp; pub(crate) mod date; pub(crate) mod debug; -pub(crate) mod docker; +// pub(crate) mod docker; pub(crate) mod echo; pub(crate) mod enter; pub(crate) mod env; @@ -80,7 +80,7 @@ pub(crate) use config::Config; pub(crate) use cp::Cpy; pub(crate) use date::Date; pub(crate) use debug::Debug; -pub(crate) use docker::Docker; +// pub(crate) use docker::Docker; pub(crate) use echo::Echo; pub(crate) use enter::Enter; pub(crate) use env::Env; diff --git a/src/commands/docker.rs b/src/commands/docker.rs deleted file mode 100644 index 0149b4e04d..0000000000 --- a/src/commands/docker.rs +++ /dev/null @@ -1,116 +0,0 @@ -use crate::commands::WholeStreamCommand; -use crate::data::meta::Span; -use crate::data::Value; -use crate::errors::ShellError; -use crate::parser::registry::Signature; -use crate::prelude::*; -use indexmap::IndexMap; -use std::process::Command; -use std::str; - -pub struct Docker; - -#[derive(Deserialize)] -pub struct DockerArgs { - sub_command: Tagged, - rest: Vec>, -} - -impl WholeStreamCommand for Docker { - fn name(&self) -> &str { - "docker" - } - - fn signature(&self) -> Signature { - Signature::build(self.name()) - .required("sub_command", SyntaxShape::Member) - .rest(SyntaxShape::Member) - } - - fn usage(&self) -> &str { - "e.g. docker ps, docker images" - } - - fn run( - &self, - args: CommandArgs, - registry: &CommandRegistry, - ) -> Result { - args.process(registry, docker_arg)?.run() - // docker(args, registry) - } -} -pub fn docker_arg( - DockerArgs { - sub_command, - rest: _fields, - }: DockerArgs, - RunnableContext { input: _, name, .. }: RunnableContext, -) -> Result { - match sub_command.item().as_str() { - "ps" => docker_ps(name), - "images" => docker_images(name), - _ => Err(ShellError::labeled_error( - "Unsupported Docker command", - format!("'{}'?", sub_command.item()), - Span::unknown(), - )), - } -} - -fn process_docker_output(cmd_output: &str, tag: Tag) -> Result { - let mut docker_out = VecDeque::new(); - let columns: Vec<&str> = cmd_output.lines().collect(); - - let header: Vec<&str> = columns - .iter() - .take(1) - .next() - .unwrap() - .split_whitespace() - .collect(); - - for line in columns.iter().skip(1) { - let values: Vec<&str> = line - .trim_end() - .split(" ") // Some columns values contains spaces to split by two spaces - .filter(|s| s.trim() != "") - .collect(); - - let mut indexmap = IndexMap::new(); - for (i, v) in values.iter().enumerate() { - indexmap.insert( - header[i].to_string(), - Value::string(v.trim().to_string()).tagged(tag), - ); - } - - docker_out.push_back(Value::Row(indexmap.into()).tagged(tag)) - } - - Ok(docker_out.to_output_stream()) -} - -pub fn docker_images(tag: Tag) -> Result { - let output = Command::new("docker") - .arg("images") - .output() - .expect("failed to execute process."); - - let ps_output = str::from_utf8(&output.stdout).unwrap(); - let out = process_docker_output(ps_output, tag); - - out -} - -pub fn docker_ps(tag: Tag) -> Result { - let output = Command::new("docker") - .arg("ps") - .output() - .expect("failed to execute process."); - - let ps_output = str::from_utf8(&output.stdout).unwrap(); - let out = process_docker_output(ps_output, tag); - - out -} diff --git a/src/plugins/docker.rs b/src/plugins/docker.rs new file mode 100644 index 0000000000..9cb8a52e80 --- /dev/null +++ b/src/plugins/docker.rs @@ -0,0 +1,120 @@ +use futures::executor::block_on; +use nu::{ + serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature, + SyntaxShape, Tag, Tagged, TaggedDictBuilder, Value, +}; + +use std::process::Command; +use std::str; + +struct Docker; + +impl Docker { + fn new() -> Self { + Self + } +} + +async fn docker(sub_command: &String, name: Tag) -> Result>, ShellError> { + match sub_command.as_str() { + "ps" => docker_ps(name), + "images" => docker_images(name), + _ => Err(ShellError::labeled_error( + "Unsupported Docker command", + format!("'{}'?", sub_command), + name.span, + )), + } +} + +fn process_docker_output(cmd_output: &str, tag: Tag) -> Result>, ShellError> { + let columns: Vec<&str> = cmd_output.lines().collect(); + + let header: Vec<&str> = columns + .iter() + .take(1) + .next() + .unwrap() + .split_whitespace() + .collect(); + + let mut output = vec![]; + for line in columns.iter().skip(1) { + let values: Vec<&str> = line + .trim_end() + .split(" ") // Some columns values contains spaces to split by two spaces + .filter(|s| s.trim() != "") + .collect(); + + let mut dict = TaggedDictBuilder::new(tag); + for (i, v) in values.iter().enumerate() { + dict.insert(header[i].to_string(), Value::string(v.trim().to_string())); + } + + output.push(dict.into_tagged_value()); + } + + Ok(output) +} + +pub fn docker_images(tag: Tag) -> Result>, ShellError> { + let output = Command::new("docker") + .arg("images") + .output() + .expect("failed to execute process."); + + let ps_output = str::from_utf8(&output.stdout).unwrap(); + let out = process_docker_output(ps_output, tag); + + out +} + +pub fn docker_ps(tag: Tag) -> Result>, ShellError> { + let output = Command::new("docker") + .arg("ps") + .output() + .expect("failed to execute process."); + + let ps_output = str::from_utf8(&output.stdout).unwrap(); + let out = process_docker_output(ps_output, tag); + + out +} + +impl Plugin for Docker { + fn config(&mut self) -> Result { + Ok(Signature::build("docker") + .required("sub_command", SyntaxShape::Member) + .filter()) + } + + fn begin_filter(&mut self, callinfo: CallInfo) -> Result, ShellError> { + if let Some(args) = callinfo.args.positional { + match &args[0] { + Tagged { + item: Value::Primitive(Primitive::String(s)), + .. + } => match block_on(docker(&s, callinfo.name_tag)) { + Ok(v) => return Ok(v.into_iter().map(ReturnSuccess::value).collect()), + Err(e) => return Err(e), + }, + _ => { + return Err(ShellError::string(format!( + "Unrecognized type in params: {:?}", + args[0] + ))) + } + } + } + + Ok(vec![]) + } + + fn filter(&mut self, _: Tagged) -> Result, ShellError> { + Ok(vec![]) + } +} + +fn main() { + serve_plugin(&mut Docker::new()); +}