Skip to content

Commit

Permalink
DockerComposeContainer: add 'removeVolumes' parameter (#7009)
Browse files Browse the repository at this point in the history
Closes #7008 


Co-authored-by: Eddú Meléndez <[email protected]>
  • Loading branch information
daniel-odrinski and eddumelendez authored May 12, 2023
1 parent 31430f6 commit 5b9c639
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ public class DockerComposeContainer<SELF extends DockerComposeContainer<SELF>>

private RemoveImages removeImages;

private boolean removeVolumes = true;

@Deprecated
public DockerComposeContainer(File composeFile, String identifier) {
this(identifier, composeFile);
Expand Down Expand Up @@ -368,7 +370,11 @@ public void stop() {
ambassadorContainer.stop();

// Kill the services using docker-compose
String cmd = "down -v";
String cmd = "down";

if (removeVolumes) {
cmd += " -v";
}
if (removeImages != null) {
cmd += " --rmi " + removeImages.dockerRemoveImagesType();
}
Expand Down Expand Up @@ -600,6 +606,17 @@ public SELF withRemoveImages(RemoveImages removeImages) {
return self();
}

/**
* Remove volumes after containers shut down.
*
* @param removeVolumes whether volumes are to be removed.
* @return this instance, for chaining.
*/
public SELF withRemoveVolumes(boolean removeVolumes) {
this.removeVolumes = removeVolumes;
return self();
}

/**
* Set the maximum startup timeout all the waits set are bounded to.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package org.testcontainers.junit;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.DockerComposeContainer;

import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

@RunWith(Parameterized.class)
public class DockerComposeContainerVolumeRemovalTest {

public DockerComposeContainerVolumeRemovalTest(
final boolean removeVolumes,
final boolean shouldVolumesBePresentAfterRunning
) {
this.removeVolumes = removeVolumes;
this.shouldVolumesBePresentAfterRunning = shouldVolumesBePresentAfterRunning;
}

public final boolean removeVolumes;

public final boolean shouldVolumesBePresentAfterRunning;

@Parameterized.Parameters(name = "removeVolumes = {0}")
public static Object[][] params() {
return new Object[][] { { true, false }, { false, true } };
}

@Test
public void performTest() {
final File composeFile = new File("src/test/resources/compose-test.yml");

final AtomicReference<String> volumeName = new AtomicReference<>("");
try (
DockerComposeContainer environment = new DockerComposeContainer<>(composeFile)
.withExposedService("redis", 6379)
.withRemoveVolumes(this.removeVolumes)
.withRemoveImages(DockerComposeContainer.RemoveImages.ALL)
) {
environment.start();

volumeName.set(volumeNameForRunningContainer("_redis_1"));
final boolean isVolumePresentWhileRunning = isVolumePresent(volumeName.get());
assertThat(isVolumePresentWhileRunning).as("the container volume is present while running").isEqualTo(true);
}

await()
.untilAsserted(() -> {
final boolean isVolumePresentAfterRunning = isVolumePresent(volumeName.get());
assertThat(isVolumePresentAfterRunning)
.as("the container volume is present after running")
.isEqualTo(this.shouldVolumesBePresentAfterRunning);
});
}

private String volumeNameForRunningContainer(final String containerNameSuffix) {
return DockerClientFactory
.instance()
.client()
.listContainersCmd()
.exec()
.stream()
.filter(it -> Stream.of(it.getNames()).anyMatch(name -> name.endsWith(containerNameSuffix)))
.findFirst()
.map(container -> container.getMounts().get(0).getName())
.orElseThrow(IllegalStateException::new);
}

private boolean isVolumePresent(final String volumeName) {
Set<String> nameFilter = new LinkedHashSet<>(1);
nameFilter.add(volumeName);
return DockerClientFactory
.instance()
.client()
.listVolumesCmd()
.withFilter("name", nameFilter)
.exec()
.getVolumes()
.stream()
.findFirst()
.isPresent();
}
}

0 comments on commit 5b9c639

Please sign in to comment.