diff options
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | examples/images.rs | 2 | ||||
-rw-r--r-- | src/builder.rs | 148 | ||||
-rw-r--r-- | src/errors.rs | 32 | ||||
-rw-r--r-- | src/lib.rs | 129 | ||||
-rw-r--r-- | src/rep.rs | 488 | ||||
-rw-r--r-- | src/transport.rs | 6 |
7 files changed, 389 insertions, 419 deletions
@@ -17,16 +17,15 @@ http = "0.1" hyper = "0.12" hyper-openssl = "0.6" hyperlocal = { version = "0.6", optional = true } -jed = "0.1" log = "0.4" mime = "0.3" openssl = "0.10" -rustc-serialize = "0.3" tar = "0.4" tokio = "0.1" url = "1.7" serde = "1" serde_derive = "1" +serde_json = "1" [dev-dependencies] env_logger = "0.5" diff --git a/examples/images.rs b/examples/images.rs index 531cd02..195ea06 100644 --- a/examples/images.rs +++ b/examples/images.rs @@ -5,6 +5,6 @@ fn main() { let images = docker.images().list(&Default::default()).unwrap(); println!("docker images in stock"); for i in images { - println!("{:?}", i.RepoTags); + println!("{:?}", i.repo_tags); } } diff --git a/src/builder.rs b/src/builder.rs index ffc0cf1..0171a3e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,13 +1,15 @@ //! Interfaces for building various structures use self::super::Result; -use rustc_serialize::json::{self, Json, ToJson}; +use serde::Serialize; +use serde_json::{self, Value, Number, map::Map}; use std::cmp::Eq; use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; use std::iter::IntoIterator; use std::iter::Peekable; use url::form_urlencoded; +use errors::Error; #[derive(Default)] pub struct PullOptions { @@ -254,7 +256,7 @@ impl ContainerListOptionsBuilder { } // structure is a a json encoded object mapping string keys to a list // of string values - self.params.insert("filters", json::encode(¶m).unwrap()); + self.params.insert("filters", serde_json::to_string(¶m).unwrap()); self } @@ -284,42 +286,22 @@ impl ContainerListOptionsBuilder { } /// Interface for building a new docker container from an existing image +#[derive(Serialize)] pub struct ContainerOptions { pub name: Option<String>, - params: HashMap<&'static str, Json>, + params: HashMap<&'static str, Value>, params_list: HashMap<&'static str, Vec<String>>, params_hash: HashMap<String, Vec<HashMap<String, String>>>, } -impl ToJson for ContainerOptions { - fn to_json(&self) -> Json { - let mut body_members = BTreeMap::new(); - - // The HostConfig element gets initialized to an empty object, - // for backward compatibility. - body_members.insert( - "HostConfig".to_string(), - Json::Object(BTreeMap::new()), - ); - - let mut body = Json::Object(body_members); - - self.parse_from(&self.params, &mut body); - self.parse_from(&self.params_list, &mut body); - self.parse_from(&self.params_hash, &mut body); - - body - } -} - /// 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, + parent_node: &mut Value, ) where - V: ToJson, + V: Serialize, I: Iterator<Item = &'a str>, { let local_key = key_path.next().unwrap(); @@ -329,13 +311,13 @@ fn insert<'a, I, V>( .as_object_mut() .unwrap() .entry(local_key.to_string()) - .or_insert(Json::Object(BTreeMap::new())); + .or_insert(Value::Object(Map::new())); insert(key_path, value, node); } else { parent_node.as_object_mut().unwrap().insert( local_key.to_string(), - value.to_json(), + serde_json::to_value(value).unwrap(), ); } } @@ -348,17 +330,32 @@ impl ContainerOptions { /// serialize options as a string. returns None if no options are defined pub fn serialize(&self) -> Result<String> { - Ok(json::encode(&self.to_json())?) + Ok(serde_json::to_string(&self.to_json())?) + } + + fn to_json(&self) -> Value { + let mut body_members = Map::new(); + // The HostConfig element gets initialized to an empty object, + // for backward compatibility. + body_members.insert( + "HostConfig".to_string(), + Value::Object(Map::new()), + ); + let mut body = Value::Object(body_members); + self.parse_from(&self.params, &mut body); + self.parse_from(&self.params_list, &mut body); + self.parse_from(&self.params_hash, &mut body); + body } pub fn parse_from<'a, K, V>( &self, params: &'a HashMap<K, V>, - body: &mut Json, + body: &mut Value, ) where &'a HashMap<K, V>: IntoIterator, K: ToString + Eq + Hash, - V: ToJson, + V: Serialize, { for (k, v) in params.iter() { let key_string = k.to_string(); @@ -370,7 +367,7 @@ impl ContainerOptions { #[derive(Default)] pub struct ContainerOptionsBuilder { name: Option<String>, - params: HashMap<&'static str, Json>, + params: HashMap<&'static str, Value>, params_list: HashMap<&'static str, Vec<String>>, params_hash: HashMap<String, Vec<HashMap<String, String>>>, } @@ -381,7 +378,7 @@ impl ContainerOptionsBuilder { let params_list = HashMap::new(); let params_hash = HashMap::new(); - params.insert("Image", Json::String(image.to_owned())); + params.insert("Image", Value::String(image.to_owned())); ContainerOptionsBuilder { name: None, params: params, @@ -419,22 +416,22 @@ impl ContainerOptionsBuilder { } pub fn memory(&mut self, memory: u64) -> &mut ContainerOptionsBuilder { - self.params.insert("HostConfig.Memory", Json::U64(memory)); + self.params.insert("HostConfig.Memory", Value::Number(Number::from(memory))); self } pub fn labels(&mut self, labels: &HashMap<&str, &str>) -> &mut ContainerOptionsBuilder { - let mut json_labels : BTreeMap<String, Json> = BTreeMap::new(); + let mut json_labels = Map::new(); for (k, v) in labels { let key : &str = k.as_ref(); let value : &str = v.as_ref(); - json_labels.insert(key .to_owned(), Json::String(value.to_string())); + json_labels.insert(key .to_owned(), Value::String(value.to_string())); } self.params.insert( "Labels", - Json::Object(json_labels), + Value::Object(json_labels), ); self @@ -474,7 +471,7 @@ impl ContainerOptionsBuilder { if !network.is_empty() { self.params.insert( "HostConfig.NetworkMode", - Json::String(network.to_owned()), + Value::String(network.to_owned()), ); } self @@ -505,7 +502,7 @@ impl ContainerOptionsBuilder { if !entrypoint.is_empty() { self.params.insert( "Entrypoint", - Json::String(entrypoint.to_owned()), + Value::String(entrypoint.to_owned()), ); } self @@ -544,7 +541,7 @@ impl ContainerOptionsBuilder { if !log_driver.is_empty() { self.params.insert( "HostConfig.LogConfig.Type", - Json::String(log_driver.to_owned()), + Value::String(log_driver.to_owned()), ); } self @@ -558,13 +555,13 @@ impl ContainerOptionsBuilder { if !name.is_empty() { self.params.insert( "HostConfig.RestartPolicy.Name", - Json::String(name.to_owned()), + Value::String(name.to_owned()), ); } if name == "on-failure" { self.params.insert( "HostConfig.RestartPolicy.MaximumRetryCount", - Json::U64(maximum_retry_count), + Value::Number(Number::from(maximum_retry_count)), ); } self @@ -580,6 +577,7 @@ impl ContainerOptionsBuilder { } } +#[derive(Serialize)] pub struct ExecContainerOptions { params: HashMap<&'static str, Vec<String>>, params_bool: HashMap<&'static str, bool>, @@ -593,17 +591,7 @@ impl ExecContainerOptions { /// serialize options as a string. returns None if no options are defined pub fn serialize(&self) -> Result<String> { - let mut body = BTreeMap::new(); - - for (k, v) in &self.params { - body.insert(k.to_string(), v.to_json()); - } - for (k, v) in &self.params_bool { - body.insert(k.to_string(), v.to_json()); - } - - let json_obj: Json = body.to_json(); - Ok(json::encode(&json_obj)?) + Ok(serde_json::to_string(self)?) } } @@ -794,7 +782,7 @@ impl EventsOptionsBuilder { }; } - self.params.insert("filters", json::encode(¶ms).unwrap()); + self.params.insert("filters", serde_json::to_string(¶ms).unwrap()); self } @@ -942,7 +930,7 @@ impl ImageListOptionsBuilder { } // structure is a a json encoded object mapping string keys to a list // of string values - self.params.insert("filters", json::encode(¶m).unwrap()); + self.params.insert("filters", serde_json::to_string(¶m).unwrap()); self } @@ -1020,23 +1008,13 @@ impl NetworkListOptions { } /// Interface for creating new docker network +#[derive(Serialize)] pub struct NetworkCreateOptions { pub name: Option<String>, params: HashMap<&'static str, String>, params_hash: HashMap<String, Vec<HashMap<String, String>>>, } -impl ToJson for NetworkCreateOptions { - fn to_json(&self) -> Json { - let mut body: BTreeMap<String, Json> = BTreeMap::new(); - - self.parse_from(&self.params, &mut body); - self.parse_from(&self.params_hash, &mut body); - - body.to_json() - } -} - impl NetworkCreateOptions { /// return a new instance of a builder for options pub fn builder(name: &str) -> NetworkCreateOptionsBuilder { @@ -1045,21 +1023,21 @@ impl NetworkCreateOptions { /// serialize options as a string. returns None if no options are defined pub fn serialize(&self) -> Result<String> { - Ok(json::encode(&self.to_json())?) + serde_json::to_string(self).map_err(Error::from) } pub fn parse_from<'a, K, V>( &self, params: &'a HashMap<K, V>, - body: &mut BTreeMap<String, Json>, + body: &mut BTreeMap<String, Value>, ) where &'a HashMap<K, V>: IntoIterator, K: ToString + Eq + Hash, - V: ToJson, + V: Serialize, { for (k, v) in params.iter() { let key = k.to_string(); - let value = v.to_json(); + let value = serde_json::to_value(v).unwrap(); body.insert(key, value); } @@ -1116,38 +1094,30 @@ impl NetworkCreateOptionsBuilder { } /// Interface for connect container to network +#[derive(Serialize)] pub struct ContainerConnectionOptions { - pub Container: Option<String>, + pub container: Option<String>, params: HashMap<&'static str, String>, } -impl ToJson for ContainerConnectionOptions { - fn to_json(&self) -> Json { - let mut body: BTreeMap<String, Json> = BTreeMap::new(); - self.parse_from(&self.params, &mut body); - body.to_json() - } -} - - impl ContainerConnectionOptions { /// serialize options as a string. returns None if no options are defined pub fn serialize(&self) -> Result<String> { - Ok(json::encode(&self.to_json())?) + serde_json::to_string(self).map_err(Error::from) } pub fn parse_from<'a, K, V>( &self, params: &'a HashMap<K, V>, - body: &mut BTreeMap<String, Json>, + body: &mut BTreeMap<String, Value>, ) where &'a HashMap<K, V>: IntoIterator, K: ToString + Eq + Hash, - V: ToJson, + V: Serialize, { for (k, v) in params.iter() { let key = k.to_string(); - let value = v.to_json(); + let value = serde_json::to_value(v).unwrap(); body.insert(key, value); } @@ -1157,7 +1127,7 @@ impl ContainerConnectionOptions { let mut params = HashMap::new(); params.insert("Container", container_id.to_owned()); ContainerConnectionOptions { - Container: None, + container: None, params: params.clone(), } } @@ -1165,7 +1135,7 @@ impl ContainerConnectionOptions { pub fn force(&mut self) -> ContainerConnectionOptions { self.params.insert("Force", "true".to_owned()); ContainerConnectionOptions { - Container: None, + container: None, params: self.params.clone(), } } @@ -1230,8 +1200,10 @@ mod tests { .restart_policy("on-failure", 10) .build(); - assert_eq!(r#"{"HostConfig":{"RestartPolicy":{"MaximumRetryCount":10,"Name":"on-failure"}},"Image":"test_image"}"#, - options.serialize().unwrap()); + assert_eq!( + r#"{"HostConfig":{"RestartPolicy":{"MaximumRetryCount":10,"Name":"on-failure"}},"Image":"test_image"}"#, + options.serialize().unwrap() + ); options = ContainerOptionsBuilder::new("test_image") .restart_policy("always", 0) diff --git a/src/errors.rs b/src/errors.rs index d4905a1..44be52a 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -2,37 +2,23 @@ use http; use hyper::{self, StatusCode}; -use rustc_serialize::json::{DecoderError, EncoderError, ParserError}; +use serde_json::Error as SerdeError; use std::error::Error as ErrorTrait; use std::fmt; use std::io::Error as IoError; #[derive(Debug)] pub enum Error { - Decoding(DecoderError), - Encoding(EncoderError), - Parse(ParserError), + SerdeJsonError(SerdeError), Hyper(hyper::Error), Http(http::Error), IO(IoError), Fault { code: StatusCode, message: String }, } -impl From<ParserError> for Error { - fn from(error: ParserError) -> Error { - Error::Parse(error) - } -} - -impl From<DecoderError> for Error { - fn from(error: DecoderError) -> Error { - Error::Decoding(error) - } -} - -impl From<EncoderError> for Error { - fn from(error: EncoderError) -> Error { - Error::Encoding(error) +impl From<SerdeError> for Error { + fn from(error: SerdeError) -> Error { + Error::SerdeJsonError(error) } } @@ -58,9 +44,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Docker Error: ")?; match self { - &Error::Decoding(ref err) => return err.fmt(f), - &Error::Encoding(ref err) => return err.fmt(f), - &Error::Parse(ref err) => return err.fmt(f), + &Error::SerdeJsonError(ref err) => return err.fmt(f), &Error::Http(ref err) => return err.fmt(f), &Error::Hyper(ref err) => return err.fmt(f), &Error::IO(ref err) => return err.fmt(f), @@ -76,9 +60,7 @@ impl ErrorTrait for Error { fn cause(&self) -> Option<&ErrorTrait> { match self { - &Error::Decoding(ref err) => Some(err), - &Error::Encoding(ref err) => Some(err), - &Error::Parse(ref err) => Some(err), + &Error::SerdeJsonError(ref err) => Some(err), &Error::Http(ref err) => Some(err), &Error::IO(ref err) => Some(err), _ => None, @@ -9,7 +9,7 @@ //! let images = docker.images().list(&Default::default()).unwrap(); //! println!("docker images in stock"); //! for i in images { -//! println!("{:?}", i.RepoTags); +//! println!("{:?}", i.repo_tags); //! } //! ``` @@ -22,15 +22,14 @@ extern crate hyper; extern crate hyper_openssl; #[cfg(feature = "unix-socket")] extern crate hyperlocal; -extern crate jed; extern crate mime; extern crate openssl; -extern crate rustc_serialize; extern crate tar; extern crate url; #[macro_use] extern crate serde_derive; extern crate serde; +extern crate serde_json; extern crate tokio; pub mod builder; @@ -63,12 +62,11 @@ use rep::{ Version, }; use rep::{NetworkCreateInfo, NetworkDetails as NetworkInfo}; -use rustc_serialize::json::{self, Json}; +use serde_json::Value; use std::borrow::Cow; use std::cell::RefCell; use std::env; use std::io::prelude::*; -use std::iter::IntoIterator; use std::path::Path; use std::time::Duration; use transport::{tar, Transport}; @@ -106,7 +104,7 @@ impl<'a, 'b> Image<'a, 'b> { let raw = self .docker .get(&format!("/images/{}/json", self.name)[..])?; - Ok(json::decode::<ImageDetails>(&raw)?) + Ok(serde_json::from_str::<ImageDetails>(&raw)?) } /// Lists the history of the images set of changes @@ -114,25 +112,25 @@ impl<'a, 'b> Image<'a, 'b> { let raw = self .docker .get(&format!("/images/{}/history", self.name)[..])?; - Ok(json::decode::<Vec<History>>(&raw)?) + Ok(serde_json::from_str::<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| { + Ok(match serde_json::from_str(&raw)? { + Value::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() + sha.as_str() .expect("expected Untagged to be a string") .to_owned(), ) }).or(obj.get("Deleted").map(|sha| { Status::Deleted( - sha.as_string() + sha.as_str() .expect("expected Deleted to be a string") .to_owned(), ) @@ -164,7 +162,7 @@ impl<'a> Images<'a> { pub fn build( &self, opts: &BuildOptions, - ) -> Result<Box<Iterator<Item = Json>>> { + ) -> Result<Vec<Value>> { let mut path = vec!["/build".to_owned()]; if let Some(query) = opts.serialize() { path.push(query) @@ -174,11 +172,12 @@ impl<'a> Images<'a> { tarball::dir(&mut bytes, &opts.path[..])?; - let raw = self + self .docker - .stream_post(&path.join("?"), Some((Body::from(bytes), tar())))?; - let it = jed::Iter::new(raw).into_iter(); - Ok(Box::new(it)) + .stream_post(&path.join("?"), Some((Body::from(bytes), tar()))) + .and_then(|r| { + serde_json::from_reader::<_, Vec<Value>>(r).map_err(Error::from) + }) } /// Lists the docker images on the current docker host @@ -188,7 +187,7 @@ impl<'a> Images<'a> { path.push(query); } let raw = self.docker.get(&path.join("?"))?; - Ok(json::decode::<Vec<ImageRep>>(&raw)?) + Ok(serde_json::from_str::<Vec<ImageRep>>(&raw)?) } /// Returns a reference to a set of operations available for a named image @@ -202,21 +201,23 @@ impl<'a> Images<'a> { .append_pair("term", term) .finish(); let raw = self.docker.get(&format!("/images/search?{}", query)[..])?; - Ok(json::decode::<Vec<SearchResult>>(&raw)?) + Ok(serde_json::from_str::<Vec<SearchResult>>(&raw)?) } /// Pull and create a new docker images from an existing image pub fn pull( &self, opts: &PullOptions, - ) -> Result<Box<Iterator<Item = Json>>> { + ) -> Result<Vec<Value>> { let mut path = vec!["/images/create".to_owned()]; if let Some(query) = opts.serialize() { path.push(query); } - let raw = self.docker.stream_post::<Body>(&path.join("?"), None)?; - let it = jed::Iter::new(raw).into_iter(); - Ok(Box::new(it)) + self.docker + .stream_post::<Body>(&path.join("?"), None) + .and_then(|r| { + serde_json::from_reader::<_, Vec<Value>>(r).map_err(Error::from) + }) } /// exports a collection of named images, @@ -263,7 +264,7 @@ impl<'a, 'b> Container<'a, 'b> { let raw = self .docker .get(&format!("/containers/{}/json", self.id)[..])?; - Ok(json::decode::<ContainerDetails>(&raw)?) + Ok(serde_json::from_str::<ContainerDetails>(&raw)?) } /// Returns a `top` view of information about the container process @@ -277,7 +278,7 @@ impl<'a, 'b> Container<'a, 'b> { } let raw = self.docker.get(&path.join("?"))?; - Ok(json::decode::<Top>(&raw)?) + Ok(serde_json::from_str::<Top>(&raw)?) } /// Returns a stream of logs emitted but the container instance @@ -294,7 +295,7 @@ impl<'a, 'b> Container<'a, 'b> { let raw = self .docker .get(&format!("/containers/{}/changes", self.id)[..])?; - Ok(json::decode::<Vec<Change>>(&raw)?) + Ok(serde_json::from_str::<Vec<Change>>(&raw)?) } /// Exports the current docker container into a tarball @@ -304,17 +305,13 @@ impl<'a, 'b> Container<'a, 'b> { } /// Returns a stream of stats specific to this container instance - pub fn stats(&self) -> Result<Box<Iterator<Item = Stats>>> { - let raw = self + pub fn stats(&self) -> Result<Vec<Stats>> { + 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); - let s = json::encode(&j).unwrap(); - json::decode::<Stats>(&s).unwrap() - }); - Ok(Box::new(it)) + .stream_get(&format!("/containers/{}/stats", self.id)[..]) + .and_then(|r|{ + serde_json::from_reader::<_, Vec<Stats>>(r).map_err(Error::from) + }) } /// Start the container instance @@ -392,7 +389,7 @@ impl<'a, 'b> Container<'a, 'b> { let raw = self .docker .post::<Body>(&format!("/containers/{}/wait", self.id)[..], None)?; - Ok(json::decode::<Exit>(&raw)?) + Ok(serde_json::from_str::<Exit>(&raw)?) } /// Delete the container instance @@ -426,19 +423,25 @@ impl<'a, 'b> Container<'a, 'b> { Ok(res) => { let data = "{}"; let mut bytes = data.as_bytes(); - self.docker - .stream_post( - &format!( - "/exec/{}/start", - Json::from_str(res.as_str()) - .unwrap() - .search("Id") - .unwrap() - .as_string() - .unwrap() - )[..], - Some((bytes, mime::APPLICATION_JSON)), - ).map(|stream| Tty::new(stream)) + let json: Value = serde_json::from_str(res.as_str())?; + + if let Value::Object(ref obj) = json { + self.docker + .stream_post( + &format!( + "/exec/{}/start", + obj + .get("Id") + .unwrap() + .as_str() + .unwrap() + )[..], + Some((bytes, mime::APPLICATION_JSON)), + ).map(|stream| Tty::new(stream)) + } else { + // TODO + panic!() + } } } } @@ -467,7 +470,7 @@ impl<'a> Containers<'a> { path.push(query) } let raw = self.docker.get(&path.join("?"))?; - Ok(json::decode::<Vec<ContainerRep>>(&raw)?) + Ok(serde_json::from_str::<Vec<ContainerRep>>(&raw)?) } /// Returns a reference to a set of operations available to a specific container instance @@ -480,7 +483,7 @@ impl<'a> Containers<'a> { &'a self, opts: &ContainerOptions, ) -> Result<ContainerCreateInfo> { - let data = opts.serialize()?; + let data = serde_json::to_string(opts)?; let bytes = data.into_bytes(); let mut path = vec!["/containers/create".to_owned()]; @@ -495,7 +498,7 @@ impl<'a> Containers<'a> { let raw = self .docker .post(&path.join("?"), Some((bytes, mime::APPLICATION_JSON)))?; - Ok(json::decode::<ContainerCreateInfo>(&raw)?) + Ok(serde_json::from_str::<ContainerCreateInfo>(&raw)?) } } @@ -517,7 +520,7 @@ impl<'a> Networks<'a> { path.push(query); } let raw = self.docker.get(&path.join("?"))?; - Ok(json::decode::<Vec<NetworkInfo>>(&raw)?) + Ok(serde_json::from_str::<Vec<NetworkInfo>>(&raw)?) } /// Returns a reference to a set of operations available to a specific network instance @@ -536,7 +539,7 @@ impl<'a> Networks<'a> { let raw = self .docker .post(&path.join("?"), Some((bytes, mime::APPLICATION_JSON)))?; - Ok(json::decode::<NetworkCreateInfo>(&raw)?) + Ok(serde_json::from_str::<NetworkCreateInfo>(&raw)?) } } @@ -566,7 +569,7 @@ impl<'a, 'b> Network<'a, 'b> { /// Inspects the current docker network instance's details pub fn inspect(&self) -> Result<NetworkInfo> { let raw = self.docker.get(&format!("/networks/{}", self.id)[..])?; - Ok(json::decode::<NetworkInfo>(&raw)?) + Ok(serde_json::from_str::<NetworkInfo>(&raw)?) } /// Delete the network instance @@ -729,13 +732,13 @@ impl Docker { /// Returns version information associated with the docker daemon pub fn version(&self) -> Result<Version> { let raw = self.get("/version")?; - Ok(json::decode::<Version>(&raw)?) + Ok(serde_json::from_str::<Version>(&raw)?) } /// Returns information associated with the docker daemon pub fn info(&self) -> Result<Info> { let raw = self.get("/info")?; - Ok(json::decode::<Info>(&raw)?) + Ok(serde_json::from_str::<Info>(&raw)?) } /// Returns a simple ping response indicating the docker daemon is accessible @@ -747,19 +750,13 @@ impl Docker { pub fn events( &self, opts: &EventsOptions, - ) -> Result<Box<Iterator<Item = Event>>> { + ) -> Result<Vec<Event>> { let mut path = vec!["/events".to_owned()]; if let Some(query) = opts.serialize() { path.push(query); } - let raw = self.stream_get(&path.join("?")[..])?; - let it = jed::Iter::new(raw).into_iter().map(|j| { - debug!("{:?}", j); - // fixme: better error handling - let s = json::encode(&j).unwrap(); - json::decode::<Event>(&s).unwrap() - }); - Ok(Box::new(it)) + self.stream_get(&path.join("?")[..]) + .and_then(|r| serde_json::from_reader::<_, Vec<Event>>(r).map_err(Error::from)) } fn get(&self, endpoint: &str) -> Result<String> { @@ -2,7 +2,7 @@ use std::collections::HashMap; -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct SearchResult { pub description: String, pub is_official: bool, @@ -11,172 +11,184 @@ pub struct SearchResult { pub star_count: u64, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -#[allow(non_snake_case)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct Image { - pub Created: u64, - pub Id: String, - pub ParentId: String, - pub Labels: Option<HashMap<String, String>>, - pub RepoTags: Option<Vec<String>>, - pub RepoDigests: Option<Vec<String>>, - pub VirtualSize: u64, + pub created: u64, + pub id: String, + pub parent_id: String, + pub labels: Option<HashMap<String, String>>, + pub repo_tags: Option<Vec<String>>, + pub repo_digests: Option<Vec<String>>, + pub virtual_size: u64, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -#[allow(non_snake_case)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct ImageDetails { - pub Architecture: String, - pub Author: String, - pub Comment: String, - pub Config: Config, - pub Created: String, - pub DockerVersion: String, - pub Id: String, - pub Os: String, - pub Parent: String, - pub Size: u64, - pub VirtualSize: u64, -} - -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -#[allow(non_snake_case)] + pub architecture: String, + pub author: String, + pub comment: String, + pub config: Config, + pub created: String, + pub docker_version: String, + pub id: String, + pub os: String, + pub parent: String, + pub size: u64, + pub virtual_size: u64, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct Container { - pub Created: u64, - pub Command: String, - pub Id: String, - pub Image: String, - pub Labels: HashMap<String, String>, - pub Names: Vec<String>, - pub Ports: Vec<Port>, - pub Status: String, - pub SizeRw: Option<u64>, - pub SizeRootFs: Option<u64>, -} - -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)] -#[allow(non_snake_case)] + pub created: u64, + pub command: String, + pub id: String, + pub image: String, + pub labels: HashMap<String, String>, + pub names: Vec<String>, + pub ports: Vec<Port>, + pub status: String, + pub size_rw: Option<u64>, + pub size_root_fs: Option<u64>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct ContainerDetails { - pub AppArmorProfile: String, - pub Args: Vec<String>, - pub Config: Config, - pub Created: String, - pub Driver: String, + pub app_armor_profile: String, + pub args: Vec<String>, + pub config: Config, + pub created: String, + pub driver: String, // pub ExecIDs: ?? - pub HostConfig: HostConfig, - pub HostnamePath: String, - pub HostsPath: String, - pub LogPath: String, - pub Id: String, - pub Image: String, - pub MountLabel: String, - pub Name: String, - pub NetworkSettings: NetworkSettings, - pub Path: String, - pub ProcessLabel: String, - pub ResolvConfPath: String, - pub RestartCount: u64, - pub State: State, - pub Mounts: Vec<Mount>, -} - -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)] -#[allow(non_snake_case)] + pub host_config: HostConfig, + pub hostname_path: String, + pub hosts_path: String, + pub log_path: String, + pub id: String, + pub image: String, + pub mount_label: String, + pub name: String, + pub network_settings: NetworkSettings, + pub path: String, + pub process_label: String, + pub resolv_conf_path: String, + pub restart_count: u64, + pub state: State, + pub mounts: Vec<Mount>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct Mount { - pub Source: String, - pub Destination: String, - pub Mode: String, - pub RW: bool, + pub source: String, + pub destination: String, + pub mode: String, + #[serde(rename = "RW")] + pub rw: bool, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)] -#[allow(non_snake_case)] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] pub struct State { - pub Error: String, - pub ExitCode: u64, - pub FinishedAt: String, - pub OOMKilled: bool, - pub Paused: bool, - pub Pid: u64, - pub Restarting: bool, - pub Running: bool, - pub StartedAt: String, -} - -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, Serialize, Deserialize)] -#[allow(non_snake_case)] + pub error: String, + pub exit_code: u64, + pub finished_at: String, + #[serde(rename = "OOMKilled")] + pub oom_killed: bool, |