Transfered Docker to a plugin instead of a Command.

This commit is contained in:
Jonathan Rothberg 2019-09-24 20:42:18 -07:00
parent a1f26d947d
commit f0b638063d
6 changed files with 128 additions and 119 deletions

View File

@ -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"

1
debian/install vendored
View File

@ -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

View File

@ -248,7 +248,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
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),

View File

@ -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;

View File

@ -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<String>,
rest: Vec<Tagged<String>>,
}
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<OutputStream, ShellError> {
args.process(registry, docker_arg)?.run()
// docker(args, registry)
}
}
pub fn docker_arg(
DockerArgs {
sub_command,
rest: _fields,
}: DockerArgs,
RunnableContext { input: _, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
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<OutputStream, ShellError> {
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<OutputStream, 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<OutputStream, 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
}

120
src/plugins/docker.rs Normal file
View File

@ -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<Vec<Tagged<Value>>, 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<Vec<Tagged<Value>>, 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<Vec<Tagged<Value>>, 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<Vec<Tagged<Value>>, 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<Signature, ShellError> {
Ok(Signature::build("docker")
.required("sub_command", SyntaxShape::Member)
.filter())
}
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, 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<Value>) -> Result<Vec<ReturnValue>, ShellError> {
Ok(vec![])
}
}
fn main() {
serve_plugin(&mut Docker::new());
}