use crate::{
models,
opts::{
ClearCacheOpts, ImageBuildOpts, ImageListOpts, ImagePruneOpts, ImagePushOpts,
ImageRemoveOpts, PullOpts, TagOpts,
},
};
use std::io::Read;
use futures_util::{stream::Stream, TryFutureExt, TryStreamExt};
use containers_api::{
conn::{Headers, Payload, AUTH_HEADER},
tarball,
url::{construct_ep, encoded_pair, encoded_pairs},
};
use crate::Result;
impl_api_ty!(Image => name);
impl Image {
impl_api_ep! {img: Image, resp
Inspect -> &format!("/images/{}/json", img.name), rs_docker_api_stubs::models::ImageInspect
}
api_doc! { Image => Delete
|
pub async fn remove(&self, opts: &ImageRemoveOpts) -> Result<Vec<rs_docker_api_stubs::models::ImageDeleteResponseItem>> {
let ep =
containers_api::url::construct_ep(format!("/images/{}", self.name), opts.serialize());
self.docker.delete_json(ep.as_ref()).await
}}
api_doc! { Image => Delete
|
pub async fn delete(&self) -> Result<Vec<rs_docker_api_stubs::models::ImageDeleteResponseItem>> {
self.docker
.delete_json(&format!("/images/{}", self.name))
.await
}}
api_doc! { Image => History
|
pub async fn history(&self) -> Result<rs_docker_api_stubs::models::ImageHistory200Response> {
self.docker
.get_json(&format!("/images/{}/history", self.name))
.await
}}
api_doc! { Image => Get
|
pub fn export(&self) -> impl Stream<Item = Result<Vec<u8>>> + Unpin + '_ {
Box::pin(
self.docker
.get_stream(format!("/images/{}/get", self.name))
.map_ok(|c| c.to_vec()),
)
}}
api_doc! { Image => Tag
|
pub async fn tag(&self, opts: &TagOpts) -> Result<()> {
let ep = construct_ep(format!("/images/{}/tag", self.name), opts.serialize());
self.docker
.post_string(&ep, Payload::empty(), Headers::none())
.await
.map(|_| ())
}}
api_doc! { Image => Push
|
pub async fn push(&self, opts: &ImagePushOpts) -> Result<()> {
let ep = construct_ep(format!("/images/{}/push", self.name), opts.serialize());
let headers = opts
.auth_header()
.map(|auth| Headers::single(AUTH_HEADER, auth))
.unwrap_or_else(Headers::default);
self.docker
.post_string(&ep, Payload::empty(), Some(headers))
.await
.map(|_| ())
}}
api_doc! { Distribution => Inspect
|
pub async fn distribution_inspect(&self) -> Result<rs_docker_api_stubs::models::DistributionInspect> {
self.docker
.post_json(
&format!("/distribution/{}/json", self.name),
Payload::empty(),
Headers::none(),
)
.await
}}
}
impl Images {
impl_api_ep! {img: Image, resp
List -> "/images/json", rs_docker_api_stubs::models::ImageSummary
Prune -> "/images/prune", rs_docker_api_stubs::models::ImagePrune200Response
}
api_doc! { Image => Build
|
pub fn build<'docker>(
&'docker self,
opts: &ImageBuildOpts,
) -> impl Stream<Item = Result<models::ImageBuildChunk>> + Unpin + 'docker {
let ep = construct_ep("/build", opts.serialize());
let mut bytes = vec![];
let tar_result = tarball::dir(&mut bytes, &opts.path);
let docker = &self.docker;
Box::pin(
async move {
tar_result?;
let value_stream =
docker.post_into_stream(ep, Payload::Tar(bytes), Headers::none());
Ok(value_stream)
}
.try_flatten_stream(),
)
}}
api_doc! { Image => Build
|
#[cfg(feature = "par-compress")]
pub fn build_par<'docker>(
&'docker self,
opts: &ImageBuildOpts,
) -> impl Stream<Item = Result<models::ImageBuildChunk>> + Unpin + 'docker {
let ep = construct_ep("/build", opts.serialize());
let tar_result = tarball::dir_par(&opts.path);
let docker = &self.docker;
Box::pin(
async move {
let bytes = tar_result?;
let value_stream =
docker.post_into_stream(ep, Payload::Tar(bytes), Headers::none());
Ok(value_stream)
}
.try_flatten_stream(),
)
}}
api_doc! { Image => Search
|
pub async fn search<T>(&self, term: T) -> Result<rs_docker_api_stubs::models::ImageSearch200Response>
where
T: AsRef<str>,
{
self.docker
.get_json(&construct_ep(
"/images/search",
Some(encoded_pair("term", term.as_ref())),
))
.await
}}
api_doc! { Image => Pull
|
pub fn pull<'docker>(
&'docker self,
opts: &PullOpts,
) -> impl Stream<Item = Result<models::ImageBuildChunk>> + Unpin + 'docker {
let headers = opts.auth_header().map(|a| Headers::single(AUTH_HEADER, a));
Box::pin(self.docker.post_into_stream(
construct_ep("/images/create", opts.serialize()),
Payload::empty(),
headers,
))
}}
api_doc! { Image => GetAll
|
pub fn export<'docker>(
&'docker self,
names: Vec<&str>,
) -> impl Stream<Item = Result<Vec<u8>>> + 'docker {
self.docker
.get_stream(format!(
"/images/get?{}",
encoded_pairs(names.iter().map(|n| ("names", *n)))
))
.map_ok(|c| c.to_vec())
}}
api_doc! { Image => Load
|
pub fn import<'docker, R>(
&'docker self,
mut tarball: R,
) -> impl Stream<Item = Result<models::ImageBuildChunk>> + Unpin + 'docker
where
R: Read + Send + 'docker,
{
Box::pin(
async move {
let mut bytes = Vec::default();
tarball.read_to_end(&mut bytes)?;
let value_stream = self.docker.post_into_stream(
"/images/load",
Payload::Tar(bytes),
Headers::none(),
);
Ok(value_stream)
}
.try_flatten_stream(),
)
}}
api_doc! { Image => Push
|
pub async fn push(&self, name: impl Into<crate::Id>, opts: &ImagePushOpts) -> Result<()> {
let image = Image::new(self.docker.clone(), name);
image.push(opts).await
}}
api_doc! { Build => Prune
|
pub async fn clear_cache(
&self,
opts: &ClearCacheOpts,
) -> Result<rs_docker_api_stubs::models::BuildPrune200Response> {
self.docker
.post_json(
construct_ep("/build/prune", opts.serialize()),
Payload::empty(),
Headers::none(),
)
.await
}}
}