async_docker/communicate/
docker.rs

1use 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
42/// Entry point interface for communicating with docker daemon
43pub trait DockerApi
44{
45    /// Returns version information associated with the docker daemon
46    fn version(&self) -> Box<Future<Item=Version, Error=Error> + Send>;
47
48    /// Returns information associated with the docker daemon
49    fn info(&self) -> Box<Future<Item=Info, Error=Error> + Send>;
50
51    /// Returns a simple ping response indicating the docker daemon is accessible
52    fn ping(&self) -> Box<Future<Item=StatusCode, Error=Error> + Send>;
53
54    /// Returns an iterator over streamed docker events
55    fn events(&self, opts: &EventsOptions) -> Box<Stream<Item=Result<Event>, Error=Error> + Send>;
56
57    /// Exports an interface for interacting with docker container
58    fn container(&self, id: Cow<'static, str>) -> Container;
59
60    /// Exports an interface for interacting with docker containers
61    fn containers(&self) -> Containers;
62
63    /// Exports an interface for interacting with docker image
64    fn image<'a>(&self, id: Cow<'a, str>) -> Image<'a>;
65
66    /// Exports an interface for interacting with images
67    fn images(&self) -> Images;
68
69    /// Exports an interface for interacting with network
70    fn network<'a>(&self, id: Cow<'a, str>) -> Network<'a>;
71
72    /// Exports an interface for interacting with networks
73    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
171/// Creates the docker struct relevant to the provided Uri
172pub 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}