From 537f0be2a027bea56f02cd166cf945ceb0c66757 Mon Sep 17 00:00:00 2001 From: chordtoll Date: Sat, 27 Jan 2024 00:51:26 -0800 Subject: [PATCH 1/2] Add support for the docker /containers/{}/export API endpoint --- src/container.rs | 29 +++++++++++++++++++++++++++ tests/container_test.rs | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/src/container.rs b/src/container.rs index 767c7380..68b03928 100644 --- a/src/container.rs +++ b/src/container.rs @@ -2234,6 +2234,35 @@ impl Docker { self.process_into_body(req) } + + /// --- + /// + /// # Export Container + /// + /// Get a tarball containing the filesystem contents of a container. + /// + /// See the [Docker API documentation](https://docs.docker.com/engine/api/v1.40/#operation/ContainerExport) + /// for more information. + /// # Arguments + /// - The `container_name` string referring to an individual container + /// + /// # Returns + /// - An uncompressed TAR archive + pub fn export_container( + &self, + container_name: &str, + ) -> impl Stream> { + let url = format!("/containers/{container_name}/export"); + let req = self.build_request( + &url, + Builder::new() + .method(Method::GET) + .header(CONTENT_TYPE, "application/json"), + None::, + Ok(Full::new(Bytes::new())), + ); + self.process_into_body(req) + } } #[cfg(test)] diff --git a/tests/container_test.rs b/tests/container_test.rs index 9a7b0f75..bbc0bbc2 100644 --- a/tests/container_test.rs +++ b/tests/container_test.rs @@ -12,10 +12,13 @@ use bollard::image::{CreateImageOptions, PushImageOptions, TagImageOptions}; use bollard::models::*; use bollard::Docker; +use futures_util::future::ready; use futures_util::stream::TryStreamExt; +use futures_util::StreamExt; use tokio::io::AsyncWriteExt; use tokio::runtime::Runtime; +use std::fs::{remove_file, File}; use std::io::Write; #[macro_use] @@ -798,6 +801,41 @@ async fn mount_volume_container_test(docker: Docker) -> Result<(), Error> { Ok(()) } +async fn export_container_test(docker: Docker) -> Result<(), Error> { + create_image_hello_world(&docker).await?; + + let temp_file = if cfg!(windows) { + "C:\\Users\\appveyor\\Appdata\\Local\\Temp\\bollard_test_container_export.tar" + } else { + "/tmp/bollard_test_container_export.tar" + }; + + create_container_hello_world(&docker, "integration_test_export_container").await?; + let res = docker.export_container("integration_test_export_container"); + + let mut archive_file = File::create(temp_file).unwrap(); + // Shouldn't load the whole file into memory, stream it to disk instead + res.for_each(move |data| { + archive_file.write_all(&data.unwrap()).unwrap(); + archive_file.sync_all().unwrap(); + ready(()) + }) + .await; + + docker + .remove_container("integration_test_export_container", None) + .await?; + + // assert that the file containg the exported archive actually exists + let test_file = File::open(temp_file).unwrap(); + // and metadata can be read + test_file.metadata().unwrap(); + + // And delete it to clean up + remove_file(temp_file).unwrap(); + Ok(()) +} + #[test] fn integration_test_list_containers() { connect_to_docker_and_run!(list_containers_test); @@ -888,3 +926,8 @@ fn integration_test_attach_container() { fn integration_test_resize_container_tty() { connect_to_docker_and_run!(resize_container_test); } + +#[test] +fn integration_test_export_container() { + connect_to_docker_and_run!(export_container_test); +} From b7848e2613e32de4d1dc2a7f60e981e9a6e6c87d Mon Sep 17 00:00:00 2001 From: chordtoll Date: Sat, 27 Jan 2024 01:09:35 -0800 Subject: [PATCH 2/2] doesn't work on windows, gate integration test by platform --- tests/container_test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/container_test.rs b/tests/container_test.rs index bbc0bbc2..a251152a 100644 --- a/tests/container_test.rs +++ b/tests/container_test.rs @@ -927,7 +927,9 @@ fn integration_test_resize_container_tty() { connect_to_docker_and_run!(resize_container_test); } +// note: container exports aren't supported on Windows #[test] +#[cfg(not(windows))] fn integration_test_export_container() { connect_to_docker_and_run!(export_container_test); }