Skip to content

Add DockerImageName constructors to ComposeContainer #10356

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,28 +69,85 @@ public class ComposeContainer extends FailureDetectingExternalResource implement

private List<String> filesInDirectory = new ArrayList<>();

/**
* Creates a new ComposeContainer with a random identifier using the specified Docker image and compose files.
*
* @param image The Docker image to use for the container
* @param composeFiles One or more Docker Compose configuration files
*/
public ComposeContainer(DockerImageName image, File... composeFiles) {
this(image, Arrays.asList(composeFiles));
}

/**
* Creates a new ComposeContainer with a random identifier using the specified Docker image and compose files.
*
* @param image The Docker image to use for the container
* @param composeFiles A list of Docker Compose configuration files
*/
public ComposeContainer(DockerImageName image, List<File> composeFiles) {
this(image, Base58.randomString(6).toLowerCase(), composeFiles);
}

/**
* Creates a new ComposeContainer with the specified Docker image, identifier, and compose files.
*
* @param image The Docker image to use for the container
* @param identifier A unique identifier for this compose environment
* @param composeFiles One or more Docker Compose configuration files
*/
public ComposeContainer(DockerImageName image, String identifier, File... composeFiles) {
this(image, identifier, Arrays.asList(composeFiles));
}

/**
* Creates a new ComposeContainer with the specified Docker image, identifier, and compose files.
* This is the primary constructor that all other constructors delegate to.
*
* @param image The Docker image to use for the container
* @param identifier A unique identifier for this compose environment
* @param composeFiles A list of Docker Compose configuration files
*/
public ComposeContainer(DockerImageName image, String identifier, List<File> composeFiles) {
this.composeDelegate =
new ComposeDelegate(ComposeDelegate.ComposeVersion.V2, composeFiles, identifier, COMPOSE_EXECUTABLE, image);
this.project = this.composeDelegate.getProject();
}

/**
* @deprecated
* Use the new constructor ComposeContainer(DockerImageName image, File... composeFiles)
*/
@Deprecated
public ComposeContainer(File... composeFiles) {
this(Arrays.asList(composeFiles));
this(DEFAULT_IMAGE_NAME, Arrays.asList(composeFiles));
}

/**
* @deprecated
* Use the new constructor ComposeContainer(DockerImageName image,List composeFiles)
*/
@Deprecated
public ComposeContainer(List<File> composeFiles) {
this(Base58.randomString(6).toLowerCase(), composeFiles);
this(DEFAULT_IMAGE_NAME, composeFiles);
}

/**
* @deprecated
* Use the new constructor ComposeContainer(DockerImageName image, String identifier, File... composeFile)
*/
@Deprecated
public ComposeContainer(String identifier, File... composeFiles) {
this(identifier, Arrays.asList(composeFiles));
this(DEFAULT_IMAGE_NAME, identifier, Arrays.asList(composeFiles));
}

