summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Schreiber <schrieveslaach@online.de>2019-02-23 20:48:17 +0100
committerdoug tangren <d.tangren@gmail.com>2019-02-23 14:48:17 -0500
commit0ae953c69ce7a336794244adc29bbc206320705d (patch)
treed32b35c42675b7ee9403a0d42659d6e4c1345943
parentebb293813fb1c92149a5cc802043ba41f4ddf1a5 (diff)
Copy a byte slice as file into a container (#151)
- add function copy_file_into to container - add example
-rw-r--r--examples/containercopyinto.rs28
-rw-r--r--src/lib.rs43
2 files changed, 70 insertions, 1 deletions
diff --git a/examples/containercopyinto.rs b/examples/containercopyinto.rs
new file mode 100644
index 0000000..df56ca2
--- /dev/null
+++ b/examples/containercopyinto.rs
@@ -0,0 +1,28 @@
+use shiplift::Docker;
+use std::{env, path};
+use tokio::prelude::Future;
+
+fn main() {
+ let docker = Docker::new();
+ let path = env::args()
+ .nth(1)
+ .expect("Usage: cargo run --example containercopyinto -- <local path> <container>");
+ let id = env::args()
+ .nth(2)
+ .expect("Usage: cargo run --example containercopyinto -- <local path> <container>");
+
+
+ use std::fs::File;
+ use std::io::prelude::*;
+
+ let mut file = File::open(&path).unwrap();
+ let mut bytes = Vec::new();
+ file.read_to_end(&mut bytes).expect("Cannot read file on the localhost.");
+
+ let fut = docker
+ .containers()
+ .get(&id)
+ .copy_file_into(path::Path::new(&path), &bytes[..])
+ .map_err(|e| eprintln!("Error: {}", e));
+ tokio::run(fut);
+}
diff --git a/src/lib.rs b/src/lib.rs
index b0f1479..7d7283f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -497,7 +497,37 @@ impl<'a, 'b> Container<'a, 'b> {
.map(|c| c.to_vec())
}
- // TODO: copy_into
+ /// Copy a byte slice as file into (see `bytes`) the container.
+ ///
+ /// The file will be copied at the given location (see `path`) and will be owned by root
+ /// with access mask 644. The specified `path` parent location must exists, otherwise the
+ /// creation of the file fails.
+ pub fn copy_file_into(
+ &self,
+ path: &Path,
+ bytes: &[u8]
+ ) -> impl Future<Item = (), Error = Error> {
+
+ let mut ar = tar::Builder::new(Vec::new());
+ let mut header = tar::Header::new_gnu();
+ header.set_size(bytes.len() as u64);
+ header.set_mode(0o0644);
+ ar.append_data(&mut header,
+ path.file_name().map(|f| f.to_str().unwrap()).unwrap(),
+ bytes
+ ).unwrap();
+ let data = ar.into_inner().unwrap();
+
+ let body = Some((data, "application/x-tar".parse::<Mime>().unwrap()));
+
+ let path_arg = form_urlencoded::Serializer::new(String::new())
+ .append_pair("path", &path.parent().map(|p| p.to_string_lossy()).unwrap())
+ .finish();
+
+ self.docker
+ .put(&format!("/containers/{}/archive?{}", self.id, path_arg), body)
+ .map(|_| ())
+ }
}
/// Interface for docker containers
@@ -961,6 +991,17 @@ impl Docker {
self.transport.request(Method::POST, endpoint, body)
}
+ fn put<B>(
+ &self,
+ endpoint: &str,
+ body: Option<(B, Mime)>,
+ ) -> impl Future<Item = String, Error = Error>
+ where
+ B: Into<Body>,
+ {
+ self.transport.request(Method::PUT, endpoint, body)
+ }
+
fn post_json<B, T>(
&self,
endpoint: &str,