Skip to content

Commit

Permalink
Merge pull request #369 from chordtoll/master
Browse files Browse the repository at this point in the history
Add support for the docker /containers/{}/export API endpoint
  • Loading branch information
fussybeaver authored Jan 27, 2024
2 parents ea0b79f + b7848e2 commit 8b39971
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Item = Result<Bytes, Error>> {
let url = format!("/containers/{container_name}/export");
let req = self.build_request(
&url,
Builder::new()
.method(Method::GET)
.header(CONTENT_TYPE, "application/json"),
None::<String>,
Ok(Full::new(Bytes::new())),
);
self.process_into_body(req)
}
}

#[cfg(test)]
Expand Down
45 changes: 45 additions & 0 deletions tests/container_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -888,3 +926,10 @@ fn integration_test_attach_container() {
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);
}

0 comments on commit 8b39971

Please sign in to comment.