summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsoftprops <d.tangren@gmail.com>2016-01-03 18:06:21 -0500
committersoftprops <d.tangren@gmail.com>2016-01-03 18:06:21 -0500
commit455a1482d92a26e109ccb0b723136c09bb4eff2e (patch)
tree3d3044f439df69315bf15b4be700acf0044a5e4d
parent00b269ffcfcbacd2c32fbdfe98e916f5260c8349 (diff)
migrate builder interfaces into interfaces that just build options to improve testability
-rw-r--r--examples/containers.rs8
-rw-r--r--examples/events.rs2
-rw-r--r--examples/info.rs2
-rw-r--r--src/builder.rs127
-rw-r--r--src/lib.rs31
5 files changed, 97 insertions, 73 deletions
diff --git a/examples/containers.rs b/examples/containers.rs
index e4df6b3..60990a4 100644
--- a/examples/containers.rs
+++ b/examples/containers.rs
@@ -1,15 +1,11 @@
extern crate shiplift;
-use shiplift::{ContainerFilter, Docker};
+use shiplift::Docker;
fn main() {
let docker = Docker::new();
for c in docker.containers().
- list()
- .sized()
- .filter(vec![
- ContainerFilter::Label("foo".to_owned(), "bar".to_owned())
- ]).build().unwrap() {
+ list(&Default::default()).unwrap() {
println!("container -> {:?}", c)
}
}
diff --git a/examples/events.rs b/examples/events.rs
index 8e70f70..f1518d3 100644
--- a/examples/events.rs
+++ b/examples/events.rs
@@ -5,7 +5,7 @@ use shiplift::Docker;
fn main() {
let docker = Docker::new();
println!("listening for events");
- for e in docker.events().build().unwrap() {
+ for e in docker.events(&Default::default()).unwrap() {
println!("event -> {:?}", e)
}
}
diff --git a/examples/info.rs b/examples/info.rs
index 85f2128..c3ad9d6 100644
--- a/examples/info.rs
+++ b/examples/info.rs
@@ -3,6 +3,6 @@ extern crate shiplift;
use shiplift::Docker;
fn main() {
- let mut docker = Docker::new();
+ let docker = Docker::new();
println!("info {:?}", docker.info().unwrap());
}
diff --git a/src/builder.rs b/src/builder.rs
index de83b6a..8df0d12 100644
--- a/src/builder.rs
+++ b/src/builder.rs
@@ -6,18 +6,32 @@ extern crate url;
use self::super::{Docker, Result};
use self::super::transport::Body;
-use self::super::rep::{ContainerCreateInfo, Event};
-use self::super::rep::Container as ContainerRep;
+use self::super::rep::ContainerCreateInfo;
use std::collections::{BTreeMap, HashMap};
use rustc_serialize::json::{self, Json, ToJson};
use url::form_urlencoded;
-/// Interface for building container list request
-pub struct ContainerListBuilder<'a> {
- docker: &'a Docker,
- params: HashMap<&'static str, String>,
+#[derive(Default)]
+pub struct ContainerListOptions {
+ params: HashMap<&'static str, String>
}
+impl ContainerListOptions {
+ /// return a new instance of a builder for options
+ pub fn builder() -> ContainerListOptionsBuilder {
+ ContainerListOptionsBuilder::new()
+ }
+
+ /// serialize options as a string. returns None if no options are defined
+ pub fn serialize(&self) -> Option<String> {
+ if self.params.is_empty() { None }
+ else {
+ Some(form_urlencoded::serialize(&self.params))
+ }
+ }
+}
+
+/// Filter options for container listings
pub enum ContainerFilter {
ExitCode(u64),
Status(String),
@@ -25,15 +39,20 @@ pub enum ContainerFilter {
Label(String, String)
}
-impl<'a> ContainerListBuilder<'a> {
- pub fn new(docker: &'a Docker) -> ContainerListBuilder<'a> {
- ContainerListBuilder {
- docker: docker,
- params: HashMap::new(),
+/// Interface for building container list request
+#[derive(Default)]
+pub struct ContainerListOptionsBuilder {
+ params: HashMap<&'static str, String>,
+}
+
+impl ContainerListOptionsBuilder {
+ pub fn new() -> ContainerListOptionsBuilder {
+ ContainerListOptionsBuilder {
+ ..Default::default()
}
}
- pub fn filter(&mut self, filters: Vec<ContainerFilter>) -> &mut ContainerListBuilder<'a> {
+ pub fn filter(&mut self, filters: Vec<ContainerFilter>) -> &mut ContainerListOptionsBuilder {
let mut param = HashMap::new();
for f in filters {
match f {
@@ -50,34 +69,30 @@ impl<'a> ContainerListBuilder<'a> {
self
}
- pub fn all(&mut self) -> &mut ContainerListBuilder<'a> {
+ pub fn all(&mut self) -> &mut ContainerListOptionsBuilder {
self.params.insert("all", "true".to_owned());
self
}
- pub fn since(&mut self, since: &str) -> &mut ContainerListBuilder<'a> {
+ pub fn since(&mut self, since: &str) -> &mut ContainerListOptionsBuilder {
self.params.insert("since", since.to_owned());
self
}
- pub fn before(&mut self, before: &str) -> &mut ContainerListBuilder<'a> {
+ pub fn before(&mut self, before: &str) -> &mut ContainerListOptionsBuilder {
self.params.insert("before", before.to_owned());
self
}
- pub fn sized(&mut self) -> &mut ContainerListBuilder<'a> {
+ pub fn sized(&mut self) -> &mut ContainerListOptionsBuilder {
self.params.insert("size", "true".to_owned());
self
}
- pub fn build(&self) -> Result<Vec<ContainerRep>> {
- let mut path = vec!["/containers/json".to_owned()];
- if !self.params.is_empty() {
- let encoded = form_urlencoded::serialize(&self.params);
- path.push(encoded)
+ pub fn build(&self) -> ContainerListOptions {//Result<Vec<ContainerRep>> {
+ ContainerListOptions {
+ params: self.params.clone()
}
- let raw = try!(self.docker.get(&path.join("?")));
- Ok(try!(json::decode::<Vec<ContainerRep>>(&raw)))
}
}
@@ -124,54 +139,52 @@ impl<'a, 'b> ContainerBuilder<'a, 'b> {
}
}
+#[derive(Default)]
+pub struct EventsOptions {
+ params: HashMap<&'static str, String>
+}
+
+impl EventsOptions {
+ pub fn builder() -> EventsOptionsBuilder {
+ EventsOptionsBuilder::new()
+ }
+
+ pub fn serialize(&self) -> Option<String> {
+ if self.params.is_empty() { None }
+ else {
+ Some(form_urlencoded::serialize(&self.params))
+ }
+ }
+}
+
/// Interface for buiding an events request
-pub struct EventsBuilder<'a, 'b, 'c> {
- docker: &'a Docker,
- since: Option<&'b u64>,
- until: Option<&'c u64>,
+#[derive(Default)]
+pub struct EventsOptionsBuilder {
+ params: HashMap<&'static str, String>
}
-impl<'a, 'b, 'c> EventsBuilder<'a, 'b, 'c> {
- pub fn new(docker: &'a Docker) -> EventsBuilder<'a, 'b, 'c> {
- EventsBuilder {
- docker: docker,
- since: None,
- until: None,
+impl EventsOptionsBuilder {
+ pub fn new() -> EventsOptionsBuilder {
+ EventsOptionsBuilder {
+ ..Default::default()
}
}
/// Filter events since a given timestamp
- pub fn since(&mut self, ts: &'b u64) -> &mut EventsBuilder<'a, 'b, 'c> {
- self.since = Some(ts);
+ pub fn since(&mut self, ts: &u64) -> &mut EventsOptionsBuilder {
+ self.params.insert("since", ts.to_string());
self
}
/// Filter events until a given timestamp
- pub fn until(&mut self, ts: &'c u64) -> &mut EventsBuilder<'a, 'b, 'c> {
- self.until = Some(ts);
+ pub fn until(&mut self, ts: &u64) -> &mut EventsOptionsBuilder {
+ self.params.insert("until", ts.to_string());
self
}
- /// Returns an interator over streamed docker events
- pub fn build(&self) -> Result<Box<Iterator<Item = Event>>> {
- let mut params = Vec::new();
- if let Some(s) = self.since {
- params.push(("since", s.to_string()));
- }
- if let Some(u) = self.until {
- params.push(("until", u.to_string()));
- }
- let mut path = vec!["/events".to_owned()];
- if !params.is_empty() {
- let encoded = form_urlencoded::serialize(params);
- path.push(encoded)
+ pub fn build(&self) -> EventsOptions {
+ EventsOptions {
+ params: self.params.clone()
}
- let raw = try!(self.docker.stream_get(&path.join("?")[..]));
- let it = jed::Iter::new(raw).into_iter().map(|j| {
- // fixme: better error handling
- let s = json::encode(&j).unwrap();
- json::decode::<Event>(&s).unwrap()
- });
- Ok(Box::new(it))
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 95743bb..b347a53 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -26,9 +26,9 @@ pub mod transport;
pub mod errors;
pub use errors::Error;
-pub use builder::ContainerFilter;
+pub use builder::{ContainerListOptions, ContainerFilter, EventsOptions};
-use builder::{ContainerBuilder, ContainerListBuilder, EventsBuilder};
+use builder::ContainerBuilder;
use hyper::{Client, Url};
use hyper::net::{HttpsConnector, Openssl};
use hyper::method::Method;
@@ -36,7 +36,7 @@ use hyperlocal::UnixSocketConnector;
use openssl::x509::X509FileType;
use openssl::ssl::{SslContext, SslMethod};
use rep::Image as ImageRep;
-use rep::{Change, ContainerDetails, Exit, History, ImageDetails, Info, SearchResult, Stats,
+use rep::{Change, ContainerDetails, Container as ContainerRep, Event, Exit, History, ImageDetails, Info, SearchResult, Stats,
Status, Top, Version};
use rustc_serialize::json::{self, Json};
use std::env::{self, VarError};
@@ -283,8 +283,13 @@ impl<'a> Containers<'a> {
}
/// Lists the container instances on the docker host
- pub fn list(&self) -> ContainerListBuilder<'a> {
- ContainerListBuilder::new(self.docker)
+ pub fn list(&self, opts: &ContainerListOptions) -> Result<Vec<ContainerRep>> {
+ let mut path = vec!["/containers/json".to_owned()];
+ if let Some(query) = opts.serialize() {
+ path.push(query)
+ }
+ let raw = try!(self.docker.get(&path.join("?")));
+ Ok(try!(json::decode::<Vec<ContainerRep>>(&raw)))
}
/// Returns a reference to a set of operations available to a specific container instance
@@ -395,9 +400,19 @@ impl Docker {
self.get("/_ping")
}
- /// Retruns a stream of events ocurring on the current docker host
- pub fn events(&self) -> EventsBuilder {
- EventsBuilder::new(self)
+ /// Returns an interator over streamed docker events
+ pub fn events(&self, opts: &EventsOptions) -> Result<Box<Iterator<Item = Event>>> {
+ let mut path = vec!["/events".to_owned()];
+ if let Some(query) = opts.serialize() {
+ path.push(query);
+ }
+ let raw = try!(self.stream_get(&path.join("?")[..]));
+ let it = jed::Iter::new(raw).into_iter().map(|j| {
+ // fixme: better error handling
+ let s = json::encode(&j).unwrap();
+ json::decode::<Event>(&s).unwrap()
+ });
+ Ok(Box::new(it))
}
fn get(&self, endpoint: &str) -> Result<String> {