async_docker/communicate/
docker.rs1use hyper::client::connect::Connect;
2use futures::Future;
3use hyper::rt::Stream;
4
5use errors::{Result, Error, ErrorKind};
6
7use transport::status_code;
8use transport::parse_to_trait;
9use transport::parse_to_stream;
10use communicate::util::AsSlice;
11
12use std::env;
13
14use build::{
15 EventsOptions,
16};
17
18use representation::rep::{
19 Info, Version, Event
20};
21
22use hyper::Uri;
23use hyper::StatusCode;
24use transport::interact::InteractApi;
25use transport::interact::InteractApiExt;
26use std::sync::Arc;
27use std::borrow::Cow;
28use super::tcp_docker::TcpDocker;
29#[cfg(target_os = "linux")]
30use super::unix_docker::UnixDocker;
31#[cfg(feature = "ssl")]
32use super::ssl_tcp_docker::TcpSSLDocker;
33use std::marker::PhantomData;
34use communicate::Container;
35use communicate::image::Image;
36use communicate::Images;
37use communicate::containers::Containers;
38use communicate::networks::Networks;
39use communicate::Network;
40
41
42pub trait DockerApi
44{
45 fn version(&self) -> Box<Future<Item=Version, Error=Error> + Send>;
47
48 fn info(&self) -> Box<Future<Item=Info, Error=Error> + Send>;
50
51 fn ping(&self) -> Box<Future<Item=StatusCode, Error=Error> + Send>;
53
54 fn events(&self, opts: &EventsOptions) -> Box<Stream<Item=Result<Event>, Error=Error> + Send>;
56
57 fn container(&self, id: Cow<'static, str>) -> Container;
59
60 fn containers(&self) -> Containers;
62
63 fn image<'a>(&self, id: Cow<'a, str>) -> Image<'a>;
65
66 fn images(&self) -> Images;
68
69 fn network<'a>(&self, id: Cow<'a, str>) -> Network<'a>;
71
72 fn networks(&self) -> Networks;
74}
75
76pub(crate) struct Docker<C>
77 where C: Connect + 'static
78{
79 interact: Arc<InteractApi>,
80 phantom: PhantomData<C>,
81}
82
83impl <C> Docker<C>
84 where C: Connect + 'static
85{
86 pub(super) fn new_inner(interact: Arc<InteractApi>) -> Self
87 {
88 Self {
89 interact,
90 phantom: PhantomData
91 }
92 }
93}
94
95impl <C> DockerApi for Docker<C>
96 where C: Connect + 'static
97{
98 fn version(&self) -> Box<Future<Item=Version, Error=Error> + Send> {
99 let arg = "/version";
100
101 Box::new(parse_to_trait::<Version>(self.interact.get(arg)))
102 }
103
104 fn info(&self) -> Box<Future<Item=Info, Error=Error> + Send> {
105 let arg = "/info";
106
107 Box::new(parse_to_trait::<Info>(self.interact.get(arg)))
108 }
109
110 fn ping(&self) -> Box<Future<Item=StatusCode, Error=Error> + Send> {
111 let arg = "/_ping";
112
113 Box::new(status_code(self.interact.get(arg)))
114 }
115
116 fn events(&self, opts: &EventsOptions) -> Box<Stream<Item=Result<Event>, Error=Error> + Send> {
117 let query = opts.serialize();
118 let arg = ("/events", query.as_slice());
119
120 Box::new(parse_to_stream::<Event>(self.interact.get(arg)))
121 }
122
123 fn container(&self, id: Cow<'static, str>) -> Container
124 {
125 let interact = self.interact.clone();
126 Container::new(interact, id)
127 }
128
129 fn containers(&self) -> Containers
130 {
131 let interact = self.interact.clone();
132 Containers::new(interact)
133 }
134
135 fn image<'a>(&self, id: Cow<'a, str>) -> Image<'a>
136 {
137 let interact = self.interact.clone();
138 Image::new(interact, id)
139 }
140
141 fn images(&self) -> Images
142 {
143 let interact = self.interact.clone();
144 Images::new(interact)
145 }
146
147 fn network<'a>(&self, id: Cow<'a, str>) -> Network<'a>
148 {
149 let interact = self.interact.clone();
150 Network::new(interact, id)
151 }
152
153 fn networks(&self) -> Networks
154 {
155 let interact = self.interact.clone();
156 Networks::new(interact)
157 }
158}
159
160fn default_uri(uri: Option<Uri>) -> Result<Uri> {
161 use communicate::util::{URI_ENV, DEFAULT_URI};
162 match uri {
163 None => match env::var(URI_ENV) {
164 Ok(var) => var.parse().map_err(Error::from),
165 Err(_) => DEFAULT_URI.parse().map_err(Error::from),
166 },
167 Some(x) => Ok(x)
168 }
169}
170
171pub fn new_docker(host: Option<Uri>) -> Result<Box<DockerApi>>
173{
174 let host = default_uri(host)?;
175 let scheme = host.scheme_part().map(|a| a.as_str().to_string());
176 match scheme.as_slice() {
177 Some(scheme) => match scheme {
178 #[cfg(target_os = "linux")]
179 "unix" => UnixDocker::new(host),
180 #[cfg(feature = "ssl")]
181 "https" => TcpSSLDocker::new(host),
182 "http" => TcpDocker::new(host),
183 _ => Err(ErrorKind::InvalidScheme.into()),
184 }
185 None => Err(ErrorKind::EmptyScheme.into())
186 }
187}