diff options
author | softprops <d.tangren@gmail.com> | 2015-03-25 23:15:58 -0400 |
---|---|---|
committer | softprops <d.tangren@gmail.com> | 2015-03-25 23:15:58 -0400 |
commit | a22cc5f3204d0825ccdd86faa098c0f6ab63d30d (patch) | |
tree | 839115d64b804198aeb1a273c7533acb631f029b |
sketch
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 156 | ||||
-rw-r--r-- | Cargo.toml | 13 | ||||
-rw-r--r-- | src/lib.rs | 127 | ||||
-rw-r--r-- | src/main.rs | 10 |
5 files changed, 307 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c9cc035 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,156 @@ +[root] +name = "shiplift" +version = "0.0.1" +dependencies = [ + "hyper 0.3.2", + "openssl 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unix_socket 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cookie" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "openssl 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "httparse" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hyper" +version = "0.3.2" +dependencies = [ + "cookie 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "url 0.2.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libressl-pnacl-sys" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pnacl-build-helper 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "mime" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libressl-pnacl-sys 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pnacl-build-helper" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-serialize" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "time" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unix_socket" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..73d17c8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,13 @@ +[package] + +name = "shiplift" +version = "0.0.1" +authors = ["softprops <d.tangren@gmail.com>"] + +[dependencies.hyper] +path="/Users/dougtangren/code/rust/hyper" + +[dependencies] +openssl = "0.5.0" +unix_socket = "0.2.1" +url = "0.2.26"
\ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5ec2d6d --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,127 @@ +extern crate hyper; +extern crate openssl; +extern crate unix_socket; +extern crate url; + +use hyper::{ Client, Url }; +use hyper::method::Method; +use hyper::net::NetworkConnector; +use openssl::x509::X509FileType; +use std::io::{ Read, Write }; +use std::{ env, result }; +use std::path::Path; +use std::io::Error; +use unix_socket::UnixStream; +use url::{ Host, RelativeSchemeData, SchemeData }; + +pub type Result<T> = result::Result<T, Error>; + +trait Transport { + fn request(&mut self, method: Method, endpoint: &str) -> Result<String>; +} + +pub struct Docker { + transport: Box<Transport> +} + +impl Transport for UnixStream { + fn request(&mut self, method: Method, endpoint: &str) -> Result<String> { + let method_str = match method { + Method::Put => "PUT", + Method::Post => "POST", + Method::Delete => "DELETE", + _ => "GET" + }; + let req = format!("{} {} HTTP/1.0\r\n\r\n", method_str, endpoint); + try!(self.write_all(req.as_bytes())); + let mut result = String::new(); + self.read_to_string(&mut result).map(|_| result) + } +} + +impl<C: NetworkConnector> Transport for (Client<C>, String) { + fn request(&mut self, method: Method, endpoint: &str) -> Result<String> { + let uri = format!("{}{}", self.1, endpoint); + let req = match method { + Method::Put => self.0.put(&uri[..]), + Method::Post => self.0.post(&uri[..]), + Method::Delete => self.0.delete(&uri[..]), + _ => self.0.get(&uri[..]) + }; + let mut res = match req.send() { + Ok(r) => r, + Err(e) => panic!("failed request {:?}", e) + }; + let mut body = String::new(); + res.read_to_string(&mut body).map(|_| body) + } +} + + + +// https://docs.docker.com/reference/api/docker_remote_api_v1.17/ +impl Docker { + pub fn new() -> Docker { + let host = env::var("DOCKER_HOST") + .map(|h| Url::parse(&h).ok() + .expect("invalid url")) + .ok() + .expect("expected host"); + let domain = match host.scheme_data { + SchemeData::NonRelative(s) => s, + SchemeData::Relative(RelativeSchemeData { host: host, .. }) => + match host { + Host::Domain(s) => s, + Host::Ipv6(a) => a.to_string() + } + }; + match &host.scheme[..] { + "unix" => { + let stream = + match UnixStream::connect(domain) { + Err(_) => panic!("failed to connect to socket"), + Ok(s) => s + }; + Docker { transport: Box::new(stream) } + }, + _ => { + let mut client = Client::new(); + client.set_ssl_verifier(Box::new(|ssl_ctx| { + match env::var("DOCKER_CERT_PATH").ok() { + Some(ref certs) => { + let cert = &format!("{}/cert.pem", certs); + let key = &format!("{}/key.pem", certs); + ssl_ctx.set_certificate_file(&Path::new(cert), X509FileType::PEM); + ssl_ctx.set_private_key_file(&Path::new(key), X509FileType::PEM); + match env::var("DOCKER_TLS_VERIFY").ok() { + Some(_) => { + let ca = &format!("{}/ca.pem", certs); + ssl_ctx.set_CA_file(&Path::new(ca)); + }, _ => () + }; + () + }, _ => () + } + })); + let tup = (client, format!("https:{}", domain.to_string())); + Docker { transport: Box::new(tup) } + } + } + } + + pub fn images(&mut self) -> Result<String> { + self.get("/images/json") + } + + pub fn version(&mut self) -> Result<String> { + self.get("/version") + } + + pub fn info(&mut self) -> Result<String> { + self.get("/info") + } + + fn get(&mut self, endpoint: &str) -> Result<String> { + (*self.transport).request(Method::Get, endpoint) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..6a6ed77 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,10 @@ +extern crate shiplift; + +use shiplift::Docker; + +fn main() { + match Docker::new().info() { + Ok(e) => println!("-> {:?}", e), + Err(e) => panic!("<- {:?}", e) + }; +} |