From 77251a17dad3ee3aa6017229f856d46a4a8689b8 Mon Sep 17 00:00:00 2001 From: Gapmeister66 Date: Mon, 14 Sep 2020 20:30:02 +0100 Subject: [PATCH] Add support for Docker compose `withOptions(...)` (#2827) Co-authored-by: Peter Lewis Co-authored-by: Richard North --- .../containers/DockerComposeContainer.java | 27 +++++++- ...DockerComposeContainerWithOptionsTest.java | 62 +++++++++++++++++++ .../with-deploy-block.yml | 8 +++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java create mode 100644 core/src/test/resources/compose-options-test/with-deploy-block.yml diff --git a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java index d2702b3db5b..bd06083644d 100644 --- a/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java +++ b/core/src/main/java/org/testcontainers/containers/DockerComposeContainer.java @@ -45,6 +45,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -81,6 +82,7 @@ public class DockerComposeContainer> e private boolean localCompose; private boolean pull = true; private boolean build = false; + private Set options = new HashSet<>(); private boolean tailChildContainers; private String project; @@ -213,7 +215,7 @@ private void createServices() { .distinct() .collect(joining(" ")); - String command = "up -d"; + String command = optionsAsString() + "up -d"; if (build) { command += " --build"; @@ -231,6 +233,19 @@ private void createServices() { runWithCompose(command); } + private String optionsAsString() { + String optionsString = options + .stream() + .collect(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; + } + } + private void waitUntilServiceStarted() { listChildContainers().forEach(this::createServiceInstance); @@ -517,6 +532,16 @@ public SELF withBuild(boolean build) { return self(); } + /** + * Adds options to the docker-compose command, e.g. docker-compose --compatibility. + * + * @return this instance, for chaining + */ + public SELF withOptions(String... options) { + this.options = new HashSet<>(Arrays.asList(options)); + return self(); + } + /** * Remove images after containers shutdown. * diff --git a/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java new file mode 100644 index 00000000000..375c9baa070 --- /dev/null +++ b/core/src/test/java/org/testcontainers/junit/DockerComposeContainerWithOptionsTest.java @@ -0,0 +1,62 @@ +package org.testcontainers.junit; + +import com.google.common.collect.ImmutableSet; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.testcontainers.containers.DockerComposeContainer; + +import java.io.File; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests the options associated with the docker-compose command. + */ +@RunWith(Parameterized.class) +public class DockerComposeContainerWithOptionsTest { + + public DockerComposeContainerWithOptionsTest(final File composeFile, final boolean local, final Set options, final boolean expectError) { + this.composeFile = composeFile; + this.local = local; + this.options = options; + this.expectError = expectError; + } + + private final File composeFile; + private final boolean local; + + private final Set options; + private final boolean expectError; + + @Parameterized.Parameters(name = "docker-compose test [compose file: {0}, local: {1}, options: {2}, expected result: {3}]") + + public static Object[][] params() { + return new Object[][]{ + // Test the happy day case. THe compatibility option should be accepted by docker-compose. + {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of("--compatibility"), false}, + // Test with flags absent. Docker compose will warn but continue, ignoring the deploy block. + {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of(""), false}, + // Test with a bad option. Compose will complain. + {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), false, ImmutableSet.of("--bad-option"), true}, + // Local compose + {new File("src/test/resources/compose-options-test/with-deploy-block.yml"), true, ImmutableSet.of("--compatibility"), false}, + }; + } + + @Test + public void performTest() { + + try (DockerComposeContainer environment = new DockerComposeContainer<>(composeFile) + .withOptions(options.stream().toArray(String[]::new)) + .withLocalCompose(local)) { + environment.start(); + assertThat(expectError).isEqualTo(false); + } catch (Exception e) { + assertThat(expectError).isEqualTo(true); + } + + } + +} diff --git a/core/src/test/resources/compose-options-test/with-deploy-block.yml b/core/src/test/resources/compose-options-test/with-deploy-block.yml new file mode 100644 index 00000000000..f52f6747122 --- /dev/null +++ b/core/src/test/resources/compose-options-test/with-deploy-block.yml @@ -0,0 +1,8 @@ +version: '3.7' +services: + redis: + image: redis:2.6.17 + deploy: + resources: + limits: + memory: 150M