summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Caldwell <andy.m.caldwell@googlemail.com>2019-02-13 05:12:42 +0000
committerdoug tangren <d.tangren@gmail.com>2019-02-13 00:12:42 -0500
commit2a40dc00e6aeb611db8095dc8646e5132fea356b (patch)
tree30929a1ee4f0386d0879054939eabd12b0a9dcda
parent31a913b4a1a6a51179ddd3c3b7b6727984e829e5 (diff)
Copy from container (#150)
* Add 'copy_from' function to 'Container' * Run clippy * Update deps
-rw-r--r--Cargo.toml40
-rw-r--r--examples/containercopyfrom.rs26
-rw-r--r--src/builder.rs4
-rw-r--r--src/lib.rs30
-rw-r--r--src/rep.rs4
-rw-r--r--src/transport.rs2
-rw-r--r--src/tty.rs8
7 files changed, 87 insertions, 27 deletions
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 -- <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));
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<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()
+ }
+}
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<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
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 {