/**
* @deprecated
* Use the new constructor ComposeContainer(DockerImageName image,String identifier, List composeFiles)
*/
@Deprecated
public ComposeContainer(String identifier, List<File> composeFiles) {
this.composeDelegate =
new ComposeDelegate(
ComposeDelegate.ComposeVersion.V2,
composeFiles,
identifier,
COMPOSE_EXECUTABLE,
DEFAULT_IMAGE_NAME
);
this.project = this.composeDelegate.getProject();
this(DEFAULT_IMAGE_NAME, identifier, composeFiles);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -62,39 +63,107 @@ public class DockerComposeContainer<SELF extends DockerComposeContainer<SELF>>

public static final String COMPOSE_EXECUTABLE = SystemUtils.IS_OS_WINDOWS ? "docker-compose.exe" : "docker-compose";

private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("docker/compose:1.29.2");

private final ComposeDelegate composeDelegate;

private String project;

private List<String> filesInDirectory = new ArrayList<>();

/**
* Creates a new DockerComposeContainer with the specified Docker image, identifier, and a single compose file.
*
* @param image The Docker image to use for the container
* @param identifier A unique identifier for this compose environment
* @param composeFile A Docker Compose configuration file
*/
public DockerComposeContainer(DockerImageName image, String identifier, File composeFile) {
this(image, identifier, Collections.singletonList(composeFile));
}

/**
* Creates a new DockerComposeContainer with a random identifier using the specified Docker image and compose files.
*
* @param image The Docker image to use for the container
* @param composeFiles A list of Docker Compose configuration files
*/
public DockerComposeContainer(DockerImageName image, List<File> composeFiles) {
this(image, Base58.randomString(6).toLowerCase(), composeFiles);
}

/**
* Creates a new DockerComposeContainer with the specified Docker image, identifier, and compose files.
*
* @param image The Docker image to use for the container
* @param identifier A unique identifier for this compose environment
* @param composeFiles One or more Docker Compose configuration files
*/
public DockerComposeContainer(DockerImageName image, String identifier, File... composeFiles) {
this(image, identifier, Arrays.asList(composeFiles));
}

/**
* Creates a new DockerComposeContainer with the specified Docker image, identifier, and compose files.
* This is the primary constructor that all other constructors delegate to.
*
* @param image The Docker image to use for the container
* @param identifier A unique identifier for this compose environment
* @param composeFiles A list of Docker Compose configuration files
*/
public DockerComposeContainer(DockerImageName image, String identifier, List<File> composeFiles) {
this.composeDelegate =
new ComposeDelegate(ComposeDelegate.ComposeVersion.V1, composeFiles, identifier, COMPOSE_EXECUTABLE, image);
this.project = this.composeDelegate.getProject();
}

/**
* @deprecated
* Use the new constructor DockerComposeContainer(File composeFile, String identifier)
*/
@Deprecated
public DockerComposeContainer(File composeFile, String identifier) {
this(identifier, composeFile);
}

/**
* @deprecated
* Use the new constructor DockerComposeContainer(File... composeFiles)
*/
@Deprecated
public DockerComposeContainer(File... composeFiles) {
this(Arrays.asList(composeFiles));
}

/**
* @deprecated
* Use the new constructor DockerComposeContainer(List composeFiles)
*/
@Deprecated
public DockerComposeContainer(List<File> composeFiles) {
this(Base58.randomString(6).toLowerCase(), composeFiles);
}

/**
* @deprecated
* Use the new constructor DockerComposeContainer(String identifier,File... composeFiles)
*/
@Deprecated
public DockerComposeContainer(String identifier, File... composeFiles) {
this(identifier, Arrays.asList(composeFiles));
}

/**
* @deprecated
* Use the new constructor DockerComposeContainer(String identifier,List composeFiles)
*/
@Deprecated
public DockerComposeContainer(String identifier, List<File> composeFiles) {
this.composeDelegate =
new ComposeDelegate(
ComposeDelegate.ComposeVersion.V1,
composeFiles,
identifier,
COMPOSE_EXECUTABLE,
DEFAULT_IMAGE_NAME
DockerImageName.parse("docker/compose:1.29.2")
);
this.project = this.composeDelegate.getProject();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ private String getConfigurable(
}

for (final Properties properties : propertiesSources) {
if (properties.get(propertyName) != null) {
if (properties.get(propertyName) != null && !properties.get(propertyName).toString().trim().isEmpty()) {
return (String) properties.get(propertyName);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.testcontainers.containers;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.TestcontainersConfiguration;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class ComposeContainerTest {

public static final String DOCKER_IMAGE = "docker:25.0.2";

private static final String COMPOSE_FILE_PATH = "src/test/resources/docker-compose-imagename-parsing-v2.yml";

private ComposeContainer composeContainer;

private TestLogAppender testLogAppender;

private Logger rootLogger;

@Before
public void setup() {
testLogAppender = new TestLogAppender();
testLogAppender.start();
rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(testLogAppender);
TestcontainersConfiguration.getInstance().updateUserConfig("compose.container.image", DOCKER_IMAGE);
}

@After
public void tearDown() {
composeContainer.stop();
rootLogger.detachAppender(testLogAppender);
TestcontainersConfiguration.getInstance().updateUserConfig("compose.container.image", "");
System.clearProperty("compose.container.image");
}

@Test
public void testWithCustomDockerImage() {
composeContainer = new ComposeContainer(DockerImageName.parse(DOCKER_IMAGE), new File(COMPOSE_FILE_PATH));
composeContainer.start();
verifyContainerCreation();
}

@Test
public void testWithCustomDockerImageAndIdentifier() {
composeContainer =
new ComposeContainer(DockerImageName.parse(DOCKER_IMAGE), "myidentifier", new File(COMPOSE_FILE_PATH));
composeContainer.start();
verifyContainerCreation();
}

private void verifyContainerCreation() {
List<String> logs = testLogAppender.getLogs();

assertThat(logs).isNotNull().anyMatch(line -> line.contains("Creating container for image: " + DOCKER_IMAGE));
}

private static class TestLogAppender extends AppenderBase<ILoggingEvent> {

private final List<String> logs = new ArrayList<>();

@Override
protected void append(ILoggingEvent eventObject) {
logs.add(eventObject.getFormattedMessage());
}

public List<String> getLogs() {
return logs;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.testcontainers.containers;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.testcontainers.utility.DockerImageName;
import org.testcontainers.utility.TestcontainersConfiguration;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

public class DockerComposeContainerCustomImageTest {

public static final String DOCKER_IMAGE = "docker/compose:debian-1.29.2";

private static final String COMPOSE_FILE_PATH = "src/test/resources/docker-compose-imagename-parsing-v1.yml";

private DockerComposeContainer composeContainer;

private TestLogAppender testLogAppender;

private Logger rootLogger;

@Before
public void setup() {
testLogAppender = new TestLogAppender();
testLogAppender.start();
rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.addAppender(testLogAppender);
TestcontainersConfiguration.getInstance().updateUserConfig("compose.container.image", DOCKER_IMAGE);
}

@After
public void tearDown() {
rootLogger.detachAppender(testLogAppender);
TestcontainersConfiguration.getInstance().updateUserConfig("compose.container.image", "");
System.clearProperty("compose.container.image");
composeContainer.stop();
}

@Test
public void testWithCustomDockerImage() {
composeContainer =
new DockerComposeContainer(DockerImageName.parse(DOCKER_IMAGE), "testing", new File(COMPOSE_FILE_PATH));
composeContainer.start();
verifyContainerCreation();
}

@Test
public void testWithCustomDockerImageAndIdentifier() {
composeContainer =
new DockerComposeContainer(
DockerImageName.parse(DOCKER_IMAGE),
"myidentifier",
new File(COMPOSE_FILE_PATH)
);
composeContainer.start();
verifyContainerCreation();
}

private void verifyContainerCreation() {
List<String> logs = testLogAppender.getLogs();

assertThat(logs).isNotNull().anyMatch(line -> line.contains("Creating container for image: " + DOCKER_IMAGE));
}

private static class TestLogAppender extends AppenderBase<ILoggingEvent> {

private final List<String> logs = new ArrayList<>();

@Override
protected void append(ILoggingEvent eventObject) {
logs.add(eventObject.getFormattedMessage());
}

public List<String> getLogs() {
return logs;
}
}
}