diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/builder.rs | 252 | ||||
-rw-r--r-- | src/errors.rs | 7 | ||||
-rw-r--r-- | src/lib.rs | 346 | ||||
-rw-r--r-- | src/tarball.rs | 15 | ||||
-rw-r--r-- | src/transport.rs | 82 | ||||
-rw-r--r-- | src/tty.rs | 6 |
6 files changed, 431 insertions, 277 deletions
diff --git a/src/builder.rs b/src/builder.rs index bb7adba..042f8da 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -41,28 +41,32 @@ impl PullOptionsBuilder { } pub fn image<I>(&mut self, img: I) -> &mut PullOptionsBuilder - where I: Into<String> + where + I: Into<String>, { self.params.insert("fromImage", img.into()); self } pub fn src<S>(&mut self, s: S) -> &mut PullOptionsBuilder - where S: Into<String> + where + S: Into<String>, { self.params.insert("fromSrc", s.into()); self } pub fn repo<R>(&mut self, r: R) -> &mut PullOptionsBuilder - where R: Into<String> + where + R: Into<String>, { self.params.insert("repo", r.into()); self } pub fn tag<T>(&mut self, t: T) -> &mut PullOptionsBuilder - where T: Into<String> + where + T: Into<String>, { self.params.insert("tag", t.into()); self @@ -84,7 +88,8 @@ impl BuildOptions { /// path is expected to be a file path to a directory containing a Dockerfile /// describing how to build a Docker image pub fn builder<S>(path: S) -> BuildOptionsBuilder - where S: Into<String> + where + S: Into<String>, { BuildOptionsBuilder::new(path) } @@ -109,14 +114,19 @@ impl BuildOptionsBuilder { /// path is expected to be a file path to a directory containing a Dockerfile /// describing how to build a Docker image pub fn new<S>(path: S) -> BuildOptionsBuilder - where S: Into<String> + where + S: Into<String>, { - BuildOptionsBuilder { path: path.into(), ..Default::default() } + BuildOptionsBuilder { + path: path.into(), + ..Default::default() + } } /// set the name of the docker file. defaults to "DockerFile" pub fn dockerfile<P>(&mut self, path: P) -> &mut BuildOptionsBuilder - where P: Into<String> + where + P: Into<String>, { self.params.insert("dockerfile", path.into()); self @@ -124,14 +134,16 @@ impl BuildOptionsBuilder { /// tag this image with a name after building it pub fn tag<T>(&mut self, t: T) -> &mut BuildOptionsBuilder - where T: Into<String> + where + T: Into<String>, { self.params.insert("t", t.into()); self } pub fn remote<R>(&mut self, r: R) -> &mut BuildOptionsBuilder - where R: Into<String> + where + R: Into<String>, { self.params.insert("remote", r.into()); self @@ -280,24 +292,26 @@ impl ToJson for ContainerOptions { /// Function to insert a JSON value into a tree where the desired /// location of the value is given as a path of JSON keys. -fn insert<'a, I, V>(key_path: &mut Peekable<I>, - value: &V, - parent_node: &mut Json) - where V: ToJson, - I: Iterator<Item=&'a str> +fn insert<'a, I, V>(key_path: &mut Peekable<I>, value: &V, parent_node: &mut Json) +where + V: ToJson, + I: Iterator<Item = &'a str>, { let local_key = key_path.next().unwrap(); if key_path.peek().is_some() { let node = parent_node - .as_object_mut().unwrap() - .entry(local_key.to_string()).or_insert(Json::Object(BTreeMap::new())); + .as_object_mut() + .unwrap() + .entry(local_key.to_string()) + .or_insert(Json::Object(BTreeMap::new())); insert(key_path, value, node); - } - else { - parent_node.as_object_mut().unwrap() - .insert(local_key.to_string(), value.to_json()); + } else { + parent_node.as_object_mut().unwrap().insert( + local_key.to_string(), + value.to_json(), + ); } } @@ -312,18 +326,15 @@ impl ContainerOptions { Ok(json::encode(&self.to_json())?) } - pub fn parse_from<'a, K, V>(&self, - params: &'a HashMap<K, V>, - body: &mut Json) - where &'a HashMap<K, V>: IntoIterator, - K: ToString + Eq + Hash, - V: ToJson + pub fn parse_from<'a, K, V>(&self, params: &'a HashMap<K, V>, body: &mut Json) + where + &'a HashMap<K, V>: IntoIterator, + K: ToString + Eq + Hash, + V: ToJson, { for (k, v) in params.iter() { let key_string = k.to_string(); - insert(&mut key_string.split(".").peekable(), - v, - body) + insert(&mut key_string.split(".").peekable(), v, body) } } } @@ -358,14 +369,20 @@ impl ContainerOptionsBuilder { pub fn volumes(&mut self, volumes: Vec<&str>) -> &mut ContainerOptionsBuilder { for v in volumes { - self.params_list.entry("HostConfig.Binds").or_insert(Vec::new()).push(v.to_owned()); + self.params_list + .entry("HostConfig.Binds") + .or_insert(Vec::new()) + .push(v.to_owned()); } self } pub fn links(&mut self, links: Vec<&str>) -> &mut ContainerOptionsBuilder { for link in links { - self.params_list.entry("HostConfig.Links").or_insert(Vec::new()).push(link.to_owned()); + self.params_list + .entry("HostConfig.Links") + .or_insert(Vec::new()) + .push(link.to_owned()); } self } @@ -393,65 +410,91 @@ impl ContainerOptionsBuilder { pub fn network_mode(&mut self, network: &str) -> &mut ContainerOptionsBuilder { if !network.is_empty() { - self.params.insert("HostConfig.NetworkMode", Json::String(network.to_owned())); + self.params.insert( + "HostConfig.NetworkMode", + Json::String(network.to_owned()), + ); } self } pub fn env(&mut self, envs: Vec<&str>) -> &mut ContainerOptionsBuilder { for env in envs { - self.params_list.entry("Env").or_insert(Vec::new()).push(env.to_owned()); + self.params_list.entry("Env").or_insert(Vec::new()).push( + env.to_owned(), + ); } self } pub fn cmd(&mut self, cmds: Vec<&str>) -> &mut ContainerOptionsBuilder { for cmd in cmds { - self.params_list.entry("Cmd").or_insert(Vec::new()).push(cmd.to_owned()); + self.params_list.entry("Cmd").or_insert(Vec::new()).push( + cmd.to_owned(), + ); } self } pub fn entrypoint(&mut self, entrypoint: &str) -> &mut ContainerOptionsBuilder { if !entrypoint.is_empty() { - self.params.insert("Entrypoint", Json::String(entrypoint.to_owned())); + self.params.insert( + "Entrypoint", + Json::String(entrypoint.to_owned()), + ); } self } pub fn capabilities(&mut self, capabilities: Vec<&str>) -> &mut ContainerOptionsBuilder { for c in capabilities { - self.params_list.entry("HostConfig.CapAdd").or_insert(Vec::new()).push(c.to_owned()); + self.params_list + .entry("HostConfig.CapAdd") + .or_insert(Vec::new()) + .push(c.to_owned()); } self } - pub fn devices(&mut self, - devices: Vec<HashMap<String, String>>) - -> &mut ContainerOptionsBuilder { + pub fn devices( + &mut self, + devices: Vec<HashMap<String, String>>, + ) -> &mut ContainerOptionsBuilder { for d in devices { - self.params_hash.entry("HostConfig.Devices".to_string()).or_insert(Vec::new()).push(d); + self.params_hash + .entry("HostConfig.Devices".to_string()) + .or_insert(Vec::new()) + .push(d); } self } pub fn log_driver(&mut self, log_driver: &str) -> &mut ContainerOptionsBuilder { if !log_driver.is_empty() { - self.params.insert("HostConfig.LogConfig.Type", Json::String(log_driver.to_owned())); + self.params.insert( + "HostConfig.LogConfig.Type", + Json::String(log_driver.to_owned()), + ); } self } - pub fn restart_policy(&mut self, - name: &str, - maximum_retry_count: u64) - -> &mut ContainerOptionsBuilder { + pub fn restart_policy( + &mut self, + name: &str, + maximum_retry_count: u64, + ) -> &mut ContainerOptionsBuilder { if !name.is_empty() { - self.params.insert("HostConfig.RestartPolicy.Name", Json::String(name.to_owned())); + self.params.insert( + "HostConfig.RestartPolicy.Name", + Json::String(name.to_owned()), + ); } if name == "on-failure" { - self.params.insert("HostConfig.RestartPolicy.MaximumRetryCount", - Json::U64(maximum_retry_count)); + self.params.insert( + "HostConfig.RestartPolicy.MaximumRetryCount", + Json::U64(maximum_retry_count), + ); } self } @@ -501,14 +544,18 @@ pub struct ExecContainerOptionsBuilder { impl ExecContainerOptionsBuilder { pub fn new() -> ExecContainerOptionsBuilder { - ExecContainerOptionsBuilder { params: HashMap::new(), - params_bool: HashMap::new() } + ExecContainerOptionsBuilder { + params: HashMap::new(), + params_bool: HashMap::new(), + } } /// Command to run, as an array of strings pub fn cmd(&mut self, cmds: Vec<&str>) -> &mut ExecContainerOptionsBuilder { for cmd in cmds { - self.params.entry("Cmd").or_insert(Vec::new()).push(cmd.to_owned()); + self.params.entry("Cmd").or_insert(Vec::new()).push( + cmd.to_owned(), + ); } self } @@ -516,26 +563,30 @@ impl ExecContainerOptionsBuilder { /// A list of environment variables in the form "VAR=value" pub fn env(&mut self, envs: Vec<&str>) -> &mut ExecContainerOptionsBuilder { for env in envs { - self.params.entry("Env").or_insert(Vec::new()).push(env.to_owned()); + self.params.entry("Env").or_insert(Vec::new()).push( + env.to_owned(), + ); } self } -/// Attach to stdout of the exec command + /// Attach to stdout of the exec command pub fn attach_stdout(&mut self, stdout: bool) -> &mut ExecContainerOptionsBuilder { self.params_bool.insert("AttachStdout", stdout); self } -/// Attach to stderr of the exec command + /// Attach to stderr of the exec command pub fn attach_stderr(&mut self, stderr: bool) -> &mut ExecContainerOptionsBuilder { self.params_bool.insert("AttachStderr", stderr); self } pub fn build(&self) -> ExecContainerOptions { - ExecContainerOptions { params: self.params.clone(), - params_bool: self.params_bool.clone() } + ExecContainerOptions { + params: self.params.clone(), + params_bool: self.params_bool.clone(), + } } } @@ -835,7 +886,6 @@ pub struct NetworkListOptions { } impl NetworkListOptions { - /// serialize options as a string. returns None if no options are defined pub fn serialize(&self) -> Option<String> { if self.params.is_empty() { @@ -850,7 +900,7 @@ impl NetworkListOptions { pub struct NetworkCreateOptions { pub name: Option<String>, params: HashMap<&'static str, String>, - params_hash: HashMap<String, Vec<HashMap<String, String>>> + params_hash: HashMap<String, Vec<HashMap<String, String>>>, } impl ToJson for NetworkCreateOptions { @@ -875,12 +925,11 @@ impl NetworkCreateOptions { Ok(json::encode(&self.to_json())?) } - pub fn parse_from<'a, K, V>(&self, - params: &'a HashMap<K, V>, - body: &mut BTreeMap<String, Json>) - where &'a HashMap<K, V>: IntoIterator, - K: ToString + Eq + Hash, - V: ToJson + pub fn parse_from<'a, K, V>(&self, params: &'a HashMap<K, V>, body: &mut BTreeMap<String, Json>) + where + &'a HashMap<K, V>: IntoIterator, + K: ToString + Eq + Hash, + V: ToJson, { for (k, v) in params.iter() { let key = k.to_string(); @@ -889,14 +938,13 @@ impl NetworkCreateOptions { body.insert(key, value); } } - } #[derive(Default)] pub struct NetworkCreateOptionsBuilder { name: Option<String>, params: HashMap<&'static str, String>, - params_hash: HashMap<String, Vec<HashMap<String, String>>> + params_hash: HashMap<String, Vec<HashMap<String, String>>>, } impl NetworkCreateOptionsBuilder { @@ -919,9 +967,15 @@ impl NetworkCreateOptionsBuilder { self } - pub fn label(&mut self, labels: Vec<HashMap<String, String>>) -> &mut NetworkCreateOptionsBuilder { + pub fn label( + &mut self, + labels: Vec<HashMap<String, String>>, + ) -> &mut NetworkCreateOptionsBuilder { for l in labels { - self.params_hash.entry("Labels".to_string()).or_insert(Vec::new()).push(l) + self.params_hash + .entry("Labels".to_string()) + .or_insert(Vec::new()) + .push(l) } self } @@ -938,7 +992,7 @@ impl NetworkCreateOptionsBuilder { /// Interface for connect container to network pub struct ContainerConnectionOptions { pub Container: Option<String>, - params: HashMap<&'static str, String> + params: HashMap<&'static str, String>, } impl ToJson for ContainerConnectionOptions { @@ -956,12 +1010,11 @@ impl ContainerConnectionOptions { Ok(json::encode(&self.to_json())?) } - pub fn parse_from<'a, K, V>(&self, - params: &'a HashMap<K, V>, - body: &mut BTreeMap<String, Json>) - where &'a HashMap<K, V>: IntoIterator, - K: ToString + Eq + Hash, - V: ToJson + pub fn parse_from<'a, K, V>(&self, params: &'a HashMap<K, V>, body: &mut BTreeMap<String, Json>) + where + &'a HashMap<K, V>: IntoIterator, + K: ToString + Eq + Hash, + V: ToJson, { for (k, v) in params.iter() { let key = k.to_string(); @@ -984,7 +1037,7 @@ impl ContainerConnectionOptions { self.params.insert("Force", "true".to_owned()); ContainerConnectionOptions { Container: None, - params: self.params.clone() + params: self.params.clone(), } } } @@ -998,62 +1051,67 @@ mod tests { let builder = ContainerOptionsBuilder::new("test_image"); let options = builder.build(); - assert_eq!(r#"{"HostConfig":{},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"HostConfig":{},"Image":"test_image"}"#, + options.serialize().unwrap() + ); } #[test] fn container_options_env() { - let options = - ContainerOptionsBuilder::new("test_image") + let options = ContainerOptionsBuilder::new("test_image") .env(vec!["foo", "bar"]) .build(); - assert_eq!(r#"{"Env":["foo","bar"],"HostConfig":{},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"Env":["foo","bar"],"HostConfig":{},"Image":"test_image"}"#, + options.serialize().unwrap() + ); } #[test] fn container_options_host_config() { - let options = - ContainerOptionsBuilder::new("test_image") + let options = ContainerOptionsBuilder::new("test_image") .network_mode("host") .build(); - assert_eq!(r#"{"HostConfig":{"NetworkMode":"host"},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"HostConfig":{"NetworkMode":"host"},"Image":"test_image"}"#, + options.serialize().unwrap() + ); } /// Test container options that are nested 3 levels deep. #[test] fn container_options_nested() { - let options = - ContainerOptionsBuilder::new("test_image") + let options = ContainerOptionsBuilder::new("test_image") .log_driver("fluentd") .build(); - assert_eq!(r#"{"HostConfig":{"LogConfig":{"Type":"fluentd"}},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"HostConfig":{"LogConfig":{"Type":"fluentd"}},"Image":"test_image"}"#, + options.serialize().unwrap() + ); } /// Test the restart policy settings #[test] fn container_options_restart_policy() { - let mut options = - ContainerOptionsBuilder::new("test_image") + let mut options = ContainerOptionsBuilder::new("test_image") .restart_policy("on-failure", 10) .build(); assert_eq!(r#"{"HostConfig":{"RestartPolicy":{"MaximumRetryCount":10,"Name":"on-failure"}},"Image":"test_image"}"#, options.serialize().unwrap()); - options = - ContainerOptionsBuilder::new("test_image") + options = ContainerOptionsBuilder::new("test_image") .restart_policy("always", 0) .build(); - assert_eq!(r#"{"HostConfig":{"RestartPolicy":{"Name":"always"}},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"HostConfig":{"RestartPolicy":{"Name":"always"}},"Image":"test_image"}"#, + options.serialize().unwrap() + ); } } diff --git a/src/errors.rs b/src/errors.rs index 323b609..bb69ea5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -14,10 +14,7 @@ pub enum Error { Parse(ParserError), Http(HttpError), IO(IoError), - Fault { - code: StatusCode, - message: String, - }, + Fault { code: StatusCode, message: String }, } impl From<ParserError> for Error { @@ -76,7 +73,7 @@ impl ErrorTrait for Error { &Error::Parse(ref err) => Some(err), &Error::Http(ref err) => Some(err), &Error::IO(ref err) => Some(err), - _ => None + _ => None, } } } @@ -36,12 +36,12 @@ mod tarball; pub use errors::Error; pub use builder::{BuildOptions, ContainerOptions, ContainerListOptions, ContainerFilter, - EventsOptions, ImageFilter, ImageListOptions, LogsOptions, - PullOptions, RmContainerOptions, ExecContainerOptions, - NetworkListOptions, NetworkCreateOptions, ContainerConnectionOptions}; + EventsOptions, ImageFilter, ImageListOptions, LogsOptions, PullOptions, + RmContainerOptions, ExecContainerOptions, NetworkListOptions, + NetworkCreateOptions, ContainerConnectionOptions}; use hyper::{Client, Url}; use hyper::header::ContentType; -use hyper::net::{HttpsConnector}; +use hyper::net::HttpsConnector; use hyper::method::Method; use hyper_openssl::OpensslClient; use hyperlocal::UnixSocketConnector; @@ -62,7 +62,7 @@ use std::path::Path; use std::time::Duration; use transport::{tar, Transport}; use hyper::client::Body; -use url::{form_urlencoded}; +use url::form_urlencoded; /// Represents the result of all docker operations pub type Result<T> = std::result::Result<T, Error>; @@ -81,7 +81,8 @@ pub struct Image<'a, 'b> { impl<'a, 'b> Image<'a, 'b> { /// Exports an interface for operations that may be performed against a named image pub fn new<S>(docker: &'a Docker, name: S) -> Image<'a, 'b> - where S: Into<Cow<'b, str>> + where + S: Into<Cow<'b, str>>, { Image { docker: docker, @@ -97,40 +98,48 @@ impl<'a, 'b> Image<'a, 'b> { /// Lists the history of the images set of changes pub fn history(&self) -> Result<Vec<History>> { - let raw = self.docker.get(&format!("/images/{}/history", self.name)[..])?; + let raw = self.docker.get( + &format!("/images/{}/history", self.name)[..], + )?; Ok(json::decode::<Vec<History>>(&raw)?) } /// Delete's an image pub fn delete(&self) -> Result<Vec<Status>> { let raw = self.docker.delete(&format!("/images/{}", self.name)[..])?; - Ok(match Json::from_str(&raw)? { - Json::Array(ref xs) => { - xs.iter().map(|j| { - let obj = j.as_object().expect("expected json object"); - obj.get("Untagged") - .map(|sha| { - Status::Untagged(sha.as_string() - .expect("expected Untagged to be a string") - .to_owned()) - }) - .or(obj.get("Deleted") - .map(|sha| { - Status::Deleted(sha.as_string() - .expect("expected Deleted to be a string") - .to_owned()) - })) - .expect("expected Untagged or Deleted") - }) - } - _ => unreachable!(), - } - .collect()) + Ok( + match Json::from_str(&raw)? { + Json::Array(ref xs) => { + xs.iter().map(|j| { + let obj = j.as_object().expect("expected json object"); + obj.get("Untagged") + .map(|sha| { + Status::Untagged( + sha.as_string() + .expect("expected Untagged to be a string") + .to_owned(), + ) + }) + .or(obj.get("Deleted").map(|sha| { + Status::Deleted( + sha.as_string() + .expect("expected Deleted to be a string") + .to_owned(), + ) + })) + .expect("expected Untagged or Deleted") + }) + } + _ => unreachable!(), + }.collect(), + ) } /// Export this image to a tarball pub fn export(&self) -> Result<Box<Read>> { - self.docker.stream_get(&format!("/images/{}/get", self.name)[..]) + self.docker.stream_get( + &format!("/images/{}/get", self.name)[..], + ) } } @@ -156,20 +165,20 @@ impl<'a> Images<'a> { tarball::dir(&mut bytes, &opts.path[..])?; - let raw = self.docker.stream_post(&path.join("?"), - Some((Body::BufBody(&bytes[..], bytes.len()), - tar())))?; + let raw = self.docker.stream_post( + &path.join("?"), + Some( + (Body::BufBody(&bytes[..], bytes.len()), tar()), + ), + )?; let it = jed::Iter::new(raw).into_iter().map(|j| { // fixme: better error handling debug!("{:?}", j); let obj = j.as_object().expect("expected json object"); if let Some(stream) = obj.get("stream") { - Output::Stream(stream.as_string() - .expect("expected json object") - .into()) - } - else if obj.contains_key("status") { + Output::Stream(stream.as_string().expect("expected json object").into()) + } else if obj.contains_key("status") { let s = json::encode(&j).unwrap(); json::decode::<PullInfo>(&s) .map(|info| { @@ -179,15 +188,18 @@ impl<'a> Images<'a> { progress: info.progress, progress_detail: info.progressDetail, } - }).expect("expected status object") - } - else if let Some(error) = obj.get("error") { - Output::Err(error.as_string() - .expect("expected error to be a string") - .to_owned()) + }) + .expect("expected status object") + } else if let Some(error) = obj.get("error") { + Output::Err( + error + .as_string() + .expect("expected error to be a string") + .to_owned(), + ) } else { - panic!("expected build output stream or error"); - } + panic!("expected build output stream or error"); + } }); Ok(Box::new(it)) } @@ -220,8 +232,10 @@ impl<'a> Images<'a> { if let Some(query) = opts.serialize() { path.push(query); } - let raw = self.docker - .stream_post(&path.join("?"), None as Option<(&'a str, ContentType)>)?; + let raw = self.docker.stream_post( + &path.join("?"), + None as Option<(&'a str, ContentType)>, + )?; let it = jed::Iter::new(raw).into_iter().map(|j| { // fixme: better error handling debug!("{:?}", j); @@ -236,14 +250,18 @@ impl<'a> Images<'a> { } }) .ok() - .or(j.as_object() - .expect("expected json object") - .get("error") - .map(|err| { - Output::Err(err.as_string() - .expect("expected error to be a string") - .to_owned()) - })) + .or( + j.as_object() + .expect("expected json object") + .get("error") + .map(|err| { + Output::Err( + err.as_string() + .expect("expected error to be a string") + .to_owned(), + ) + }), + ) .expect("expected pull status or error") }); Ok(Box::new(it)) @@ -252,11 +270,14 @@ impl<'a> Images<'a> { /// exports a collection of named images, /// either by name, name:tag, or image id, into a tarball pub fn export(&self, names: Vec<&str>) -> Result<Box<Read>> { - let params = names.iter() - .map(|n| ("names", *n)) - .collect::<Vec<(&str, &str)>>(); + let params = names + .iter() + .map(|n| ("names", *n)) + .collect::<Vec<(&str, &str)>>(); let query = form_urlencoded::serialize(params); - self.docker.stream_get(&format!("/images/get?{}", query)[..]) + self.docker.stream_get( + &format!("/images/get?{}", query)[..], + ) } // pub fn import(self, tarball: Box<Read>) -> Result<()> { @@ -273,7 +294,8 @@ pub struct Container<'a, 'b> { impl<'a, 'b> Container<'a, 'b> { /// Exports an interface exposing operations against a container instance pub fn new<S>(docker: &'a Docker, id: S) -> Container<'a, 'b> - where S: Into<Cow<'b, str>> + where + S: Into<Cow<'b, str>>, { Container { docker: docker, @@ -282,11 +304,15 @@ impl<'a, 'b> Container<'a, 'b> { } /// a getter for the container id - pub fn id(&self) -> &str { &self.id } + pub fn id(&self) -> &str { + &self.id + } /// Inspects the current docker container instance's details pub fn inspect(&self) -> Result<ContainerDetails> { - let raw = self.docker.get(&format!("/containers/{}/json", self.id)[..])?; + let raw = self.docker.get( + &format!("/containers/{}/json", self.id)[..], + )?; Ok(json::decode::<ContainerDetails>(&raw)?) } @@ -313,18 +339,24 @@ impl<'a, 'b> Container<'a, 'b> { /// Returns a set of changes made to the container instance pub fn changes(&self) -> Result<Vec<Change>> { - let raw = self.docker.get(&format!("/containers/{}/changes", self.id)[..])?; + let raw = self.docker.get( + &format!("/containers/{}/changes", self.id)[..], + )?; Ok(json::decode::<Vec<Change>>(&raw)?) } /// Exports the current docker container into a tarball pub fn export(&self) -> Result<Box<Read>> { - self.docker.stream_get(&format!("/containers/{}/export", self.id)[..]) + self.docker.stream_get( + &format!("/containers/{}/export", self.id)[..], + ) } /// Returns a stream of stats specific to this container instance pub fn stats(&self) -> Result<Box<Iterator<Item = Stats>>> { - let raw = self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..])?; + let raw = self.docker.stream_get( + &format!("/containers/{}/stats", self.id)[..], + )?; let it = jed::Iter::new(raw).into_iter().map(|j| { // fixme: better error handling debug!("{:?}", j); @@ -337,8 +369,10 @@ impl<'a, 'b> Container<'a, 'b> { /// Start the container instance pub fn start(&'a self) -> Result<()> { self.docker - .post(&format!("/containers/{}/start", self.id)[..], - None as Option<(&'a str, ContentType)>) + .post( + &format!("/containers/{}/start", self.id)[..], + None as Option<(&'a str, ContentType)>, + ) .map(|_| ()) } @@ -349,7 +383,9 @@ impl<'a, 'b> Container<'a, 'b> { let encoded = form_urlencoded::serialize(vec![("t", w.as_secs().to_string())]); path.push(encoded) } - self.docker.post(&path.join("?"), None as Option<(&'a str, ContentType)>).map(|_| ()) + self.docker + .post(&path.join("?"), None as Option<(&'a str, ContentType)>) + .map(|_| ()) } /// Restart the container instance @@ -359,7 +395,9 @@ impl<'a, 'b> Container<'a, 'b> { let encoded = form_urlencoded::serialize(vec![("t", w.as_secs().to_string())]); path.push(encoded) } - self.docker.post(&path.join("?"), None as Option<(&'a str, ContentType)>).map(|_| ()) + self.docker + .post(&path.join("?"), None as Option<(&'a str, ContentType)>) + .map(|_| ()) } /// Kill the container instance @@ -369,38 +407,48 @@ impl<'a, 'b> Container<'a, 'b> { let encoded = form_urlencoded::serialize(vec![("signal", sig.to_owned())]); path.push(encoded) } - self.docker.post(&path.join("?"), None as Option<(&'a str, ContentType)>).map(|_| ()) + self.docker + .post(&path.join("?"), None as Option<(&'a str, ContentType)>) + .map(|_| ()) } /// Rename the container instance pub fn rename(&self, name: &str) -> Result<()> { let query = form_urlencoded::serialize(vec![("name", name)]); self.docker - .post(&format!("/containers/{}/rename?{}", self.id, query)[..], - None as Option<(&'a str, ContentType)>) + .post( + &format!("/containers/{}/rename?{}", self.id, query)[..], + None as Option<(&'a str, ContentType)>, + ) .map(|_| ()) } /// Pause the container instance pub fn pause(&self) -> Result<()> { self.docker - .post(&format!("/containers/{}/pause", self.id)[..], - None as Option<(&'a str, ContentType)>) + .post( + &format!("/containers/{}/pause", self.id)[..], + None as Option<(&'a str, ContentType)>, + ) .map(|_| ()) } /// Unpause the container instance pub fn unpause(&self) -> Result<()> { self.docker - .post(&format!("/containers/{}/unpause", self.id)[..], - None as Option<(&'a str, ContentType)>) + .post( + &format!("/containers/{}/unpause", self.id)[..], + None as Option<(&'a str, ContentType)>, + ) .map(|_| ()) } /// Wait until the container stops pub fn wait(&self) -> Result<Exit> { - let raw = self.docker.post(&format!("/containers/{}/wait", self.id)[..], - None as Option<(&'a str, ContentType)>)?; + let raw = self.docker.post( + &format!("/containers/{}/wait", self.id)[..], + None as Option<(&'a str, ContentType)>, + )?; Ok(json::decode::<Exit>(&raw)?) } @@ -408,7 +456,9 @@ impl<'a, 'b> Container<'a, 'b> { /// /// Use remove instead to use the force/v options. pub fn delete(&self) -> Result<()> { - self.docker.delete(&format!("/containers/{}", self.id)[..]).map(|_| ()) + self.docker + .delete(&format!("/containers/{}", self.id)[..]) + .map(|_| ()) } /// Delete the container instance (todo: force/v) @@ -425,23 +475,28 @@ impl<'a, 'b> Container<'a, 'b> { pub fn exec(&self, opts: &ExecContainerOptions) -> Result<Tty> { let data = opts.serialize()?; let mut bytes = data.as_bytes(); - match self.docker - .post(&format!("/containers/{}/exec", self.id)[..], - Some((&mut bytes, ContentType::json()))) { + match self.doc |