diff options
author | Marc Schreiber <schrieveslaach@online.de> | 2019-02-23 20:48:17 +0100 |
---|---|---|
committer | doug tangren <d.tangren@gmail.com> | 2019-02-23 14:48:17 -0500 |
commit | 0ae953c69ce7a336794244adc29bbc206320705d (patch) | |
tree | d32b35c42675b7ee9403a0d42659d6e4c1345943 | |
parent | ebb293813fb1c92149a5cc802043ba41f4ddf1a5 (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.rs | 28 | ||||
-rw-r--r-- | src/lib.rs | 43 |
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); +} @@ -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, |