Housekeeping: Use org.testcontainer.*Container #2945
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughMigrates embedded modules from generic containers to typed Testcontainers, adds dependencies, replaces bind mounts with copy-to-container, removes legacy helpers, and applies Java idiom modernizations across code and tests. ChangesTestcontainers Container Type & Dependency Upgrades
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerScope.java (1)
91-96:⚠️ Potential issue | 🟠 Major | ⚡ Quick winProtect lifecycle iteration over
instancesfrom concurrent mutation.
get/removesynchronize oninstances, but both lifecycle methods iterateinstances.values()without the same lock. Under parallel test execution this can throwConcurrentModificationExceptionor skip callbacks.Suggested fix
public void afterTestMethod(TestContext testContext) { - instances.values().stream() + final var snapshot = synchronizedSnapshot(); + snapshot.stream() .filter(TestLifecycleAware.class::isInstance) .map(TestLifecycleAware.class::cast) .forEach(value -> value.afterTest(testDescription(testContext), Optional.ofNullable(testContext.getTestException()))); } @@ public void beforeTestMethod(TestContext testContext) { - instances.values().stream() + final var snapshot = synchronizedSnapshot(); + snapshot.stream() .filter(TestLifecycleAware.class::isInstance) .map(TestLifecycleAware.class::cast) .forEach(value -> value.beforeTest(testDescription(testContext))); } + +private java.util.List<Object> synchronizedSnapshot() { + synchronized (this.instances) { + return new java.util.ArrayList<>(this.instances.values()); + } +}Also applies to: 113-117
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerScope.java` around lines 91 - 96, The iteration over the instances map in afterTestMethod (and the analogous lifecycle method at lines 113-117) is not protected against concurrent mutation; wrap the iteration and callback invocation in the same lock used by get/remove (synchronize on the instances object) or alternatively take a safe snapshot (e.g., new ArrayList<>(instances.values())) before streaming, so TestLifecycleAware callbacks (afterTest in TestcontainerScope) cannot throw ConcurrentModificationException or miss callbacks under parallel test execution; apply the same fix to the other lifecycle method that iterates instances.values().embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java (1)
64-83:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPubSub emulator port must be explicitly configured to respect the
embedded.google.pubsub.portproperty override.Currently,
PubSubEmulatorContainerstarts with hardcoded port 8085 and only exposes that port. Ifembedded.google.pubsub.portis overridden to a different value,container.getMappedPort(properties.getPort())at line 82 will fail because the overridden port is not exposed. Similarly, toxiproxy setup at line 55 will break when attempting to proxy a non-existent exposed port.Add
.withExposedPorts(properties.getPort())and configure the emulator command to use the property-driven port via.withCommand()or environment variable, consistent with how other modules (Redis, MySQL, Solr, etc.) handle configurable ports. Additionally, add a test that verifies port override works correctly end-to-end.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java` around lines 64 - 83, The PubSub emulator currently always exposes hardcoded 8085 which breaks overrides; update the pubsub(...) builder to call .withExposedPorts(properties.getPort()) and configure the emulator to listen on that port (use .withCommand(...) or an env var in PubSubEmulatorContainer) so the started container actually exposes properties.getPort(); ensure configureCommonsAndStart(...) and the toxiproxy setup use the exposed port, and add an integration test that sets embedded.google.pubsub.port to a non-default value and asserts registerPubsubEnvironment(...) returns the mapped port and that pubsub accepts connections on that overridden port.embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java (1)
86-97:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftBind→copy switch silently breaks data persistence to the host.
Same concern as in
KafkaContainerConfiguration: replacing the bidirectional bind withwithCopyToContainer(MountableFile.forHostPath(...), "/tmp/kafka-logs")makes the mount one-way (host → container at startup). Users who enabledfileSystemBindto inspect or reuse Kafka logs after the container stops will silently lose that capability.Use
withFileSystemBind(kafkaData.toString(), "/tmp/kafka-logs", BindMode.READ_WRITE)if persistence is intended, or update the property name/docs to reflect copy-in-only semantics.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java` around lines 86 - 97, The current configureFileSystemBind method uses nativeKafka.withCopyToContainer(MountableFile.forHostPath(...), "/tmp/kafka-logs") which performs a one-way copy and breaks host persistence; change the behavior to mount a bidirectional bind when fileSystemBind.isEnabled() by using nativeKafka.withFileSystemBind(kafkaData.toString(), "/tmp/kafka-logs", BindMode.READ_WRITE) (or otherwise surface the copy-only semantics in the FileSystemBind property/docs) so that FileSystemBind results in persistent host ↔ container logs; update references in configureFileSystemBind, FileSystemBind usage, and the call site that creates kafkaData to reflect this replacement.embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java (1)
76-95:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winBehavior change:
embedded.selenium.argumentsis no longer applied to the container.Previously,
withCapabilities(capabilities)passed user-configuredChromeOptions/FirefoxOptions(populated viaproperties.apply(options)) to the container, so values likeembedded.selenium.arguments=--headlesswere automatically used. With this refactor, theChromeOptions/FirefoxOptionsbeans are still defined but never passed toBrowserWebDriverContainer. Users now have to manually@Autowired ChromeOptions optionsand pass it tonew RemoteWebDriver(...)themselves. The README example does this, but users upgrading without reading the doc will silently lose their browser arguments.Consider documenting this as a breaking change in the module's README/migration notes (the
embedded.selenium.argumentsdoc on Line 21 still says "list of browser arguments passed to ChromeOptions/FirefoxOptions" which is technically still true, but no longer applied to the container automatically).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java` around lines 76 - 95, The container factory method selenium(...) no longer applies user-configured browser options to BrowserWebDriverContainer, so embedded.selenium.arguments are ignored; fix by creating and applying the Capabilities built from the existing ChromeOptions/FirefoxOptions beans (the same options that properties.apply(...) produces) to the BrowserWebDriverContainer via withCapabilities(...) before starting it (update the selenium(...) method to obtain the Options/Capabilities from SeleniumProperties or call properties.apply(...) and pass the resulting Capabilities to container.withCapabilities(...)); additionally document this behavioral change in the module README/migration notes and clarify that embedded.selenium.arguments are automatically applied to the container (or note the breaking change if you prefer to require manual wiring).embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java (1)
223-254:⚠️ Potential issue | 🟠 Major | 🏗️ Heavy liftBind→copy switch silently breaks data persistence to the host.
Switching from
addFileSystemBind(..., BindMode.READ_WRITE)towithCopyToContainer(MountableFile.forHostPath(...), ...)changes the semantics from a bidirectional bind (data written by Kafka/ZooKeeper inside the container is visible on the host after the run) to a one-way copy (host → container at start; nothing flows back). For users who enabledfileSystemBind/zookeeperFileSystemBindprecisely to inspect or reuse Kafka/ZooKeeper data across runs, this is a silent regression.If the intent is to keep persistence, prefer
withFileSystemBind(host, target, BindMode.READ_WRITE)(the non-deprecated replacement foraddFileSystemBind) so writes propagate back. If the intent is only to seed initial data, the user-facing property naming and docs should be updated to reflect the new "copy-in only" behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java` around lines 223 - 254, The current kafkaFileSystemBind and zookeperFileSystemBind methods use withCopyToContainer which only copies host→container and breaks persistence; change both methods to call kafka.withFileSystemBind(hostPath, containerPath, BindMode.READ_WRITE) (the non-deprecated replacement for addFileSystemBind) so container writes are visible on the host, keeping the existing createPathAndParentOrMakeWritable calls to ensure the host dirs exist and are writable; if the original intent was only seeding, instead update the property/docs to reflect copy-in-only behavior.embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java (1)
73-78:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winSecret values containing spaces will silently corrupt the
kv putcommand.
String.join(" ", secrets)concatenates allkey=valuetokens with spaces. Internally,withInitCommandpasses the command string throughbuildExecCommandwhich splits on whitespace. A value such as"my key=hello world"or"key=hello world"becomes extra broken tokens in the exec array, causing the vault CLI call to fail or store incorrect data.Consider rejecting or quoting secret values with spaces at this level, or document that values containing spaces are unsupported:
🛡️ Proposed guard
String[] secrets = properties.getSecrets().entrySet().stream() .map(entry -> String.format("%s=%s", entry.getKey(), entry.getValue())) .toArray(String[]::new); + + boolean hasSpaces = properties.getSecrets().entrySet().stream() + .anyMatch(e -> e.getKey().contains(" ") || e.getValue().contains(" ")); + if (hasSpaces) { + throw new IllegalArgumentException( + "Vault secret keys and values must not contain spaces when using withInitCommand"); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java` around lines 73 - 78, The constructed init command in EmbeddedVaultBootstrapConfiguration uses String.join(" ", secrets) which breaks when secret values contain whitespace; update the code that builds the secrets (the properties.getSecrets mapping before calling vault.withInitCommand) to validate each value and reject any that contain whitespace by throwing an IllegalArgumentException with a clear message (include the offending key and hint to remove/escape spaces), so that vault.withInitCommand is never passed a malformed command; alternatively, implement proper shell-quoting/escaping of values before assembling the command if you prefer to support spaces.
🧹 Nitpick comments (6)
embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java (1)
19-20: 💤 Low value
otlpHttpPortis injected but unused.The field is read from
embedded.grafana.otlp.http.portbut never referenced by any test in this class. Either drop it or add a corresponding reachability test (e.g. POSTing to/v1/tracesor hitting/v1/health) to justify the injection.♻️ Proposed cleanup
- `@Value`("${embedded.grafana.otlp.http.port}") - private int otlpHttpPort;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java` around lines 19 - 20, The field otlpHttpPort in EmbeddedGrafanaBootstrapConfigurationTest is injected but never used; either remove the field declaration or add a minimal reachability test that uses it (e.g., in method within EmbeddedGrafanaBootstrapConfigurationTest perform an HTTP request to the Grafana OTLP endpoint using otlpHttpPort — e.g., GET http://localhost:{otlpHttpPort}/v1/health or a POST to /v1/traces with a small payload — and assert a successful status) so the injected value is actually referenced.embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java (1)
50-56: 💤 Low valueExtract the hard-coded internal port
8080into a named constant.
8080is repeated as a magic value here. Define a constant (e.g.,WIREMOCK_INTERNAL_PORT = 8080) and reuse it forembedded.wiremock.internalPortto make intent explicit and ease future changes.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java` around lines 50 - 56, Replace the hard-coded 8080 in registerWiremockEnvironment with a named constant; declare a private static final int WIREMOCK_INTERNAL_PORT = 8080 (or similar) in EmbeddedWiremockBootstrapConfiguration and use that constant when putting "embedded.wiremock.internalPort" into the map to remove the magic number and make the intent explicit.embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java (1)
161-189: 💤 Low valueMisleading fallback at the end of
getHostName(...).For any OS that is not Mac/Darwin/Windows/Linux (e.g. *BSD, Solaris), the method now returns
DOCKER_FOR_LINUX_STATIC_IP(172.17.0.1), which is specifically the Docker bridge gateway on Linux and likely incorrect on other platforms. Either log a warning and returnhost.docker.internal(the more portable Docker default in modern engines) or make the fallback explicit so users know it's a Linux-only assumption.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java` around lines 161 - 189, The fallback in getHostName(...) currently returns the Linux-specific DOCKER_FOR_LINUX_STATIC_IP for any unrecognized OS; change this so unknown/non-mac-win-linux platforms do not silently get a Linux IP: detect the branch where OS isn't mac/win/nux, log a warning (include the OS string) using the existing logger, and return "host.docker.internal" instead of DOCKER_FOR_LINUX_STATIC_IP; update references in getHostName and keep DOCKER_FOR_LINUX_STATIC_IP only for the explicit linux branch so the Linux assumption is not applied to other platforms.embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java (1)
113-113: ⚡ Quick winConsider making
configureCommonsAndStartgeneric to eliminate the unchecked cast.The
(AzuriteContainer)cast is necessary becauseconfigureCommonsAndStartreturnsGenericContainer<?>while the variable is typed asAzuriteContainer. The method returns the same instance it receives (seeContainerUtils.javaline 67-98), but the wildcard generic type forces callers to cast. Making the method generic—e.g.,<T extends GenericContainer<T>> T configureCommonsAndStart(T container, ...)—would preserve type safety and eliminate this cast.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java` at line 113, The unchecked cast on azuriteContainer comes from configureCommonsAndStart returning GenericContainer<?>; change configureCommonsAndStart to a generic signature (e.g. <T extends GenericContainer<?>> T configureCommonsAndStart(T container, TestcontainersConfigurationProperties properties, Log log) or <T extends GenericContainer<T>> T configureCommonsAndStart(...)) in the implementation (ContainerUtils.configureCommonsAndStart) and its declaration so it preserves the concrete container type, then call it from EmbeddedAzuriteBootstrapConfiguration without casting (azuriteContainer = configureCommonsAndStart(azuriteContainer, properties, log)); ensure method usages elsewhere are updated to the new generic signature.embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java (1)
39-39: 💤 Low valueOptional: keep Lombok
@Slf4jfor consistency.The class previously used Lombok’s
@Slf4j; switching to a manualLoggerFactoryhere introduces a stylistic inconsistency with the rest of the module (e.g.,BaseNatsTeststill uses@Slf4j). Unless there’s a specific reason (e.g., dropping Lombok), reverting to@Slf4jkeeps things uniform.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java` at line 39, The class defines a manual Logger field "log" via LoggerFactory which breaks module stylistic consistency; replace it by reintroducing Lombok's `@Slf4j` on the EmbeddedNatsBootstrapConfiguration class and remove the private static final Logger log declaration so the class uses the Lombok-generated "log" instead (ensure Lombok is enabled in the module and imports are adjusted accordingly).embedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.java (1)
118-134: 💤 Low valueConsider using
asInstanceOffor a type-safe assertion without an explicit cast.The current pattern (
.isInstanceOf(...)+ manual cast inside.satisfies(...)) is functional, but AssertJ provides a cleaner single-step alternative that eliminates the unchecked cast:♻️ Proposed refactor using
asInstanceOf+import org.assertj.core.api.InstanceOfAssertFactories; ... assertThat(beanFactory.getBean(BEAN_NAME_EMBEDDED_GOOGLE_STORAGE_SERVER)) .isNotNull() - .isInstanceOf(FakeGcsServerContainer.class) - .satisfies(bean -> { - FakeGcsServerContainer container = (FakeGcsServerContainer) bean; - - assertThat(container.getExposedPorts()).containsExactly(4443); - assertThat(container.getContainerInfo().getConfig().getEntrypoint()) - .containsExactly( - "/bin/fake-gcs-server", - "-backend", "memory", - "-scheme", "http", - "-host", "0.0.0.0", - "-port", "4443", - "-location", "US-EAST1"); - }); + .asInstanceOf(InstanceOfAssertFactories.type(FakeGcsServerContainer.class)) + .satisfies(container -> { + assertThat(container.getExposedPorts()).containsExactly(4443); + assertThat(container.getContainerInfo().getConfig().getEntrypoint()) + .containsExactly( + "/bin/fake-gcs-server", + "-backend", "memory", + "-scheme", "http", + "-host", "0.0.0.0", + "-port", "4443", + "-location", "US-EAST1"); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.java` around lines 118 - 134, Replace the isInstanceOf + manual cast pattern in shouldHaveContainerWithExpectedDefaultProperties with AssertJ's type-safe asInstanceOf: call asInstanceOf(InstanceOfAssertFactories.type(FakeGcsServerContainer.class)) on the beanFactory.getBean(BEAN_NAME_EMBEDDED_GOOGLE_STORAGE_SERVER) assertion so the lambda passed to satisfies receives a typed FakeGcsServerContainer (no explicit cast), then keep the same assertions on getExposedPorts() and getContainerInfo().getConfig().getEntrypoint().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java`:
- Around line 105-109: The lambda passed to withCreateContainerCmdModifier uses
Arrays.asList(cmd.getCmd()) which throws NPE because CreateContainerCmd.getCmd()
can be null; update the modifier in EmbeddedAzuriteBootstrapConfiguration so it
first checks cmd.getCmd() for null and builds the args list accordingly (e.g.,
start from an empty List if null or new ArrayList<>(Arrays.asList(cmd.getCmd()))
if non-null), then add "--skipApiVersionCheck" and call cmd.withCmd(args) as
before; reference the CreateContainerCmd instance named cmd and the existing
cmd.withCmd(...) call when making the change.
In `@embedded-grafana/README.adoc`:
- Around line 30-39: The example under embedded.grafana.filesToInclude uses the
standard Grafana path which is incorrect for the grafana/otel-lgtm image; update
the containerPath value in the example to the otel-lgtm provisioning location
(/otel-lgtm/grafana/conf/provisioning/datasources/my-datasource.yml) so that
embedded.grafana.filesToInclude points classpath resources into the correct
otel-lgtm container provisioning directory.
In `@embedded-keycloak/pom.xml`:
- Around line 17-18: The POM pins testcontainers-keycloak.version to 3.3.0 which
targets Keycloak 24 and Testcontainers 1.19.6; update the
testcontainers-keycloak.version property (reference:
testcontainers-keycloak.version) to a compatible release (e.g., 3.4.x if you
want Keycloak 25.x compatibility or 4.x if you plan to move to Keycloak
26+/Testcontainers 2.x), and also align any Keycloak docker image tags and the
Testcontainers baseline managed by the parent (Spring Boot) so the
testcontainers-keycloak client, Keycloak image tag and Testcontainers runtime
are mutually compatible before running tests.
In
`@embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java`:
- Around line 82-109: The applyDbConfig method in
EmbeddedKeycloakBootstrapConfiguration is setting legacy DB_* env vars; change
it to set the Keycloak 25 names (e.g. KC_DB, KC_DB_URL_HOST, KC_DB_URL_PORT,
KC_DB_URL_DATABASE, KC_DB_SCHEMA, KC_DB_USERNAME, KC_DB_PASSWORD) on the
KeycloakContainer instead of DB_*; remove emitting DB_USER_FILE/DB_PASSWORD_FILE
env vars and, when KeycloakProperties.getDbUserFile() or getDbPasswordFile() is
provided, read those files' contents inside applyDbConfig and set the
corresponding KC_DB_USERNAME / KC_DB_PASSWORD values on the KeycloakContainer
(or fall back to getDbUser()/getDbPassword() if present), ensuring no *_FILE env
vars are passed to the container. Reference: applyDbConfig(KeycloakContainer,
KeycloakProperties), KeycloakContainer.withEnv(...),
KeycloakProperties.getDbUserFile()/getDbPasswordFile()/getDbUser()/getDbPassword().
- Around line 63-79: The container is not started with the configured context
path and the auth URL is being composed manually; update the KeycloakContainer
creation in keycloakContainer(...) to call
.withContextPath(properties.getAuthBasePath()) on the KeycloakContainer
instance, and after starting/configuring the container (i.e., after
configureCommonsAndStart(...)) replace any manual buildAuthServerUrl(...) usage
with keycloak.getAuthServerUrl() when registering/exporting the
embedded.keycloak.auth-server-url in registerEnvironment(...), ensuring
KeycloakContainer.getAuthServerUrl() is used to obtain the resolved URL.
In
`@embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.java`:
- Around line 74-77: The override of getCommand() returns null and thus drops
any configured embedded.keycloak.command; restore inherited behavior by removing
this getCommand() override or change it to return super.getCommand() so
ContainerUtils.configureCommonsAndStart() can detect and apply the command (or
if you intentionally migrated to the new container API, map the configured
command into the newer API call such as the container's custom command setter
instead of returning null). Ensure references: getCommand(),
ContainerUtils.configureCommonsAndStart(), and the withCommand()/new custom
command API are handled accordingly.
In
`@embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java`:
- Around line 97-103: The code currently adds the plaintext password via
memsql.getPassword() into the properties map and then logs the entire map with
log.info in EmbeddedMemSqlBootstrapConfiguration, which leaks credentials;
remove the plaintext secret from the logged data by either not adding
"embedded.memsql.password" to the map used for logging or replacing its value
with a redaction (e.g., "REDACTED" or masked string) before calling log.info,
leaving the actual property assignment to the internal configuration if needed;
update references around map, memsql.getPassword(), and the log.info("Started
memsql server. Connection details {} ", map) call so only non-sensitive
connection details are logged.
- Around line 79-81: The code incorrectly checks
System.getProperty("system.arch") and uses memsql.withCommand(...) to try to set
Docker platform; change to read System.getProperty("os.arch") (null-safe) and
detect ARM variants (e.g. check if the string contains or starts with "arm" or
"aarch" or equals "aarch64"), and replace the withCommand call on the memsql
object with the Testcontainers API memsql.withCreateContainerCmdModifier(cmd ->
cmd.withPlatform("linux/amd64")) so the container is created with the correct
platform; update any surrounding null/empty checks accordingly around memsql and
the os.arch value.
In
`@embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java`:
- Around line 28-31: The withUsername method in MemSqlContainer currently
accepts arbitrary usernames while the container only provisions root
credentials, causing unreachable credentials; update withUsername(String
username) in class MemSqlContainer to validate input and fail fast by throwing
an IllegalArgumentException (or IllegalStateException) if the caller passes a
non-root username (i.e., anything other than "root"), or alternatively implement
user provisioning in the container configuration flow (the configure/start
methods) to create the requested user; reference the withUsername method and the
container configuration/start logic (where root credentials are set) and ensure
getUsername/getPassword/getJdbcUrl return only credentials that the container
actually provisions.
In
`@embedded-minio/src/test/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfigurationTest.java`:
- Around line 100-102: The convertStreamToString helper creates a Scanner over
the provided InputStream but never closes it, leaking resources; update
convertStreamToString to use a try-with-resources (or explicitly close) for the
Scanner (which will also close the InputStream) so the Scanner and underlying
stream are always closed after reading, and return the same string result;
reference: convertStreamToString(java.io.InputStream).
In `@embedded-selenium/README.adoc`:
- Around line 40-57: The README is inconsistent with the bootstrap wiring:
either restore the embedded.selenium.browser property to the documented
"Consumes" list and clarify Edge is unsupported, or change
EmbeddedSeleniumBootstrapConfiguration so options are derived from the Docker
image; to fix quickly, update the docs to mention embedded.selenium.browser and
that Chrome/Firefox selection still requires setting
embedded.selenium.browser=CHROMIUM|FIREFOX and that Edge is not yet supported
(no EdgeOptions bean), or alternatively implement EdgeOptions and add logic in
EmbeddedSeleniumBootstrapConfiguration (see chromeOptions, firefoxOptions
factory methods) to parse the selenium image name and select/create the matching
Options bean automatically instead of relying on the property.
In `@embedded-wiremock/pom.xml`:
- Line 18: Update the wiremock-testcontainers-module version property value from
1.0-alpha-13 to 1.0-alpha-15 in the Maven POM by changing the
<wiremock-testcontainers-module.version> property (the property named
wiremock-testcontainers-module.version) so the project uses the newer alpha-15
release; then run a quick mvn -U test or dependency:resolve to ensure the new
artifact resolves and adjust any failing tests if API/behavior changed.
In
`@testcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/ContainerUtils.java`:
- Around line 86-88: The change from addFileSystemBind to withCopyToContainer
breaks bind-mount semantics and drops BindMode and getBinds(); revert the loop
in ContainerUtils that iterates properties.getMountVolumes() to call
addFileSystemBind(...) (using mountVolume.getHostPath(),
mountVolume.getContainerPath(), and mountVolume.getMode()) instead of
withCopyToContainer, and capture the returned GenericContainer into
updatedContainer (consistent with the withCopyFileToContainer usage) so binds
and modes are preserved and tests like
ContainerUtilsTest.configureCommonsAndStart still see getBinds(); if you
intentionally wanted one-way copy instead, update ContainerUtilsTest to assert
getCopyToFileContainerPathMap() and remove/annotate MountVolume.getMode() as
ignored.
---
Outside diff comments:
In
`@embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java`:
- Around line 64-83: The PubSub emulator currently always exposes hardcoded 8085
which breaks overrides; update the pubsub(...) builder to call
.withExposedPorts(properties.getPort()) and configure the emulator to listen on
that port (use .withCommand(...) or an env var in PubSubEmulatorContainer) so
the started container actually exposes properties.getPort(); ensure
configureCommonsAndStart(...) and the toxiproxy setup use the exposed port, and
add an integration test that sets embedded.google.pubsub.port to a non-default
value and asserts registerPubsubEnvironment(...) returns the mapped port and
that pubsub accepts connections on that overridden port.
In
`@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java`:
- Around line 223-254: The current kafkaFileSystemBind and
zookeperFileSystemBind methods use withCopyToContainer which only copies
host→container and breaks persistence; change both methods to call
kafka.withFileSystemBind(hostPath, containerPath, BindMode.READ_WRITE) (the
non-deprecated replacement for addFileSystemBind) so container writes are
visible on the host, keeping the existing createPathAndParentOrMakeWritable
calls to ensure the host dirs exist and are writable; if the original intent was
only seeding, instead update the property/docs to reflect copy-in-only behavior.
In
`@embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java`:
- Around line 86-97: The current configureFileSystemBind method uses
nativeKafka.withCopyToContainer(MountableFile.forHostPath(...),
"/tmp/kafka-logs") which performs a one-way copy and breaks host persistence;
change the behavior to mount a bidirectional bind when
fileSystemBind.isEnabled() by using
nativeKafka.withFileSystemBind(kafkaData.toString(), "/tmp/kafka-logs",
BindMode.READ_WRITE) (or otherwise surface the copy-only semantics in the
FileSystemBind property/docs) so that FileSystemBind results in persistent host
↔ container logs; update references in configureFileSystemBind, FileSystemBind
usage, and the call site that creates kafkaData to reflect this replacement.
In
`@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java`:
- Around line 76-95: The container factory method selenium(...) no longer
applies user-configured browser options to BrowserWebDriverContainer, so
embedded.selenium.arguments are ignored; fix by creating and applying the
Capabilities built from the existing ChromeOptions/FirefoxOptions beans (the
same options that properties.apply(...) produces) to the
BrowserWebDriverContainer via withCapabilities(...) before starting it (update
the selenium(...) method to obtain the Options/Capabilities from
SeleniumProperties or call properties.apply(...) and pass the resulting
Capabilities to container.withCapabilities(...)); additionally document this
behavioral change in the module README/migration notes and clarify that
embedded.selenium.arguments are automatically applied to the container (or note
the breaking change if you prefer to require manual wiring).
In
`@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerScope.java`:
- Around line 91-96: The iteration over the instances map in afterTestMethod
(and the analogous lifecycle method at lines 113-117) is not protected against
concurrent mutation; wrap the iteration and callback invocation in the same lock
used by get/remove (synchronize on the instances object) or alternatively take a
safe snapshot (e.g., new ArrayList<>(instances.values())) before streaming, so
TestLifecycleAware callbacks (afterTest in TestcontainerScope) cannot throw
ConcurrentModificationException or miss callbacks under parallel test execution;
apply the same fix to the other lifecycle method that iterates
instances.values().
In
`@embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java`:
- Around line 73-78: The constructed init command in
EmbeddedVaultBootstrapConfiguration uses String.join(" ", secrets) which breaks
when secret values contain whitespace; update the code that builds the secrets
(the properties.getSecrets mapping before calling vault.withInitCommand) to
validate each value and reject any that contain whitespace by throwing an
IllegalArgumentException with a clear message (include the offending key and
hint to remove/escape spaces), so that vault.withInitCommand is never passed a
malformed command; alternatively, implement proper shell-quoting/escaping of
values before assembling the command if you prefer to support spaces.
---
Nitpick comments:
In
`@embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java`:
- Line 113: The unchecked cast on azuriteContainer comes from
configureCommonsAndStart returning GenericContainer<?>; change
configureCommonsAndStart to a generic signature (e.g. <T extends
GenericContainer<?>> T configureCommonsAndStart(T container,
TestcontainersConfigurationProperties properties, Log log) or <T extends
GenericContainer<T>> T configureCommonsAndStart(...)) in the implementation
(ContainerUtils.configureCommonsAndStart) and its declaration so it preserves
the concrete container type, then call it from
EmbeddedAzuriteBootstrapConfiguration without casting (azuriteContainer =
configureCommonsAndStart(azuriteContainer, properties, log)); ensure method
usages elsewhere are updated to the new generic signature.
In
`@embedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.java`:
- Around line 118-134: Replace the isInstanceOf + manual cast pattern in
shouldHaveContainerWithExpectedDefaultProperties with AssertJ's type-safe
asInstanceOf: call
asInstanceOf(InstanceOfAssertFactories.type(FakeGcsServerContainer.class)) on
the beanFactory.getBean(BEAN_NAME_EMBEDDED_GOOGLE_STORAGE_SERVER) assertion so
the lambda passed to satisfies receives a typed FakeGcsServerContainer (no
explicit cast), then keep the same assertions on getExposedPorts() and
getContainerInfo().getConfig().getEntrypoint().
In
`@embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java`:
- Around line 19-20: The field otlpHttpPort in
EmbeddedGrafanaBootstrapConfigurationTest is injected but never used; either
remove the field declaration or add a minimal reachability test that uses it
(e.g., in method within EmbeddedGrafanaBootstrapConfigurationTest perform an
HTTP request to the Grafana OTLP endpoint using otlpHttpPort — e.g., GET
http://localhost:{otlpHttpPort}/v1/health or a POST to /v1/traces with a small
payload — and assert a successful status) so the injected value is actually
referenced.
In
`@embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java`:
- Line 39: The class defines a manual Logger field "log" via LoggerFactory which
breaks module stylistic consistency; replace it by reintroducing Lombok's `@Slf4j`
on the EmbeddedNatsBootstrapConfiguration class and remove the private static
final Logger log declaration so the class uses the Lombok-generated "log"
instead (ensure Lombok is enabled in the module and imports are adjusted
accordingly).
In
`@embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java`:
- Around line 161-189: The fallback in getHostName(...) currently returns the
Linux-specific DOCKER_FOR_LINUX_STATIC_IP for any unrecognized OS; change this
so unknown/non-mac-win-linux platforms do not silently get a Linux IP: detect
the branch where OS isn't mac/win/nux, log a warning (include the OS string)
using the existing logger, and return "host.docker.internal" instead of
DOCKER_FOR_LINUX_STATIC_IP; update references in getHostName and keep
DOCKER_FOR_LINUX_STATIC_IP only for the explicit linux branch so the Linux
assumption is not applied to other platforms.
In
`@embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.java`:
- Around line 50-56: Replace the hard-coded 8080 in registerWiremockEnvironment
with a named constant; declare a private static final int WIREMOCK_INTERNAL_PORT
= 8080 (or similar) in EmbeddedWiremockBootstrapConfiguration and use that
constant when putting "embedded.wiremock.internalPort" into the map to remove
the magic number and make the intent explicit.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a4d3e000-d1bd-4c59-a57c-5eb97f5b7957
📒 Files selected for processing (71)
embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeTestOperations.javaembedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeWaitStrategy.javaembedded-azurite/pom.xmlembedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.javaembedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.javaembedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationTest.javaembedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.javaembedded-git/src/test/java/config/CustomTransportConfigCallback.javaembedded-google-pubsub/pom.xmlembedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.javaembedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/PubsubProperties.javaembedded-google-pubsub/src/test/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfigurationTest.javaembedded-google-storage/pom.xmlembedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.javaembedded-google-storage/src/main/java/com/playtika/testcontainer/storage/GoogleCloudStorageHttpClient.javaembedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.javaembedded-grafana/README.adocembedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.javaembedded-grafana/src/main/java/com/playtika/testcontainer/grafana/GrafanaProperties.javaembedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.javaembedded-grafana/src/test/resources/bootstrap.yamlembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.javaembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/KafkaConfigurationProperties.javaembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/SchemaRegistryConfigurationProperties.javaembedded-keycloak/pom.xmlembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainerFactory.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/spring/EmbeddedKeycloakBootstrapConfigurationTest.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/util/KeycloakJwtAuthenticationConverter.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/vanilla/KeycloakContainerTest.javaembedded-keydb/src/main/java/com/playtika/testcontainer/keydb/wait/KeyDbClusterStatusCheck.javaembedded-memsql/pom.xmlembedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.javaembedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.javaembedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/DefaultMinioWaitStrategy.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/MinioWaitStrategy.javaembedded-minio/src/test/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.javaembedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.javaembedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.javaembedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurerTest.javaembedded-nats/README.adocembedded-nats/pom.xmlembedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.javaembedded-nats/src/test/java/com/playtika/testcontainer/nats/BaseNatsTest.javaembedded-neo4j/src/test/java/com/playtika/testcontainer/neo4j/Person.javaembedded-redis/src/main/java/com/playtika/testcontainer/redis/wait/RedisClusterStatusCheck.javaembedded-selenium/README.adocembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerContextCustomizerFactory.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerScope.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerTestExecutionListener.javaembedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.javaembedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.javaembedded-wiremock/README.adocembedded-wiremock/pom.xmlembedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.javaembedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/spring/AbstractDependsOnPostProcessor.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/ContainerUtils.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/DateUtils.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/FileUtils.javatestcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/ContainerUtilsTest.javatestcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/MountVolumesTest.java
💤 Files with no reviewable changes (7)
- embedded-minio/src/main/java/com/playtika/testcontainer/minio/MinioWaitStrategy.java
- embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainerFactory.java
- embedded-minio/src/main/java/com/playtika/testcontainer/minio/DefaultMinioWaitStrategy.java
- embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/GoogleCloudStorageHttpClient.java
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java
- embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java
| .withCreateContainerCmdModifier(cmd -> { | ||
| List<String> args = new ArrayList<>(Arrays.asList(cmd.getCmd())); | ||
| args.add("--skipApiVersionCheck"); | ||
| cmd.withCmd(args); | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether AzuriteContainer in testcontainers-java calls withCommand() internally,
# which would determine if cmd.getCmd() can safely return non-null.
fd -i "AzuriteContainer.java" --exec cat {}Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
fd "EmbeddedAzuriteBootstrapConfiguration.java" --exec cat {}Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 7654
🏁 Script executed:
cd embedded-azurite && find . -name "pom.xml" -o -name "build.gradle" | head -1 | xargs cat | grep -A 5 -i testcontainersRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 1089
🌐 Web query:
testcontainers CreateContainerCmd getCmd() null Docker Java SDK
💡 Result:
No definitive evidence found of CreateContainerCmd.getCmd returning null in Testcontainers or Docker Java SDK under normal usage. The getCmd method in docker-java's CreateContainerCmd interface returns String[] annotated with @CheckForNull, meaning it can be null if no command (CMD) has been set via withCmd [1][2][3][4]. Testcontainers' GenericContainer creates a CreateContainerCmd via dockerClient.createContainerCmd(image) and applies modifiers, including command if withCommand is used [5][6]. If no explicit command is set, getCmd may legitimately return null, as the container uses the image's default CMD [7]. No GitHub issues or docs report getCmd unexpectedly null in Testcontainers contexts, including with Testcontainers Desktop [1-33]. Potential related issues include Docker connection problems [8][9][10] or modifier deadlocks [11], but not getCmd null specifically. Ensure withCommand is called if a custom CMD is needed, or check Docker client initialization.
Citations:
- 1: https://github.com/docker-java/docker-java/blob/master/docker-java-api/src/main/java/com/github/dockerjava/api/command/CreateContainerCmd.java
- 2: https://javadoc.io/static/com.github.docker-java/docker-java/1.4.0/com/github/dockerjava/api/command/CreateContainerCmd.html
- 3: https://javadoc.io/static/com.github.docker-java/docker-java/3.0.5/com/github/dockerjava/core/command/CreateContainerCmdImpl.html
- 4: https://github.com/docker-java/docker-java/blob/master/docker-java-core/src/main/java/com/github/dockerjava/core/command/CreateContainerCmdImpl.java
- 5: https://github.com/testcontainers/testcontainers-java/blob/main/core/src/main/java/org/testcontainers/containers/GenericContainer.java
- 6: https://java.testcontainers.org/features/advanced_options/
- 7: https://java.testcontainers.org/features/commands/
- 8: [Bug]: Testcontainers does not work with latest Docker Desktop on Mac testcontainers/testcontainers-java#11240
- 9: [Bug]: TestContainers not working with Docker Version: 29.1.3 testcontainers/testcontainers-java#11422
- 10: https://stackoverflow.com/questions/61108655/test-container-test-cases-are-failing-due-to-could-not-find-a-valid-docker-envi
- 11: [Bug]: Parallel container startup hungs when withCreateContainerCmdModifier is used testcontainers/testcontainers-java#8618
🌐 Web query:
AzuriteContainer testcontainers withCommand entrypoint
💡 Result:
AzuriteContainer is available in multiple Testcontainers libraries for different languages, providing a convenient way to spin up Azurite (Azure Storage emulator) in tests. Official modules handle the default command/entrypoint automatically, matching the Azurite Dockerfile CMD: ["azurite", "-l", "/data", "--blobHost", "0.0.0.0","--queueHost", "0.0.0.0", "--tableHost", "0.0.0.0"][1][2]. To customize using withCommand (overrides CMD) or entrypoint (overrides ENTRYPOINT), use language-specific methods on the AzuriteContainer or underlying GenericContainer: Java (org.testcontainers:azure module): AzuriteContainer extends SingleOffsetMapContainer and configures ports/envs but inherits.withCommand(String... cmd) and.withEntrypoint(String... entrypoint) from GenericContainer[3][4][5]. Example: AzuriteContainer azurite = new AzuriteContainer("mcr.microsoft.com/azure-storage/azurite:3.33.0") .withCommand("azurite", "--loose", "--blobHost", "0.0.0.0") .withExposedPorts(10000, 10001, 10002); azurite.start(); Default usage without custom command: new AzuriteContainer(image).start;[6][5]..NET (Testcontainers.Azurite): Use AzuriteBuilder.WithCommand(params string[] command)[7]. Example for HTTPS: var container = new AzuriteBuilder("mcr.microsoft.com/azure-storage/azurite:latest") .WithCommand("--cert", "/workspace/127.0.0.1.pem", "--key", "/workspace/127.0.0.1-key.pem", "--oauth", "basic") .WithResourceMapping(...) .Build(); [6]. Rust (testcontainers-modules): Azurite implements ImageArgsExt.with_cmd(vec![String])[8]. Example: let azurite = Azurite::default().with_cmd(vec!["azurite".to_owned(), "--loose".to_owned()]).start(); [8]. Python/Node.js: Specialized methods like withSsl internally handle commands; fall back to GenericContainer equivalents[9][10]. For blob-only:.withCommand("azurite-blob", "--blobHost", "0.0.0.0")[2][11]. Expose only needed ports. Official Testcontainers docs prioritize simple new AzuriteContainer.start as it uses correct defaults[12][6][5]. Custom commands needed for options like --loose, custom ports, SSL[9][7].
Citations:
- 1: https://github.com/Azure/Azurite/blob/main/Dockerfile
- 2: https://github.com/Azure/Azurite/blob/main/README.mcr.md
- 3: https://github.com/testcontainers/testcontainers-java/blob/main/modules/azure/src/test/java/org/testcontainers/azure/AzuriteContainerTest.java
- 4: https://github.com/testcontainers/testcontainers-java/blob/main/modules/azure/src/main/java/org/testcontainers/azure/AzuriteContainer.java
- 5: https://www.testcontainers.org/modules/azure/
- 6: https://testcontainers.com/modules/azurite
- 7: https://iharmaiseyeu.net/use-testcontainers-for-running-azurite-in-azure-devops-pipeline
- 8: https://docs.rs/testcontainers-modules/latest/testcontainers_modules/azurite/struct.Azurite.html
- 9: https://node.testcontainers.org/modules/azurite
- 10: https://testcontainers-python.readthedocs.io/en/testcontainers-v4.5.1/modules/azurite/README.html
- 11: https://docs.azure.cn/en-us/storage/common/storage-install-azurite
- 12: https://testcontainers.com/modules/azurite/
cmd.getCmd() returns null when no command is explicitly set, causing an NPE via Arrays.asList.
The CreateContainerCmd.getCmd() method is annotated with @CheckForNull in the Docker Java SDK, confirming it can return null when no command has been set via withCmd. Since AzuriteContainer does not call withCommand() internally and relies on the image's default CMD, getCmd() returns null when new AzuriteContainer(image) is created without prior customization. Calling Arrays.asList(cmd.getCmd()) on a null input throws a NullPointerException.
Add a null guard to safely handle this case:
Proposed fix
.withCreateContainerCmdModifier(cmd -> {
- List<String> args = new ArrayList<>(Arrays.asList(cmd.getCmd()));
+ String[] existing = cmd.getCmd();
+ List<String> args = existing != null ? new ArrayList<>(Arrays.asList(existing)) : new ArrayList<>();
args.add("--skipApiVersionCheck");
cmd.withCmd(args);
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .withCreateContainerCmdModifier(cmd -> { | |
| List<String> args = new ArrayList<>(Arrays.asList(cmd.getCmd())); | |
| args.add("--skipApiVersionCheck"); | |
| cmd.withCmd(args); | |
| }); | |
| .withCreateContainerCmdModifier(cmd -> { | |
| String[] existing = cmd.getCmd(); | |
| List<String> args = existing != null ? new ArrayList<>(Arrays.asList(existing)) : new ArrayList<>(); | |
| args.add("--skipApiVersionCheck"); | |
| cmd.withCmd(args); | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java`
around lines 105 - 109, The lambda passed to withCreateContainerCmdModifier uses
Arrays.asList(cmd.getCmd()) which throws NPE because CreateContainerCmd.getCmd()
can be null; update the modifier in EmbeddedAzuriteBootstrapConfiguration so it
first checks cmd.getCmd() for null and builds the args list accordingly (e.g.,
start from an empty List if null or new ArrayList<>(Arrays.asList(cmd.getCmd()))
if non-null), then add "--skipApiVersionCheck" and call cmd.withCmd(args) as
before; reference the CreateContainerCmd instance named cmd and the existing
cmd.withCmd(...) call when making the change.
| * `embedded.grafana.filesToInclude` Classpath resources to copy into the container at startup. Use this to provision custom Grafana datasources, dashboards, or alert rules. Example `bootstrap.yaml`: | ||
|
|
||
| [source,yaml] | ||
| ---- | ||
| embedded: | ||
| grafana: | ||
| filesToInclude: | ||
| - classpathResource: /embedded/grafana/provisioning/datasources/my-datasource.yml | ||
| containerPath: /etc/grafana/provisioning/datasources/my-datasource.yml | ||
| ---- |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
grafana otel-lgtm image grafana provisioning datasources path location
💡 Result:
In the grafana/otel-lgtm Docker image, Grafana provisioning files for datasources are located at /otel-lgtm/grafana/conf/provisioning/datasources/. The default datasource configuration file is grafana-datasources.yaml, which provisions Prometheus, Tempo, Loki, and Pyroscope datasources.[1][2][3] This follows standard Grafana provisioning conventions, where YAML files in the provisioning/datasources directory define datasources.[4] For dashboards, provisioning files are at /otel-lgtm/grafana/conf/provisioning/dashboards/, with examples like grafana-dashboards.yaml.[5][2][6] To customize, mount your own YAML files into these paths via Docker volumes, as shown in the repo examples for dashboards (analogous for datasources).[5] Grafana data is at /data/grafana (overridable via GF_PATHS_DATA), but provisioning configs are in the fixed /otel-lgtm/grafana/conf/provisioning structure.[7]
Citations:
- 1: https://github.com/grafana/docker-otel-lgtm/blob/0fa1021c/docker/grafana-datasources.yaml
- 2: https://github.com/grafana/docker-otel-lgtm/blob/0fa1021c/docker/Dockerfile
- 3: https://github.com/grafana/docker-otel-lgtm/blob/main/docker/grafana-datasources.yaml
- 4: https://grafana.com/docs/grafana/latest/administration/provisioning/
- 5: https://github.com/grafana/docker-otel-lgtm/?tab=readme-ov-file
- 6: Make grafana-dashboards.yaml configurable grafana/docker-otel-lgtm#117
- 7: https://github.com/grafana/docker-otel-lgtm/blob/main/run-lgtm.sh
Update the filesToInclude example to use the correct provisioning path for otel-lgtm.
The example path /etc/grafana/provisioning/datasources/my-datasource.yml is the standard Grafana OSS location, but the grafana/otel-lgtm image uses a custom bundled layout. Change the example to /otel-lgtm/grafana/conf/provisioning/datasources/my-datasource.yml so users who copy it will actually provision datasources correctly.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@embedded-grafana/README.adoc` around lines 30 - 39, The example under
embedded.grafana.filesToInclude uses the standard Grafana path which is
incorrect for the grafana/otel-lgtm image; update the containerPath value in the
example to the otel-lgtm provisioning location
(/otel-lgtm/grafana/conf/provisioning/datasources/my-datasource.yml) so that
embedded.grafana.filesToInclude points classpath resources into the correct
otel-lgtm container provisioning directory.
| <!-- renovate: datasource=github-releases depName=dasniko/testcontainers-keycloak --> | ||
| <testcontainers-keycloak.version>3.3.0</testcontainers-keycloak.version> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the embedded-keycloak/pom.xml file
cat -n embedded-keycloak/pom.xml | head -40Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 1958
🏁 Script executed:
# Check the KeycloakProperties.java file for the image version
find . -name "KeycloakProperties.java" -type fRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 176
🏁 Script executed:
# Check the parent POM for Testcontainers version
find . -name "pom.xml" -type f -path "*/testcontainers-*" | head -5
cat pom.xml | grep -A 5 -B 5 "testcontainers" | head -40Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 1846
🌐 Web query:
testcontainers-keycloak 3.3.0 compatibility Keycloak Testcontainers version matrix
💡 Result:
testcontainers-keycloak version 3.3.0 (released around March 2024 [1]) is compatible with Keycloak 24.0, as per the official version matrix in the project's docs [2]. It uses Testcontainers 1.19.6 [2]. The full version compatibility matrix from the official docs/versions.md [2] is: | Testcontainers-Keycloak | Testcontainers | Keycloak | |-------------------------|----------------|----------| | 4.2.x | 2.0.4 | 26.6 | | 4.1.x | 2.0.3 | 26.5 | | 4.0.x (Docker 29+) | 2.0.2 | 26.4 | | 3.9.x | 1.21.3 | 26.4 | | 3.8.x | 1.21.3 | 26.3 | | 3.7.x | 1.20.6 | 26.2 | | 3.6.x | 1.20.4 | 26.1 | | 3.5.x | 1.20.2 | 26.0 | | 3.4.x | 1.19.8 | 25.0 | | 3.3.x | 1.19.6 | 24.0 | | 3.2.x | 1.19.3 | 23.0 | | 3.1.x | 1.18.3 | 22.0.5 | | 3.0.x | 1.18.3 | 22.0 | A GitHub issue [3] groups 3.0.x-3.3.x as supporting Keycloak 22.x-25.x, which aligns with the matrix since 3.3.x defaults to 24.0 but may support the range via custom images. Newer versions like 3.4.x require Keycloak 25.x+ due to wait strategy changes [3], and 3.5.x requires 26.x+ [3]. The repo README notes version 3.x handles Keycloak 22.x and up [4]. By default, it uses quay.io/keycloak/keycloak:24.0 [2].
Citations:
- 1: https://mvnrepository.com/artifact/com.github.dasniko/testcontainers-keycloak/3.3.0
- 2: https://github.com/dasniko/testcontainers-keycloak/blob/main/docs/versions.md
- 3: Outdated Keycloak version compatibility documentation dasniko/testcontainers-keycloak#163
- 4: https://github.com/dasniko/testcontainers-keycloak
🏁 Script executed:
# Read KeycloakProperties.java to find the image version
cat embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.java | grep -A 2 -B 2 "image\|25\.0\|keycloak:" | head -20Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 225
🏁 Script executed:
# Check testcontainers-spring-boot-parent/pom.xml for Testcontainers version
cat -n testcontainers-spring-boot-parent/pom.xml | grep -A 5 -B 5 "testcontainers.version" | head -30Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
# Also check what Testcontainers version is in the parent or BOM
rg "testcontainers" testcontainers-spring-boot-parent/pom.xml -A 2 -B 2Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 1488
🏁 Script executed:
# Check the full testcontainers-spring-boot-parent/pom.xml for version properties
cat testcontainers-spring-boot-parent/pom.xml | head -100Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 4481
🏁 Script executed:
# Look for testcontainers BOM import or version in the parent
rg "org.testcontainers" testcontainers-spring-boot-parent/pom.xml -B 2 -A 5Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 382
🏁 Script executed:
# Check full parent pom.xml for any testcontainers BOM import
cat testcontainers-spring-boot-parent/pom.xml | grep -A 10 "testcontainers"Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 2451
🏁 Script executed:
# Check BOM pom.xml for testcontainers configuration
cat testcontainers-spring-boot-bom/pom.xml | head -100Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 4496
🌐 Web query:
Spring Boot 4.0.6 testcontainers version dependency
💡 Result:
For Spring Boot 4.0.6, the Testcontainers dependency version managed by the Spring Boot BOM (spring-boot-dependencies) is 2.0.5. This is confirmed in the official release notes for v4.0.6, which explicitly state "Upgrade to Testcontainers 2.0.5 #50135" [1]. Spring Boot manages third-party dependencies like Testcontainers (org.testcontainers:testcontainers) through its BOM, so when using Spring Boot 4.0.6 as the parent or importing the BOM, Testcontainers is aligned to this version without needing an explicit version declaration. To use Testcontainers support in tests with Spring Boot 4.0.6, add the test-scoped dependency: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-testcontainers</artifactId> <scope>test</scope> </dependency> The spring-boot-testcontainers artifact itself is version 4.0.6 (aligned with Spring Boot), and it depends on org.testcontainers:testcontainers 2.0.5 as managed [2][1]. Official docs recommend spring-boot-testcontainers for @ServiceConnection with Testcontainers [3]. Spring Boot 4.0.6 was released on 2026-04-23 [1][4].
Citations:
- 1: https://github.com/spring-projects/spring-boot/releases/tag/v4.0.6
- 2: https://central.sonatype.com/artifact/org.springframework.boot/spring-boot-testcontainers/4.0.0
- 3: https://docs.spring.io/spring-boot/reference/testing/testcontainers.html
- 4: https://spring.io/blog/2026/04/23/spring-boot-4-0-6-available-now
Upgrade testcontainers-keycloak to align with Keycloak 25.0.6 and Testcontainers 2.x baseline.
testcontainers-keycloak 3.3.0 is designed for Keycloak 24.0 and Testcontainers 1.19.6, but this module defaults to Keycloak 25.0.6 and the repo parent manages Testcontainers 2.0.5 (via Spring Boot 4.0.6). This mismatch is likely to cause startup or API breakage. Consider upgrading to a compatible version—e.g., 3.4.x (Keycloak 25.0, Testcontainers 1.19.8) or 4.x (Keycloak 26.x, Testcontainers 2.x, requires Docker 29+), potentially paired with a corresponding Keycloak image update.
Affected locations
Lines 17-18, 31-33
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@embedded-keycloak/pom.xml` around lines 17 - 18, The POM pins
testcontainers-keycloak.version to 3.3.0 which targets Keycloak 24 and
Testcontainers 1.19.6; update the testcontainers-keycloak.version property
(reference: testcontainers-keycloak.version) to a compatible release (e.g.,
3.4.x if you want Keycloak 25.x compatibility or 4.x if you plan to move to
Keycloak 26+/Testcontainers 2.x), and also align any Keycloak docker image tags
and the Testcontainers baseline managed by the parent (Spring Boot) so the
testcontainers-keycloak client, Keycloak image tag and Testcontainers runtime
are mutually compatible before running tests.
| public KeycloakContainer keycloakContainer(ConfigurableEnvironment environment, | ||
| KeycloakProperties properties, | ||
| ResourceLoader resourceLoader, | ||
| Optional<Network> network) { | ||
| KeycloakContainer keycloak = new KeycloakContainer(ContainerUtils.getDockerImageName(properties).toString()) | ||
| .withNetworkAliases(KEYCLOAK_NETWORK_ALIAS) | ||
| .withAdminUsername(properties.getAdminUser()) | ||
| .withAdminPassword(properties.getAdminPassword()); | ||
|
|
||
| applyDbConfig(keycloak, properties); | ||
| applyImportFile(keycloak, properties, resourceLoader); | ||
|
|
||
| network.ifPresent(keycloak::withNetwork); | ||
|
|
||
| keycloak = (KeycloakContainer) configureCommonsAndStart(keycloak, properties, log); | ||
| registerEnvironment(keycloak, environment, properties); | ||
| return keycloak; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "EmbeddedKeycloakBootstrapConfiguration.java" -type fRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 196
🏁 Script executed:
find . -name "KeycloakProperties.java" -type fRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 176
🏁 Script executed:
find . -name "*.java" -path "*keycloak*" | head -20Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 1358
🏁 Script executed:
wc -l ./embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 200
🏁 Script executed:
cat -n ./embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 8972
🏁 Script executed:
cat -n ./embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 3621
🏁 Script executed:
find ./embedded-keycloak -name "pom.xml" -type fRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 110
🏁 Script executed:
cat ./embedded-keycloak/pom.xml | grep -A 5 -B 5 "dasniko"Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 820
🌐 Web query:
dasniko testcontainers-keycloak 3.3.0 withContextPath getAuthServerUrl
💡 Result:
In dasniko/testcontainers-keycloak 3.3.0, KeycloakContainer.getAuthServerUrl appends the configured context path (KEYCLOAK_CONTEXT_PATH) to the returned auth server URL. If you do not change the context path (default is “/”), the returned URL ends with a trailing “/”. [1][2][3] What this means for withContextPath - If you call.withContextPath("/auth"), then getAuthServerUrl ends with "/auth" (so you should use keycloak.getAuthServerUrl as-is when building endpoints like.../realms/{realm}/...). This behavior is explicitly tested for a non-default context path. [3] - If you do not modify the context path (default “/”), then getAuthServerUrl ends with “/”. A known issue is that this can lead to double-slash problems when consumers build URLs by concatenation; the project discusses that getAuthServerUrl ends with the context path and that the default “/” causes a trailing “/”. [1] Quick example (issuer-uri construction) - Use string concatenation exactly once, e.g. registry.add("...issuer-uri", -> keycloak.getAuthServerUrl + "/realms/test"); (the official README example does this). [2] Sources: [1][2][3]
Citations:
- 1: Fix default context path dasniko/testcontainers-keycloak#108
- 2: https://github.com/dasniko/testcontainers-keycloak
- 3: https://github.com/dasniko/testcontainers-keycloak/blob/master/src/test/java/dasniko/testcontainers/keycloak/KeycloakContainerTest.java
🌐 Web query:
dasniko testcontainers-keycloak KeycloakContainer API documentation 3.3.0
💡 Result:
The official API documentation for the KeycloakContainer class in dasniko/testcontainers-keycloak version 3.3.0 is available in the project's Javadoc JAR, published to Maven Central [1][2]. Download testcontainers-keycloak-3.3.0-javadoc.jar from https://repo1.maven.org/maven2/com/github/dasniko/testcontainers-keycloak/3.3.0/testcontainers-keycloak-3.3.0-javadoc.jar [2] and extract it to view the full API docs, including dasniko.testcontainers.keycloak.KeycloakContainer. No hosted online Javadoc specific to 3.3.0 was found; current javadoc.io hosts latest version (4.1.1+) [3]. The primary usage and method documentation is in the GitHub README [4][5], which covers version 3.3.0 features like withDefaultProviderClasses added in 3.3 [4]. Key methods and usage from README and tests [4][6][7]: - Constructors: new KeycloakContainer (default, deprecated in later versions) [4]; new KeycloakContainer(String imageName) e.g., new KeycloakContainer("quay.io/keycloak/keycloak:26.4") [4]. - withRealmImportFile(String path) - Import realm JSON from classpath [6][7]. - withRealmImportFiles(String... paths) - Multiple realms [6]. - withProviderClassesFrom(String... classpaths) or withDefaultProviderClasses (since 3.3) - Add custom providers [8][4]. - withContextPath(String path) e.g., "/auth" [4]. - getAuthServerUrl - Returns http(s)://host:port/contextPath/realms [4][6]. - getKeycloakAdminClient - Returns org.keycloak.admin.Keycloak instance with admin credentials [4]. - withAdminPassword(String password) - Set admin password [6]. - withStartupTimeout(Duration) [6]. - withCustomCommand(String... parts) - Added around 3.4, may be available [8]. - useTls, withOptimizedFlag, etc. [9]. Full source code is viewable on GitHub main branch (post-3.3.0, minor changes) at https://github.com/dasniko/testcontainers-keycloak/blob/main/src/main/java/dasniko/testcontainers/keycloak/KeycloakContainer.java (inferred path from tests [6]). For exact 3.3.0 source, check tag v3.3.0 [10][11]. Example usage [4][7]: `@Container` KeycloakContainer keycloak = new KeycloakContainer("quay.io/keycloak/keycloak:25.0") .withRealmImportFile("test-realm.json"); keycloak.start(); String authServerUrl = keycloak.getAuthServerUrl(); Keycloak admin = keycloak.getKeycloakAdminClient(); Version 3.3.0 released 2024-03-04 [1][12].
Citations:
- 1: https://mvnrepository.com/artifact/com.github.dasniko/testcontainers-keycloak/3.3.0
- 2: https://repo1.maven.org/maven2/com/github/dasniko/testcontainers-keycloak/3.3.0/
- 3: https://javadoc.io/doc/com.github.dasniko/testcontainers-keycloak
- 4: https://github.com/dasniko/testcontainers-keycloak
- 5: https://github.com/dasniko/testcontainers-keycloak/blob/main/README.md
- 6: https://github.com/dasniko/testcontainers-keycloak/blob/master/src/test/java/dasniko/testcontainers/keycloak/KeycloakContainerTest.java
- 7: https://testcontainers.com/modules/keycloak/
- 8: dasniko/testcontainers-keycloak@v.3.3.1...3.4.0
- 9: https://github.com/dasniko/testcontainers-keycloak/blob/main/src/test/java/dasniko/testcontainers/keycloak/KeycloakContainerOptimizedTest.java
- 10: https://github.com/dasniko/testcontainers-keycloak/releases
- 11: https://github.com/dasniko/testcontainers-keycloak/releases/tag/3.4.0
- 12: https://central.sonatype.com/artifact/com.github.dasniko/testcontainers-keycloak
🏁 Script executed:
rg "withContextPath|getAuthServerUrl" ./embedded-keycloak --type javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
rg "getAuthServerUrl" . --type javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
rg "withContextPath" . --type javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
grep -n "authBasePath" ./embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
🏁 Script executed:
grep -n "getAuthBasePath" ./embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 201
Wire authBasePath into the container using withContextPath(...), not just the exported property.
authBasePath is only used when composing embedded.keycloak.auth-server-url (line 150), so a non-default value like /auth will publish an /auth URL even though the container is still started on /. The dasniko container provides withContextPath(...) to configure the context path and getAuthServerUrl() to retrieve the resolved auth server URL, which should be used instead of manual URL composition.
- Add
.withContextPath(properties.getAuthBasePath())to the container initialization (line 67-70) - Replace the manual
buildAuthServerUrl(...)call withkeycloak.getAuthServerUrl()(line 134)
Suggested changes
KeycloakContainer keycloak = new KeycloakContainer(ContainerUtils.getDockerImageName(properties).toString())
.withNetworkAliases(KEYCLOAK_NETWORK_ALIAS)
+ .withContextPath(properties.getAuthBasePath())
.withAdminUsername(properties.getAdminUser())
.withAdminPassword(properties.getAdminPassword());- String authServerUrl = buildAuthServerUrl(keycloak, properties);
+ String authServerUrl = keycloak.getAuthServerUrl();🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java`
around lines 63 - 79, The container is not started with the configured context
path and the auth URL is being composed manually; update the KeycloakContainer
creation in keycloakContainer(...) to call
.withContextPath(properties.getAuthBasePath()) on the KeycloakContainer
instance, and after starting/configuring the container (i.e., after
configureCommonsAndStart(...)) replace any manual buildAuthServerUrl(...) usage
with keycloak.getAuthServerUrl() when registering/exporting the
embedded.keycloak.auth-server-url in registerEnvironment(...), ensuring
KeycloakContainer.getAuthServerUrl() is used to obtain the resolved URL.
| private void applyDbConfig(KeycloakContainer keycloak, KeycloakProperties properties) { | ||
| if (properties.getDbVendor() != null) { | ||
| keycloak.withEnv("DB", properties.getDbVendor()); | ||
| } | ||
| if (properties.getDbAddr() != null) { | ||
| keycloak.withEnv("DB_URL_HOST", properties.getDbAddr()); | ||
| } | ||
| if (properties.getDbPort() != null) { | ||
| keycloak.withEnv("DB_URL_PORT", properties.getDbPort()); | ||
| } | ||
| if (properties.getDbDatabase() != null) { | ||
| keycloak.withEnv("DB_URL_DATABASE", properties.getDbDatabase()); | ||
| } | ||
| if (properties.getDbSchema() != null) { | ||
| keycloak.withEnv("DB_SCHEMA", properties.getDbSchema()); | ||
| } | ||
| if (properties.getDbUser() != null) { | ||
| keycloak.withEnv("DB_USERNAME", properties.getDbUser()); | ||
| } | ||
| if (properties.getDbUserFile() != null) { | ||
| keycloak.withEnv("DB_USER_FILE", properties.getDbUserFile()); | ||
| } | ||
| if (properties.getDbPassword() != null) { | ||
| keycloak.withEnv("DB_PASSWORD", properties.getDbPassword()); | ||
| } | ||
| if (properties.getDbPasswordFile() != null) { | ||
| keycloak.withEnv("DB_PASSWORD_FILE", properties.getDbPasswordFile()); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Keycloak 25 database environment variables KC_DB documentation
💡 Result:
In Keycloak 25, database configuration via environment variables uses the KC_DB_* format, corresponding to CLI options and keycloak.conf properties. This has not changed from previous versions based on official documentation and release notes [1][2][3]. Key KC_DB environment variables for the main (default) datasource include: - KC_DB: Specifies the database vendor (e.g., postgres, mariadb, mysql, mssql, oracle, dev-file). CLI: --db, default: dev-file (deprecated in production) [1][4]. - KC_DB_USERNAME: Database username. CLI: --db-username [1][5]. - KC_DB_PASSWORD: Database password. Use KCRAW_DB_PASSWORD if password contains $ or ${...} to preserve literals [1][6]. - KC_DB_URL: Full JDBC URL (overrides host/database/port). CLI: --db-url [1][4]. - KC_DB_URL_HOST: Database host. CLI: --db-url-host [1]. - KC_DB_URL_PORT: Database port. CLI: --db-url-port [1]. - KC_DB_URL_DATABASE: Database name. CLI: --db-url-database [1]. - KC_DB_SCHEMA: Database schema (default: keycloak for most DBs). CLI: --db-schema [1][5]. Additional pool/options: - KC_DB_POOL_MIN_SIZE, KC_DB_POOL_MAX_SIZE: Connection pool sizes [4]. - KC_DB_CONNECT_TIMEOUT: Connection timeout in milliseconds [4]. - KC_TRANSACTION_XA_ENABLED: Enable XA transactions (default: true) [5]. Examples from docs [1][5]: For Docker/container: ENV KC_DB=postgres ENV KC_DB_URL_HOST=keycloak-postgres ENV KC_DB_USERNAME=keycloak ENV KC_DB_PASSWORD=change_me Configuration can be set at build or start steps. In production, explicitly set KC_DB (dev-file unsuitable) [1]. For passwords with special chars, use KCRAW_ prefix [1][6]. Full list at https://www.keycloak.org/server/all-config [4]. No breaking DB env var changes in Keycloak 25 release notes [2][3][7].
Citations:
- 1: https://www.keycloak.org/server/db
- 2: https://www.keycloak.org/docs/25.0.6/release_notes/
- 3: https://github.com/keycloak/keycloak/releases/tag/25.0.0
- 4: https://www.keycloak.org/server/all-config
- 5: https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/24.0/html/server_guide/db-
- 6: https://www.keycloak.org/server/configuration
- 7: https://github.com/keycloak/keycloak/blob/main/docs/documentation/upgrading/topics/changes/changes-25_0_0.adoc
🌐 Web query:
Keycloak Quarkus database configuration environment variables KC_DB_USERNAME KC_DB_PASSWORD
💡 Result:
Environment variables for Keycloak (Quarkus distribution) database credentials are: 1) KC_DB_USERNAME - Maps to the Keycloak database config option db-username, exposed as environment variable KC_DB_USERNAME [1]. 2) KC_DB_PASSWORD - Maps to the Keycloak database config option db-password, exposed as environment variable KC_DB_PASSWORD [1]. Notes (important when using env vars) - If your DB password contains $ or ${…} characters, Keycloak documentation says to use the KCRAW_DB_PASSWORD environment variable instead of KC_DB_PASSWORD so the value is preserved as-is [2][3]. - Configuration via environment variables is supported as an alternative to configuring via conf/keycloak.conf or CLI args [2]. Example (PostgreSQL) export KC_DB=postgres export KC_DB_URL_HOST=keycloak-postgres export KC_DB_USERNAME=keycloak export KC_DB_PASSWORD='change_me' [2][4][1] If you want, tell me your database type (postgres/mysql/mssql/oracle) and whether you run kc.sh build before kc.sh start, and I can suggest the exact minimal set of env vars for your setup.
Citations:
- 1: https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/22.0/html/server_guide/all-config-
- 2: https://www.keycloak.org/server/db
- 3: https://www.keycloak.org/server/configuration
- 4: https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.4/html/server_configuration_guide/db-
🌐 Web query:
Keycloak 25 DB_USER_FILE DB_PASSWORD_FILE environment variable support
💡 Result:
Keycloak 25 does not natively support DB_USER_FILE or DB_PASSWORD_FILE environment variables for reading database credentials from files. Official documentation lists the environment variable for database password as KC_DB_PASSWORD and for username as KC_DB_USERNAME, with no mention of *_FILE variants [1][2][3][4]. A feature request for general *_FILE support exists but remains open without implementation [5]. The kc.sh script does not process *_FILE variables [6].
Citations:
- 1: https://www.keycloak.org/server/db
- 2: https://docs.redhat.com/en/documentation/red_hat_build_of_keycloak/26.4/html/server_configuration_guide/db-
- 3: https://www.keycloak.org/server/all-config
- 4: https://keycloak.org/server/db
- 5: Read secrets from files keycloak/keycloak#10816
- 6: https://github.com/keycloak/keycloak/blob/main/quarkus/dist/src/main/content/bin/kc.sh
Use the Keycloak 25 KC_* database env keys instead of legacy DB_* variables.
The code currently uses unprefixed DB* variables, which are not the documented or supported environment variables in Keycloak 25. The official Keycloak documentation specifies the proper keys as KC_DB, KC_DB_URL_HOST, KC_DB_URL_PORT, KC_DB_URL_DATABASE, KC_DB_SCHEMA, KC_DB_USERNAME, and KC_DB_PASSWORD. Configuration using the current DB* names will not be applied and Keycloak will fall back to its defaults.
Additionally, Keycloak does not support *_FILE variants for reading credentials from files. The DB_USER_FILE and DB_PASSWORD_FILE branches need alternative implementations, such as reading the file contents in this configuration method and passing them directly via KC_DB_USERNAME and KC_DB_PASSWORD, or using Docker secrets/volume mounts with a custom entrypoint.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java`
around lines 82 - 109, The applyDbConfig method in
EmbeddedKeycloakBootstrapConfiguration is setting legacy DB_* env vars; change
it to set the Keycloak 25 names (e.g. KC_DB, KC_DB_URL_HOST, KC_DB_URL_PORT,
KC_DB_URL_DATABASE, KC_DB_SCHEMA, KC_DB_USERNAME, KC_DB_PASSWORD) on the
KeycloakContainer instead of DB_*; remove emitting DB_USER_FILE/DB_PASSWORD_FILE
env vars and, when KeycloakProperties.getDbUserFile() or getDbPasswordFile() is
provided, read those files' contents inside applyDbConfig and set the
corresponding KC_DB_USERNAME / KC_DB_PASSWORD values on the KeycloakContainer
(or fall back to getDbUser()/getDbPassword() if present), ensuring no *_FILE env
vars are passed to the container. Reference: applyDbConfig(KeycloakContainer,
KeycloakProperties), KeycloakContainer.withEnv(...),
KeycloakProperties.getDbUserFile()/getDbPasswordFile()/getDbUser()/getDbPassword().
| public MemSqlContainer withUsername(String username) { | ||
| this.username = username; | ||
| return self(); | ||
| } |
There was a problem hiding this comment.
withUsername currently allows credentials the container never provisions
Line 28 accepts any username, but Line 45-53 only configures root credentials, while Line 66 returns the custom username. This can produce unreachable credentials (jdbcUrl + username/password that cannot authenticate).
Proposed fix (fail fast unless root is used)
public MemSqlContainer withUsername(String username) {
- this.username = username;
+ if (!"root".equals(username)) {
+ throw new IllegalArgumentException("MemSqlContainer currently supports only 'root' username");
+ }
+ this.username = username;
return self();
}Also applies to: 45-53, 66-68
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java`
around lines 28 - 31, The withUsername method in MemSqlContainer currently
accepts arbitrary usernames while the container only provisions root
credentials, causing unreachable credentials; update withUsername(String
username) in class MemSqlContainer to validate input and fail fast by throwing
an IllegalArgumentException (or IllegalStateException) if the caller passes a
non-root username (i.e., anything other than "root"), or alternatively implement
user provisioning in the container configuration flow (the configure/start
methods) to create the requested user; reference the withUsername method and the
container configuration/start logic (where root credentials are set) and ensure
getUsername/getPassword/getJdbcUrl return only credentials that the container
actually provisions.
| private static String convertStreamToString(java.io.InputStream is) { | ||
| java.util.Scanner s = new java.util.Scanner(is, StandardCharsets.UTF_8.name()).useDelimiter("\\A"); | ||
| java.util.Scanner s = new java.util.Scanner(is, StandardCharsets.UTF_8).useDelimiter("\\A"); | ||
| return s.hasNext() ? s.next() : ""; |
There was a problem hiding this comment.
Close stream/scanner in convertStreamToString to avoid leaked resources.
This helper creates a Scanner over an InputStream and never closes either. In repeated test runs this can leak response streams.
Suggested fix
- private static String convertStreamToString(java.io.InputStream is) {
- java.util.Scanner s = new java.util.Scanner(is, StandardCharsets.UTF_8).useDelimiter("\\A");
- return s.hasNext() ? s.next() : "";
- }
+ private static String convertStreamToString(java.io.InputStream is) {
+ try (java.io.InputStream in = is;
+ java.util.Scanner s = new java.util.Scanner(in, StandardCharsets.UTF_8).useDelimiter("\\A")) {
+ return s.hasNext() ? s.next() : "";
+ }
+ }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-minio/src/test/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfigurationTest.java`
around lines 100 - 102, The convertStreamToString helper creates a Scanner over
the provided InputStream but never closes it, leaking resources; update
convertStreamToString to use a try-with-resources (or explicitly close) for the
Scanner (which will also close the InputStream) so the Scanner and underlying
stream are always closed after reading, and return the same string result;
reference: convertStreamToString(java.io.InputStream).
|
|
||
| <properties> | ||
| <wiremock.version>3.13.2</wiremock.version> | ||
| <wiremock-testcontainers-module.version>1.0-alpha-13</wiremock-testcontainers-module.version> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and read the pom.xml file mentioned
find . -name "pom.xml" -path "*/embedded-wiremock/*" | head -20Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 110
🏁 Script executed:
# Read the embedded-wiremock/pom.xml file to verify line 18
cat -n embedded-wiremock/pom.xml | sed -n '15,25p'Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 530
🌐 Web query:
wiremock-testcontainers-module latest version Maven Central 2025
💡 Result:
The latest version of wiremock-testcontainers-module on Maven Central is 1.0-alpha-15, released on 2025-03-30 [1][2][3]. This is confirmed by the official Maven Central artifact page, GitHub packages, and repository, with no newer versions listed as of 2026-05-07 [1][4][2][5]. Maven dependency: <dependency><groupId>org.wiremock.integrations.testcontainers</groupId><artifactId>wiremock-testcontainers-module</artifactId><version>1.0-alpha-15</version><scope>test</scope></dependency> [1][3].
Citations:
- 1: https://central.sonatype.com/artifact/org.wiremock.integrations.testcontainers/wiremock-testcontainers-module
- 2: https://github.com/wiremock/wiremock-testcontainers-java/packages/1839722
- 3: https://github.com/wiremock/wiremock-testcontainers-java
- 4: https://github.com/wiremock/wiremock-testcontainers-java/packages/1839722/versions
- 5: https://mvnrepository.com/artifact/org.wiremock.integrations.testcontainers/wiremock-testcontainers-module/versions
Update wiremock-testcontainers-module from 1.0-alpha-13 to 1.0-alpha-15.
The current version is two alpha releases behind the latest available version on Maven Central. Upgrading captures bug fixes and potential Testcontainers compatibility improvements from alpha-14 and alpha-15.
Proposed update
-<wiremock-testcontainers-module.version>1.0-alpha-13</wiremock-testcontainers-module.version>
+<wiremock-testcontainers-module.version>1.0-alpha-15</wiremock-testcontainers-module.version>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@embedded-wiremock/pom.xml` at line 18, Update the
wiremock-testcontainers-module version property value from 1.0-alpha-13 to
1.0-alpha-15 in the Maven POM by changing the
<wiremock-testcontainers-module.version> property (the property named
wiremock-testcontainers-module.version) so the project uses the newer alpha-15
release; then run a quick mvn -U test or dependency:resolve to ensure the new
artifact resolves and adjust any failing tests if API/behavior changed.
| for (MountVolume mountVolume : properties.getMountVolumes()) { | ||
| updatedContainer.addFileSystemBind(mountVolume.getHostPath(), mountVolume.getContainerPath(), mountVolume.getMode()); | ||
| updatedContainer.withCopyToContainer(MountableFile.forHostPath(mountVolume.getHostPath()), mountVolume.getContainerPath()); | ||
| } |
There was a problem hiding this comment.
addFileSystemBind → withCopyToContainer is a breaking semantic change and causes the CI failure.
withCopyToContainer copies files into the container once at startup (one-way); it does not create a live bind-mount. This has two direct consequences:
BindModeis silently dropped —READ_WRITEcallers (e.g., apgdatavolume intended for persistence) will no longer see writes reflected on the host.getBinds()now returns an empty list, directly causing the pipeline failure inContainerUtilsTest.configureCommonsAndStartat line 88 (Expected size: 2 but was: 0).
Additionally, the return value of withCopyToContainer is not captured (unlike the withCopyFileToContainer call at line 83), which is a stylistic inconsistency (though harmless since GenericContainer mutates in-place).
If the intent is to keep bind-mount semantics, revert to addFileSystemBind:
🐛 Proposed fix — restore bind-mount semantics and fix return-value capture
for (MountVolume mountVolume : properties.getMountVolumes()) {
- updatedContainer.withCopyToContainer(MountableFile.forHostPath(mountVolume.getHostPath()), mountVolume.getContainerPath());
+ updatedContainer = updatedContainer.withFileSystemBind(mountVolume.getHostPath(), mountVolume.getContainerPath(), mountVolume.getMode());
}If withCopyToContainer is intentional (e.g., to support read-only container filesystems), the test assertions in ContainerUtilsTest lines 82–89 must be rewritten to verify getCopyToFileContainerPathMap() instead of getBinds(), and MountVolume.getMode() should either be removed or have its ignored state documented.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@testcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/ContainerUtils.java`
around lines 86 - 88, The change from addFileSystemBind to withCopyToContainer
breaks bind-mount semantics and drops BindMode and getBinds(); revert the loop
in ContainerUtils that iterates properties.getMountVolumes() to call
addFileSystemBind(...) (using mountVolume.getHostPath(),
mountVolume.getContainerPath(), and mountVolume.getMode()) instead of
withCopyToContainer, and capture the returned GenericContainer into
updatedContainer (consistent with the withCopyFileToContainer usage) so binds
and modes are preserved and tests like
ContainerUtilsTest.configureCommonsAndStart still see getBinds(); if you
intentionally wanted one-way copy instead, update ContainerUtilsTest to assert
getCopyToFileContainerPathMap() and remove/annotate MountVolume.getMode() as
ignored.
| } | ||
|
|
||
| return String.join(",", servers); | ||
| protected void containerIsStarting(InspectContainerResponse containerInfo) { |
There was a problem hiding this comment.
The change is driven by the migration from KafkaContainer to ConfluentKafkaContainer. These two classes use different extension mechanisms: Old KafkaContainer — exposed getBootstrapServers() as the override point. Overriding it let you control what address string clients receive when they ask "where is Kafka?"
New ConfluentKafkaContainer — uses an entrypoint script pattern. The container's startup script is /tmp/testcontainers_start.sh, which sets KAFKA_ADVERTISED_LISTENERS as an env var before launching Kafka's actual process (/etc/confluent/docker/run). containerIsStarting(InspectContainerResponse) is a lifecycle hook on GenericContainer that fires after the container is created and ports are mapped, but before the wait strategy runs. This is exactly the right moment to write the startup script — at this point getMappedPort() is available (so you know the actual host ports), but Kafka hasn't launched yet (so the script will be read before Kafka starts).
In short: getBootstrapServers() no longer exists as an override point on ConfluentKafkaContainer, so the equivalent configuration had to move to containerIsStarting() where you write the KAFKA_ADVERTISED_LISTENERS value into the startup script that Confluent's Docker image reads on launch.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java (1)
233-243:⚠️ Potential issue | 🟠 Major | ⚡ Quick win
withCopyToContainerdrops thefileSystemBindpersistence behavior.This is now a one-way snapshot taken before startup, not a writable host mount. Kafka/ZooKeeper writes will stay inside the container, so the
embedded.*.fileSystemBindpaths created here will remain empty and the existing persistence contract is broken. Please keep these paths mounted read/write instead of copied.Also applies to: 246-263
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java` around lines 233 - 243, The code currently uses withCopyToContainer which snapshots files into the container and breaks the intended persistent read/write mount behavior; replace the withCopyToContainer calls in KafkaContainerConfiguration.kafkaFileSystemBind and the analogous Zookeeper bind block (lines ~246-263) with testcontainers' bind mount API (e.g., GenericContainer/ConfluentKafkaContainer.withFileSystemBind or withFileSystemBind(hostPath, containerPath, BindMode.RW)) so the host kafkaData path is mounted into the container as a read/write volume (keep createPathAndParentOrMakeWritable(kafkaData) as-is and use BindMode.RW). Ensure you reference the same container paths ("/var/lib/kafka/data" and the Zookeeper container path) and import/namespace BindMode if required.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java`:
- Around line 233-243: The code currently uses withCopyToContainer which
snapshots files into the container and breaks the intended persistent read/write
mount behavior; replace the withCopyToContainer calls in
KafkaContainerConfiguration.kafkaFileSystemBind and the analogous Zookeeper bind
block (lines ~246-263) with testcontainers' bind mount API (e.g.,
GenericContainer/ConfluentKafkaContainer.withFileSystemBind or
withFileSystemBind(hostPath, containerPath, BindMode.RW)) so the host kafkaData
path is mounted into the container as a read/write volume (keep
createPathAndParentOrMakeWritable(kafkaData) as-is and use BindMode.RW). Ensure
you reference the same container paths ("/var/lib/kafka/data" and the Zookeeper
container path) and import/namespace BindMode if required.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: da0f235f-da41-4938-a6fc-3cebc0b606b3
📒 Files selected for processing (1)
embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java
528c5eb to
fef2ab8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
testcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/ContainerUtilsTest.java (1)
96-101: 💤 Low valueReflection on this private Testcontainers field is an intentional testing pattern, but extraction remains worthwhile.
The field
copyToTransferableContainerPathMapis internal toGenericContainerand annotated@VisibleForTesting, indicating deliberate design by Testcontainers for test access. There is no public API to inspect this map (the publicwithCopyToContainer()method only writes to it), so reflection here is the only practical approach. That said, consider extracting this helper into a shared test utility so future Testcontainers API changes require updates in only one place. The existingNoSuchFieldExceptionhandling is sufficient.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@testcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/ContainerUtilsTest.java` around lines 96 - 101, Extract the reflection helper getCopyToTransferableContainerPathMap into a shared test utility class (e.g., TestcontainerReflectionUtils) so all tests reuse a single implementation; the method should still use reflection to access GenericContainer's private field copyToTransferableContainerPathMap, keep the same `@SuppressWarnings` and NoSuchFieldException/reflective access handling, and update callers (like the current EchoContainer test) to call TestcontainerReflectionUtils.getCopyToTransferableContainerPathMap(container) to centralize future maintenance when Testcontainers internals change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java`:
- Line 226: The zookeperFileSystemBind(...) call and setting
withEnv("ZOOKEEPER_SASL_ENABLED", "false") are ineffective for
ConfluentKafkaContainer running in KRaft mode; remove the
zookeperFileSystemBind(...) invocation and the ZOOKEEPER_SASL_ENABLED env set
from KafkaContainerConfiguration (and clean up related
ZookeeperConfigurationProperties.FileSystemBind usage) OR keep the property for
compatibility but add a clear warning when zookeeperFileSystemBind.isEnabled()
is true (log via the class logger in KafkaContainerConfiguration stating the
setting is ignored under KRaft); also add a brief migration note to the
changelog if you remove the feature.
---
Nitpick comments:
In
`@testcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/ContainerUtilsTest.java`:
- Around line 96-101: Extract the reflection helper
getCopyToTransferableContainerPathMap into a shared test utility class (e.g.,
TestcontainerReflectionUtils) so all tests reuse a single implementation; the
method should still use reflection to access GenericContainer's private field
copyToTransferableContainerPathMap, keep the same `@SuppressWarnings` and
NoSuchFieldException/reflective access handling, and update callers (like the
current EchoContainer test) to call
TestcontainerReflectionUtils.getCopyToTransferableContainerPathMap(container) to
centralize future maintenance when Testcontainers internals change.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d012582c-6f1b-497d-9856-228bd0a67729
📒 Files selected for processing (71)
embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeTestOperations.javaembedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeWaitStrategy.javaembedded-azurite/pom.xmlembedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.javaembedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.javaembedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationTest.javaembedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.javaembedded-git/src/test/java/config/CustomTransportConfigCallback.javaembedded-google-pubsub/pom.xmlembedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.javaembedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/PubsubProperties.javaembedded-google-pubsub/src/test/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfigurationTest.javaembedded-google-storage/pom.xmlembedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.javaembedded-google-storage/src/main/java/com/playtika/testcontainer/storage/GoogleCloudStorageHttpClient.javaembedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.javaembedded-grafana/README.adocembedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.javaembedded-grafana/src/main/java/com/playtika/testcontainer/grafana/GrafanaProperties.javaembedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.javaembedded-grafana/src/test/resources/bootstrap.yamlembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.javaembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/KafkaConfigurationProperties.javaembedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/SchemaRegistryConfigurationProperties.javaembedded-keycloak/pom.xmlembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainerFactory.javaembedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/spring/EmbeddedKeycloakBootstrapConfigurationTest.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/util/KeycloakJwtAuthenticationConverter.javaembedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/vanilla/KeycloakContainerTest.javaembedded-keydb/src/main/java/com/playtika/testcontainer/keydb/wait/KeyDbClusterStatusCheck.javaembedded-memsql/pom.xmlembedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.javaembedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.javaembedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/DefaultMinioWaitStrategy.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.javaembedded-minio/src/main/java/com/playtika/testcontainer/minio/MinioWaitStrategy.javaembedded-minio/src/test/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.javaembedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.javaembedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.javaembedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.javaembedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurerTest.javaembedded-nats/README.adocembedded-nats/pom.xmlembedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.javaembedded-nats/src/test/java/com/playtika/testcontainer/nats/BaseNatsTest.javaembedded-neo4j/src/test/java/com/playtika/testcontainer/neo4j/Person.javaembedded-redis/src/main/java/com/playtika/testcontainer/redis/wait/RedisClusterStatusCheck.javaembedded-selenium/README.adocembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerContextCustomizerFactory.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerScope.javaembedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerTestExecutionListener.javaembedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.javaembedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.javaembedded-wiremock/README.adocembedded-wiremock/pom.xmlembedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfiguration.javaembedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/spring/AbstractDependsOnPostProcessor.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/ContainerUtils.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/DateUtils.javatestcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/FileUtils.javatestcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/ContainerUtilsTest.javatestcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/MountVolumesTest.java
💤 Files with no reviewable changes (7)
- embedded-minio/src/main/java/com/playtika/testcontainer/minio/DefaultMinioWaitStrategy.java
- embedded-wiremock/src/main/java/com/playtika/testcontainers/wiremock/WiremockProperties.java
- embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/GoogleCloudStorageHttpClient.java
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainerFactory.java
- embedded-minio/src/main/java/com/playtika/testcontainer/minio/MinioWaitStrategy.java
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java
- embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java
✅ Files skipped from review due to trivial changes (17)
- embedded-nats/pom.xml
- embedded-git/src/test/java/config/CustomTransportConfigCallback.java
- embedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/spring/EmbeddedKeycloakBootstrapConfigurationTest.java
- embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeWaitStrategy.java
- embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/AerospikeTestOperations.java
- embedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationTest.java
- testcontainers-common/src/test/java/com/playtika/testcontainer/common/utils/MountVolumesTest.java
- embedded-wiremock/README.adoc
- embedded-nats/README.adoc
- embedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.java
- embedded-redis/src/main/java/com/playtika/testcontainer/redis/wait/RedisClusterStatusCheck.java
- embedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/util/KeycloakJwtAuthenticationConverter.java
- testcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/FileUtils.java
- embedded-grafana/README.adoc
- embedded-neo4j/src/test/java/com/playtika/testcontainer/neo4j/Person.java
- embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.java
- embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/KafkaConfigurationProperties.java
🚧 Files skipped from review as they are similar to previous changes (41)
- embedded-wiremock/pom.xml
- embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerContextCustomizerFactory.java
- embedded-minio/src/test/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfigurationTest.java
- embedded-google-storage/pom.xml
- embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.java
- embedded-google-storage/src/test/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfigurationTest.java
- embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java
- embedded-memsql/pom.xml
- embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.java
- embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/wait/KeyDbClusterStatusCheck.java
- embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/properties/SchemaRegistryConfigurationProperties.java
- embedded-keycloak/pom.xml
- embedded-google-pubsub/pom.xml
- testcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/DateUtils.java
- embedded-azurite/pom.xml
- embedded-google-pubsub/src/test/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfigurationTest.java
- embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java
- testcontainers-common/src/main/java/com/playtika/testcontainer/common/utils/ContainerUtils.java
- testcontainers-common/src/main/java/com/playtika/testcontainer/common/spring/AbstractDependsOnPostProcessor.java
- embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.java
- embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java
- embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java
- embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.java
- embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.java
- embedded-nats/src/test/java/com/playtika/testcontainer/nats/BaseNatsTest.java
- embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java
- embedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.java
- embedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.java
- embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakProperties.java
- embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.java
- embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/testscope/TestcontainerTestExecutionListener.java
- embedded-keycloak/src/test/java/com/playtika/testcontainer/keycloak/vanilla/KeycloakContainerTest.java
- embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java
- embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java
- embedded-grafana/src/test/resources/bootstrap.yaml
- embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurerTest.java
- embedded-selenium/README.adoc
- embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java
- embedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.java
- embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java
| @@ -217,12 +225,12 @@ public String getBootstrapServers() { | |||
| kafkaFileSystemBind(kafkaProperties, kafka); | |||
| zookeperFileSystemBind(zookeeperProperties, kafka); | |||
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Confluent ConfluentKafkaContainer testcontainers KRaft ZooKeeper data directory
💡 Result:
In Confluent Platform images used by Testcontainers (confluentinc/cp-kafka), Kafka’s on-disk data directory is /var/lib/kafka/data (Kafka log storage is persisted there via the image’s configured VOLUME and Confluent’s Docker guidance) [1][2]. If you run cp-kafka in KRaft mode (the ConfluentDocker examples default to KRaft, and Confluent’s config docs describe KRaft metadata stored in the configured metadata/KRaft log directories), the KRaft metadata log location is controlled by metadata.log.dir (otherwise placed in the first log directory from log.dirs) [3]. For Testcontainers specifics: - The Java module docs confirm ConfluentKafkaContainer supports confluentinc/cp-kafka (7.4.0+) and runs Kafka via the Confluent image startup scripts [4][5]. - The Confluent Platform Docker documentation for external volumes explicitly shows mounting host /var/lib/kafka/data to the container path /var/lib/kafka/data (example using -v /vol1/kafka-data:/var/lib/kafka/data) [1]. ZooKeeper data directory (only relevant for ZooKeeper-mode setups): - ZooKeeper uses /var/lib/zookeeper/data and /var/lib/zookeeper/log (as set via the zookeeper.properties in Testcontainers’ KafkaContainer implementation) [6] and aligns with Confluent’s docker-volume guidance that ZooKeeper persists “transaction logs” via volumes (and that you should mount the relevant directories) [1]. Practical takeaway for your testcontainers setup: - For ConfluentKafkaContainer (cp-kafka), bind-mount/persist /var/lib/kafka/data. - For any ZooKeeper-mode container, persist /var/lib/zookeeper/data (and, if needed, /var/lib/zookeeper/log). [1][6]
Citations:
- 1: http://docs.confluent.io/current/installation/docker/operations/external-volumes.html
- 2: How to avoid the data loss on zookeeper/kafka server restart? confluentinc/cp-docker-images#825
- 3: https://docs.confluent.io/platform/current/kafka-metadata/config-kraft.html
- 4: https://java.testcontainers.org/modules/kafka/
- 5: https://tessl.io/registry/tessl/maven-org-testcontainers--kafka/1.21.0/files/docs/confluent-kafka-container.md
- 6: https://github.com/testcontainers/testcontainers-java/blob/57ca6ad4f0a6ee8bb5feaf428b5c66c7d25259c4/modules/kafka/src/main/java/org/testcontainers/containers/KafkaContainer.java
🏁 Script executed:
# Find the zookeperFileSystemBind method definition
rg -A 10 "def zookeperFileSystemBind|void zookeperFileSystemBind" --type javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 2098
🏁 Script executed:
# Check the KafkaContainerConfiguration class around lines 226 and 215-264
fd "KafkaContainerConfiguration.java" --type f | head -1 | xargs wc -lRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 195
🏁 Script executed:
# Get the relevant sections of the file
fd "KafkaContainerConfiguration.java" --type f | head -1 | xargs cat -n | sed -n '210,270p'Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 4364
🏁 Script executed:
# Verify the kafkaFileSystemBind method (for comparison with zookeperFileSystemBind)
# to understand the intended behavior
sed -n '233,244p' embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.javaRepository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 862
🏁 Script executed:
# Check if there are any properties or configurations that control whether
# ZooKeeper filesystem binding should be skipped in KRaft mode
rg "zookeeperFileSystemBind|ZookeeperConfigurationProperties" --type java -B 2 -A 2 | head -60Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 8093
🏁 Script executed:
# Check if there's any documentation or comments about the KRaft migration
rg "KRaft|kraft" --type java -B 1 -A 1 | head -40Repository: PlaytikaOSS/testcontainers-spring-boot
Length of output: 64
zookeperFileSystemBind has no effect under ConfluentKafkaContainer running in KRaft mode.
ConfluentKafkaContainer (using confluentinc/cp-kafka image) runs Kafka in KRaft mode without a ZooKeeper process. The method copies directories to /var/lib/zookeeper/data and /var/lib/zookeeper/log inside the container, but KRaft metadata is persisted elsewhere (/var/lib/kafka/data via metadata.log.dir). Users who enable embedded.zookeeper.fileSystemBind.enabled=true will see logs and directories created on the host, but persistence will not work as expected — the copied ZooKeeper directories remain unused.
Consider:
- Removing
zookeperFileSystemBind(...)and the relatedZookeeperConfigurationProperties.FileSystemBindusage entirely, with a migration note in the changelog. - Or, if retaining the property surface for backward compatibility, log a warning when
zookeeperFileSystemBind.isEnabled()is true to alert users that the setting is now ignored.
Similarly, withEnv("ZOOKEEPER_SASL_ENABLED", "false") (line 215) is no longer meaningful under KRaft and can be removed in the same cleanup.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java`
at line 226, The zookeperFileSystemBind(...) call and setting
withEnv("ZOOKEEPER_SASL_ENABLED", "false") are ineffective for
ConfluentKafkaContainer running in KRaft mode; remove the
zookeperFileSystemBind(...) invocation and the ZOOKEEPER_SASL_ENABLED env set
from KafkaContainerConfiguration (and clean up related
ZookeeperConfigurationProperties.FileSystemBind usage) OR keep the property for
compatibility but add a clear warning when zookeeperFileSystemBind.isEnabled()
is true (log via the class logger in KafkaContainerConfiguration stating the
setting is ignored under KRaft); also add a brief migration note to the
changelog if you remove the feature.
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. ❌ Failed to clone repository into sandbox. Please try again. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java (1)
78-82: ⚡ Quick winUpdate parameter type to KafkaContainer for consistency.
The
nativeKafkabean now returnsKafkaContainer, but this method still acceptsGenericContainer<?>. For consistency with the typed container migration, update the parameter type to match.♻️ Proposed fix to use KafkaContainer type
`@Bean` `@ConditionalOnMissingBean` public NativeKafkaTopicsConfigurer nativeKafkaTopicsConfigurer( - GenericContainer<?> nativeKafka, + KafkaContainer nativeKafka, NativeKafkaConfigurationProperties nativeKafkaProperties) { return new NativeKafkaTopicsConfigurer(nativeKafka, nativeKafkaProperties); }Note: This requires updating the
NativeKafkaTopicsConfigurerconstructor to acceptKafkaContainerinstead ofGenericContainer<?>.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java` around lines 78 - 82, Change the parameter type of the nativeKafkaTopicsConfigurer factory method from GenericContainer<?> to KafkaContainer and update the NativeKafkaTopicsConfigurer constructor signature to accept KafkaContainer as well (replace usages of GenericContainer<?> in the class to KafkaContainer) so the method nativeKafkaTopicsConfigurer(GenericContainer<?> nativeKafka, ...) becomes nativeKafkaTopicsConfigurer(KafkaContainer nativeKafka, ...) and the NativeKafkaTopicsConfigurer(GenericContainer<?> nativeKafka, ...) constructor becomes NativeKafkaTopicsConfigurer(KafkaContainer nativeKafka, ...); ensure all internal references and imports are adjusted to KafkaContainer.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java`:
- Around line 78-82: Change the parameter type of the
nativeKafkaTopicsConfigurer factory method from GenericContainer<?> to
KafkaContainer and update the NativeKafkaTopicsConfigurer constructor signature
to accept KafkaContainer as well (replace usages of GenericContainer<?> in the
class to KafkaContainer) so the method
nativeKafkaTopicsConfigurer(GenericContainer<?> nativeKafka, ...) becomes
nativeKafkaTopicsConfigurer(KafkaContainer nativeKafka, ...) and the
NativeKafkaTopicsConfigurer(GenericContainer<?> nativeKafka, ...) constructor
becomes NativeKafkaTopicsConfigurer(KafkaContainer nativeKafka, ...); ensure all
internal references and imports are adjusted to KafkaContainer.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3f8dabf4-58bc-4f3f-90e5-f3b6788c0f23
📒 Files selected for processing (1)
embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #2945 +/- ##
=============================================
- Coverage 82.45% 81.82% -0.64%
+ Complexity 692 683 -9
=============================================
Files 205 202 -3
Lines 3147 3092 -55
Branches 146 150 +4
=============================================
- Hits 2595 2530 -65
- Misses 483 492 +9
- Partials 69 70 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Replace GenericContainer with AzuriteContainer and add testcontainers-azure dependency. Update container initialization to use AzuriteContainer API with command modifier for skipApiVersionCheck flag.
Replace custom KeycloakContainer and KeycloakContainerFactory implementations with dasniko/testcontainers-keycloak dependency. Consolidate container configuration logic into EmbeddedKeycloakBootstrapConfiguration and refactor tests to use ApplicationContextRunner.
… Zookeeper Replace deprecated KafkaContainer imports with new testcontainers-kafka module classes. Use KafkaContainer for embedded-kafka and ConfluentKafkaContainer for embedded-native-kafka. Remove withEmbeddedZookeeper() call as newer Kafka versions use KRaft mode.
…it strategies Replace custom MinioWaitStrategy with built-in Wait.forHttp() from testcontainers. Update container initialization to use MinIOContainer's withUserName/withPassword API instead of environment variables. Remove DefaultMinioWaitStrategy and MinioWaitStrategy classes. Add wiremock-testcontainers-module version property.
…move redundant port exposure Replace withSecretInVault API with withInitCommand using kv put command. Remove withExposedPorts call as port exposure is handled by VaultContainer. Remove unused Arrays import.
…stcontainers-gcloud module Replace GenericContainer with PubSubEmulatorContainer and add testcontainers-gcloud dependency. Update container initialization to use PubSubEmulatorContainer API with getEmulatorEndpoint(). Change default port from 8089 to 8085 and update Docker image to gcr.io/google.com/cloudsdktool/google-cloud-cli:559.0.0-emulators. Remove custom command construction and wait strategy as they are handled by PubSubEmulatorContainer.
…stcontainers-fake-gcs-server library Replace GenericContainer with FakeGcsServerContainer and add testcontainers-fake-gcs-server dependency. Remove GoogleCloudStorageHttpClient and custom endpoint configuration logic as they are handled by FakeGcsServerContainer's url() method. Update container initialization to use FakeGcsServerContainer API.
…atabaseContainer Replace GenericContainer with MemSqlContainer extending JdbcDatabaseContainer. Add testcontainers-jdbc dependency. Implement MemSqlContainer with withDatabaseName/withUsername/withPassword/withLicenseKey API and JDBC-specific methods (getJdbcUrl, getDriverClassName, getTestQueryString). Update container initialization to use MemSqlContainer API and remove manual environment variable configuration. Add jdbcUrl to registered environment properties.
…i, Tempo, and OTLP support Replace GenericContainer with LgtmStackContainer and update default image to grafana/otel-lgtm:0.9.3. Add port configurations for Loki (3100), Tempo (3200), OTLP gRPC (4317), and OTLP HTTP (4318). Remove custom wait strategy and manual port exposure as they are handled by LgtmStackContainer. Update environment properties to expose all service ports. Comment out gitflow-incremental-builder plugin. Update README documentation with new image source and port configurations. Simplify test configuration.
…containers-module Replace GenericContainer with WireMockContainer and add wiremock-testcontainers-module dependency. Remove custom wait strategy and port configuration as they are handled by WireMockContainer. Update container initialization to use WireMockContainer API and remove manual command/port exposure. Replace Lombok @slf4j with standard LoggerFactory. Update registered environment properties to use container's getPort() and getHost() methods with hardcoded internal port 8080. Remove port property from WiremockProperties.
…ibrary Replace GenericContainer with NatsContainer and add nats-testcontainers dependency. Remove custom wait strategy, port configuration, and nats-server.conf as they are handled by NatsContainer. Update container initialization to use NatsContainer API and remove manual port exposure. Replace Lombok @slf4j with standard LoggerFactory. Update registered environment properties to use container's getClientPort(), getHttpMonitoringPort(), and getRoutingPort() methods with hardcoded internal ports. Remove port properties from NatsProperties.
…n and remove port configuration Remove port property from configuration section and update bean type from GenericContainer to WireMockContainer in produces section.
…selenium library Replace BrowserWebDriverContainer import from core with testcontainers-selenium module. Remove deprecated wait strategy implementation and capabilities/docker-image conditional logic. Update container initialization to use BrowserWebDriverContainer constructor with getDockerImageName(). Remove unused utility methods (isNotBlank, getWaitStrategy). Update README to reflect browser selection via Docker image instead of capabilities. Simplify TestcontainerScope and TestcontainerTestExecutionListener implementations. Replace indexOf with contains for OS detection.
Remove unnecessary lambda braces in AbstractDependsOnPostProcessor. Replace Files.write with Files.writeString in FileUtils. Replace addFileSystemBind with withCopyToContainer in ContainerUtils. Use pattern matching for instanceof in DateUtils. Remove redundant type parameters in ContainerUtilsTest. Make ApplicationContextRunner final in MountVolumesTest.
Replace Arrays.asList with List.of for single-element and immutable collections. Use pattern matching for instanceof checks. Replace replaceAll with replace for literal strings. Convert Lombok @value classes to records. Remove unnecessary lambda braces and redundant toString() calls. Use text blocks for multi-line log messages. Replace Integer.valueOf with Integer.parseInt. Remove unused imports and parameters. Replace addFileSystemBind with withCopyToContainer. Use StandardCharsets.UTF_8 directly instead of name(). Replace Hamcrest matchers with AssertJ assertions. Simplify Optional assertions with hasValue().
…nstead of getBinds Replace deprecated getBinds() assertions with reflection-based access to copyToTransferableContainerPathMap field. Update mount volume verification to check Transferable entries instead of Bind objects. Remove unused docker-java imports (AccessMode, Bind) and add reflection-related imports (Field, GenericContainer, Transferable).
…ntainerIsStarting for advertised listeners configuration Replace KafkaContainer with ConfluentKafkaContainer. Override containerIsStarting() instead of getBootstrapServers() to dynamically configure advertised listeners using Transferable script injection. Add CONTROLLER listener configuration for KRaft mode. Update all method signatures and type casts from KafkaContainer to ConfluentKafkaContainer.
…entKafkaContainer Replace ConfluentKafkaContainer with KafkaContainer and remove asCompatibleSubstituteFor() call. Update all method signatures and type casts from ConfluentKafkaContainer to KafkaContainer.
…precated getWebDriver() Replace container.getWebDriver() calls with getDriver() helper method that creates RemoteWebDriver from container's Selenium address and autowired capabilities. Update package import from testcontainers.containers to testcontainers.selenium. Add capabilities autowiring and lazy driver initialization. Re-enable EmbeddedFirefoxSeleniumBeanConfigurationTest with proper browser and image configuration. Update space formatting in type casts.
…ion check Override waitUntilContainerStarted() to connect to root URL and create database before delegating to parent. This prevents "Unknown database" error since JdbcDatabaseContainer connects to getJdbcUrl() which includes the database name. Add database existence verification and proper exception handling. Simplify status check query by removing schema.sql sourcing and database USE statement.
…otstrapConfiguration Remove manual logger instantiation and use @slf4j annotation. Remove unused LoggerFactory and Logger imports.
…otstrapConfiguration Remove manual logger instantiation and use @slf4j annotation. Remove unused LoggerFactory and Logger imports.
…gned certificate Add httpsEnabled and oauthEnabled properties to AzuriteProperties. Implement configureSsl() to handle PEM/PFX certificates with fallback to embedded self-signed certificate for localhost. Update endpoint URLs to use https:// protocol when HTTPS is enabled. Add --oauth basic command line argument when OAuth is enabled. Include certificate resolution logic supporting both classpath and file system paths. Update README with HTTPS/OAuth configuration examples and fix typo (convient → convenient).
Add `anonymousAuthEnabled` and `anonymousOrgRole` properties to GrafanaProperties. Configure `GF_AUTH_ANONYMOUS_ENABLED` and `GF_AUTH_ANONYMOUS_ORG_ROLE` environment variables when anonymous auth is enabled. Add test to verify environment variables and unauthenticated API access. Update README with configuration examples.
Enable Toxiproxy in bootstrap properties. Add ToxiproxyClientProxy autowiring and implement latency emulation test using toxics API. Update JDBC URL to use toxiproxy host/port. Replace disabled test with working implementation using upstream latency toxic and assertion with offset tolerance.
79d588e to
021b29f
Compare
Replace GenericContainer with AzuriteContainer and add testcontainers-azure dependency. Update container initialization to use AzuriteContainer API with command modifier for skipApiVersionCheck flag.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Refactor