diff options
author | Andy Caldwell <andy.m.caldwell@googlemail.com> | 2019-02-13 05:12:42 +0000 |
---|---|---|
committer | doug tangren <d.tangren@gmail.com> | 2019-02-13 00:12:42 -0500 |
commit | 2a40dc00e6aeb611db8095dc8646e5132fea356b (patch) | |
tree | 30929a1ee4f0386d0879054939eabd12b0a9dcda | |
parent | 31a913b4a1a6a51179ddd3c3b7b6727984e829e5 (diff) |
Copy from container (#150)
* Add 'copy_from' function to 'Container'
* Run clippy
* Update deps
-rw-r--r-- | Cargo.toml | 40 | ||||
-rw-r--r-- | examples/containercopyfrom.rs | 26 | ||||
-rw-r--r-- | src/builder.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 30 | ||||
-rw-r--r-- | src/rep.rs | 4 | ||||
-rw-r--r-- | src/transport.rs | 2 | ||||
-rw-r--r-- | src/tty.rs | 8 |
7 files changed, 87 insertions, 27 deletions
@@ -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 -- <container> <path in container>"); + let path = env::args() + .nth(2) + .expect("Usage: cargo run --example containercopyfrom -- <container> <path in container>"); + 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)); @@ -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<Item = Vec<u8>, 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() + } +} @@ -106,6 +106,8 @@ pub struct State { pub started_at: String, } +type PortDescription = HashMap<String, Option<Vec<HashMap<String, String>>>>; + #[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<HashMap<String, Option<Vec<HashMap<String, String>>>>>, + pub ports: Option<PortDescription>, pub networks: HashMap<String, NetworkEntry>, } 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<Body> + '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 @@ -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 { |