use std::fmt::{Display, Formatter};
use hyper_tls::native_tls::TlsConnector;
use crate::client::{DecContainer, DecContainers, DecExec, DecImages, DecNetwork, DecNetworks, DecVolume, DecVolumes};
use crate::errors::{DecCreateError, DecUseError};
use crate::imp::api::{DockerEngineApi, DockerEngineServer, SchemedUrl};
use crate::imp::http_proxy::DockerEngineHttpClient;
use crate::imp::hyper_proxy::HyperHttpClient;
use crate::model::RegistryAuth;
use crate::responses::VersionResponse;
pub const DOCKER_ENGINE_VERSION: &str = "v1.41";
#[derive(Clone, Debug)]
pub struct DockerEngineClient {
pub(super) http: DockerEngineHttpClient,
pub(super) registry_auth: Option<RegistryAuth>,
pub(super) url: DockerEngineApi
}
impl Display for DockerEngineClient {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.url)
}
}
impl DockerEngineClient {
pub fn new() -> Result<DockerEngineClient, DecCreateError> {
match crate::imp::env::docker_host() {
Some(host) => {
Self::with_server(host)
},
#[cfg(not(windows))]
None => {
Self::with_server(crate::imp::env::default_server())
}
#[cfg(windows)]
None => {
Err(DecCreateError::NamedPipesNotSupported)
}
}
}
pub fn with_registry_auth(mut self, v: RegistryAuth) -> Self {
self.registry_auth = Some(v);
self
}
pub fn with_server<U: ToString>(uri_or_unix_socket: U) -> Result<DockerEngineClient, DecCreateError> {
let server = DockerEngineServer::new(uri_or_unix_socket.to_string())?;
let hyper_client = match server.base.implied_url() {
SchemedUrl::Http(_) =>
HyperHttpClient::http(),
SchemedUrl::Https(_) => {
let tls = TlsConnector::new()?;
HyperHttpClient::https(tls)
},
#[cfg(unix)]
SchemedUrl::Unix(_) =>
HyperHttpClient::unix(),
};
let result = DockerEngineClient {
http: DockerEngineHttpClient::new(hyper_client),
registry_auth: None,
url: DockerEngineApi::new(server)
};
Ok(result)
}
pub fn with_tls_config<U: ToString>(https_url: U, tls: TlsConnector) -> Result<DockerEngineClient, DecCreateError> {
let result = DockerEngineClient {
http: DockerEngineHttpClient::new(HyperHttpClient::https(tls)),
registry_auth: None,
url: DockerEngineApi::with_server(https_url.to_string())?
};
Ok(result)
}
pub fn container<C: Into<String>>(&'_ self, name_or_id: C) -> DecContainer<'_> {
DecContainer {
client: self,
container_id: name_or_id.into()
}
}
pub fn containers(&'_ self) -> DecContainers<'_> {
DecContainers {
client: self
}
}
pub fn exec<E: Into<String>>(&'_ self, id: E) -> DecExec<'_> {
DecExec {
client: self,
exec_id: id.into()
}
}
pub fn images(&'_ self) -> DecImages<'_> {
DecImages {
client: self
}
}
pub fn network<N: Into<String>>(&'_ self, id: N) -> DecNetwork<'_> {
DecNetwork {
client: self,
network_id: id.into()
}
}
pub fn networks(&'_ self) -> DecNetworks<'_> {
DecNetworks {
client: self
}
}
pub async fn version(&self) -> Result<VersionResponse, DecUseError> {
let url = self.url.version();
self.http
.get(url)?
.execute()
.await?
.parse()
}
pub fn volume<V: Into<String>>(&'_ self, id: V) -> DecVolume<'_> {
DecVolume {
client: self,
volume_id: id.into()
}
}
pub fn volumes(&'_ self) -> DecVolumes<'_> {
DecVolumes {
client: self
}
}
}
#[cfg(test)]
mod test_docker_engine_client {
use hyper_tls::native_tls::TlsConnector;
use crate::DockerEngineClient;
#[test]
fn display_http() {
let dec = DockerEngineClient::with_server("http://foo")
.unwrap();
let actual = format!("{}", dec);
assert_eq!("Docker engine at http://foo".to_string(), actual);
}
#[test]
fn display_https() {
let tls = TlsConnector::builder()
.build()
.unwrap();
let dec = DockerEngineClient::with_tls_config("https://foo", tls)
.unwrap();
let actual = format!("{}", dec);
assert_eq!("Docker engine at https://foo".to_string(), actual);
}
#[test]
fn display_tcp() {
let dec = DockerEngineClient::with_server("tcp://foo")
.unwrap();
let actual = format!("{}", dec);
assert_eq!("Docker engine at tcp://foo".to_string(), actual);
}
#[test]
#[cfg(unix)]
fn display_unix() {
let dec = DockerEngineClient::with_server("/var/run/docker.sock")
.unwrap();
let actual = format!("{}", dec);
assert_eq!("Docker engine at /var/run/docker.sock".to_string(), actual);
}
#[test]
#[cfg(unix)]
fn display_unix_stripped() {
let dec = DockerEngineClient::with_server("unix:///var/run/docker.sock")
.unwrap();
let actual = format!("{}", dec);
assert_eq!("Docker engine at /var/run/docker.sock".to_string(), actual);
}
}