diff options
author | softprops <d.tangren@gmail.com> | 2016-01-03 02:21:58 -0500 |
---|---|---|
committer | softprops <d.tangren@gmail.com> | 2016-01-03 02:21:58 -0500 |
commit | 6b9f98106c57af84dd1260234b90fed78cbd3806 (patch) | |
tree | 11032c38c86ae29cdce59c32e4b458e45873e691 | |
parent | b9170de9dcd95342ea869097d33fed81ac6d04cb (diff) |
rustfmt
-rw-r--r-- | src/builder.rs | 224 | ||||
-rw-r--r-- | src/lib.rs | 658 | ||||
-rw-r--r-- | src/rep.rs | 415 | ||||
-rw-r--r-- | src/transport.rs | 113 |
4 files changed, 724 insertions, 686 deletions
diff --git a/src/builder.rs b/src/builder.rs index 99e5368..32f8374 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -6,143 +6,147 @@ extern crate url; use self::super::Docker; use self::super::transport::Body; -use self::super::rep::{ ContainerCreateInfo, Event }; +use self::super::rep::{ContainerCreateInfo, Event}; use self::super::rep::Container as ContainerRep; -use std::collections::{ BTreeMap, HashMap }; +use std::collections::{BTreeMap, HashMap}; use std::io::Result; use rustc_serialize::json::{self, Json, ToJson}; /// Interface for building container list request pub struct ContainerListBuilder<'a> { - docker: &'a mut Docker, - params: HashMap<&'static str, String> + docker: &'a mut Docker, + params: HashMap<&'static str, String>, } impl<'a> ContainerListBuilder<'a> { - pub fn new(docker: &'a mut Docker) -> ContainerListBuilder<'a> { - ContainerListBuilder { - docker: docker, - params: HashMap::new() + pub fn new(docker: &'a mut Docker) -> ContainerListBuilder<'a> { + ContainerListBuilder { + docker: docker, + params: HashMap::new(), + } } - } - - pub fn all(mut self) -> ContainerListBuilder<'a> { - self.params.insert("all", "true".to_owned()); - self - } - - pub fn since(mut self, since: &str) -> ContainerListBuilder<'a> { - self.params.insert("since", since.to_owned()); - self - } - - pub fn before(mut self, before: &str) -> ContainerListBuilder<'a> { - self.params.insert("before", before.to_owned()); - self - } - - pub fn sized(mut self) -> ContainerListBuilder<'a> { - self.params.insert("size", "true".to_owned()); - self - } - - pub fn get(self) -> Result<Vec<ContainerRep>> { - let mut params = Vec::new(); - for (k, v) in self.params { - params.push(format!("{}={}", k, v)) + + pub fn all(mut self) -> ContainerListBuilder<'a> { + self.params.insert("all", "true".to_owned()); + self + } + + pub fn since(mut self, since: &str) -> ContainerListBuilder<'a> { + self.params.insert("since", since.to_owned()); + self + } + + pub fn before(mut self, before: &str) -> ContainerListBuilder<'a> { + self.params.insert("before", before.to_owned()); + self + } + + pub fn sized(mut self) -> ContainerListBuilder<'a> { + self.params.insert("size", "true".to_owned()); + self } - let mut path = vec!["/containers/json".to_owned()]; - if !params.is_empty() { - path.push(params.join("&")) + + pub fn get(self) -> Result<Vec<ContainerRep>> { + let mut params = Vec::new(); + for (k, v) in self.params { + params.push(format!("{}={}", k, v)) + } + let mut path = vec!["/containers/json".to_owned()]; + if !params.is_empty() { + path.push(params.join("&")) + } + let raw = try!(self.docker.get(&path.join("?"))); + Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap()) } - let raw = try!(self.docker.get(&path.join("?"))); - Ok(json::decode::<Vec<ContainerRep>>(&raw).unwrap()) - } } /// Interface for building a new docker container from an existing image pub struct ContainerBuilder<'a, 'b> { - docker: &'a mut Docker, - image: &'b str, - hostname: Option<String>, - user: Option<String>, - memory: Option<u64> + docker: &'a mut Docker, + image: &'b str, + hostname: Option<String>, + user: Option<String>, + memory: Option<u64>, } impl<'a, 'b> ContainerBuilder<'a, 'b> { - pub fn new(docker: &'a mut Docker, image: &'b str) -> ContainerBuilder<'a,'b> { - ContainerBuilder { - docker: docker, image: image, - hostname: None, user: None, - memory: None + pub fn new(docker: &'a mut Docker, image: &'b str) -> ContainerBuilder<'a, 'b> { + ContainerBuilder { + docker: docker, + image: image, + hostname: None, + user: None, + memory: None, + } + } + pub fn hostname(mut self, h: &str) -> ContainerBuilder<'a, 'b> { + self.hostname = Some(h.to_owned()); + self + } + + pub fn user(mut self, u: &str) -> ContainerBuilder<'a, 'b> { + self.user = Some(u.to_owned()); + self + } + + pub fn build(self) -> Result<ContainerCreateInfo> { + let mut body = BTreeMap::new(); + body.insert("Image".to_owned(), self.image.to_json()); + let json_obj: Json = body.to_json(); + let data = json::encode(&json_obj).unwrap(); + let mut bytes = data.as_bytes(); + let raw = try!(self.docker.post("/containers/create", + Some(Body::new(&mut Box::new(&mut bytes), + bytes.len() as u64)))); + Ok(json::decode::<ContainerCreateInfo>(&raw).unwrap()) } - } - pub fn hostname(mut self, h: &str) -> ContainerBuilder<'a,'b> { - self.hostname = Some(h.to_owned()); - self - } - - pub fn user(mut self, u: &str) -> ContainerBuilder<'a, 'b> { - self.user = Some(u.to_owned()); - self - } - - pub fn build(self) -> Result<ContainerCreateInfo> { - let mut body = BTreeMap::new(); - body.insert("Image".to_owned(), self.image.to_json()); - let json_obj: Json = body.to_json(); - let data = json::encode(&json_obj).unwrap(); - let mut bytes = data.as_bytes(); - let raw = try!(self.docker.post("/containers/create", Some(Body::new(&mut Box::new(&mut bytes), bytes.len() as u64)))); - Ok(json::decode::<ContainerCreateInfo>(&raw).unwrap()) - } } /// Interface for buiding an events request -pub struct Events<'a,'b,'c> { - docker: &'a mut Docker, - since: Option<&'b u64>, - until: Option<&'c u64> +pub struct Events<'a, 'b, 'c> { + docker: &'a mut Docker, + since: Option<&'b u64>, + until: Option<&'c u64>, } -impl<'a,'b,'c> Events<'a,'b,'c> { - pub fn new(docker: &'a mut Docker) -> Events<'a,'b,'c> { - Events { - docker: docker, - since: None, - until: None +impl<'a, 'b, 'c> Events<'a, 'b, 'c> { + pub fn new(docker: &'a mut Docker) -> Events<'a, 'b, 'c> { + Events { + docker: docker, + since: None, + until: None, + } } - } - - /// Filter events since a given timestamp - pub fn since(mut self, ts: &'b u64) -> Events<'a,'b,'c> { - self.since = Some(ts); - self - } - - /// Filter events until a given timestamp - pub fn until(mut self, ts: &'c u64) -> Events<'a,'b,'c> { - self.until = Some(ts); - self - } - - pub fn get(mut self) -> Result<Box<Iterator<Item=Event>>> { - let mut params = Vec::new(); - if let Some(s) = self.since { - params.push(format!("since={}", s)); + + /// Filter events since a given timestamp + pub fn since(mut self, ts: &'b u64) -> Events<'a, 'b, 'c> { + self.since = Some(ts); + self } - if let Some(u) = self.until { - params.push(format!("until={}", u)); + + /// Filter events until a given timestamp + pub fn until(mut self, ts: &'c u64) -> Events<'a, 'b, 'c> { + self.until = Some(ts); + self } - let mut path = vec!["/events".to_owned()]; - if !params.is_empty() { - path.push(params.join("&")) + + pub fn get(mut self) -> Result<Box<Iterator<Item = Event>>> { + let mut params = Vec::new(); + if let Some(s) = self.since { + params.push(format!("since={}", s)); + } + if let Some(u) = self.until { + params.push(format!("until={}", u)); + } + let mut path = vec!["/events".to_owned()]; + if !params.is_empty() { + path.push(params.join("&")) + } + let raw = try!(self.docker.stream_get(&path.join("?")[..])); + let it = jed::Iter::new(raw).into_iter().map(|j| { + let s = json::encode(&j).unwrap(); + json::decode::<Event>(&s).unwrap() + }); + Ok(Box::new(it)) } - let raw = try!(self.docker.stream_get(&path.join("?")[..])); - let it = jed::Iter::new(raw).into_iter().map(|j| { - let s = json::encode(&j).unwrap(); - json::decode::<Event>(&s).unwrap() - }); - Ok(Box::new(it)) - } } @@ -18,371 +18,393 @@ extern crate hyperlocal; extern crate jed; extern crate openssl; extern crate rustc_serialize; -extern crate unix_socket; extern crate url; pub mod builder; pub mod rep; pub mod transport; -use builder::{ ContainerBuilder, ContainerListBuilder, Events }; -use hyper::{ Client, Url }; -use hyper::net::{ HttpsConnector, Openssl }; +use builder::{ContainerBuilder, ContainerListBuilder, Events}; +use hyper::{Client, Url}; +use hyper::net::{HttpsConnector, Openssl}; use hyper::method::Method; use hyperlocal::UnixSocketConnector; use openssl::x509::X509FileType; -use openssl::ssl::{ SslContext, SslMethod }; +use openssl::ssl::{SslContext, SslMethod}; use rep::Image as ImageRep; -use rep::{ - Change, ContainerDetails, Exit, History, - ImageDetails, Info, SearchResult, Stats, Status, - Top, Version -}; -use rustc_serialize::json::{ self, Json }; -use std::env::{ self, VarError }; -use std::io::{ Read, Result }; +use rep::{Change, ContainerDetails, Exit, History, ImageDetails, Info, SearchResult, Stats, + Status, Top, Version}; +use rustc_serialize::json::{self, Json}; +use std::env::{self, VarError}; +use std::io::{Read, Result}; use std::iter::IntoIterator; use std::path::Path; use std::sync::Arc; -use transport::{ Body, Transport }; -use url::{ Host, RelativeSchemeData, SchemeData }; +use transport::{Body, Transport}; +use url::{Host, RelativeSchemeData, SchemeData}; /// Entrypoint interface for communicating with docker daemon pub struct Docker { - transport: Transport + transport: Transport, } /// Interface for accessing and manipulating a named docker image pub struct Image<'a, 'b> { - docker: &'a mut Docker, - name: &'b str + docker: &'a mut Docker, + name: &'b str, } impl<'a, 'b> Image<'a, 'b> { - /// Exports an interface for operations that may be performed against a named image - pub fn new(docker: &'a mut Docker, name: &'b str) -> Image<'a, 'b> { - Image { docker: docker, name: name } - } - - /// Inspects a named image's details - pub fn inspect(self) -> Result<ImageDetails> { - let raw = try!(self.docker.get(&format!("/images/{}/json", self.name)[..])); - Ok(json::decode::<ImageDetails>(&raw).unwrap()) - } - - /// Lists the history of the images set of changes - pub fn history(self) -> Result<Vec<History>> { - let raw = try!(self.docker.get(&format!("/images/{}/history", self.name)[..])); - Ok(json::decode::<Vec<History>>(&raw).unwrap()) - } - - /// Delete's an image - pub fn delete(self) -> Result<Vec<Status>> { - let raw = try!(self.docker.delete(&format!("/images/{}", self.name)[..])); - Ok(match Json::from_str(&raw).unwrap() { - Json::Array(ref xs) => xs.iter().map(|j| { - let obj = j.as_object().unwrap(); - obj.get("Untagged").map(|sha| Status::Untagged(sha.as_string().unwrap().to_string())) - .or(obj.get("Deleted").map(|sha| Status::Deleted(sha.as_string().unwrap().to_string()))) - .unwrap() - }), - _ => unreachable!("") - }.collect()) - } - - /// Export this image to a tarball - pub fn export(self) -> Result<Box<Read>> { - self.docker.stream_get(&format!("/images/{}/get", self.name)[..]) - } + /// Exports an interface for operations that may be performed against a named image + pub fn new(docker: &'a mut Docker, name: &'b str) -> Image<'a, 'b> { + Image { + docker: docker, + name: name, + } + } + + /// Inspects a named image's details + pub fn inspect(self) -> Result<ImageDetails> { + let raw = try!(self.docker.get(&format!("/images/{}/json", self.name)[..])); + Ok(json::decode::<ImageDetails>(&raw).unwrap()) + } + + /// Lists the history of the images set of changes + pub fn history(self) -> Result<Vec<History>> { + let raw = try!(self.docker.get(&format!("/images/{}/history", self.name)[..])); + Ok(json::decode::<Vec<History>>(&raw).unwrap()) + } + + /// Delete's an image + pub fn delete(self) -> Result<Vec<Status>> { + let raw = try!(self.docker.delete(&format!("/images/{}", self.name)[..])); + Ok(match Json::from_str(&raw).unwrap() { + Json::Array(ref xs) => { + xs.iter().map(|j| { + let obj = j.as_object().unwrap(); + obj.get("Untagged") + .map(|sha| Status::Untagged(sha.as_string().unwrap().to_owned())) + .or(obj.get("Deleted") + .map(|sha| Status::Deleted(sha.as_string().unwrap().to_owned()))) + .unwrap() + }) + } + _ => unreachable!(""), + } + .collect()) + } + + /// Export this image to a tarball + pub fn export(self) -> Result<Box<Read>> { + self.docker.stream_get(&format!("/images/{}/get", self.name)[..]) + } } /// Interface for docker images pub struct Images<'a> { - docker: &'a mut Docker + docker: &'a mut Docker, } impl<'a> Images<'a> { - /// Exports an interface for interacting with docker images - pub fn new(docker: &'a mut Docker) -> Images<'a> { - Images { docker: docker } - } - - /// Lists the docker images on the current docker host - pub fn list(self) -> Result<Vec<ImageRep>> { - let raw = try!(self.docker.get("/images/json")); - Ok(json::decode::<Vec<ImageRep>>(&raw).unwrap()) - } - - /// Returns a reference to a set of operations available for a named image - pub fn get(&'a mut self, name: &'a str) -> Image { - Image::new(self.docker, name) - } - - /// Search for docker images by term - pub fn search(self, term: &str) -> Result<Vec<SearchResult>> { - let raw = try!(self.docker.get(&format!("/images/search?term={}", term)[..])); - Ok(json::decode::<Vec<SearchResult>>(&raw).unwrap()) - } - - /// Create a new docker images from an existing image - pub fn create(self, from: &str) -> Result<Box<Read>> { - self.docker.stream_post(&format!("/images/create?fromImage={}", from)[..]) - } - - /// 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 query = names.iter() - .map(|n| format!("names={}", n)) - .collect::<Vec<String>>() - .join("&"); - self.docker.stream_get(&format!("/images/get?{}", query)[..]) - } - - //pub fn import(self, tarball: Box<Read>) -> Result<()> { - // self.docker.post - //} + /// Exports an interface for interacting with docker images + pub fn new(docker: &'a mut Docker) -> Images<'a> { + Images { docker: docker } + } + + /// Lists the docker images on the current docker host + pub fn list(self) -> Result<Vec<ImageRep>> { + let raw = try!(self.docker.get("/images/json")); + Ok(json::decode::<Vec<ImageRep>>(&raw).unwrap()) + } + + /// Returns a reference to a set of operations available for a named image + pub fn get(&'a mut self, name: &'a str) -> Image { + Image::new(self.docker, name) + } + + /// Search for docker images by term + pub fn search(self, term: &str) -> Result<Vec<SearchResult>> { + let raw = try!(self.docker.get(&format!("/images/search?term={}", term)[..])); + Ok(json::decode::<Vec<SearchResult>>(&raw).unwrap()) + } + + /// Create a new docker images from an existing image + pub fn create(self, from: &str) -> Result<Box<Read>> { + self.docker.stream_post(&format!("/images/create?fromImage={}", from)[..]) + } + + /// 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 query = names.iter() + .map(|n| format!("names={}", n)) + .collect::<Vec<String>>() + .join("&"); + self.docker.stream_get(&format!("/images/get?{}", query)[..]) + } + + // pub fn import(self, tarball: Box<Read>) -> Result<()> { + // self.docker.post + // } } /// Interface for accessing and manipulating a docker container pub struct Container<'a, 'b> { - docker: &'a mut Docker, - id: &'b str + docker: &'a mut Docker, + id: &'b str, } impl<'a, 'b> Container<'a, 'b> { - /// Exports an interface exposing operations against a container instance - pub fn new(docker: &'a mut Docker, id: &'b str) -> Container<'a, 'b> { - Container { docker: docker, id: id } - } - - /// Inspects the current docker container instance's details - pub fn inspect(self) -> Result<ContainerDetails> { - let raw = try!(self.docker.get(&format!("/containers/{}/json", self.id)[..])); - Ok(json::decode::<ContainerDetails>(&raw).unwrap()) - } - - /// Returns a `top` view of information about the container process - pub fn top(self) -> Result<Top> { - let raw = try!(self.docker.get(&format!("/containers/{}/top", self.id)[..])); - Ok(json::decode::<Top>(&raw).unwrap()) - } - - /// Returns a stream of logs emitted but the container instance - pub fn logs(self) -> Result<Box<Read>> { - let query = format!( - "follow={}&stdout={}&stderr={}×tamps={}&tail={}", - true, true, true, true, "all"); - self.docker.stream_get(&format!("/containers/{}/logs?{}", self.id, query)[..]) - } - - /// Returns a set of changes made to the container instance - pub fn changes(self) -> Result<Vec<Change>> { - let raw = try!(self.docker.get(&format!("/containers/{}/changes", self.id)[..])); - Ok(json::decode::<Vec<Change>>(&raw).unwrap()) - } - - /// Exports the current docker container into a tarball - pub fn export(self) -> Result<Box<Read>> { - 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 = try!(self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..])); - let it = jed::Iter::new(raw).into_iter().map(|j| { - let s = json::encode(&j).unwrap(); - json::decode::<Stats>(&s).unwrap() - }); - Ok(Box::new(it)) - } - - /// Start the container instance - pub fn start(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/start", self.id)[..], None).map(|_| ()) - } - - /// Stop the container instance - pub fn stop(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/stop", self.id)[..], None).map(|_| ()) - } - - /// Restart the container instance - pub fn restart(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/restart", self.id)[..], None).map(|_| ()) - } - - /// Kill the container instance - pub fn kill(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/kill", self.id)[..], None).map(|_| ()) - } - - /// Rename the container instance - pub fn rename(self, name: &str) -> Result<()> { - self.docker.post(&format!("/containers/{}/rename?name={}", self.id, name)[..], None).map(|_| ()) - } - - /// Pause the container instance - pub fn pause(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/pause", self.id)[..], None).map(|_| ()) - } - - /// Unpause the container instance - pub fn unpause(self) -> Result<()> { - self.docker.post(&format!("/containers/{}/unpause", self.id)[..], None).map(|_| ()) - } - - /// Wait until the container stops - pub fn wait(self) -> Result<Exit> { - let raw = try!(self.docker.post(&format!("/containers/{}/wait", self.id)[..], None)); - Ok(json::decode::<Exit>(&raw).unwrap()) - } - - /// Delete the container instance - pub fn delete(self) -> Result<()> { - self.docker.delete(&format!("/containers/{}", self.id)[..]).map(|_| ()) - } - - // todo attach, attach/ws, + /// Exports an interface exposing operations against a container instance + pub fn new(docker: &'a mut Docker, id: &'b str) -> Container<'a, 'b> { + Container { + docker: docker, + id: id, + } + } + + /// Inspects the current docker container instance's details + pub fn inspect(self) -> Result<ContainerDetails> { + let raw = try!(self.docker.get(&format!("/containers/{}/json", self.id)[..])); + Ok(json::decode::<ContainerDetails>(&raw).unwrap()) + } + + /// Returns a `top` view of information about the container process + pub fn top(self) -> Result<Top> { + let raw = try!(self.docker.get(&format!("/containers/{}/top", self.id)[..])); + Ok(json::decode::<Top>(&raw).unwrap()) + } + + /// Returns a stream of logs emitted but the container instance + pub fn logs(self) -> Result<Box<Read>> { + let query = format!("follow={}&stdout={}&stderr={}×tamps={}&tail={}", + true, + true, + true, + true, + "all"); + self.docker.stream_get(&format!("/containers/{}/logs?{}", self.id, query)[..]) + } + + /// Returns a set of changes made to the container instance + pub fn changes(self) -> Result<Vec<Change>> { + let raw = try!(self.docker.get(&format!("/containers/{}/changes", self.id)[..])); + Ok(json::decode::<Vec<Change>>(&raw).unwrap()) + } + + /// Exports the current docker container into a tarball + pub fn export(self) -> Result<Box<Read>> { + 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 = try!(self.docker.stream_get(&format!("/containers/{}/stats", self.id)[..])); + let it = jed::Iter::new(raw).into_iter().map(|j| { + let s = json::encode(&j).unwrap(); + json::decode::<Stats>(&s).unwrap() + }); + Ok(Box::new(it)) + } + + /// Start the container instance + pub fn start(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/start", self.id)[..], None).map(|_| ()) + } + + /// Stop the container instance + pub fn stop(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/stop", self.id)[..], None).map(|_| ()) + } + + /// Restart the container instance + pub fn restart(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/restart", self.id)[..], None).map(|_| ()) + } + + /// Kill the container instance + pub fn kill(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/kill", self.id)[..], None).map(|_| ()) + } + + /// Rename the container instance + pub fn rename(self, name: &str) -> Result<()> { + self.docker + .post(&format!("/containers/{}/rename?name={}", self.id, name)[..], + None) + .map(|_| ()) + } + + /// Pause the container instance + pub fn pause(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/pause", self.id)[..], None).map(|_| ()) + } + + /// Unpause the container instance + pub fn unpause(self) -> Result<()> { + self.docker.post(&format!("/containers/{}/unpause", self.id)[..], None).map(|_| ()) + } + + /// Wait until the container stops + pub fn wait(self) -> Result<Exit> { + let raw = try!(self.docker.post(&format!("/containers/{}/wait", self.id)[..], None)); + Ok(json::decode::<Exit>(&raw).unwrap()) + } + + /// Delete the container instance + pub fn delete(self) -> Result<()> { + self.docker.delete(&format!("/containers/{}", self.id)[..]).map(|_| ()) + } + + // todo attach, attach/ws, } /// Interface for docker containers pub struct Containers<'a> { - docker: &'a mut Docker + docker: &'a mut Docker, } impl<'a> Containers<'a> { - /// Exports an interface for interacting with docker containers - pub fn new(docker: &'a mut Docker) -> Containers<'a> { - Containers { docker: docker } - } - - /// Lists the container instances on the docker host - pub fn list(self) -> ContainerListBuilder<'a> { - ContainerListBuilder::new(self.docker) - } - - /// Returns a reference to a set of operations available to a specific container instance - pub fn get(&'a mut self, name: &'a str) -> Container { - Container::new(self.docker, name) - } - - /// Returns a builder interface for creating a new container instance - pub fn create(&'a mut self, image: &'a str) -> ContainerBuilder { - ContainerBuilder::new(self.docker, image) - } + /// Exports an interface for interacting with docker containers + pub fn new(docker: &'a mut Docker) -> Containers<'a> { + Containers { docker: docker } + } + + /// Lists the container instances on the docker host + pub fn list(self) -> ContainerListBuilder<'a> { + ContainerListBuilder::new(self.docker) + } + + /// Returns a reference to a set of operations available to a specific container instance + pub fn get(&'a mut self, name: &'a str) -> Container { + Container::new(self.docker, name) + } + + /// Returns a builder interface for creating a new container instance + pub fn create(&'a mut self, image: &'a str) -> ContainerBuilder { + ContainerBuilder::new(self.docker, image) + } } // https://docs.docker.com/reference/api/docker_remote_api_v1.17/ impl Docker { - /// constructs a new Docker instance for a docker host listening at a url specified by an env var `DOCKER_HOST`, - /// falling back on unix:///var/run/docker.sock - pub fn new() -> Docker { - let fallback: std::result::Result<String, VarError> = - Ok("unix:///var/run/docker.sock".to_string()); - let host = env::var("DOCKER_HOST") - .or(fallback) - .map(|h| Url::parse(&h).ok() - .expect("invalid url")) - .ok() - .expect("expected host"); - Docker::host(host) - } - - /// constructs a new Docker instance for docker host listening at the given host url - pub fn host(host: Url) -> Docker { - let domain = match host.scheme_data { - SchemeData::NonRelative(s) => s, - SchemeData::Relative(RelativeSchemeData { host, .. }) => - match host { - Host::Domain(s) => s, - Host::Ipv6(a) => a.to_string(), - Host::Ipv4(a) => a.to_string() - } - }; - match &host.scheme[..] { - "unix" => { - println!("unix.."); - Docker { - transport: Transport::Unix { - client: Client::with_connector(UnixSocketConnector), path: domain - } - } - }, - _ => { - println!("tcp..."); - let client = if let Some(ref certs) = env::var("DOCKER_CERT_PATH").ok() { - // fixme: don't unwrap before you know what's in the box - // https://github.com/hyperium/hyper/blob/master/src/net.rs#L427-L428 - let mut ssl_ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - ssl_ctx.set_cipher_list("DEFAULT").unwrap(); - let cert = &format!("{}/cert.pem", certs); - let key = &format!("{}/key.pem", certs); - let _ = ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM); - let _ = ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM); - if let Some(_) = env::var("DOCKER_TLS_VERIFY").ok() { - let ca = &format!("{}/ca.pem", certs); - let _ = ssl_ctx.set_CA_file(&Path::new(ca)); - }; - Client::with_connector(HttpsConnector::new(Openssl { context: Arc::new(ssl_ctx) })) - } else { - Client::new() + /// constructs a new Docker instance for a docker host listening at a url specified by an env var `DOCKER_HOST`, + /// falling back on unix:///var/run/docker.sock + pub fn new() -> Docker { + let fallback: std::result::Result<String, VarError> = Ok("unix:///var/run/docker.sock" + .to_owned()); + let host = env::var("DOCKER_HOST") + .or(fallback) + .map(|h| { + Url::parse(&h) + .ok() + .expect("invalid url") + }) + .ok() + .expect("expected host"); + Docker::host(host) + } + + /// constructs a new Docker instance for docker host listening at the given host url + pub fn host(host: Url) -> Docker { + let domain = match host.scheme_data { + SchemeData::NonRelative(s) => s, + SchemeData::Relative(RelativeSchemeData { host, .. }) => { + match host { + Host::Domain(s) => s, + Host::Ipv6(a) => a.to_string(), + Host::Ipv4(a) => a.to_string(), + } + } }; - Docker { transport: Transport::Tcp { client: client, host: format!("https:{}", domain.to_string()) } } - } - } - } - - /// Exports an interface for interacting with docker images - pub fn images<'a>(&'a mut self) -> Images { - Images::new(self) - } - - /// Exports an interface for interacting with docker containers - pub fn containers<'a>(&'a mut self) -> Containers { - Containers::new(self) - } - - /// Returns version information associated with the docker daemon - pub fn version(&mut self) -> Result<Version> { - let raw = try!(self.get("/version")); - Ok(json::decode::<Version>(&raw).unwrap()) - } - - /// Returns information associated with the docker daemon - pub fn info(&mut self) -> Result<Info> { - let raw = try!(self.get("/info")); - println!("{:?}", raw); - Ok(json::decode::<Info>(&raw).unwrap()) - } - - /// Returns a simple ping response indicating the docker daemon is accessible - pub fn ping(&mut self) -> Result<String> { - self.get("/_ping") - } - - /// Retruns a stream of events ocurring on the current docker host - pub fn events(&mut self) -> Events { - Events::new(self) - } - - fn get(&mut self, endpoint: &str) -> Result<String> { - self.transport.request(Method::Get, endpoint, None) - } - - fn post(&mut self, endpoint: &str, body: Option<Body>) -> Result<String> { - self.transport.request(Method::Post, endpoint, body) - } - - fn delete(&mut self, endpoint: &str) -> Result<String> { - self.transport.request(Method::Delete, endpoint, None) - } - - fn stream_post(&mut self, endpoint: &str) -> Result<Box<Read>> { - self.transport.stream(Method::Post, endpoint, None) - } - - fn stream_get(&mut self, endpoint: &str) -> Result<Box<Read>> { - self.transport.stream(Method::Get, endpoint, None) - } + match &host.scheme[..] { + "unix" => { + Docker { + transport: Transport::Unix { + client: Client::with_connector(UnixSocketConnector), + path: domain, + }, + } + } + _ => { + let client = if let Some(ref certs) = env::var("DOCKER_CERT_PATH").ok() { + // fixme: don't unwrap before you know what's in the box + // https://github.com/hyperium/hyper/blob/master/src/net.rs#L427-L428 + let mut ssl_ctx = SslContext::new(SslMethod::Sslv23).unwrap(); + ssl_ctx.set_cipher_list("DEFAULT").unwrap(); + let cert = &format!("{}/cert.pem", certs); + let key = &format!("{}/key.pem", certs); + let _ = ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM); + let _ = ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM); + if let Some(_) = env::var("DOCKER_TLS_VERIFY").ok() { + let ca = &format!("{}/ca.pem", certs); + let _ = ssl_ctx.set_CA_file(&Path::new(ca)); + }; + Client::with_connector(HttpsConnector::new(Openssl { + context: Arc::new(ssl_ctx), + })) + } else { + Client::new() + }; + Docker { + transport: Transport::Tcp { + client: client, + host: format!("https:{}", domain.to_owned()), + }, + } + } + } + } + + /// Exports an interface for interacting with docker images + pub fn images<'a>(&'a mut self) -> Images { + Images::new(self) + } + + /// Exports an interface for interacting with docker containers + pub fn containers<'a>(&'a mut self) -> Containers { + Containers::new(self) + } + + /// Returns version information associated with the docker daemon + pub fn version(&mut self) -> Result<Version> { + let raw = try!(self.get("/version")); + Ok(json::decode::<Version>(&raw).unwrap()) + } + + /// Returns information associated with the docker daemon + pub fn info(&mut self) -> Result<Info> { + let raw = try!(self.get("/info")); + Ok(json::decode::<Info>(&raw).unwrap()) + } + + /// Returns a simple ping response indicating the docker daemon is accessible + pub fn ping(&mut self) -> Result<String> { + self.get("/_ping") + } + + /// Retruns a stream of events ocurring on the current docker host + pub fn events(&mut self) -> Events { + Events::new(self) + } + + fn get(&mut self, endpoint: &str) -> Result<String> { + self.transport.request(Method::Get, endpoint, None) + } + + fn post(&mut self, endpoint: &str, body: Option<Body>) -> Result<String> { + self.transport.request(Method::Post, endpoint, body) + } + + fn delete(&mut self, endpoint: &str) -> Result<String> { |