Skip to content

Commit

Permalink
Support for Docker "--volume" mounts during integration tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
mars committed Oct 20, 2024
1 parent de993a4 commit c98ceb7
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
28 changes: 28 additions & 0 deletions libcnb-test/src/container_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct ContainerConfig {
pub(crate) command: Option<Vec<String>>,
pub(crate) env: HashMap<String, String>,
pub(crate) exposed_ports: HashSet<u16>,
pub(crate) volumes: Option<Vec<String>>,
}

impl ContainerConfig {
Expand Down Expand Up @@ -198,4 +199,31 @@ impl ContainerConfig {

self
}

/// Attaches container volumes. Useful for integration tests that
/// depend on persistent storage shared between container executions.
///
/// See: [Docker CLI, Mount Volume](https://docs.docker.com/reference/cli/docker/container/run/#volume)
///
/// # Example
/// ```no_run
/// use libcnb_test::{BuildConfig, ContainerConfig, TestRunner};
///
/// TestRunner::default().build(
/// BuildConfig::new("heroku/builder:22", "tests/fixtures/app"),
/// |context| {
/// // ...
/// context.start_container(
/// ContainerConfig::new().volumes(["/shared/cache:/workspace/cache"]),
/// |container| {
/// // ...
/// },
/// );
/// },
/// );
/// ```
pub fn volumes<I: IntoIterator<Item = S>, S: Into<String>>(&mut self, volumes: I) -> &mut Self {
self.volumes = Some(volumes.into_iter().map(S::into).collect());
self
}
}
19 changes: 19 additions & 0 deletions libcnb-test/src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(crate) struct DockerRunCommand {
image_name: String,
platform: Option<String>,
remove: bool,
volumes: Option<Vec<String>>,
}

impl DockerRunCommand {
Expand All @@ -27,6 +28,7 @@ impl DockerRunCommand {
image_name: image_name.into(),
platform: None,
remove: false,
volumes: None,
}
}

Expand Down Expand Up @@ -67,6 +69,14 @@ impl DockerRunCommand {
self.remove = remove;
self
}

pub(crate) fn volumes<I: IntoIterator<Item = S>, S: Into<String>>(
&mut self,
volumes: I,
) -> &mut Self {
self.volumes = Some(volumes.into_iter().map(S::into).collect());
self
}
}

impl From<DockerRunCommand> for Command {
Expand Down Expand Up @@ -98,6 +108,12 @@ impl From<DockerRunCommand> for Command {
command.args(["--publish", &format!("127.0.0.1::{port}")]);
}

if let Some(container_volumes) = docker_run_command.volumes {
command.args(container_volumes.into_iter().fold(vec![], |acc, v| {
[acc, vec!["--volume".to_string(), v]].concat()
}));
}

command.arg(docker_run_command.image_name);

if let Some(container_command) = docker_run_command.command {
Expand Down Expand Up @@ -315,6 +331,7 @@ mod tests {
docker_run_command.expose_port(55555);
docker_run_command.platform("linux/amd64");
docker_run_command.remove(true);
docker_run_command.volumes(["./.test-cache:/cache"]);

let command: Command = docker_run_command.clone().into();
assert_eq!(
Expand All @@ -337,6 +354,8 @@ mod tests {
"127.0.0.1::12345",
"--publish",
"127.0.0.1::55555",
"--volume",
"./.test-cache:/cache",
"my-image",
"echo",
"hello",
Expand Down
4 changes: 4 additions & 0 deletions libcnb-test/src/test_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ impl<'a> TestContext<'a> {
docker_run_command.expose_port(*port);
});

if let Some(volume) = &config.volumes {
docker_run_command.volumes(volume);
}

// We create the ContainerContext early to ensure the cleanup in ContainerContext::drop
// is still performed even if the Docker command panics.
let container_context = ContainerContext {
Expand Down

0 comments on commit c98ceb7

Please sign in to comment.