use bollard::models::CreateImageInfo;
use bollard::{image::CreateImageOptions, Docker};
use futures_util::stream::{Stream, TryStreamExt};
use futures_util::task::{Context, Poll};
use hyper::body::Body;
use std::env::args;
use std::fs::File;
use std::io::{Read, Result as IOResult};
use std::pin::Pin;
const BUFFER_SIZE: usize = 1048576;
struct FileStreamer {
file: File,
done: bool,
}
impl Stream for FileStreamer {
type Item = IOResult<Vec<u8>>;
fn poll_next(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Option<Self::Item>> {
if self.done {
return Poll::Ready(None);
}
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
match self.file.read(&mut buffer[..]) {
Ok(BUFFER_SIZE) => Poll::Ready(Some(Ok(buffer.to_vec()))),
Ok(n) => {
self.done = true;
Poll::Ready(Some(Ok(buffer[0..n].to_vec())))
}
Err(e) => Poll::Ready(Some(Err(e))),
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
let arguments: Vec<String> = args().collect();
if arguments.len() == 1 || arguments.len() > 2 {
println!("Usage: image_from_scratch <path to tar archive>");
return Ok(());
}
let file = File::open(&arguments[1]).expect("Could not find archive.");
let docker = Docker::connect_with_socket_defaults().unwrap();
let options = CreateImageOptions {
from_src: "-", repo: "bollard_image_scratch_example", tag: "1.0.0", ..Default::default()
};
let reader = FileStreamer { file, done: false };
let req_body: Body = Body::wrap_stream(reader);
let result: Vec<CreateImageInfo> = docker
.create_image(Some(options), Some(req_body), None)
.try_collect()
.await?;
dbg!(&result[0]);
Ok(())
}