1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::{
container::ContainerBuilder,
error::{Error::Docker as DockerError, Result},
};
use async_std::prelude::StreamExt;
use bollard::{
auth::DockerCredentials,
image::{CreateImageOptions, ListImagesOptions},
Docker,
};
use std::collections::HashMap;
#[derive(Default)]
pub struct Image {
name: String,
credentials: Option<DockerCredentials>,
}
impl Image {
pub fn new(name: &str) -> Self {
Image {
name: name.to_string(),
..Default::default()
}
}
pub fn with_credentials(self, credentials: DockerCredentials) -> Self {
self.with_optional_credentials(Some(credentials))
}
pub fn with_optional_credentials(mut self, credentials: Option<DockerCredentials>) -> Self {
self.credentials = credentials;
self
}
async fn pull_image(&self, docker: &Docker) -> Result<()> {
let filters = HashMap::from([("reference".to_string(), vec![self.name.to_string()])]);
let list_options = Some(ListImagesOptions {
filters,
..Default::default()
});
let image_list = docker.list_images(list_options).await?;
if image_list.is_empty() {
let image_options = Some(CreateImageOptions {
from_image: self.name.to_string(),
..Default::default()
});
let mut stream = docker.create_image(image_options.clone(), None, None);
let mut pull_completed = false;
while !pull_completed {
match stream.next().await {
Some(Ok(info)) => {
match info.progress {
None => println!("{}", info.status.as_ref().unwrap()),
_ => println!(
"{}: {}",
info.status.as_ref().unwrap(),
info.progress.as_ref().unwrap()
),
}
if info.status
== Some(format!(
"Status: Downloaded newer image for {}",
image_options.as_ref().unwrap().from_image
))
{
pull_completed = true;
}
}
Some(Err(error)) => {
return Err(DockerError(error));
}
_ => {
return Ok(());
}
}
}
}
Ok(())
}
pub async fn build(&self, docker: &Docker) -> Result<ContainerBuilder> {
self.pull_image(docker).await?;
Ok(ContainerBuilder::new(&self.name))
}
}