From 33e9f6480395b775c789812d6b61c13c8bd95063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edd=C3=BA=20Mel=C3=A9ndez=20Gonzales?= Date: Tue, 30 Jul 2024 14:31:37 -0500 Subject: [PATCH] Pass options to compose down command (#9040) Currently, setting options are supported for the `up` command. But, the same are not passed to the `down` command. Support for this has been added. Also, adding an example using `--profiles`. Fixes #5041 --- .../containers/ComposeCommand.java | 37 +++++++++++++++++++ .../containers/ComposeContainer.java | 3 +- .../containers/ComposeDelegate.java | 22 +---------- .../containers/DockerComposeContainer.java | 2 +- .../containers/ComposeProfilesOptionTest.java | 35 ++++++++++++++++++ .../DockerComposeProfilesOptionTest.java | 35 ++++++++++++++++++ .../compose-profile-option/compose-test.yml | 11 ++++++ 7 files changed, 122 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/org/testcontainers/containers/ComposeCommand.java create mode 100644 core/src/test/java/org/testcontainers/containers/ComposeProfilesOptionTest.java create mode 100644 core/src/test/java/org/testcontainers/containers/DockerComposeProfilesOptionTest.java create mode 100644 core/src/test/resources/compose-profile-option/compose-test.yml diff --git a/core/src/main/java/org/testcontainers/containers/ComposeCommand.java b/core/src/main/java/org/testcontainers/containers/ComposeCommand.java new file mode 100644 index 00000000000..d85f093578e --- /dev/null +++ b/core/src/main/java/org/testcontainers/containers/ComposeCommand.java @@ -0,0 +1,37 @@ +package org.testcontainers.containers; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Set; + +class ComposeCommand { + + static String getDownCommand(ComposeDelegate.ComposeVersion composeVersion, Set options) { + String composeOptions = optionsAsString(options); + if (composeOptions == null || composeOptions.equals("")) { + return composeVersion == ComposeDelegate.ComposeVersion.V1 ? "down" : "compose down"; + } + String cmd = composeVersion == ComposeDelegate.ComposeVersion.V1 ? "%s down" : "compose %s down"; + return String.format(cmd, composeOptions); + } + + static String getUpCommand(ComposeDelegate.ComposeVersion composeVersion, Set options) { + String composeOptions = optionsAsString(options); + if (composeOptions == null || composeOptions.equals("")) { + return composeVersion == ComposeDelegate.ComposeVersion.V1 ? "up -d" : "compose up -d"; + } + String cmd = composeVersion == ComposeDelegate.ComposeVersion.V1 ? "%s up -d" : "compose %s up -d"; + return String.format(cmd, composeOptions); + } + + private static String optionsAsString(final Set options) { + String optionsString = String.join(" ", options); + if (!optionsString.isEmpty()) { + // ensures that there is a space between the options and 'up' if options are passed. + return optionsString; + } else { + // otherwise two spaces would appear between 'docker-compose' and 'up' + return StringUtils.EMPTY; + } + } +} diff --git a/core/src/main/java/org/testcontainers/containers/ComposeContainer.java b/core/src/main/java/org/testcontainers/containers/ComposeContainer.java index 5add02183ae..0a804cfddb2 100644 --- a/core/src/main/java/org/testcontainers/containers/ComposeContainer.java +++ b/core/src/main/java/org/testcontainers/containers/ComposeContainer.java @@ -161,7 +161,8 @@ public void stop() { this.composeDelegate.getAmbassadorContainer().stop(); // Kill the services using docker - String cmd = "compose down"; + String cmd = ComposeCommand.getDownCommand(ComposeDelegate.ComposeVersion.V2, this.options); + if (removeVolumes) { cmd += " -v"; } diff --git a/core/src/main/java/org/testcontainers/containers/ComposeDelegate.java b/core/src/main/java/org/testcontainers/containers/ComposeDelegate.java index 0b09e9c2683..4dc396a6922 100644 --- a/core/src/main/java/org/testcontainers/containers/ComposeDelegate.java +++ b/core/src/main/java/org/testcontainers/containers/ComposeDelegate.java @@ -10,7 +10,6 @@ import lombok.NonNull; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.testcontainers.DockerClientFactory; import org.testcontainers.containers.output.OutputFrame; import org.testcontainers.containers.output.Slf4jLogConsumer; @@ -146,7 +145,7 @@ void createServices( .distinct() .collect(Collectors.joining(" ")); - String command = getUpCommand(optionsAsString(options)); + String command = ComposeCommand.getUpCommand(this.composeVersion, options); if (build) { command += " --build"; @@ -164,25 +163,6 @@ void createServices( runWithCompose(localCompose, command, env, fileCopyInclusions); } - private String getUpCommand(String options) { - if (options == null || options.equals("")) { - return this.composeVersion == ComposeVersion.V1 ? "up -d" : "compose up -d"; - } - String cmd = this.composeVersion == ComposeVersion.V1 ? "%s up -d" : "compose %s up -d"; - return String.format(cmd, options); - } - - private String optionsAsString(final Set options) { - String optionsString = options.stream().collect(Collectors.joining(" ")); - if (optionsString.length() != 0) { - // ensures that there is a space between the options and 'up' if options are passed. - return optionsString; - } else { - // otherwise two spaces would appear between 'docker-compose' and 'up' - return StringUtils.EMPTY; - } - } - void waitUntilServiceStarted(boolean tailChildContainers) { listChildContainers().forEach(container -> createServiceInstance(container, tailChildContainers)); diff --git a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java index 748c0c59174..cf78cfa4be2 100644 --- a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java +++ b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java @@ -167,7 +167,7 @@ public void stop() { this.composeDelegate.getAmbassadorContainer().stop(); // Kill the services using docker-compose - String cmd = "down"; + String cmd = ComposeCommand.getDownCommand(ComposeDelegate.ComposeVersion.V1, this.options); if (removeVolumes) { cmd += " -v"; diff --git a/core/src/test/java/org/testcontainers/containers/ComposeProfilesOptionTest.java b/core/src/test/java/org/testcontainers/containers/ComposeProfilesOptionTest.java new file mode 100644 index 00000000000..4c22024aee8 --- /dev/null +++ b/core/src/test/java/org/testcontainers/containers/ComposeProfilesOptionTest.java @@ -0,0 +1,35 @@ +package org.testcontainers.containers; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Parameterized.class) +public class ComposeProfilesOptionTest { + + @Parameterized.Parameters(name = "{0}") + public static Boolean[] local() { + return new Boolean[] { Boolean.TRUE, Boolean.FALSE }; + } + + @Parameterized.Parameter + public boolean local; + + public static final File COMPOSE_FILE = new File("src/test/resources/compose-profile-option/compose-test.yml"); + + @Test + public void testProfileOption() { + try ( + ComposeContainer compose = new ComposeContainer(COMPOSE_FILE) + .withOptions("--profile=cache") + .withLocalCompose(true) + ) { + compose.start(); + assertThat(compose.listChildContainers()).hasSize(1); + } + } +} diff --git a/core/src/test/java/org/testcontainers/containers/DockerComposeProfilesOptionTest.java b/core/src/test/java/org/testcontainers/containers/DockerComposeProfilesOptionTest.java new file mode 100644 index 00000000000..371525432bf --- /dev/null +++ b/core/src/test/java/org/testcontainers/containers/DockerComposeProfilesOptionTest.java @@ -0,0 +1,35 @@ +package org.testcontainers.containers; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Parameterized.class) +public class DockerComposeProfilesOptionTest { + + @Parameterized.Parameters(name = "{0}") + public static Boolean[] local() { + return new Boolean[] { Boolean.TRUE, Boolean.FALSE }; + } + + @Parameterized.Parameter + public boolean local; + + public static final File COMPOSE_FILE = new File("src/test/resources/compose-profile-option/compose-test.yml"); + + @Test + public void testProfileOption() { + try ( + DockerComposeContainer compose = new DockerComposeContainer<>(COMPOSE_FILE) + .withOptions("--profile=cache") + .withLocalCompose(this.local) + ) { + compose.start(); + assertThat(compose.listChildContainers()).hasSize(1); + } + } +} diff --git a/core/src/test/resources/compose-profile-option/compose-test.yml b/core/src/test/resources/compose-profile-option/compose-test.yml new file mode 100644 index 00000000000..8d85bf49967 --- /dev/null +++ b/core/src/test/resources/compose-profile-option/compose-test.yml @@ -0,0 +1,11 @@ +services: + redis: + image: redis + profiles: + - cache + db: + image: mysql:8.0.36 + environment: + MYSQL_RANDOM_ROOT_PASSWORD: "true" + profiles: + - db