From 2a40dc00e6aeb611db8095dc8646e5132fea356b Mon Sep 17 00:00:00 2001 From: Andy Caldwell Date: Wed, 13 Feb 2019 05:12:42 +0000 Subject: Copy from container (#150) * Add 'copy_from' function to 'Container' * Run clippy * Update deps --- Cargo.toml | 40 ++++++++++++++++++++-------------------- examples/containercopyfrom.rs | 26 ++++++++++++++++++++++++++ src/builder.rs | 4 ++-- src/lib.rs | 30 ++++++++++++++++++++++++++++-- src/rep.rs | 4 +++- src/transport.rs | 2 +- src/tty.rs | 8 +++++++- 7 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 examples/containercopyfrom.rs diff --git a/Cargo.toml b/Cargo.toml index 55a0a03..0def440 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,28 +18,28 @@ coveralls = { repository = "softprops/shipflit" } maintenance = { status = "actively-developed" } [dependencies] -byteorder = "1" -bytes = "0.4" -flate2 = "1" -futures = "0.1" -http = "0.1" -hyper = "0.12" -hyper-openssl = { version = "0.6", optional = true } -hyperlocal = { version = "0.6", optional = true } -log = "0.4" -mime = "0.3" -openssl = { version = "0.10", optional = true } -tar = "0.4" -tokio = "0.1" -tokio-codec = "0.1" -tokio-io = "0.1" -url = "1.7" -serde = "1" -serde_derive = "1" -serde_json = "1" +byteorder = "1.3.1" +bytes = "0.4.11" +flate2 = "1.0.6" +futures = "0.1.25" +http = "0.1.15" +hyper = "0.12.24" +hyper-openssl = { version = "0.7.0", optional = true } +hyperlocal = { version = "0.6.0", optional = true } +log = "0.4.6" +mime = "0.3.13" +openssl = { version = "0.10.16", optional = true } +tar = "0.4.20" +tokio = "0.1.15" +tokio-codec = "0.1.1" +tokio-io = "0.1.11" +url = "1.7.2" +serde = "1.0.87" +serde_derive = "1.0.87" +serde_json = "1.0.38" [dev-dependencies] -env_logger = "0.5" +env_logger = "0.6.0" [features] default = ["unix-socket", "tls"] diff --git a/examples/containercopyfrom.rs b/examples/containercopyfrom.rs new file mode 100644 index 0000000..2ebeccf --- /dev/null +++ b/examples/containercopyfrom.rs @@ -0,0 +1,26 @@ +use shiplift::Docker; +use std::{env, path}; +use tokio::prelude::{Future, Stream}; + +fn main() { + let docker = Docker::new(); + let id = env::args() + .nth(1) + .expect("Usage: cargo run --example containercopyfrom -- "); + let path = env::args() + .nth(2) + .expect("Usage: cargo run --example containercopyfrom -- "); + let fut = docker + .containers() + .get(&id) + .copy_from(path::Path::new(&path)) + .collect() + .and_then(|stream| { + let tar = stream.concat(); + let mut archive = tar::Archive::new(tar.as_slice()); + archive.unpack(env::current_dir()?)?; + Ok(()) + }) + .map_err(|e| eprintln!("Error: {}", e)); + tokio::run(fut); +} diff --git a/src/builder.rs b/src/builder.rs index 7d9ba7b..d815af2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -467,9 +467,9 @@ impl ContainerOptionsBuilder { for (key, val) in self .params .get("HostConfig.PortBindings") - .unwrap_or(&mut json!(null)) + .unwrap_or(&json!(null)) .as_object() - .unwrap_or(&mut Map::new()) + .unwrap_or(&Map::new()) .iter() { binding.insert(key.to_string(), json!(val)); diff --git a/src/lib.rs b/src/lib.rs index 020699b..b0f1479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -477,7 +477,27 @@ impl<'a, 'b> Container<'a, 'b> { .flatten_stream() } - // todo attach, attach/ws, copy, archive + /// Copy a file/folder from the container. The resulting stream is a tarball of the extracted + /// files. + /// + /// If `path` is not an absolute path, it is relative to the container’s root directory. The + /// resource specified by `path` must exist. To assert that the resource is expected to be a + /// directory, `path` should end in `/` or `/`. (assuming a path separator of `/`). If `path` + /// ends in `/.` then this indicates that only the contents of the path directory should be + /// copied. A symlink is always resolved to its target. + pub fn copy_from( + &self, + path: &Path, + ) -> impl Stream, Error = Error> { + let path_arg = form_urlencoded::Serializer::new(String::new()) + .append_pair("path", &path.to_string_lossy()) + .finish(); + self.docker + .stream_get(&format!("/containers/{}/archive?{}", self.id, path_arg)) + .map(|c| c.to_vec()) + } + + // TODO: copy_into } /// Interface for docker containers @@ -838,7 +858,7 @@ impl Docker { "{}://{}:{}", host.scheme_part().map(|s| s.as_str()).unwrap(), host.host().unwrap().to_owned(), - host.port().unwrap_or(80) + host.port_u16().unwrap_or(80) ); match host.scheme_part().map(|s| s.as_str()) { @@ -1011,3 +1031,9 @@ impl Docker { .stream_upgrade_multiplexed(Method::POST, endpoint, body) } } + +impl Default for Docker { + fn default() -> Self { + Self::new() + } +} diff --git a/src/rep.rs b/src/rep.rs index 097ae9e..4f27688 100644 --- a/src/rep.rs +++ b/src/rep.rs @@ -106,6 +106,8 @@ pub struct State { pub started_at: String, } +type PortDescription = HashMap>>>; + #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct NetworkSettings { @@ -116,7 +118,7 @@ pub struct NetworkSettings { #[serde(rename = "IPPrefixLen")] pub ip_prefix_len: u64, pub mac_address: String, - pub ports: Option>>>>, + pub ports: Option, pub networks: HashMap, } diff --git a/src/transport.rs b/src/transport.rs index 0d64b5a..c465b7c 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -240,7 +240,7 @@ impl Transport { B: Into + 'static, { self.stream_upgrade(method, endpoint, body) - .map(|u| crate::tty::Multiplexed::new(u)) + .map(crate::tty::Multiplexed::new) } /// Extract the error message content from an HTTP response that diff --git a/src/tty.rs b/src/tty.rs index 038fde0..603c821 100644 --- a/src/tty.rs +++ b/src/tty.rs @@ -70,6 +70,12 @@ impl TtyDecoder { } } +impl Default for TtyDecoder { + fn default() -> Self { + Self::new() + } +} + impl Decoder for TtyDecoder { type Item = Chunk; type Error = Error; @@ -226,7 +232,7 @@ where }); util::stop_on_err(stream, |e| e.kind() != io::ErrorKind::UnexpectedEof) - .map_err(|e| crate::Error::from(e)) + .map_err(crate::Error::from) } mod util { -- cgit v1.2.3