diff --git a/core/src/test/java/org/testcontainers/junit/ComposeContainerFileCopyInclusionsTest.java b/core/src/test/java/org/testcontainers/junit/ComposeContainerFileCopyInclusionsTest.java new file mode 100644 index 00000000000..792b150c805 --- /dev/null +++ b/core/src/test/java/org/testcontainers/junit/ComposeContainerFileCopyInclusionsTest.java @@ -0,0 +1,95 @@ +package org.testcontainers.junit; + +import org.junit.Test; +import org.testcontainers.containers.ComposeContainer; +import org.testcontainers.containers.ContainerLaunchException; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class ComposeContainerFileCopyInclusionsTest { + + @Test + public void testShouldCopyAllFilesByDefault() throws IOException { + try ( + ComposeContainer environment = new ComposeContainer( + new File("src/test/resources/compose-file-copy-inclusions/compose.yml") + ) + .withExposedService("app", 8080) + ) { + environment.start(); + + Integer servicePort = environment.getServicePort("app-1", 8080); + String serviceHost = environment.getServiceHost("app-1", 8080); + String response = readStringFromURL("http://" + serviceHost + ":" + servicePort + "/env"); + assertThat(response).isEqualTo("MY_ENV_VARIABLE: override"); + } + } + + @Test + public void testWithFileCopyInclusionUsingFilePath() throws IOException { + try ( + ComposeContainer environment = new ComposeContainer( + new File("src/test/resources/compose-file-copy-inclusions/compose-root-only.yml") + ) + .withExposedService("app", 8080) + .withFileCopyInclusions("Dockerfile", "EnvVariableRestEndpoint.java", ".env") + ) { + environment.start(); + + Integer servicePort = environment.getServicePort("app-1", 8080); + String serviceHost = environment.getServiceHost("app-1", 8080); + String response = readStringFromURL("http://" + serviceHost + ":" + servicePort + "/env"); + + // The `test/.env` file is not copied, now so we get the original value + assertThat(response).isEqualTo("MY_ENV_VARIABLE: original"); + } + } + + @Test + public void testWithFileCopyInclusionUsingDirectoryPath() throws IOException { + try ( + ComposeContainer environment = new ComposeContainer( + new File("src/test/resources/compose-file-copy-inclusions/compose-test-only.yml") + ) + .withExposedService("app", 8080) + .withFileCopyInclusions("Dockerfile", "EnvVariableRestEndpoint.java", "test") + ) { + environment.start(); + + Integer servicePort = environment.getServicePort("app-1", 8080); + String serviceHost = environment.getServiceHost("app-1", 8080); + String response = readStringFromURL("http://" + serviceHost + ":" + servicePort + "/env"); + // The test directory (with its contents) is copied, so we get the override + assertThat(response).isEqualTo("MY_ENV_VARIABLE: override"); + } + } + + @Test + public void testShouldNotBeAbleToStartIfNeededEnvFileIsNotCopied() { + try ( + ComposeContainer environment = new ComposeContainer( + new File("src/test/resources/compose-file-copy-inclusions/compose-test-only.yml") + ) + .withExposedService("app", 8080) + .withFileCopyInclusions("Dockerfile", "EnvVariableRestEndpoint.java") + ) { + assertThatExceptionOfType(ContainerLaunchException.class) + .isThrownBy(environment::start) + .withMessage("Container startup failed for image docker:24.0.2"); + } + } + + private static String readStringFromURL(String requestURL) throws IOException { + try (Scanner scanner = new Scanner(new URL(requestURL).openStream(), StandardCharsets.UTF_8.toString())) { + scanner.useDelimiter("\\A"); + return scanner.hasNext() ? scanner.next() : ""; + } + } +} diff --git a/core/src/test/resources/compose-file-copy-inclusions/.env b/core/src/test/resources/compose-file-copy-inclusions/.env new file mode 100644 index 00000000000..bb5b5beb3e2 --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/.env @@ -0,0 +1 @@ +MY_ENV_VARIABLE=original diff --git a/core/src/test/resources/compose-file-copy-inclusions/Dockerfile b/core/src/test/resources/compose-file-copy-inclusions/Dockerfile new file mode 100644 index 00000000000..851086d68c2 --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/Dockerfile @@ -0,0 +1,9 @@ +FROM jbangdev/jbang-action + +WORKDIR /app +COPY EnvVariableRestEndpoint.java . + +RUN jbang export portable --force EnvVariableRestEndpoint.java + +EXPOSE 8080 +CMD ["./EnvVariableRestEndpoint.java"] diff --git a/core/src/test/resources/compose-file-copy-inclusions/EnvVariableRestEndpoint.java b/core/src/test/resources/compose-file-copy-inclusions/EnvVariableRestEndpoint.java new file mode 100644 index 00000000000..ead172bbb35 --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/EnvVariableRestEndpoint.java @@ -0,0 +1,45 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpExchange; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; + +public class EnvVariableRestEndpoint { + private static final String ENV_VARIABLE_NAME = "MY_ENV_VARIABLE"; + private static final int PORT = 8080; + + public static void main(String[] args) throws IOException { + HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0); + server.createContext("/env", new EnvVariableHandler()); + server.setExecutor(null); + server.start(); + System.out.println("Server started on port " + PORT); + } + + static class EnvVariableHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + if ("GET".equals(exchange.getRequestMethod())) { + String envValue = System.getenv(ENV_VARIABLE_NAME); + String response = envValue != null + ? ENV_VARIABLE_NAME + ": " + envValue + : "Environment variable " + ENV_VARIABLE_NAME + " not found"; + + exchange.sendResponseHeaders(200, response.length()); + try (OutputStream os = exchange.getResponseBody()) { + os.write(response.getBytes()); + } + } else { + String response = "Method not allowed"; + exchange.sendResponseHeaders(405, response.length()); + try (OutputStream os = exchange.getResponseBody()) { + os.write(response.getBytes()); + } + } + } + } +} diff --git a/core/src/test/resources/compose-file-copy-inclusions/compose-root-only.yml b/core/src/test/resources/compose-file-copy-inclusions/compose-root-only.yml new file mode 100644 index 00000000000..fa17d5f472d --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/compose-root-only.yml @@ -0,0 +1,7 @@ +services: + app: + build: . + ports: + - "8080:8080" + env_file: + - '.env' diff --git a/core/src/test/resources/compose-file-copy-inclusions/compose-test-only.yml b/core/src/test/resources/compose-file-copy-inclusions/compose-test-only.yml new file mode 100644 index 00000000000..943f908ce20 --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/compose-test-only.yml @@ -0,0 +1,7 @@ +services: + app: + build: . + ports: + - "8080:8080" + env_file: + - './test/.env' diff --git a/core/src/test/resources/compose-file-copy-inclusions/compose.yml b/core/src/test/resources/compose-file-copy-inclusions/compose.yml new file mode 100644 index 00000000000..2a9334d7980 --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/compose.yml @@ -0,0 +1,8 @@ +services: + app: + build: . + ports: + - "8080:8080" + env_file: + - '.env' + - './test/.env' diff --git a/core/src/test/resources/compose-file-copy-inclusions/test/.env b/core/src/test/resources/compose-file-copy-inclusions/test/.env new file mode 100644 index 00000000000..09867ae6d5d --- /dev/null +++ b/core/src/test/resources/compose-file-copy-inclusions/test/.env @@ -0,0 +1 @@ +MY_ENV_VARIABLE=override