diff --git a/README.adoc b/README.adoc index 7c653d956..59f29b9e7 100644 --- a/README.adoc +++ b/README.adoc @@ -24,6 +24,9 @@ Usage of Spring Cloud in your production code is optional, but __you will need i |3.2.X, 3.3.X, 3.4.X, 3.5.X |3.1.X + +|4.0.X +|4.0.X |=== [[how-to-use]] diff --git a/embedded-aerospike-enterprise/src/main/resources/META-INF/spring.factories b/embedded-aerospike-enterprise/src/main/resources/META-INF/spring.factories index 8517337fb..bae3b128e 100644 --- a/embedded-aerospike-enterprise/src/main/resources/META-INF/spring.factories +++ b/embedded-aerospike-enterprise/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.cloud.bootstrap.BootstrapConfiguration=\ +com.playtika.testcontainer.aerospike.EmbeddedAerospikeBootstrapConfiguration,\ com.playtika.testcontainers.aerospike.enterprise.SetupEnterpriseAerospikeBootstrapConfiguration diff --git a/embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/EmbeddedAerospikeBootstrapConfiguration.java b/embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/EmbeddedAerospikeBootstrapConfiguration.java index 32aaf089c..733d72761 100644 --- a/embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/EmbeddedAerospikeBootstrapConfiguration.java +++ b/embedded-aerospike/src/main/java/com/playtika/testcontainer/aerospike/EmbeddedAerospikeBootstrapConfiguration.java @@ -21,10 +21,10 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeScansTest.java b/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeScansTest.java index d3102c6f5..0af7072dc 100644 --- a/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeScansTest.java +++ b/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeScansTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class AerospikeScansTest extends BaseAerospikeTest { @@ -15,7 +15,7 @@ void shouldDetectScans() { queryWithoutFilter(); - assertThrows(AssertionError.class, () -> aerospikeTestOperations.assertNoScans()); + assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> aerospikeTestOperations.assertNoScans()); int scansCount = aerospikeTestOperations.getScans().size(); assertThat(scansCount - initialScansCount).isEqualTo(1); @@ -27,4 +27,4 @@ private void queryWithoutFilter() { statement.setNamespace(namespace); client.query(policy, statement); } -} \ No newline at end of file +} diff --git a/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeTimeTravelTest.java b/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeTimeTravelTest.java index a927cc5df..7e7a9b876 100644 --- a/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeTimeTravelTest.java +++ b/embedded-aerospike/src/test/java/com/playtika/testcontainer/aerospike/AerospikeTimeTravelTest.java @@ -4,7 +4,6 @@ import com.aerospike.client.Key; import com.aerospike.client.policy.WritePolicy; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +15,7 @@ import static java.time.Duration.ofDays; import static java.time.Duration.ofHours; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; public class AerospikeTimeTravelTest extends BaseAerospikeTest { @@ -91,7 +91,7 @@ public void shouldSetFutureTime() { @Test public void shouldNotSetFutureTime() { OffsetDateTime minusDay = DateTimeUtils.now().minusDays(1); - Assertions.assertThrows(IllegalArgumentException.class, () -> aerospikeTestOperations.timeTravelTo(minusDay)); + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> aerospikeTestOperations.timeTravelTo(minusDay)); } @Test @@ -115,4 +115,4 @@ private void putBin(Key key, int expiration) { client.put(writePolicy, key, bin); } -} \ No newline at end of file +} diff --git a/embedded-artifactory/README.adoc b/embedded-artifactory/README.adoc index 82199d363..ca2c6c5a7 100644 --- a/embedded-artifactory/README.adoc +++ b/embedded-artifactory/README.adoc @@ -16,13 +16,20 @@ * `embedded.artifactory.enabled` `(true|false, default is true)` * `embedded.artifactory.reuseContainer` `(true|false, default is false)` -* `embedded.artifactory.dockerImage` `(default is 'releases-docker.jfrog.io/jfrog/artifactory-oss:7.77.12')` +* `embedded.artifactory.dockerImage` `(default is 'releases-docker.jfrog.io/jfrog/artifactory-oss:7.84.14')` ** Release notes on https://www.jfrog.com/confluence/display/JFROG/Artifactory+Release+Notes[jfrog.com] * `embedded.artifactory.networkAlias` `(default is 'artifactory')` * `embedded.artifactory.username` `(default is 'admin')` * `embedded.artifactory.password` `(default is 'password')` +* `embedded.artifactory.databaseName` `(default is 'artifactory')` - Database name for PostgreSQL connection +* `embedded.artifactory.databaseUser` `(default is 'artifactory')` - Database user for PostgreSQL connection +* `embedded.artifactory.databasePassword` `(default is 'password')` - Database password for PostgreSQL connection +* `embedded.artifactory.securityMasterKey` `(default is a fixed 64 hex chars value)` - Master key for Artifactory 7.x bootstrap (env: `JF_SHARED_SECURITY_MASTER_KEY`) +* `embedded.artifactory.securityJoinKey` `(default is a fixed 64 hex chars value)` - Join key for JFrog platform bootstrap (env: `JF_SHARED_SECURITY_JOIN_KEY`) * `embedded.toxiproxy.proxies.artifactory.enabled` Enables both creation of the container with ToxiProxy TCP proxy and a proxy to the `embedded-artifactory` container. +NOTE: Artifactory OSS 7.84+ requires PostgreSQL as the database backend. The `embedded-postgresql` module is automatically started as a dependency. Ensure that PostgreSQL database properties (`embedded.postgresql.user`, `embedded.postgresql.password`, `embedded.postgresql.database`) match the Artifactory database properties for proper connection. + ==== Produces * `embedded.artifactory.host` diff --git a/embedded-artifactory/pom.xml b/embedded-artifactory/pom.xml index afd391cac..c9c497de1 100644 --- a/embedded-artifactory/pom.xml +++ b/embedded-artifactory/pom.xml @@ -23,6 +23,11 @@ com.playtika.testcontainers embedded-toxiproxy + + com.playtika.testcontainers + embedded-postgresql + ${project.version} + io.rest-assured @@ -47,4 +52,4 @@ - \ No newline at end of file + diff --git a/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/ArtifactoryProperties.java b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/ArtifactoryProperties.java index b34370d49..4a853a556 100644 --- a/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/ArtifactoryProperties.java +++ b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/ArtifactoryProperties.java @@ -18,15 +18,29 @@ public class ArtifactoryProperties extends CommonContainerProperties { String password = "password"; int restApiPort = 8081; int generalPort = 8082; + String databaseName = "artifactory"; + String databaseUser = "artifactory"; + String databasePassword = "password"; + /** + * Artifactory 7.x requires a master key for encryption (normally stored in system.yaml / master.key). + * We provide it via env vars for ephemeral test containers. + * Expected format: 32 bytes hex (64 chars). + */ + String securityMasterKey = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + /** + * Join key is required for JFrog platform services bootstrapping in container setups. + * Expected format: 32 bytes hex (64 chars). + */ + String securityJoinKey = "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"; public ArtifactoryProperties() { - setWaitTimeoutInSeconds(120); + setWaitTimeoutInSeconds(300); } @Override public String getDefaultDockerImage() { // Please don`t remove this comment. // renovate: datasource=docker - return "releases-docker.jfrog.io/jfrog/artifactory-oss:7.77.12"; + return "releases-docker.jfrog.io/jfrog/artifactory-oss:7.84.14"; } } diff --git a/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfiguration.java b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfiguration.java index 76135b410..ef6a962f8 100644 --- a/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfiguration.java +++ b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfiguration.java @@ -2,6 +2,7 @@ import com.playtika.testcontainer.common.spring.DockerPresenceBootstrapConfiguration; import com.playtika.testcontainer.common.utils.ContainerUtils; +import com.playtika.testcontainer.postgresql.EmbeddedPostgreSQLBootstrapConfiguration; import com.playtika.testcontainer.toxiproxy.ToxiproxyClientProxy; import com.playtika.testcontainer.toxiproxy.ToxiproxyHelper; import com.playtika.testcontainer.toxiproxy.condition.ConditionalOnToxiProxyEnabled; @@ -18,24 +19,29 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.images.builder.Transferable; +import org.testcontainers.postgresql.PostgreSQLContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; -import java.util.Optional; +import java.nio.charset.StandardCharsets; import static com.playtika.testcontainer.artifactory.ArtifactoryProperties.ARTIFACTORY_BEAN_NAME; import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; +import static java.time.Duration.ofSeconds; +import static org.testcontainers.postgresql.PostgreSQLContainer.POSTGRESQL_PORT; @Slf4j @Configuration @ConditionalOnExpression("${embedded.containers.enabled:true}") -@AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) +@AutoConfigureAfter({DockerPresenceBootstrapConfiguration.class, EmbeddedPostgreSQLBootstrapConfiguration.class}) @ConditionalOnProperty(name = "embedded.artifactory.enabled", matchIfMissing = true) @EnableConfigurationProperties(ArtifactoryProperties.class) public class EmbeddedArtifactoryBootstrapConfiguration { private static final String ARTIFACTORY_NETWORK_ALIAS = "artifactory.testcontainer.docker"; + private static final String POSTGRESQL_NETWORK_ALIAS = "postgresql.testcontainer.docker"; @Bean @ConditionalOnMissingBean(name = "artifactoryWaitStrategy") @@ -43,7 +49,8 @@ public WaitStrategy artifactoryWaitStrategy(ArtifactoryProperties properties) { return new HttpWaitStrategy() .forPath("/") .forPort(properties.getGeneralPort()) - .forStatusCode(200); + .forStatusCode(200) + .withStartupTimeout(ofSeconds(properties.getWaitTimeoutInSeconds())); } @Bean @@ -69,14 +76,54 @@ public DynamicPropertyRegistrar artifactoryToxiProxyDynamicPropertyRegistrar(@Qu @Bean(name = ARTIFACTORY_BEAN_NAME, destroyMethod = "stop") public GenericContainer artifactory(ArtifactoryProperties properties, WaitStrategy artifactoryWaitStrategy, - Optional network) { + Network network, + @Qualifier("embeddedPostgreSql") PostgreSQLContainer postgresql) { + String databaseUrl = String.format("jdbc:postgresql://%s:%d/%s", + POSTGRESQL_NETWORK_ALIAS, + POSTGRESQL_PORT, + properties.getDatabaseName()); + + String systemYaml = "" + + "shared:\n" + + " database:\n" + + " type: postgresql\n" + + " driver: org.postgresql.Driver\n" + + " url: " + databaseUrl + "\n" + + " username: " + properties.getDatabaseUser() + "\n" + + " password: " + properties.getDatabasePassword() + "\n" + + " security:\n" + + " masterKey: " + properties.getSecurityMasterKey() + "\n" + + " joinKey: " + properties.getSecurityJoinKey() + "\n"; GenericContainer container = new GenericContainer<>(ContainerUtils.getDockerImageName(properties)) .withExposedPorts(properties.getRestApiPort(), properties.getGeneralPort()) - .withNetwork(Network.SHARED) + .withNetwork(network) .withNetworkAliases(properties.getNetworkAlias(), ARTIFACTORY_NETWORK_ALIAS) + .withCopyToContainer( + Transferable.of(systemYaml.getBytes(StandardCharsets.UTF_8), 0666), + "/opt/jfrog/artifactory/var/etc/system.yaml") + .withExtraHost("localhost", "127.0.0.1") + .withEnv("JF_ROUTER_ENTRYPOINTS_INTERNALHOST", "::1") + .withEnv("JF_SHARED_DATABASE_TYPE", "postgresql") + .withEnv("JF_SHARED_DATABASE_URL", databaseUrl) + .withEnv("JF_SHARED_DATABASE_USERNAME", properties.getDatabaseUser()) + .withEnv("JF_SHARED_DATABASE_PASSWORD", properties.getDatabasePassword()) + .withEnv("JF_SHARED_SECURITY_MASTER_KEY", properties.getSecurityMasterKey()) + .withEnv("JF_SHARED_SECURITY_JOIN_KEY", properties.getSecurityJoinKey()) + // Some internal services resolve config key as `shared.security.masterKey` / `shared.security.joinKey` + // (camelCase). Provide both variants. + .withEnv("JF_SHARED_SECURITY_MASTERKEY", properties.getSecurityMasterKey()) + .withEnv("JF_SHARED_SECURITY_JOINKEY", properties.getSecurityJoinKey()) + // Some Artifactory 7.x components still require the key files to exist. + // Provide them explicitly for ephemeral test containers. + .withCopyToContainer( + Transferable.of((properties.getSecurityMasterKey() + "\n").getBytes(StandardCharsets.UTF_8), 0666), + "/opt/jfrog/artifactory/var/etc/security/master.key") + .withCopyToContainer( + Transferable.of((properties.getSecurityJoinKey() + "\n").getBytes(StandardCharsets.UTF_8), 0666), + "/opt/jfrog/artifactory/var/etc/security/join.key") + .dependsOn(postgresql) .waitingFor(artifactoryWaitStrategy); - network.ifPresent(container::withNetwork); configureCommonsAndStart(container, properties, log); Integer mappedPort = container.getMappedPort(properties.generalPort); String host = container.getHost(); diff --git a/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryNetworkBootstrapConfiguration.java b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryNetworkBootstrapConfiguration.java new file mode 100644 index 000000000..54aa3a7b6 --- /dev/null +++ b/embedded-artifactory/src/main/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryNetworkBootstrapConfiguration.java @@ -0,0 +1,30 @@ +package com.playtika.testcontainer.artifactory; + +import com.playtika.testcontainer.common.spring.DockerPresenceBootstrapConfiguration; +import com.playtika.testcontainer.postgresql.EmbeddedPostgreSQLBootstrapConfiguration; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.testcontainers.containers.Network; + +@Slf4j +@Configuration +@ConditionalOnExpression("${embedded.containers.enabled:true}") +@ConditionalOnProperty(name = "embedded.artifactory.enabled", matchIfMissing = true) +@AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) +@AutoConfigureBefore(EmbeddedPostgreSQLBootstrapConfiguration.class) +public class EmbeddedArtifactoryNetworkBootstrapConfiguration { + + @Bean(destroyMethod = "close") + @ConditionalOnMissingBean(Network.class) + public Network network() { + Network network = Network.newNetwork(); + log.info("Created docker Network with id={}", network.getId()); + return network; + } +} diff --git a/embedded-artifactory/src/main/resources/META-INF/spring.factories b/embedded-artifactory/src/main/resources/META-INF/spring.factories index c1292f485..0fc318a92 100644 --- a/embedded-artifactory/src/main/resources/META-INF/spring.factories +++ b/embedded-artifactory/src/main/resources/META-INF/spring.factories @@ -1,2 +1,3 @@ org.springframework.cloud.bootstrap.BootstrapConfiguration=\ +com.playtika.testcontainer.artifactory.EmbeddedArtifactoryNetworkBootstrapConfiguration,\ com.playtika.testcontainer.artifactory.EmbeddedArtifactoryBootstrapConfiguration \ No newline at end of file diff --git a/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/BaseEmbeddedArtifactoryTest.java b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/BaseEmbeddedArtifactoryTest.java index 6005cb80b..d46ae17cf 100644 --- a/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/BaseEmbeddedArtifactoryTest.java +++ b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/BaseEmbeddedArtifactoryTest.java @@ -8,7 +8,12 @@ import org.springframework.context.annotation.Configuration; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = BaseEmbeddedArtifactoryTest.TestConfiguration.class + classes = BaseEmbeddedArtifactoryTest.TestConfiguration.class, + properties = { + "embedded.postgresql.user=artifactory", + "embedded.postgresql.password=password", + "embedded.postgresql.database=artifactory" + } ) class BaseEmbeddedArtifactoryTest { @Value("${embedded.artifactory.host}") @@ -26,4 +31,4 @@ static class TestConfiguration { } -} \ No newline at end of file +} diff --git a/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationTest.java b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationTest.java index f32905035..f90f9e5ad 100644 --- a/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationTest.java +++ b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationTest.java @@ -1,27 +1,23 @@ package com.playtika.testcontainer.artifactory; import org.junit.jupiter.api.Test; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; -import static io.restassured.RestAssured.given; +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; class EmbeddedArtifactoryBootstrapConfigurationTest extends BaseEmbeddedArtifactoryTest { + private final RestTemplate restTemplate = new RestTemplate(); + @Test void shouldStartupArtifactory() { - UriComponents uriComponents = UriComponentsBuilder.newInstance() - .scheme("http") - .host(artifactoryHost) - .port(artifactoryPort) - .path("/") - .build(); - - given() - .get(uriComponents.toUriString()) - .then() - .assertThat() - .statusCode(200); + URI artifactoryUri = URI.create(String.format("http://%s:%d/", artifactoryHost, artifactoryPort)); + ResponseEntity response = restTemplate.getForEntity(artifactoryUri, String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); } -} \ No newline at end of file +} diff --git a/embedded-artifactory/src/test/resources/bootstrap-test.yml b/embedded-artifactory/src/test/resources/bootstrap-test.yml new file mode 100644 index 000000000..f9241be51 --- /dev/null +++ b/embedded-artifactory/src/test/resources/bootstrap-test.yml @@ -0,0 +1,5 @@ +embedded: + postgresql: + database: artifactory + password: password + user: artifactory diff --git a/embedded-azurite/pom.xml b/embedded-azurite/pom.xml index baea0bb07..512ceced6 100644 --- a/embedded-azurite/pom.xml +++ b/embedded-azurite/pom.xml @@ -14,15 +14,37 @@ embedded-azurite + + com.azure + azure-storage-blob + test + + + com.azure + azure-storage-queue + test + com.azure.spring spring-cloud-azure-starter-storage-blob test + + + com.azure.spring + spring-cloud-azure-autoconfigure + + com.azure.spring spring-cloud-azure-starter-storage-queue test + + + com.azure.spring + spring-cloud-azure-autoconfigure + + com.playtika.testcontainers diff --git a/embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java b/embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java index 45aa03af3..a34c3fceb 100644 --- a/embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java +++ b/embedded-azurite/src/main/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBootstrapConfiguration.java @@ -20,7 +20,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Map; import java.util.Optional; diff --git a/embedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.java b/embedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.java index eb7690bd2..cdd9bd34b 100644 --- a/embedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.java +++ b/embedded-azurite/src/test/java/com/playtika/testcontainer/azurite/EmbeddedAzuriteBoostrapConfigurationTest.java @@ -11,8 +11,11 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ActiveProfiles; import java.util.UUID; @@ -59,9 +62,29 @@ void createAndDeleteContainerQueue() { queueClient.delete(); } + @Configuration @EnableAutoConfiguration public static class AzuriteTestConfiguration { + @Bean + public BlobServiceClientBuilder blobServiceClientBuilder( + @Value("${embedded.azurite.account-name}") String accountName, + @Value("${embedded.azurite.account-key}") String accountKey, + @Value("${embedded.azurite.blob-endpoint}") String endpoint) { + return new BlobServiceClientBuilder() + .connectionString(String.format("DefaultEndpointsProtocol=http;AccountName=%s;AccountKey=%s;BlobEndpoint=%s;", + accountName, accountKey, endpoint)); + } + + @Bean + public QueueServiceClientBuilder queueServiceClientBuilder( + @Value("${embedded.azurite.account-name}") String accountName, + @Value("${embedded.azurite.account-key}") String accountKey, + @Value("${embedded.azurite.queue-endpoint}") String endpoint) { + return new QueueServiceClientBuilder() + .connectionString(String.format("DefaultEndpointsProtocol=http;AccountName=%s;AccountKey=%s;QueueEndpoint=%s;", + accountName, accountKey, endpoint)); + } } } diff --git a/embedded-azurite/src/test/resources/application-test.yaml b/embedded-azurite/src/test/resources/application-test.yaml index 96f1c51e3..706597804 100644 --- a/embedded-azurite/src/test/resources/application-test.yaml +++ b/embedded-azurite/src/test/resources/application-test.yaml @@ -1,12 +1,14 @@ spring: cloud: azure: + keyvault: + enabled: false storage: blob: - account-name: ${embedded.azurite.account-name:devstoreaccount1} - account-key: ${embedded.azurite.account-key:Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==} - endpoint: ${embedded.azurite.blob-endpoint:http://localhost:10000/devstoreaccount1} + account-name: ${embedded.azurite.account-name} + account-key: ${embedded.azurite.account-key} + endpoint: ${embedded.azurite.blob-endpoint} queue: - account-name: ${embedded.azurite.account-name:devstoreaccount1} - account-key: ${embedded.azurite.account-key:Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==} - endpoint: ${embedded.azurite.queue-endpoint:http://localhost:10001/devstoreaccount1} \ No newline at end of file + account-name: ${embedded.azurite.account-name} + account-key: ${embedded.azurite.account-key} + endpoint: ${embedded.azurite.queue-endpoint} diff --git a/embedded-cassandra/pom.xml b/embedded-cassandra/pom.xml index 57e0d2383..5b0d60062 100644 --- a/embedded-cassandra/pom.xml +++ b/embedded-cassandra/pom.xml @@ -25,12 +25,40 @@ org.testcontainers - cassandra + testcontainers-cassandra org.springframework.data spring-data-cassandra true + + org.springframework.boot + spring-boot-autoconfigure + provided + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + test + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-data-cassandra + test + + + org.springframework.boot + spring-boot-starter-logging + + + \ No newline at end of file diff --git a/embedded-cassandra/src/main/java/com/playtika/testcontainer/cassandra/EmbeddedCassandraBootstrapConfiguration.java b/embedded-cassandra/src/main/java/com/playtika/testcontainer/cassandra/EmbeddedCassandraBootstrapConfiguration.java index 7dbeb2e98..5035d5e14 100644 --- a/embedded-cassandra/src/main/java/com/playtika/testcontainer/cassandra/EmbeddedCassandraBootstrapConfiguration.java +++ b/embedded-cassandra/src/main/java/com/playtika/testcontainer/cassandra/EmbeddedCassandraBootstrapConfiguration.java @@ -16,12 +16,12 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.CassandraContainer; +import org.testcontainers.cassandra.CassandraContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.delegate.CassandraDatabaseDelegate; import org.testcontainers.delegate.DatabaseDelegate; import org.testcontainers.ext.ScriptUtils; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import javax.script.ScriptException; @@ -71,7 +71,7 @@ public DynamicPropertyRegistrar cassandraToxiProxyDynamicPropertyRegistrar( @Bean(name = BEAN_NAME_EMBEDDED_CASSANDRA, destroyMethod = "stop") public CassandraContainer cassandra(CassandraProperties properties, Optional network) throws Exception { - CassandraContainer cassandra = new CassandraContainer<>(ContainerUtils.getDockerImageName(properties)) + CassandraContainer cassandra = new CassandraContainer(ContainerUtils.getDockerImageName(properties)) .withExposedPorts(properties.getPort()) .withNetworkAliases(CASSANDRA_NETWORK_ALIAS); network.ifPresent(cassandra::withNetwork); @@ -97,7 +97,7 @@ public DynamicPropertyRegistrar cassandraDynamicPropertyRegistrar( }; } - private void initKeyspace(CassandraProperties properties, CassandraContainer cassandra) throws ScriptException { + private void initKeyspace(CassandraProperties properties, CassandraContainer cassandra) throws ScriptException { String initScriptContent = prepareCassandraInitScript(properties); try (DatabaseDelegate databaseDelegate = new CassandraDatabaseDelegate(cassandra)) { ScriptUtils.executeDatabaseScript(databaseDelegate, "init.cql", initScriptContent); diff --git a/embedded-clickhouse/pom.xml b/embedded-clickhouse/pom.xml index c13d8812d..4839e271c 100644 --- a/embedded-clickhouse/pom.xml +++ b/embedded-clickhouse/pom.xml @@ -28,7 +28,7 @@ org.testcontainers - clickhouse + testcontainers-clickhouse ru.yandex.clickhouse @@ -43,14 +43,15 @@ - org.springframework - spring-jdbc - test - - - org.apache.tomcat - tomcat-jdbc + org.springframework.boot + spring-boot-starter-jdbc test + + + org.springframework.boot + spring-boot-starter-logging + + diff --git a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/ClickHouseProperties.java b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/ClickHouseProperties.java index b43b58f42..cc05eb28a 100644 --- a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/ClickHouseProperties.java +++ b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/ClickHouseProperties.java @@ -14,7 +14,7 @@ public class ClickHouseProperties extends CommonContainerProperties { String host = "localhost"; int port = 8123; String user = "default"; - String password = ""; + String password = "test"; String initScriptPath; diff --git a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseBootstrapConfiguration.java b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseBootstrapConfiguration.java index 08cbbd261..1dcf850c3 100644 --- a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseBootstrapConfiguration.java +++ b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseBootstrapConfiguration.java @@ -16,9 +16,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.springframework.util.StringUtils; -import org.testcontainers.containers.ClickHouseContainer; +import org.testcontainers.clickhouse.ClickHouseContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -60,18 +60,16 @@ public DynamicPropertyRegistrar clickhouseToxiProxyDynamicPropertyRegistrar(@Qua public ClickHouseContainer clickHouseContainer(ClickHouseProperties properties, Optional network) { ClickHouseContainer clickHouseContainer = new ClickHouseContainer(ContainerUtils.getDockerImageName(properties)) + .withUsername(properties.getUser()) + .withPassword(properties.getPassword()) .withInitScript(properties.getInitScriptPath()) .withNetworkAliases(CLICKHOUSE_NETWORK_ALIAS); network.ifPresent(clickHouseContainer::withNetwork); - String username = !StringUtils.hasLength(properties.getUser()) ? clickHouseContainer.getUsername() : properties.getUser(); - String password = !StringUtils.hasLength(properties.getPassword()) ? clickHouseContainer.getPassword() : properties.getPassword(); - clickHouseContainer.addEnv("CLICKHOUSE_USER", username); - clickHouseContainer.addEnv("CLICKHOUSE_PASSWORD", password == null ? "" : password); clickHouseContainer = (ClickHouseContainer) configureCommonsAndStart(clickHouseContainer, properties, log); Integer mappedPort = clickHouseContainer.getMappedPort(properties.port); String host = clickHouseContainer.getHost(); log.info("Started ClickHouse server. Connection details: schema=default, host={}, port={}, user={}, password={}, networkAlias={}, internalPort={}", - host, mappedPort, username, password, CLICKHOUSE_NETWORK_ALIAS, properties.getPort()); + host, mappedPort, clickHouseContainer.getUsername(), clickHouseContainer.getPassword(), CLICKHOUSE_NETWORK_ALIAS, properties.getPort()); return clickHouseContainer; } diff --git a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseDependenciesAutoConfiguration.java b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseDependenciesAutoConfiguration.java index a023f51f4..6b4ce8ca2 100644 --- a/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseDependenciesAutoConfiguration.java +++ b/embedded-clickhouse/src/main/java/com/playtika/testcontainer/clickhouse/EmbeddedClickHouseDependenciesAutoConfiguration.java @@ -7,13 +7,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; -@AutoConfiguration(after = DataSourceAutoConfiguration.class) +@AutoConfiguration(afterName = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration") @AutoConfigureOrder @ConditionalOnClass(DataSource.class) @ConditionalOnExpression("${embedded.containers.enabled:true}") diff --git a/embedded-clickhouse/src/test/java/com/playtika/testcontainer/clickhouse/BaseEmbeddedClickHouseTest.java b/embedded-clickhouse/src/test/java/com/playtika/testcontainer/clickhouse/BaseEmbeddedClickHouseTest.java index a26ce0597..54d773b8e 100644 --- a/embedded-clickhouse/src/test/java/com/playtika/testcontainer/clickhouse/BaseEmbeddedClickHouseTest.java +++ b/embedded-clickhouse/src/test/java/com/playtika/testcontainer/clickhouse/BaseEmbeddedClickHouseTest.java @@ -7,6 +7,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import static com.playtika.testcontainer.clickhouse.ClickHouseProperties.BEAN_NAME_EMBEDDED_CLICK_HOUSE; import static org.assertj.core.api.Assertions.assertThat; @@ -14,10 +15,10 @@ @Slf4j @SpringBootTest(classes = BaseEmbeddedClickHouseTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.clickhouse.init-script-path=initScript.sql", "embedded.toxiproxy.proxies.clickhouse.enabled=true" }) +@ActiveProfiles("enabled") public abstract class BaseEmbeddedClickHouseTest { @Autowired diff --git a/embedded-cockroachdb/pom.xml b/embedded-cockroachdb/pom.xml index 0a1e8401c..406598a88 100644 --- a/embedded-cockroachdb/pom.xml +++ b/embedded-cockroachdb/pom.xml @@ -24,12 +24,23 @@ org.testcontainers - cockroachdb + testcontainers-cockroachdb org.postgresql postgresql + + org.springframework.boot + spring-boot-starter-jdbc + test + + + org.springframework.boot + spring-boot-starter-logging + + + org.springframework spring-jdbc diff --git a/embedded-cockroachdb/src/main/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfiguration.java b/embedded-cockroachdb/src/main/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfiguration.java index 788676efb..835b697d6 100644 --- a/embedded-cockroachdb/src/main/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfiguration.java +++ b/embedded-cockroachdb/src/main/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfiguration.java @@ -15,9 +15,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.CockroachContainer; +import org.testcontainers.cockroachdb.CockroachContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/AutoConfiguredDatasourceDependsOnTest.java b/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/AutoConfiguredDatasourceDependsOnTest.java index ee65f6d5a..b9e096801 100644 --- a/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/AutoConfiguredDatasourceDependsOnTest.java +++ b/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/AutoConfiguredDatasourceDependsOnTest.java @@ -9,6 +9,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -20,10 +21,10 @@ @SpringBootTest( classes = AutoConfiguredDatasourceDependsOnTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.toxiproxy.proxies.cockroach.enabled=true" } ) +@ActiveProfiles("enabled") public class AutoConfiguredDatasourceDependsOnTest { @Autowired diff --git a/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfigurationTest.java b/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfigurationTest.java index 49539dab6..7b4d6aaa8 100644 --- a/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfigurationTest.java +++ b/embedded-cockroachdb/src/test/java/com/playtika/testcontainer/cockroach/EmbeddedCockroachDBBootstrapConfigurationTest.java @@ -17,6 +17,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -30,10 +31,10 @@ @SpringBootTest( classes = EmbeddedCockroachDBBootstrapConfigurationTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.cockroach.init-script-path=initScript.sql", "embedded.toxiproxy.proxies.cockroach.enabled=true" }) +@ActiveProfiles("enabled") public class EmbeddedCockroachDBBootstrapConfigurationTest { @Autowired diff --git a/embedded-consul/src/main/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfiguration.java b/embedded-consul/src/main/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfiguration.java index a8f9ad339..fd49f19a4 100644 --- a/embedded-consul/src/main/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfiguration.java +++ b/embedded-consul/src/main/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfiguration.java @@ -18,8 +18,8 @@ import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationConfigTest.java b/embedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationConfigTest.java index 8a34a75fe..546f282a7 100644 --- a/embedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationConfigTest.java +++ b/embedded-consul/src/test/java/com/playtika/testcontainer/consul/EmbeddedConsulBootstrapConfigurationConfigTest.java @@ -35,9 +35,7 @@ public void shouldUpdateKeyForbidden() { // with the loaded config consul should require use of an access token, // which is not provided so 403 should be returned by consul - OperationException ex = assertThrows(OperationException.class, () -> { - client.setKVValue("key", "val"); - }); + OperationException ex = assertThrows(OperationException.class, () -> client.setKVValue("key", "val")); assertThat(ex.getStatusCode()).isEqualTo(403); } } diff --git a/embedded-couchbase/pom.xml b/embedded-couchbase/pom.xml index 247f61b3c..c72f5c4c7 100644 --- a/embedded-couchbase/pom.xml +++ b/embedded-couchbase/pom.xml @@ -17,6 +17,7 @@ 3.10.0 4.12.0 + @@ -30,7 +31,7 @@ org.testcontainers - couchbase + testcontainers-couchbase com.querydsl diff --git a/embedded-couchbase/src/main/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfiguration.java b/embedded-couchbase/src/main/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfiguration.java index 0aac55a73..cf4ec606d 100644 --- a/embedded-couchbase/src/main/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfiguration.java +++ b/embedded-couchbase/src/main/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfiguration.java @@ -19,9 +19,9 @@ import org.springframework.core.Ordered; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.couchbase.BucketDefinition; import org.testcontainers.couchbase.CouchbaseContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -60,7 +60,7 @@ ToxiproxyClientProxy couchbaseContainerProxy(ToxiproxyClient toxiproxyClient, public CouchbaseContainer couchbase(CouchbaseProperties properties, Optional network) { BucketDefinition bucketDefinition = new BucketDefinition(properties.getBucket()) - .withPrimaryIndex(true) + .withPrimaryIndex(false) .withQuota(properties.getBucketRamMb()); CouchbaseContainer couchbase = new CouchbaseContainer(ContainerUtils.getDockerImageName(properties)) diff --git a/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfigurationTest.java b/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfigurationTest.java index 4e64e6df0..2a84126d5 100644 --- a/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfigurationTest.java +++ b/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/EmbeddedCouchbaseBootstrapConfigurationTest.java @@ -6,15 +6,16 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest( classes = {EmbeddedCouchbaseBootstrapConfigurationTest.TestConfiguration.class}, properties = { - "spring.profiles.active=enabled", "embedded.toxiproxy.proxies.couchbase.enabled=true" }) +@ActiveProfiles("enabled") public abstract class EmbeddedCouchbaseBootstrapConfigurationTest { @Autowired diff --git a/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.java b/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.java index 02bc87a61..5b31a10a2 100644 --- a/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.java +++ b/embedded-couchbase/src/test/java/com/playtika/testcontainer/couchbase/springdata/SpringDataTest.java @@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.data.couchbase.core.CouchbaseOperations; +import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; import java.util.List; import java.util.concurrent.Callable; @@ -23,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; +@EnableCouchbaseRepositories(basePackages = "com.playtika.testcontainer.couchbase.springdata", considerNestedRepositories = true) public class SpringDataTest extends EmbeddedCouchbaseBootstrapConfigurationTest { @Autowired diff --git a/embedded-couchbase/src/test/resources/application-enabled.properties b/embedded-couchbase/src/test/resources/application-enabled.properties deleted file mode 100644 index afb6c664e..000000000 --- a/embedded-couchbase/src/test/resources/application-enabled.properties +++ /dev/null @@ -1,7 +0,0 @@ -spring.couchbase.connection-string=couchbase://${embedded.couchbase.host:localhost}:${embedded.couchbase.bootstrapCarrierDirectPort:11210}=kv,${embedded.couchbase.host:localhost}:${embedded.couchbase.toxiproxy.port:8091}=manager -spring.couchbase.username=${embedded.couchbase.user:Administrator} -spring.couchbase.password=${embedded.couchbase.password:password} -spring.couchbase.env.timeouts.connect=20s -spring.couchbase.env.timeouts.key-value=20s -spring.data.couchbase.bucket-name=${embedded.couchbase.bucket:test} -spring.data.couchbase.auto-index=true diff --git a/embedded-couchbase/src/test/resources/application-enabled.yml b/embedded-couchbase/src/test/resources/application-enabled.yml new file mode 100644 index 000000000..b0488ba00 --- /dev/null +++ b/embedded-couchbase/src/test/resources/application-enabled.yml @@ -0,0 +1,13 @@ +spring: + couchbase: + connection-string: couchbase://${embedded.couchbase.host}:${embedded.couchbase.bootstrapCarrierDirectPort}=kv,${embedded.couchbase.host}:${embedded.couchbase.toxiproxy.port}=manager + env: + timeouts: + connect: 20s + key-value: 20s + password: ${embedded.couchbase.password} + username: ${embedded.couchbase.user} + data: + couchbase: + auto-index: true + bucket-name: ${embedded.couchbase.bucket} diff --git a/embedded-db2/README.adoc b/embedded-db2/README.adoc index 85e85c45f..c7987b682 100644 --- a/embedded-db2/README.adoc +++ b/embedded-db2/README.adoc @@ -16,7 +16,7 @@ * `embedded.db2.enabled` `(true|false, default is true)` * `embedded.db2.reuseContainer` `(true|false, default is false)` -* `embedded.db2.dockerImage` `(default is 'ibmcom/db2:latest')` +* `embedded.db2.dockerImage` `(default is 'icr.io/db2_community/db2:11.5.8.0')` ** Image versions: https://hub.docker.com/r/ibmcom/db2 * `embedded.db2.user` `(default is db2inst1)` * `embedded.db2.password` `(default is foobar1234)` diff --git a/embedded-db2/pom.xml b/embedded-db2/pom.xml index 3cc0a7f65..cdb4cb984 100644 --- a/embedded-db2/pom.xml +++ b/embedded-db2/pom.xml @@ -29,7 +29,7 @@ org.testcontainers - db2 + testcontainers-db2 org.springframework diff --git a/embedded-db2/src/main/java/com/playtika/testcontainer/db2/Db2Properties.java b/embedded-db2/src/main/java/com/playtika/testcontainer/db2/Db2Properties.java index 30a44140d..cdeb6e8d7 100644 --- a/embedded-db2/src/main/java/com/playtika/testcontainer/db2/Db2Properties.java +++ b/embedded-db2/src/main/java/com/playtika/testcontainer/db2/Db2Properties.java @@ -33,6 +33,6 @@ public class Db2Properties extends CommonContainerProperties { public String getDefaultDockerImage() { // Please don`t remove this comment. // renovate: datasource=docker - return "ibmcom/db2:11.5.8.0"; + return "icr.io/db2_community/db2:11.5.8.0"; } } diff --git a/embedded-db2/src/main/java/com/playtika/testcontainer/db2/EmbeddedDb2BootstrapConfiguration.java b/embedded-db2/src/main/java/com/playtika/testcontainer/db2/EmbeddedDb2BootstrapConfiguration.java index 2ec0b47fe..09f32c418 100644 --- a/embedded-db2/src/main/java/com/playtika/testcontainer/db2/EmbeddedDb2BootstrapConfiguration.java +++ b/embedded-db2/src/main/java/com/playtika/testcontainer/db2/EmbeddedDb2BootstrapConfiguration.java @@ -16,10 +16,10 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.springframework.util.StringUtils; -import org.testcontainers.containers.Db2Container; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; +import org.testcontainers.db2.Db2Container; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-db2/src/test/java/com/playtika/testcontainer/db2/EmbeddedDb2DependenciesAutoConfigurationTest.java b/embedded-db2/src/test/java/com/playtika/testcontainer/db2/EmbeddedDb2DependenciesAutoConfigurationTest.java index 0df76053c..6e3b41ff2 100644 --- a/embedded-db2/src/test/java/com/playtika/testcontainer/db2/EmbeddedDb2DependenciesAutoConfigurationTest.java +++ b/embedded-db2/src/test/java/com/playtika/testcontainer/db2/EmbeddedDb2DependenciesAutoConfigurationTest.java @@ -1,14 +1,20 @@ package com.playtika.testcontainer.db2; import lombok.SneakyThrows; +import org.apache.tomcat.jdbc.pool.PoolConfiguration; +import org.apache.tomcat.jdbc.pool.PoolProperties; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; -import org.testcontainers.containers.Db2Container; +import org.testcontainers.db2.Db2Container; + +import javax.sql.DataSource; import java.util.Map; @@ -23,7 +29,7 @@ @ActiveProfiles("test") class EmbeddedDb2DependenciesAutoConfigurationTest { - @Autowired(required = false) + @Autowired private JdbcTemplate jdbcTemplate; @Autowired @@ -48,6 +54,30 @@ void testCreateDb() { @EnableAutoConfiguration @Configuration static class TestConfiguration { + + @Value("${spring.datasource.url}") + private String jdbcUrl; + @Value("${spring.datasource.username}") + private String user; + @Value("${spring.datasource.password}") + private String password; + + @Bean(destroyMethod = "close") + public DataSource customDatasource() { + PoolConfiguration poolConfiguration = new PoolProperties(); + poolConfiguration.setUrl(jdbcUrl); + poolConfiguration.setDriverClassName("com.ibm.db2.jcc.DB2Driver"); + poolConfiguration.setUsername(user); + poolConfiguration.setPassword(password); + poolConfiguration.setTestOnBorrow(true); + poolConfiguration.setTestOnReturn(true); + return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource customDatasource) { + return new JdbcTemplate(customDatasource); + } } } diff --git a/embedded-db2/src/test/resources/bootstrap.properties b/embedded-db2/src/test/resources/bootstrap.properties index 92d6ec3c1..ac5fe3055 100644 --- a/embedded-db2/src/test/resources/bootstrap.properties +++ b/embedded-db2/src/test/resources/bootstrap.properties @@ -4,4 +4,5 @@ embedded.db2.password=foobar1234 embedded.db2.accept-licence=true embedded.db2.docker-image=ibmcom/db2:11.5.0.0a embedded.db2.wait-timeout-in-seconds=180 -embedded.db2.init-script-path=initScript.sql \ No newline at end of file +embedded.db2.init-script-path=initScript.sql +embedded.db2.startupLogCheckRegex=.*ACTIVATE DATABASE.*completed successfully.* \ No newline at end of file diff --git a/embedded-db2/src/test/resources/container-license-acceptance.txt b/embedded-db2/src/test/resources/container-license-acceptance.txt index e82bfd639..c4ad0a384 100644 --- a/embedded-db2/src/test/resources/container-license-acceptance.txt +++ b/embedded-db2/src/test/resources/container-license-acceptance.txt @@ -1 +1 @@ -ibmcom/db2:11.5.0.0a \ No newline at end of file +ibmcom/db2:11.5.0.0a diff --git a/embedded-dynamodb/src/main/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfiguration.java b/embedded-dynamodb/src/main/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfiguration.java index 7c1ad82f7..0231b31b3 100644 --- a/embedded-dynamodb/src/main/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfiguration.java +++ b/embedded-dynamodb/src/main/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfiguration.java @@ -19,8 +19,8 @@ import org.springframework.core.env.MapPropertySource; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.LinkedHashMap; import java.util.Optional; diff --git a/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfigurationTest.java b/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfigurationTest.java index 03384aa8e..4b777d8f8 100644 --- a/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfigurationTest.java +++ b/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBBootstrapConfigurationTest.java @@ -1,29 +1,34 @@ package com.playtika.testcontainer.dynamodb; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; +import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; +import com.amazonaws.services.dynamodbv2.model.KeyType; import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; +import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType; import com.amazonaws.services.dynamodbv2.util.TableUtils; -import com.playtika.testcontainer.dynamodb.springdata.DynamoDBConfig; -import com.playtika.testcontainer.dynamodb.springdata.User; -import com.playtika.testcontainer.dynamodb.springdata.UserRepository; import lombok.extern.slf4j.Slf4j; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; -import java.util.List; +import java.util.HashMap; +import java.util.Map; -import static com.playtika.testcontainer.dynamodb.DynamoDBProperties.BEAN_NAME_EMBEDDED_DYNAMODB; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @Slf4j @@ -31,79 +36,97 @@ classes = EmbeddedDynamoDBBootstrapConfigurationTest.TestConfiguration.class, properties = { "embedded.dynamodb.enabled=true", - "spring.profiles.active=enabled" + "amazon.aws.accesskey=n/a", + "amazon.aws.secretkey=n/a", + "amazon.aws.endpoint=http://${embedded.dynamodb.host}:${embedded.dynamodb.port}", + "amazon.aws.signingRegion=us-east-1" }) +@ActiveProfiles("enabled") public class EmbeddedDynamoDBBootstrapConfigurationTest { @Autowired - private UserRepository repository; - - @Autowired - ConfigurableListableBeanFactory beanFactory; + private AmazonDynamoDB amazonDynamoDB; @Test - public void sampleTestCase() { - User gosling = new User("James", "Gosling"); - repository.save(gosling); + public void sampleTestCase() throws InterruptedException { + String tableName = "User"; + + // Create table first + CreateTableRequest createTableRequest = new CreateTableRequest() + .withTableName(tableName) + .withKeySchema( + new KeySchemaElement("firstName", KeyType.HASH), + new KeySchemaElement("lastName", KeyType.RANGE)) + .withAttributeDefinitions( + new AttributeDefinition("firstName", ScalarAttributeType.S), + new AttributeDefinition("lastName", ScalarAttributeType.S)) + .withProvisionedThroughput(new ProvisionedThroughput(1L, 1L)); + + boolean tableWasCreatedForTest = TableUtils.createTableIfNotExists(amazonDynamoDB, createTableRequest); + + if (tableWasCreatedForTest) { + log.info("Created table {}", tableName); + } - User hoeller = new User("Juergen", "Hoeller"); - repository.save(hoeller); + TableUtils.waitUntilActive(amazonDynamoDB, tableName); + log.info("Table {} is active", tableName); - List result = repository.findByLastName("Gosling"); - Assertions.assertThat(result.size()).isOne(); - Assertions.assertThat(result).contains(gosling); - log.info("Found in table: {}", result.get(0)); - } + // Put an item + String firstName = "James"; + String lastName = "Gosling"; + Map item = new HashMap<>(); + item.put("firstName", new com.amazonaws.services.dynamodbv2.model.AttributeValue().withS(firstName)); + item.put("lastName", new com.amazonaws.services.dynamodbv2.model.AttributeValue().withS(lastName)); - @Test - public void shouldSetupDependsOnForAllDataAmazonDBs() throws Exception { - String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, AmazonDynamoDB.class); - assertThat(beanNamesForType) - .as("Auto-configured AmazonDynamoDB should be present") - .hasSize(1) - .contains("amazonDynamoDB"); - asList(beanNamesForType).forEach(this::hasDependsOn); - } + PutItemRequest putItemRequest = new PutItemRequest() + .withTableName(tableName) + .withItem(item); + amazonDynamoDB.putItem(putItemRequest); - private void hasDependsOn(String beanName) { - assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) - .isNotNull() - .isNotEmpty() - .contains(BEAN_NAME_EMBEDDED_DYNAMODB); + log.info("Successfully put item in table: {}", tableName); + assertThat(amazonDynamoDB.describeTable(tableName).getTable().getTableStatus()).isEqualTo("ACTIVE"); } - @Slf4j @EnableAutoConfiguration @Configuration - @Import(DynamoDBConfig.class) static class TestConfiguration implements InitializingBean { - @Autowired - private AmazonDynamoDB amazonDynamoDB; - - @Autowired - private DynamoDBMapper mapper; + @Value("${amazon.aws.accesskey}") + private String amazonAWSAccessKey; - @Override - public void afterPropertiesSet() throws Exception { - setupTable(); - } + @Value("${amazon.aws.endpoint}") + private String amazonAWSEndpoint; - void setupTable() throws InterruptedException { + @Value("${amazon.aws.signingRegion:us-east-1}") + private String amazonAWSSigningRegion; - CreateTableRequest ctr = mapper.generateCreateTableRequest(User.class) - .withProvisionedThroughput(new ProvisionedThroughput(1L, 1L)); + @Value("${amazon.aws.secretkey}") + private String amazonAWSSecretKey; - boolean tableWasCreatedForTest = TableUtils.createTableIfNotExists(amazonDynamoDB, ctr); + @Bean + public AWSCredentialsProvider amazonAWSCredentialsProvider(AWSCredentials amazonAWSCredentials) { + return new AWSStaticCredentialsProvider(amazonAWSCredentials); + } - if (tableWasCreatedForTest) { - log.info("Created table {}", ctr.getTableName()); - } + @Bean + public AWSCredentials amazonAWSCredentials() { + return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey); + } - TableUtils.waitUntilActive(amazonDynamoDB, ctr.getTableName()); + @Bean + public AmazonDynamoDB amazonDynamoDB(AWSCredentialsProvider amazonAWSCredentialsProvider) { + AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(amazonAWSEndpoint, amazonAWSSigningRegion); + return AmazonDynamoDBClientBuilder + .standard() + .withCredentials(amazonAWSCredentialsProvider) + .withEndpointConfiguration(endpointConfiguration) + .build(); + } - log.info("Table {} is active", ctr.getTableName()); + @Override + public void afterPropertiesSet() throws Exception { + // Table setup will happen after bean creation } } } diff --git a/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBDependenciesTest.java b/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBDependenciesTest.java new file mode 100644 index 000000000..482e3a74a --- /dev/null +++ b/embedded-dynamodb/src/test/java/com/playtika/testcontainer/dynamodb/EmbeddedDynamoDBDependenciesTest.java @@ -0,0 +1,94 @@ +package com.playtika.testcontainer.dynamodb; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ActiveProfiles; + +import java.util.Arrays; + +import static com.playtika.testcontainer.dynamodb.DynamoDBProperties.BEAN_NAME_EMBEDDED_DYNAMODB; +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest( + classes = EmbeddedDynamoDBDependenciesTest.TestConfiguration.class, + properties = { + "embedded.dynamodb.enabled=true", + "amazon.aws.accesskey=n/a", + "amazon.aws.secretkey=n/a", + "amazon.aws.endpoint=http://${embedded.dynamodb.host}:${embedded.dynamodb.port}", + "amazon.aws.signingRegion=us-east-1" + }) +@ActiveProfiles("enabled") +public class EmbeddedDynamoDBDependenciesTest { + + @Autowired + ConfigurableListableBeanFactory beanFactory; + + @Test + public void shouldSetupDependsOnForAllDataAmazonDBs() throws Exception { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, AmazonDynamoDB.class); + assertThat(beanNamesForType) + .as("Auto-configured AmazonDynamoDB should be present") + .hasSize(1) + .contains("amazonDynamoDB"); + Arrays.asList(beanNamesForType).forEach(this::hasDependsOn); + } + + private void hasDependsOn(String beanName) { + assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) + .isNotNull() + .isNotEmpty() + .contains(BEAN_NAME_EMBEDDED_DYNAMODB); + } + + @EnableAutoConfiguration + @Configuration + static class TestConfiguration { + + @Value("${amazon.aws.accesskey}") + private String amazonAWSAccessKey; + + @Value("${amazon.aws.endpoint}") + private String amazonAWSEndpoint; + + @Value("${amazon.aws.signingRegion:us-east-1}") + private String amazonAWSSigningRegion; + + @Value("${amazon.aws.secretkey}") + private String amazonAWSSecretKey; + + @Bean + public AWSCredentialsProvider amazonAWSCredentialsProvider(AWSCredentials amazonAWSCredentials) { + return new AWSStaticCredentialsProvider(amazonAWSCredentials); + } + + @Bean + public AWSCredentials amazonAWSCredentials() { + return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey); + } + + @Bean + public AmazonDynamoDB amazonDynamoDB(AWSCredentialsProvider amazonAWSCredentialsProvider) { + AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(amazonAWSEndpoint, amazonAWSSigningRegion); + return AmazonDynamoDBClientBuilder + .standard() + .withCredentials(amazonAWSCredentialsProvider) + .withEndpointConfiguration(endpointConfiguration) + .build(); + } + } +} diff --git a/embedded-elasticsearch/pom.xml b/embedded-elasticsearch/pom.xml index 79e4fda05..08f9be521 100644 --- a/embedded-elasticsearch/pom.xml +++ b/embedded-elasticsearch/pom.xml @@ -24,7 +24,7 @@ org.testcontainers - elasticsearch + testcontainers-elasticsearch org.springframework.data diff --git a/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfiguration.java b/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfiguration.java index 469440281..74f1576e5 100644 --- a/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfiguration.java +++ b/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfiguration.java @@ -16,8 +16,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchRestClientDependenciesAutoConfiguration.java b/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchRestClientDependenciesAutoConfiguration.java index 8020fc650..57a035c31 100644 --- a/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchRestClientDependenciesAutoConfiguration.java +++ b/embedded-elasticsearch/src/main/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchRestClientDependenciesAutoConfiguration.java @@ -1,7 +1,7 @@ package com.playtika.testcontainer.elasticsearch; +import co.elastic.clients.elasticsearch.ElasticsearchClient; import com.playtika.testcontainer.common.spring.DependsOnPostProcessor; -import org.elasticsearch.client.RestClient; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -12,15 +12,15 @@ import static com.playtika.testcontainer.elasticsearch.ElasticSearchProperties.BEAN_NAME_EMBEDDED_ELASTIC_SEARCH; -@AutoConfiguration(afterName = "org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration") +@AutoConfiguration(afterName = "org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration") @AutoConfigureOrder @ConditionalOnExpression("${embedded.containers.enabled:true}") -@ConditionalOnClass(RestClient.class) +@ConditionalOnClass(ElasticsearchClient.class) @ConditionalOnProperty(name = "embedded.elasticsearch.enabled", matchIfMissing = true) public class EmbeddedElasticSearchRestClientDependenciesAutoConfiguration { @Bean public static BeanFactoryPostProcessor elasticRestClientDependencyPostProcessor() { - return new DependsOnPostProcessor(RestClient.class, new String[]{BEAN_NAME_EMBEDDED_ELASTIC_SEARCH}); + return new DependsOnPostProcessor(ElasticsearchClient.class, new String[]{BEAN_NAME_EMBEDDED_ELASTIC_SEARCH}); } } diff --git a/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfigurationTest.java b/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfigurationTest.java index e7ea96da8..5f62aa6f4 100644 --- a/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfigurationTest.java +++ b/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/EmbeddedElasticSearchBootstrapConfigurationTest.java @@ -5,6 +5,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration; +import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; @@ -38,7 +41,18 @@ public void propertiesAreAvailable() { @Configuration @EnableAutoConfiguration - public static class Config { + @EnableElasticsearchRepositories(basePackages = "com.playtika.testcontainer.elasticsearch.springdata") + public static class Config extends ElasticsearchConfiguration { + + @Value("${spring.elasticsearch.uris}") + private String elasticsearchUri; + + @Override + public ClientConfiguration clientConfiguration() { + return ClientConfiguration.builder() + .connectedTo(elasticsearchUri.replace("http://", "")) + .build(); + } } -} \ No newline at end of file +} diff --git a/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/springdata/SpringDataTest.java b/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/springdata/SpringDataTest.java index 739ac65d0..8bfc87a30 100644 --- a/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/springdata/SpringDataTest.java +++ b/embedded-elasticsearch/src/test/java/com/playtika/testcontainer/elasticsearch/springdata/SpringDataTest.java @@ -1,8 +1,8 @@ package com.playtika.testcontainer.elasticsearch.springdata; +import co.elastic.clients.elasticsearch.ElasticsearchClient; import com.playtika.testcontainer.elasticsearch.ElasticSearchProperties; import com.playtika.testcontainer.elasticsearch.EmbeddedElasticSearchBootstrapConfigurationTest; -import org.elasticsearch.client.RestClient; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -26,11 +26,11 @@ public void springDataShouldWork() { String key = "test::1"; String value = "myvalue"; assertThat(documentRepository).isNotNull(); - assertThat(documentRepository.findById(key).isPresent()).isFalse(); + assertThat(documentRepository.findById(key)).isNotPresent(); TestDocument testDocument = saveDocument(key, value); - assertThat(documentRepository.findById(key).get()).isEqualTo(testDocument); + assertThat(documentRepository.findById(key)).contains(testDocument); } @Test @@ -42,25 +42,24 @@ public void queryShouldWork() { List resultList = documentRepository.findByTitle(title); - assertThat(resultList.size()).isEqualTo(2); + assertThat(resultList).hasSize(2); } @Test - public void shouldSetupDependsOnForNewClient() { - String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, RestClient.class); + public void shouldSetupDependsOnForElasticsearchClient() { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, ElasticsearchClient.class); if (beanNamesForType.length > 0) { assertThat(beanNamesForType) - .as("New client should be present") + .as("Elasticsearch client should be present") .hasSize(1) - .contains("elasticsearchRestClient"); + .contains("elasticsearchClient"); asList(beanNamesForType).forEach(this::hasDependsOn); } } private void hasDependsOn(String beanName) { assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) - .isNotNull() .isNotEmpty() .contains(ElasticSearchProperties.BEAN_NAME_EMBEDDED_ELASTIC_SEARCH); } diff --git a/embedded-git/src/main/java/com/playtika/testcontainer/git/EmbeddedGitBootstrapConfiguration.java b/embedded-git/src/main/java/com/playtika/testcontainer/git/EmbeddedGitBootstrapConfiguration.java index a751aa8f6..5b6ca1241 100644 --- a/embedded-git/src/main/java/com/playtika/testcontainer/git/EmbeddedGitBootstrapConfiguration.java +++ b/embedded-git/src/main/java/com/playtika/testcontainer/git/EmbeddedGitBootstrapConfiguration.java @@ -18,15 +18,15 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; import static com.playtika.testcontainer.git.GitProperties.BEAN_NAME_EMBEDDED_GIT; -import static org.testcontainers.shaded.org.apache.commons.lang3.StringUtils.isEmpty; -import static org.testcontainers.shaded.org.apache.commons.lang3.StringUtils.isNotEmpty; +import static org.apache.commons.lang3.ObjectUtils.isNotEmpty; +import static org.springframework.util.ObjectUtils.isEmpty; import static org.testcontainers.utility.MountableFile.forClasspathResource; @Slf4j diff --git a/embedded-git/src/test/java/EmbeddedGitBootstrapConfigurationTest.java b/embedded-git/src/test/java/EmbeddedGitBootstrapConfigurationTest.java index 96ca398f6..89372ab75 100644 --- a/embedded-git/src/test/java/EmbeddedGitBootstrapConfigurationTest.java +++ b/embedded-git/src/test/java/EmbeddedGitBootstrapConfigurationTest.java @@ -14,6 +14,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.io.Resource; +import org.springframework.test.context.ActiveProfiles; import org.testcontainers.containers.GenericContainer; import util.EncryptionUtils; @@ -24,20 +25,20 @@ import static java.io.File.separator; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.commons.io.FileUtils.contentEquals; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.testcontainers.shaded.org.apache.commons.io.FileUtils.contentEquals; @Slf4j @SpringBootTest( classes = EmbeddedGitBootstrapConfigurationTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.git.enabled=true", "embedded.git.path-to-repositories=src/test/resources/repository", "embedded.git.path-to-authorized-keys=src/test/resources/key/embedded-git.pub" } ) +@ActiveProfiles("enabled") class EmbeddedGitBootstrapConfigurationTest { @Autowired diff --git a/embedded-git/src/test/java/util/EncryptionUtils.java b/embedded-git/src/test/java/util/EncryptionUtils.java index 502004f0e..3ea2937f5 100644 --- a/embedded-git/src/test/java/util/EncryptionUtils.java +++ b/embedded-git/src/test/java/util/EncryptionUtils.java @@ -1,6 +1,7 @@ package util; import lombok.experimental.UtilityClass; +import org.apache.commons.io.IOUtils; import org.bouncycastle.openssl.PEMDecryptorProvider; import org.bouncycastle.openssl.PEMEncryptedKeyPair; import org.bouncycastle.openssl.PEMKeyPair; @@ -8,7 +9,6 @@ import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; import org.bouncycastle.util.encoders.Base64; -import org.testcontainers.shaded.org.apache.commons.io.IOUtils; import java.io.File; import java.io.FileInputStream; diff --git a/embedded-google-pubsub/pom.xml b/embedded-google-pubsub/pom.xml index af66d9894..8c0a9aa4b 100644 --- a/embedded-google-pubsub/pom.xml +++ b/embedded-google-pubsub/pom.xml @@ -25,7 +25,7 @@ org.testcontainers - gcloud + testcontainers-gcloud com.google.cloud diff --git a/embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java b/embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java index 5904c4f86..7f5672a81 100644 --- a/embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java +++ b/embedded-google-pubsub/src/main/java/com/playtika/testcontainer/pubsub/EmbeddedPubsubBootstrapConfiguration.java @@ -19,8 +19,8 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.io.IOException; import java.util.Optional; diff --git a/embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.java b/embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.java index 8a2304247..2fac13556 100644 --- a/embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.java +++ b/embedded-google-storage/src/main/java/com/playtika/testcontainer/storage/EmbeddedStorageBootstrapConfiguration.java @@ -18,7 +18,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.io.IOException; import java.util.Optional; diff --git a/embedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.java b/embedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.java index 38d836588..d3d30583a 100644 --- a/embedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.java +++ b/embedded-grafana/src/main/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfiguration.java @@ -18,9 +18,9 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java b/embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java index 87392bbb4..cd2bf2e7a 100644 --- a/embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java +++ b/embedded-grafana/src/test/java/com/playtika/testcontainer/grafana/EmbeddedGrafanaBootstrapConfigurationTest.java @@ -1,12 +1,19 @@ package com.playtika.testcontainer.grafana; +import com.jayway.jsonpath.JsonPath; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; -import static io.restassured.RestAssured.given; -import static org.hamcrest.Matchers.equalTo; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +import static org.assertj.core.api.Assertions.assertThat; class EmbeddedGrafanaBootstrapConfigurationTest extends BaseEmbeddedGrafanaTest { @Value("${embedded.grafana.username}") @@ -16,22 +23,20 @@ class EmbeddedGrafanaBootstrapConfigurationTest extends BaseEmbeddedGrafanaTest @Test void shouldProvisionDatasourceFromConfigurationFile() { - UriComponents uriComponents = UriComponentsBuilder.newInstance() - .scheme("http") - .host(grafanaHost) - .port(grafanaPort) - .path("/api/datasources/name/Prometheus") - .build(); - - given() - .auth() - .preemptive() - .basic(username, password) - .get(uriComponents.toUriString()) - .then() - .assertThat() - .body("url", equalTo("http://prometheus:9090")) - .statusCode(200); + RestTemplate restTemplate = new RestTemplate(); + String url = "http://" + grafanaHost + ":" + grafanaPort + "/api/datasources/name/Prometheus"; + + HttpHeaders headers = new HttpHeaders(); + String auth = username + ":" + password; + byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); + String authHeader = "Basic " + new String(encodedAuth, StandardCharsets.UTF_8); + headers.set("Authorization", authHeader); + + HttpEntity entity = new HttpEntity<>(headers); + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(JsonPath.parse(response.getBody()).read("$.url", String.class)).isEqualTo("http://prometheus:9090"); } -} \ No newline at end of file +} diff --git a/embedded-influxdb/pom.xml b/embedded-influxdb/pom.xml index fb579396e..030c946ca 100644 --- a/embedded-influxdb/pom.xml +++ b/embedded-influxdb/pom.xml @@ -25,7 +25,7 @@ org.testcontainers - influxdb + testcontainers-influxdb org.influxdb @@ -47,6 +47,17 @@ jackson-databind test + + org.springframework.boot + spring-boot-starter-web + test + + + org.springframework.boot + spring-boot-starter-logging + + + \ No newline at end of file diff --git a/embedded-influxdb/src/main/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfiguration.java b/embedded-influxdb/src/main/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfiguration.java index a87a02251..4a6c0090c 100644 --- a/embedded-influxdb/src/main/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfiguration.java +++ b/embedded-influxdb/src/main/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfiguration.java @@ -17,9 +17,9 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.InfluxDBContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.DockerImageName; import java.util.Optional; diff --git a/embedded-influxdb/src/test/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfigurationTest.java b/embedded-influxdb/src/test/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfigurationTest.java index 9175e90f1..bea42f2a3 100644 --- a/embedded-influxdb/src/test/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfigurationTest.java +++ b/embedded-influxdb/src/test/java/com/playtika/testcontainer/influxdb/EmbeddedInfluxDBBootstrapConfigurationTest.java @@ -1,15 +1,18 @@ package com.playtika.testcontainer.influxdb; -import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import org.apache.http.HttpStatus; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; -import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @@ -42,19 +45,23 @@ void propertiesAreAvailable() { @Test void influxDatabaseIsAvailable() { - RestAssured.baseURI = getUrl(); - ExtractableResponse response = given() - .auth().basic(influxdbUser, influxdbPassword) - .get("/ping") - .then() - .statusCode(HttpStatus.SC_NO_CONTENT) - .extract(); - - assertThat(response.statusCode()).isEqualTo(204); - } + RestTemplate restTemplate = new RestTemplate(); + String baseUrl = "http://" + influxdbHost + ":" + influxdbPort; + + HttpHeaders headers = new HttpHeaders(); + String auth = influxdbUser + ":" + influxdbPassword; + byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); + String authHeader = "Basic " + new String(encodedAuth, StandardCharsets.UTF_8); + headers.set("Authorization", authHeader); + + ResponseEntity response = restTemplate.exchange( + baseUrl + "/ping", + org.springframework.http.HttpMethod.GET, + new org.springframework.http.HttpEntity<>(headers), + String.class + ); - private String getUrl() { - return "http://" + influxdbHost + ":" + influxdbPort; + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); } @EnableAutoConfiguration diff --git a/embedded-k3s/pom.xml b/embedded-k3s/pom.xml index c62d130ab..d543110eb 100644 --- a/embedded-k3s/pom.xml +++ b/embedded-k3s/pom.xml @@ -29,7 +29,7 @@ org.testcontainers - k3s + testcontainers-k3s diff --git a/embedded-kafka/pom.xml b/embedded-kafka/pom.xml index 0323ac5a6..a4e2d7068 100644 --- a/embedded-kafka/pom.xml +++ b/embedded-kafka/pom.xml @@ -49,7 +49,7 @@ org.testcontainers - kafka + testcontainers-kafka jakarta.validation diff --git a/embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java b/embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java index 6804e4770..d882137f8 100644 --- a/embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java +++ b/embedded-kafka/src/main/java/com/playtika/testcontainer/kafka/configuration/KafkaContainerConfiguration.java @@ -24,7 +24,7 @@ import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.KafkaContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.MountableFile; import java.io.IOException; diff --git a/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryAuthTest.java b/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryAuthTest.java index 3acb1024f..cedb150da 100644 --- a/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryAuthTest.java +++ b/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryAuthTest.java @@ -3,13 +3,19 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.test.context.TestPropertySource; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; @Order(5) @TestPropertySource(properties = { @@ -32,11 +38,21 @@ class EmbeddedSchemaRegistryAuthTest extends AbstractEmbeddedKafkaTest { @Test void authenticationSucceeded() { - TestRestTemplate restTemplate = new TestRestTemplate(new RestTemplateBuilder() - .rootUri(String.format("http://%s:%d", host, port)) - .basicAuthentication(username, password)); + RestTemplate restTemplate = new RestTemplate(); + String baseUrl = String.format("http://%s:%d", host, port); + + HttpHeaders headers = new HttpHeaders(); + String auth = username + ":" + password; + byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); + String authHeader = "Basic " + new String(encodedAuth, StandardCharsets.UTF_8); + headers.set("Authorization", authHeader); - ResponseEntity response = restTemplate.getForEntity("/", String.class); + ResponseEntity response = restTemplate.exchange( + baseUrl + "/", + org.springframework.http.HttpMethod.GET, + new HttpEntity<>(headers), + String.class + ); assertThat(response) .extracting(ResponseEntity::getStatusCode) @@ -45,13 +61,12 @@ void authenticationSucceeded() { @Test void authenticationFailed() { - TestRestTemplate restTemplate = new TestRestTemplate(new RestTemplateBuilder() - .rootUri(String.format("http://%s:%d", host, port))); - - ResponseEntity response = restTemplate.getForEntity("/", String.class); + RestTemplate restTemplate = new RestTemplate(); + String baseUrl = String.format("http://%s:%d", host, port); - assertThat(response) - .extracting(ResponseEntity::getStatusCode) + assertThatThrownBy(() -> restTemplate.getForEntity(baseUrl + "/", String.class)) + .isInstanceOf(HttpClientErrorException.class) + .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) .isEqualTo(HttpStatus.UNAUTHORIZED); } } diff --git a/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryTest.java b/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryTest.java index 8dee13773..65bad8e45 100644 --- a/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryTest.java +++ b/embedded-kafka/src/test/java/com/playtika/testcontainer/kafka/EmbeddedSchemaRegistryTest.java @@ -3,12 +3,11 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; @@ -29,15 +28,15 @@ void schemasTopicAvailable() throws Exception { @Test void schemaCreation() { - TestRestTemplate restTemplate = new TestRestTemplate(new RestTemplateBuilder() - .rootUri(String.format("http://%s:%d", host, port))); + RestTemplate restTemplate = new RestTemplate(); + String baseUrl = String.format("http://%s:%d", host, port); HttpHeaders headers = new HttpHeaders(); headers.set(CONTENT_TYPE, "application/vnd.schemaregistry.v1+json"); HttpEntity request = new HttpEntity<>("{\"schema\": \"{\\\"type\\\": \\\"string\\\"}\"}", headers); - ResponseEntity response = restTemplate.postForEntity("/subjects/test-subject/versions", request, String.class); + ResponseEntity response = restTemplate.postForEntity(baseUrl + "/subjects/test-subject/versions", request, String.class); assertThat(response) .extracting(ResponseEntity::getStatusCode, ResponseEntity::getBody) diff --git a/embedded-keycloak/pom.xml b/embedded-keycloak/pom.xml index 91402725f..d4d02e45e 100644 --- a/embedded-keycloak/pom.xml +++ b/embedded-keycloak/pom.xml @@ -51,6 +51,12 @@ org.springframework.security spring-security-web test + + + commons-logging + commons-logging + + org.springframework.security @@ -61,6 +67,16 @@ org.springframework.boot spring-boot-starter-oauth2-resource-server test + + + org.springframework.boot + spring-boot-starter-logging + + + commons-logging + commons-logging + + diff --git a/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java b/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java index f4e0496c9..958945617 100644 --- a/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java +++ b/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/EmbeddedKeycloakBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java b/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java index efe3f2c30..5586fa72a 100644 --- a/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java +++ b/embedded-keycloak/src/main/java/com/playtika/testcontainer/keycloak/KeycloakContainer.java @@ -15,6 +15,7 @@ public class KeycloakContainer extends GenericContainer { public static final int KEYCLOAK_DEFAULT_HTTP_PORT_INTERNAL = 8080; + public static final int KEYCLOAK_DEFAULT_HTTPS_PORT_INTERNAL = 8443; private final KeycloakProperties properties; private final ResourceLoader resourceLoader; @@ -30,6 +31,8 @@ public KeycloakContainer(KeycloakProperties properties, protected void configure() { withEnv("HTTP_ENABLED", String.valueOf(true)); withEnv("HTTP_PORT", String.valueOf(KEYCLOAK_DEFAULT_HTTP_PORT_INTERNAL)); + withEnv("KC_HOSTNAME_STRICT", "false"); + withEnv("KC_HOSTNAME_STRICT_HTTPS", "false"); withExposedPorts(KEYCLOAK_DEFAULT_HTTP_PORT_INTERNAL); withEnv("KEYCLOAK_ADMIN", properties.getAdminUser()); withEnv("KEYCLOAK_ADMIN_PASSWORD", properties.getAdminPassword()); @@ -140,18 +143,22 @@ private void checkExists(String importFile) { private WaitStrategy waitForListeningPort() { return Wait - .forListeningPort() - .withStartupTimeout(properties.getTimeoutDuration()); + .forListeningPort() + .withStartupTimeout(properties.getTimeoutDuration()); } public String getIp() { - return getContainerIpAddress(); + return getHost(); } public Integer getHttpPort() { return getMappedPort(KEYCLOAK_DEFAULT_HTTP_PORT_INTERNAL); } + public Integer getHttpsPort() { + return getMappedPort(KEYCLOAK_DEFAULT_HTTPS_PORT_INTERNAL); + } + public String getAuthServerUrl() { return format("http://%s:%d%s", getIp(), getHttpPort(), properties.getAuthBasePath()); } diff --git a/embedded-keydb/pom.xml b/embedded-keydb/pom.xml index b5fd57732..f881d82ee 100644 --- a/embedded-keydb/pom.xml +++ b/embedded-keydb/pom.xml @@ -34,6 +34,18 @@ jedis true + + + org.springframework.boot + spring-boot-starter-data-redis + test + + + org.springframework.boot + spring-boot-starter-logging + + + diff --git a/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbBootstrapConfiguration.java b/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbBootstrapConfiguration.java index f6e291f8c..6225defad 100644 --- a/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbBootstrapConfiguration.java +++ b/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbBootstrapConfiguration.java @@ -24,8 +24,8 @@ import org.testcontainers.containers.FixedHostPortGenericContainer; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.MountableFile; import java.io.IOException; diff --git a/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbDependenciesAutoConfiguration.java b/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbDependenciesAutoConfiguration.java index 64571bfbd..5a89f1c34 100644 --- a/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbDependenciesAutoConfiguration.java +++ b/embedded-keydb/src/main/java/com/playtika/testcontainer/keydb/EmbeddedKeyDbDependenciesAutoConfiguration.java @@ -12,6 +12,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import redis.clients.jedis.Jedis; import static com.playtika.testcontainer.keydb.KeyDbProperties.BEAN_NAME_EMBEDDED_KEYDB; @@ -41,6 +42,15 @@ public static BeanFactoryPostProcessor redisTemplateDependencyPostProcessor() { } } + @Configuration + @ConditionalOnClass(StringRedisTemplate.class) + public static class StringRedisTemplateDependencyContext { + @Bean + public static BeanFactoryPostProcessor stringRedisTemplateDependencyPostProcessor() { + return new DependsOnPostProcessor(StringRedisTemplate.class, new String[]{BEAN_NAME_EMBEDDED_KEYDB}); + } + } + @Configuration @ConditionalOnClass(Jedis.class) public static class JedisDependencyContext { diff --git a/embedded-keydb/src/test/java/com/playtika/testcontainer/keydb/BaseEmbeddedKeyDbTest.java b/embedded-keydb/src/test/java/com/playtika/testcontainer/keydb/BaseEmbeddedKeyDbTest.java index 2cecb6b58..12bf6629a 100644 --- a/embedded-keydb/src/test/java/com/playtika/testcontainer/keydb/BaseEmbeddedKeyDbTest.java +++ b/embedded-keydb/src/test/java/com/playtika/testcontainer/keydb/BaseEmbeddedKeyDbTest.java @@ -2,19 +2,20 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.assertj.core.api.Assertions.assertThat; @Slf4j -@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = BaseEmbeddedKeyDbTest.TestConfiguration.class) @ActiveProfiles("enabled") public abstract class BaseEmbeddedKeyDbTest { @@ -54,4 +55,9 @@ void propertiesAreAvailable() { assertThat(keydbPassword).isNotEmpty(); } + @EnableAutoConfiguration + @Configuration + static class TestConfiguration { + } + } diff --git a/embedded-localstack/pom.xml b/embedded-localstack/pom.xml index 70b3fd09f..6b86a0a92 100644 --- a/embedded-localstack/pom.xml +++ b/embedded-localstack/pom.xml @@ -40,7 +40,7 @@ org.testcontainers - localstack + testcontainers-localstack software.amazon.awssdk diff --git a/embedded-localstack/src/main/java/com/playtika/testcontainer/localstack/EmbeddedLocalStackBootstrapConfiguration.java b/embedded-localstack/src/main/java/com/playtika/testcontainer/localstack/EmbeddedLocalStackBootstrapConfiguration.java index bae11448c..fab32d598 100644 --- a/embedded-localstack/src/main/java/com/playtika/testcontainer/localstack/EmbeddedLocalStackBootstrapConfiguration.java +++ b/embedded-localstack/src/main/java/com/playtika/testcontainer/localstack/EmbeddedLocalStackBootstrapConfiguration.java @@ -17,8 +17,8 @@ import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.localstack.LocalStackContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-mailhog/src/main/java/com/playtika/testcontainer/mailhog/EmbeddedMailHogBootstrapConfiguration.java b/embedded-mailhog/src/main/java/com/playtika/testcontainer/mailhog/EmbeddedMailHogBootstrapConfiguration.java index aafa25a62..ead4e3edb 100644 --- a/embedded-mailhog/src/main/java/com/playtika/testcontainer/mailhog/EmbeddedMailHogBootstrapConfiguration.java +++ b/embedded-mailhog/src/main/java/com/playtika/testcontainer/mailhog/EmbeddedMailHogBootstrapConfiguration.java @@ -14,7 +14,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -22,8 +21,8 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Map; import java.util.Optional; @@ -35,7 +34,7 @@ @Configuration @ConditionalOnExpression("${embedded.containers.enabled:true}") @AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) -@AutoConfigureBefore(MailSenderAutoConfiguration.class) +@AutoConfigureBefore(name = "org.springframework.boot.mail.autoconfigure.MailSenderAutoConfiguration") @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @ConditionalOnProperty(name = "embedded.mailhog.enabled", matchIfMissing = true) @EnableConfigurationProperties(MailHogProperties.class) diff --git a/embedded-mariadb/pom.xml b/embedded-mariadb/pom.xml index f2e91d231..3d51d74d9 100644 --- a/embedded-mariadb/pom.xml +++ b/embedded-mariadb/pom.xml @@ -30,7 +30,7 @@ org.testcontainers - mariadb + testcontainers-mariadb org.springframework @@ -42,5 +42,16 @@ tomcat-jdbc test + + org.springframework.boot + spring-boot-starter-jdbc + test + + + org.springframework.boot + spring-boot-starter-logging + + + diff --git a/embedded-mariadb/src/main/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfiguration.java b/embedded-mariadb/src/main/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfiguration.java index 2cf933375..5a4461f14 100644 --- a/embedded-mariadb/src/main/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfiguration.java +++ b/embedded-mariadb/src/main/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfiguration.java @@ -15,9 +15,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.mariadb.MariaDBContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -52,7 +52,7 @@ ToxiproxyClientProxy mariadbContainerProxy(ToxiproxyClient toxiproxyClient, public MariaDBContainer mariadb(MariaDBProperties properties, Optional network) throws Exception { MariaDBContainer mariadb = - new MariaDBContainer<>(ContainerUtils.getDockerImageName(properties)) + new MariaDBContainer(ContainerUtils.getDockerImageName(properties)) .withEnv("MYSQL_ALLOW_EMPTY_PASSWORD", "yes") .withUsername(properties.getUser()) .withPassword(properties.getPassword()) diff --git a/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/AutoConfiguredDatasourceDependsOnTest.java b/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/AutoConfiguredDatasourceDependsOnTest.java index 3f975f9ba..acddfc5a9 100644 --- a/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/AutoConfiguredDatasourceDependsOnTest.java +++ b/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/AutoConfiguredDatasourceDependsOnTest.java @@ -9,6 +9,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -20,10 +21,10 @@ @SpringBootTest( classes = AutoConfiguredDatasourceDependsOnTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.toxiproxy.proxies.mariadb.enabled=true" } ) +@ActiveProfiles("enabled") public class AutoConfiguredDatasourceDependsOnTest { @Autowired diff --git a/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfigurationTest.java b/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfigurationTest.java index 1d498d378..4b9829fd2 100644 --- a/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfigurationTest.java +++ b/embedded-mariadb/src/test/java/com/playtika/testcontainer/mariadb/EmbeddedMariaDBBootstrapConfigurationTest.java @@ -16,6 +16,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -29,10 +30,10 @@ @SpringBootTest( classes = EmbeddedMariaDBBootstrapConfigurationTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.mariadb.init-script-path=initScript.sql", "embedded.toxiproxy.proxies.mariadb.enabled=true" }) +@ActiveProfiles("enabled") public class EmbeddedMariaDBBootstrapConfigurationTest { @Autowired diff --git a/embedded-memsql/pom.xml b/embedded-memsql/pom.xml index ea24363da..15d969ede 100644 --- a/embedded-memsql/pom.xml +++ b/embedded-memsql/pom.xml @@ -19,6 +19,10 @@ com.playtika.testcontainers testcontainers-common + + org.testcontainers + testcontainers-jdbc + com.playtika.testcontainers embedded-toxiproxy @@ -38,5 +42,16 @@ tomcat-jdbc test + + org.springframework.boot + spring-boot-starter-jdbc + test + + + org.springframework.boot + spring-boot-starter-logging + + + diff --git a/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java b/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java index 83f85a615..e8a0c1b4e 100644 --- a/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java +++ b/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfiguration.java @@ -10,16 +10,13 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; -import org.testcontainers.utility.MountableFile; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -36,17 +33,11 @@ public class EmbeddedMemSqlBootstrapConfiguration { private static final String MEMSQL_NETWORK_ALIAS = "memsql.testcontainer.docker"; - @Bean - @ConditionalOnMissingBean - MemSqlStatusCheck memSqlStartupCheckStrategy(MemSqlProperties properties) { - return new MemSqlStatusCheck(properties); - } - @Bean @ConditionalOnToxiProxyEnabled(module = "memsql") ToxiproxyClientProxy memsqlContainerProxy(ToxiproxyClient toxiproxyClient, ToxiproxyContainer toxiproxyContainer, - @Qualifier(BEAN_NAME_EMBEDDED_MEMSQL) GenericContainer memsql, + @Qualifier(BEAN_NAME_EMBEDDED_MEMSQL) MemSqlContainer memsql, MemSqlProperties properties) { return ToxiproxyHelper.createProxy( toxiproxyClient, @@ -63,30 +54,24 @@ public DynamicPropertyRegistrar memsqlToxiProxyDynamicPropertyRegistrar(@Qualifi } @Bean(name = BEAN_NAME_EMBEDDED_MEMSQL, destroyMethod = "stop") - public GenericContainer memsql(MemSqlProperties properties, - MemSqlStatusCheck memSqlStatusCheck, - Optional network) { - GenericContainer memsql = new GenericContainer<>(ContainerUtils.getDockerImageName(properties)) - .withEnv("IGNORE_MIN_REQUIREMENTS", "1") - .withEnv("SINGLESTORE_SET_GLOBAL_DEFAULT_PARTITIONS_PER_LEAF", "1") - .withEnv("LICENSE_KEY", properties.getLicenseKey()) - .withEnv("SINGLESTORE_LICENSE", properties.getLicenseKey()) - .withEnv("ROOT_PASSWORD", properties.getPassword()) - .withEnv("START_AFTER_INIT", "Y") - .withExposedPorts(properties.port) - .withCopyFileToContainer(MountableFile.forClasspathResource("mem.sql"), "/schema.sql") - .waitingFor(memSqlStatusCheck) + public MemSqlContainer memsql( + MemSqlProperties properties, + Optional network) { + MemSqlContainer memsql = new MemSqlContainer(ContainerUtils.getDockerImageName(properties)) + .withLicenseKey(properties.getLicenseKey()) + .withUsername(properties.getUser()) + .withPassword(properties.getPassword()) + .withDatabaseName(properties.getDatabase()) + .withInitScript("mem.sql") .withNetworkAliases(MEMSQL_NETWORK_ALIAS); - if ("aarch".equals(System.getProperty("system.arch"))){ - memsql = memsql.withCommand("platform", "linux/amd64"); - } + network.ifPresent(memsql::withNetwork); - memsql = configureCommonsAndStart(memsql, properties, log); + memsql = (MemSqlContainer) configureCommonsAndStart(memsql, properties, log); return memsql; } @Bean - public DynamicPropertyRegistrar memsqlDynamicPropertyRegistrar(@Qualifier(BEAN_NAME_EMBEDDED_MEMSQL) GenericContainer memsql, MemSqlProperties properties) { + public DynamicPropertyRegistrar memsqlDynamicPropertyRegistrar(@Qualifier(BEAN_NAME_EMBEDDED_MEMSQL) MemSqlContainer memsql, MemSqlProperties properties) { return registry -> { Integer mappedPort = memsql.getMappedPort(properties.port); String host = memsql.getHost(); diff --git a/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java b/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java new file mode 100644 index 000000000..4895ce65f --- /dev/null +++ b/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlContainer.java @@ -0,0 +1,162 @@ +package com.playtika.testcontainer.memsql; + +import org.testcontainers.containers.JdbcDatabaseContainer; +import org.testcontainers.utility.DockerImageName; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +public class MemSqlContainer extends JdbcDatabaseContainer { + + private static final String IMAGE = "ghcr.io/singlestore-labs/singlestoredb-dev"; + private static final String DEFAULT_TAG = "8.9.10"; + private static final int MYSQL_PORT = 3306; + + private String licenseKey; + private String databaseName = "test_db"; + private String username = "root"; + private String password = "pass"; + + public MemSqlContainer(String dockerImageName) { + this(DockerImageName.parse(dockerImageName)); + } + + public MemSqlContainer(DockerImageName dockerImageName) { + super(dockerImageName); + dockerImageName.assertValid(); + withExposedPorts(MYSQL_PORT); + } + + public MemSqlContainer() { + this(DockerImageName.parse(IMAGE + ":" + DEFAULT_TAG)); + } + + @Override + protected void configure() { + super.configure(); + withEnv("IGNORE_MIN_REQUIREMENTS", "1"); + withEnv("SINGLESTORE_SET_GLOBAL_DEFAULT_PARTITIONS_PER_LEAF", "1"); + // Try different environment variable names for chunk size configuration + // SingleStore may use different variable names in different versions + withEnv("SINGLESTORE_MINIMUM_CHUNK_SIZE", "536870912"); + withEnv("MINIMUM_CHUNK_SIZE", "536870912"); + // Disable disk space checks if possible + withEnv("SINGLESTORE_SKIP_DISK_SPACE_CHECK", "1"); + withEnv("SKIP_DISK_SPACE_CHECK", "1"); + if (licenseKey != null) { + withEnv("LICENSE_KEY", licenseKey); + withEnv("SINGLESTORE_LICENSE", licenseKey); + } + withEnv("ROOT_PASSWORD", password); + withEnv("START_AFTER_INIT", "Y"); + // Try to reduce disk space requirements by setting additional SingleStore config + // These may not all work, but we try multiple approaches + withEnv("SINGLESTORE_REDUCE_DISK_REQUIREMENTS", "1"); + withEnv("SINGLESTORE_TEST_MODE", "1"); + + if ("aarch".equals(System.getProperty("system.arch"))) { + withCommand("platform", "linux/amd64"); + } + } + + @Override + public String getDriverClassName() { + return "org.mariadb.jdbc.Driver"; + } + + @Override + public String getJdbcUrl() { + String additionalUrlParams = constructUrlParameters("?", "&"); + // Connect without database name - MySQL/MariaDB allows this + // The init script will create the database, and applications can connect to it + // by specifying the database name in their connection strings if needed + return "jdbc:mariadb://" + getHost() + ":" + getMappedPort(MYSQL_PORT) + additionalUrlParams; + } + + /** + * Returns the JDBC URL with the database name included. + * This is used by applications that need the full connection string. + */ + public String getJdbcUrlWithDatabase() { + String additionalUrlParams = constructUrlParameters("?", "&"); + return "jdbc:mariadb://" + getHost() + ":" + getMappedPort(MYSQL_PORT) + "/" + databaseName + additionalUrlParams; + } + + @Override + protected String getTestQueryString() { + return "SELECT 1"; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public String getPassword() { + return password; + } + + public MemSqlContainer withLicenseKey(String licenseKey) { + this.licenseKey = licenseKey; + return self(); + } + + @Override + public MemSqlContainer withUsername(String username) { + this.username = username; + return self(); + } + + @Override + public MemSqlContainer withPassword(String password) { + this.password = password; + return self(); + } + + @Override + public MemSqlContainer withDatabaseName(String databaseName) { + this.databaseName = databaseName; + return self(); + } + + @Override + public String getDatabaseName() { + return databaseName; + } + + /** + * Override to set chunk size and create database manually. + * This reduces the disk space requirement from 16GB to a smaller value. + */ + @Override + protected void waitUntilContainerStarted() { + super.waitUntilContainerStarted(); + // After container is ready, try to set chunk size and create database + try (Connection connection = createConnection("")) { + try (Statement statement = connection.createStatement()) { + // Try multiple approaches to set chunk size + String[] chunkSizeCommands = { + "SET GLOBAL minimum_chunk_size_mb = 512", + "SET GLOBAL min_chunk_size = 536870912", + "SET minimum_chunk_size_mb = 512", + "SET GLOBAL default_partitions_per_leaf = 1" + }; + + for (String cmd : chunkSizeCommands) { + try { + statement.execute(cmd); + break; // If one works, stop trying + } catch (SQLException e) { + // Continue to next command + } + } + + } + } catch (Exception e) { + // If manual creation fails, let the init script handle it + // This ensures backward compatibility + } + } +} diff --git a/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlStatusCheck.java b/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlStatusCheck.java deleted file mode 100644 index 065879d79..000000000 --- a/embedded-memsql/src/main/java/com/playtika/testcontainer/memsql/MemSqlStatusCheck.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.playtika.testcontainer.memsql; - -import com.playtika.testcontainer.common.checks.AbstractCommandWaitStrategy; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -@RequiredArgsConstructor -public class MemSqlStatusCheck extends AbstractCommandWaitStrategy { - - private final MemSqlProperties properties; - - @Override - public String[] getCheckCommand() { - return new String[]{ - "memsql", - "-u" + properties.getUser(), - "-p" + properties.getPassword(), - "-h", properties.getHost(), - "-P", String.valueOf(properties.getPort()), - "-e", properties.getStatusCheck() - }; - } -} diff --git a/embedded-memsql/src/main/resources/mem.sql b/embedded-memsql/src/main/resources/mem.sql index 8267d7cd4..cb4275732 100644 --- a/embedded-memsql/src/main/resources/mem.sql +++ b/embedded-memsql/src/main/resources/mem.sql @@ -1 +1 @@ -CREATE DATABASE IF NOT EXISTS test_db; \ No newline at end of file +CREATE DATABASE IF NOT EXISTS test_db; diff --git a/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java b/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java index 40be9fa82..22eecf0c2 100644 --- a/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java +++ b/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/EmbeddedMemSqlBootstrapConfigurationTest.java @@ -10,6 +10,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -20,10 +21,8 @@ import static org.assertj.core.api.Assertions.assertThat; @Slf4j -@SpringBootTest(classes = EmbeddedMemSqlBootstrapConfigurationTest.TestConfiguration.class, - properties = { - "spring.profiles.active=enabled" - }) +@SpringBootTest(classes = EmbeddedMemSqlBootstrapConfigurationTest.TestConfiguration.class) +@ActiveProfiles("enabled") public class EmbeddedMemSqlBootstrapConfigurationTest { @Autowired diff --git a/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/NonAutoConfiguredDatasourceDependsOnTest.java b/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/NonAutoConfiguredDatasourceDependsOnTest.java index ec844fab3..3d4c20387 100644 --- a/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/NonAutoConfiguredDatasourceDependsOnTest.java +++ b/embedded-memsql/src/test/java/com/playtika/testcontainer/memsql/NonAutoConfiguredDatasourceDependsOnTest.java @@ -13,6 +13,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -21,9 +22,8 @@ import static org.assertj.core.api.Assertions.assertThat; @Slf4j -@SpringBootTest(classes = NonAutoConfiguredDatasourceDependsOnTest.TestConfiguration.class, - properties = {"spring.profiles.active=enabled"} -) +@SpringBootTest(classes = NonAutoConfiguredDatasourceDependsOnTest.TestConfiguration.class) +@ActiveProfiles("enabled") public class NonAutoConfiguredDatasourceDependsOnTest { @Autowired @@ -33,12 +33,12 @@ public class NonAutoConfiguredDatasourceDependsOnTest { JdbcTemplate jdbcTemplate; @Test - public void shouldConnectToMemSql() throws Exception { + public void shouldConnectToMemSql() { assertThat(jdbcTemplate.queryForObject("select @@version_comment", String.class)).contains("SingleStoreDB"); } @Test - public void shouldSetupDependsOnForAllDataSources() throws Exception { + public void shouldSetupDependsOnForAllDataSources() { String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, DataSource.class); assertThat(beanNamesForType) .as("Non auto-configured datasource should be present") @@ -78,5 +78,10 @@ public DataSource customDatasource() { poolConfiguration.setTestOnReturn(true); return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource customDatasource) { + return new JdbcTemplate(customDatasource); + } } } diff --git a/embedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.java b/embedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.java index 3465b8b9d..749d9b2f7 100644 --- a/embedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.java +++ b/embedded-minio/src/main/java/com/playtika/testcontainer/minio/EmbeddedMinioBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-mockserver/pom.xml b/embedded-mockserver/pom.xml index 81429a7bd..1f8cf4364 100644 --- a/embedded-mockserver/pom.xml +++ b/embedded-mockserver/pom.xml @@ -29,7 +29,7 @@ org.testcontainers - mockserver + testcontainers-mockserver org.mock-server diff --git a/embedded-mockserver/src/main/java/com/playtika/testcontainer/mockserver/EmbeddedMockServerBootstrapConfiguration.java b/embedded-mockserver/src/main/java/com/playtika/testcontainer/mockserver/EmbeddedMockServerBootstrapConfiguration.java index e189fe535..801035dd2 100644 --- a/embedded-mockserver/src/main/java/com/playtika/testcontainer/mockserver/EmbeddedMockServerBootstrapConfiguration.java +++ b/embedded-mockserver/src/main/java/com/playtika/testcontainer/mockserver/EmbeddedMockServerBootstrapConfiguration.java @@ -10,8 +10,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.MockServerContainer; import org.testcontainers.containers.Network; +import org.testcontainers.mockserver.MockServerContainer; import java.util.Optional; diff --git a/embedded-mongodb/pom.xml b/embedded-mongodb/pom.xml index 9aab5ecd8..35f357a73 100644 --- a/embedded-mongodb/pom.xml +++ b/embedded-mongodb/pom.xml @@ -4,7 +4,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - testcontainers-spring-boot-parent com.playtika.testcontainers @@ -24,6 +23,10 @@ com.playtika.testcontainers embedded-toxiproxy + + org.testcontainers + testcontainers-mongodb + org.springframework.data spring-data-mongodb @@ -34,5 +37,33 @@ mongodb-driver-sync true + + org.springframework.boot + spring-boot-autoconfigure + provided + + + + org.springframework.cloud + spring-cloud-starter-bootstrap + test + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + test + + + org.springframework.boot + spring-boot-starter-logging + + + - \ No newline at end of file + diff --git a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfiguration.java b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfiguration.java index 88ab79bcc..c9cd656e1 100644 --- a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfiguration.java +++ b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfiguration.java @@ -7,21 +7,24 @@ import com.playtika.testcontainer.toxiproxy.condition.ConditionalOnToxiProxyEnabled; import eu.rekawek.toxiproxy.ToxiproxyClient; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; import org.springframework.core.io.ClassPathResource; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.BindMode; -import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.images.builder.Transferable; -import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils; +import org.testcontainers.mongodb.MongoDBContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.io.IOException; import java.nio.charset.Charset; @@ -31,9 +34,11 @@ import static com.playtika.testcontainer.mongodb.MongodbProperties.BEAN_NAME_EMBEDDED_MONGODB; @Slf4j +@Order(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnExpression("${embedded.containers.enabled:true}") @AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) +@AutoConfigureBefore(name = "org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration") @ConditionalOnProperty( name = "embedded.mongodb.enabled", havingValue = "true", @@ -47,7 +52,7 @@ public class EmbeddedMongodbBootstrapConfiguration { @ConditionalOnToxiProxyEnabled(module = "mongodb") ToxiproxyClientProxy mongodbContainerProxy(ToxiproxyClient toxiproxyClient, ToxiproxyContainer toxiproxyContainer, - @Qualifier(BEAN_NAME_EMBEDDED_MONGODB) GenericContainer mongodb, + @Qualifier(BEAN_NAME_EMBEDDED_MONGODB) MongoDBContainer mongodb, MongodbProperties properties) { return ToxiproxyHelper.createProxy( toxiproxyClient, @@ -59,47 +64,41 @@ ToxiproxyClientProxy mongodbContainerProxy(ToxiproxyClient toxiproxyClient, } @Bean(value = BEAN_NAME_EMBEDDED_MONGODB, destroyMethod = "stop") - public GenericContainer mongodb(MongodbProperties properties, - Optional network) throws IOException, InterruptedException { + public MongoDBContainer mongodb( + MongodbProperties properties, + Optional network) throws IOException, InterruptedException{ - GenericContainer mongodb; - if (StringUtils.isBlank(properties.getReplicaSetName())) { - mongodb = new GenericContainer<>(ContainerUtils.getDockerImageName(properties)) - .withEnv("MONGO_INITDB_ROOT_USERNAME", properties.getUsername()) - .withEnv("MONGO_INITDB_ROOT_PASSWORD", properties.getPassword()) - .withEnv("MONGO_INITDB_DATABASE", properties.getDatabase()) - .withExposedPorts(properties.getPort()) - .waitingFor(new MongodbWaitStrategy(properties)) - .withNetworkAliases(MONGODB_NETWORK_ALIAS); - } else { - mongodb = new GenericContainer<>(ContainerUtils.getDockerImageName(properties)) - .withCommand("-f", "/etc/mongod.conf") - .withClasspathResourceMapping("/mongod/gen-keyfile.sh", "/docker-entrypoint-initdb.d/gen-keyfile.sh", BindMode.READ_ONLY) - .withCopyToContainer( - Transferable.of( - new ClassPathResource("/mongod/mongod.conf") - .getContentAsString(Charset.defaultCharset()) - .replace("${replica-set-name}", properties.getReplicaSetName()) - ) - , "/etc/mongod.conf") - .withEnv("MONGO_INITDB_ROOT_USERNAME", properties.getUsername()) - .withEnv("MONGO_INITDB_ROOT_PASSWORD", properties.getPassword()) - .withEnv("MONGO_INITDB_DATABASE", properties.getDatabase()) - .withEnv("MONGO_INITDB_REPL_SET_HOST", properties.getHost()) - .withExposedPorts(properties.getPort()) - .waitingFor(new MongodbWaitStrategy(properties)) - .withNetworkAliases(MONGODB_NETWORK_ALIAS); + MongoDBContainer mongodb = new MongoDBContainer(ContainerUtils.getDockerImageName(properties)) + .withEnv("MONGO_INITDB_ROOT_USERNAME", properties.getUsername()) + .withEnv("MONGO_INITDB_ROOT_PASSWORD", properties.getPassword()) + .withEnv("MONGO_INITDB_DATABASE", properties.getDatabase()) + .waitingFor(new MongodbWaitStrategy(properties)) + .withNetworkAliases(MONGODB_NETWORK_ALIAS); + + // Configure replica set if provided + if (StringUtils.isNotBlank(properties.getReplicaSetName())) { + mongodb = mongodb.withReuse(properties.isReuseContainer()) + .withEnv("MONGO_INITDB_REPL_SET_HOST", properties.getHost()) + .withCommand("-f", "/etc/mongod.conf") + .withClasspathResourceMapping("/mongod/gen-keyfile.sh", "/docker-entrypoint-initdb.d/gen-keyfile.sh", BindMode.READ_ONLY) + .withCopyToContainer( + Transferable.of( + new ClassPathResource("/mongod/mongod.conf") + .getContentAsString(Charset.defaultCharset()) + .replace("${replica-set-name}", properties.getReplicaSetName()) + ) + , "/etc/mongod.conf"); } network.ifPresent(mongodb::withNetwork); - mongodb = configureCommonsAndStart(mongodb, properties, log); + mongodb = (MongoDBContainer) configureCommonsAndStart(mongodb, properties, log); return mongodb; } @Bean public DynamicPropertyRegistrar mongodbDynamicPropertyRegistrar( - @Qualifier(BEAN_NAME_EMBEDDED_MONGODB) GenericContainer mongodb, + @Qualifier(BEAN_NAME_EMBEDDED_MONGODB) MongoDBContainer mongodb, MongodbProperties properties) { return registry -> { registry.add("embedded.mongodb.port", () -> mongodb.getMappedPort(properties.getPort())); diff --git a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbDependenciesAutoConfiguration.java b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbDependenciesAutoConfiguration.java index ea58b9bc2..f39e74158 100644 --- a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbDependenciesAutoConfiguration.java +++ b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbDependenciesAutoConfiguration.java @@ -1,5 +1,6 @@ package com.playtika.testcontainer.mongodb; +import com.mongodb.client.MongoClient; import com.playtika.testcontainer.common.spring.DependsOnPostProcessor; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AutoConfiguration; @@ -8,6 +9,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoTemplate; import static com.playtika.testcontainer.mongodb.MongodbProperties.BEAN_NAME_EMBEDDED_MONGODB; @@ -19,8 +21,20 @@ @ConditionalOnProperty(name = "embedded.mongodb.enabled", havingValue = "true", matchIfMissing = true) public class EmbeddedMongodbDependenciesAutoConfiguration { - @Bean - public static BeanFactoryPostProcessor mongoClientDependencyPostProcessor() { - return new DependsOnPostProcessor(MongoTemplate.class, new String[]{BEAN_NAME_EMBEDDED_MONGODB}); + @Configuration + @ConditionalOnClass(MongoClient.class) + public static class EmbeddedMongodbMongoClientDependencyContext { + @Bean + public static BeanFactoryPostProcessor mongoClientDependencyPostProcessor() { + return new DependsOnPostProcessor(MongoClient.class, new String[]{BEAN_NAME_EMBEDDED_MONGODB}); + } + } + + @Configuration + public static class EmbeddedMongodbMongoTemplateDependencyContext { + @Bean + public static BeanFactoryPostProcessor mongoTemplateDependencyPostProcessor() { + return new DependsOnPostProcessor(MongoTemplate.class, new String[]{BEAN_NAME_EMBEDDED_MONGODB}); + } } } diff --git a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/MongodbProperties.java b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/MongodbProperties.java index d21da34d7..c678fdfc6 100644 --- a/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/MongodbProperties.java +++ b/embedded-mongodb/src/main/java/com/playtika/testcontainer/mongodb/MongodbProperties.java @@ -34,11 +34,11 @@ public MongodbProperties() { this.setCapabilities(List.of(Capability.ALL)); } + // https://hub.docker.com/_/mongo @Override public String getDefaultDockerImage() { // Please don`t remove this comment. // renovate: datasource=docker - // https://hub.docker.com/_/mongo return "mongodb/mongodb-community-server:8.2.2-ubuntu2204"; } } diff --git a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.java b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.java index ffc2020f9..02019b224 100644 --- a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.java +++ b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapAuthConfigurationTest.java @@ -18,16 +18,11 @@ @Slf4j @SpringBootTest( - properties = { - "embedded.mongodb.username=root", - "embedded.mongodb.password=letmein", - "spring.data.mongodb.host=${embedded.mongodb.host}", - "spring.data.mongodb.port=${embedded.mongodb.port}", - "spring.data.mongodb.username=${embedded.mongodb.username}", - "spring.data.mongodb.password=${embedded.mongodb.password}", - "spring.data.mongodb.database=${embedded.mongodb.database}", - "spring.data.mongodb.authentication-database=admin" - } + properties = { + "embedded.mongodb.username=root", + "embedded.mongodb.password=letmein", + "spring.mongodb.uri=mongodb://${embedded.mongodb.username}:${embedded.mongodb.password}@${embedded.mongodb.host}:${embedded.mongodb.port}/${embedded.mongodb.database}?authSource=admin" + } ,classes = EmbeddedMongodbBootstrapAuthConfigurationTest.TestConfiguration.class ) public class EmbeddedMongodbBootstrapAuthConfigurationTest { diff --git a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.java b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.java index 41c48a551..3fd3f0082 100644 --- a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.java +++ b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapConfigurationTest.java @@ -12,6 +12,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.test.context.ActiveProfiles; import java.time.Instant; import java.util.UUID; @@ -22,11 +23,12 @@ @Slf4j @SpringBootTest( properties = { - "spring.data.mongodb.uri=mongodb://${embedded.mongodb.host}:${embedded.mongodb.toxiproxy.port}/${embedded.mongodb.database}", - "embedded.toxiproxy.proxies.mongodb.enabled=true" + "spring.mongodb.uri=mongodb://${embedded.mongodb.host}:${embedded.mongodb.toxiproxy.port}/${embedded.mongodb.database}", + "embedded.toxiproxy.proxies.mongodb.enabled=true" } , classes = EmbeddedMongodbBootstrapConfigurationTest.TestConfiguration.class ) +@ActiveProfiles("enabled") public class EmbeddedMongodbBootstrapConfigurationTest { @Autowired diff --git a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.java b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.java index e65cce468..fb6234750 100644 --- a/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.java +++ b/embedded-mongodb/src/test/java/com/playtika/testcontainer/mongodb/EmbeddedMongodbBootstrapReplicaSetConfigurationTest.java @@ -22,7 +22,7 @@ "embedded.mongodb.username=root", "embedded.mongodb.password=letmein", "embedded.mongodb.replica-set-name=rs0", - "spring.data.mongodb.uri=mongodb://${embedded.mongodb.username}:${embedded.mongodb.password}@${embedded.mongodb.host}:${embedded.mongodb.port}/${embedded.mongodb.database}?replicaSet=${embedded.mongodb.replica-set-name}&directConnection=true&authSource=admin" + "spring.mongodb.uri=mongodb://${embedded.mongodb.username}:${embedded.mongodb.password}@${embedded.mongodb.host}:${embedded.mongodb.port}/${embedded.mongodb.database}?replicaSet=${embedded.mongodb.replica-set-name}&directConnection=true&authSource=admin" } , classes = EmbeddedMongodbBootstrapReplicaSetConfigurationTest.TestConfiguration.class ) diff --git a/embedded-mssqlserver/pom.xml b/embedded-mssqlserver/pom.xml index 9669241e5..5c999a84a 100644 --- a/embedded-mssqlserver/pom.xml +++ b/embedded-mssqlserver/pom.xml @@ -29,7 +29,22 @@ org.testcontainers - mssqlserver + testcontainers-mssqlserver + + + org.springframework.boot + spring-boot + true + + + org.springframework.boot + spring-boot-autoconfigure + true + + + org.springframework.boot + spring-boot-jdbc + true org.springframework diff --git a/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerBootstrapConfiguration.java b/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerBootstrapConfiguration.java index bd52ec288..b7e51a96a 100644 --- a/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerBootstrapConfiguration.java +++ b/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerBootstrapConfiguration.java @@ -18,9 +18,9 @@ import org.springframework.util.StringUtils; import org.testcontainers.containers.MSSQLServerContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfiguration.java b/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfiguration.java index a04924e30..471d0e4d1 100644 --- a/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfiguration.java +++ b/embedded-mssqlserver/src/main/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfiguration.java @@ -10,7 +10,7 @@ import javax.sql.DataSource; -@AutoConfiguration(afterName = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration") +@AutoConfiguration(afterName = "org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration") @ConditionalOnClass(DataSource.class) @ConditionalOnExpression("${embedded.containers.enabled:true}") @ConditionalOnProperty(name = "embedded.mssqlserver.enabled", matchIfMissing = true) diff --git a/embedded-mssqlserver/src/test/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfigurationTest.java b/embedded-mssqlserver/src/test/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfigurationTest.java index 6e8c9c5dc..b01b8406b 100644 --- a/embedded-mssqlserver/src/test/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfigurationTest.java +++ b/embedded-mssqlserver/src/test/java/com/playtika/testcontainer/mssqlserver/EmbeddedMSSQLServerDependenciesAutoConfigurationTest.java @@ -4,12 +4,18 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; +import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; +import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -24,7 +30,7 @@ ) @ActiveProfiles("test") class EmbeddedMSSQLServerDependenciesAutoConfigurationTest { - @Autowired(required = false) + @Autowired private JdbcTemplate jdbcTemplate; @Autowired @@ -33,21 +39,36 @@ class EmbeddedMSSQLServerDependenciesAutoConfigurationTest { @Test void injectedJdbs() { assertThat(jdbcTemplate).isNotNull(); + assertThat(mssqlServerContainer.isRunning()).isTrue(); } @Test @SneakyThrows void testCreateDb() { - Map map = jdbcTemplate.queryForMap("SELECT first_name, last_name FROM users WHERE first_name = 'Sam'"); + Map actual = jdbcTemplate.queryForMap("SELECT first_name, last_name FROM users WHERE first_name = 'Sam'"); + Map normalizedActual = actual.entrySet() + .stream() + .collect(Collectors.toMap( + entry -> entry.getKey().toLowerCase(Locale.ROOT), + Map.Entry::getValue, + (left, right) -> right, + LinkedHashMap::new + )); + + Map expected = Map.of( + "first_name", "Sam", + "last_name", "Brannen" + ); - assertThat(map) - .containsKey("first_name") - .containsKey("last_name") - .extractingByKey("last_name").isEqualTo("Brannen"); + assertThat(normalizedActual).isEqualTo(expected); } @EnableAutoConfiguration @Configuration + @ImportAutoConfiguration({ + DataSourceAutoConfiguration.class, + JdbcTemplateAutoConfiguration.class + }) static class TestConfiguration { } diff --git a/embedded-mssqlserver/src/test/resources/application-test.properties b/embedded-mssqlserver/src/test/resources/application-test.properties index 26f6801b2..46fb27096 100644 --- a/embedded-mssqlserver/src/test/resources/application-test.properties +++ b/embedded-mssqlserver/src/test/resources/application-test.properties @@ -1,4 +1,6 @@ spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource.url=jdbc:sqlserver://${embedded.mssqlserver.host}:${embedded.mssqlserver.port};databaseName=${embedded.mssqlserver.database};trustServerCertificate=true spring.datasource.username=${embedded.mssqlserver.user} -spring.datasource.password=${embedded.mssqlserver.password} \ No newline at end of file +spring.datasource.password=${embedded.mssqlserver.password} + + diff --git a/embedded-mysql/pom.xml b/embedded-mysql/pom.xml index 79b49f219..617ab726c 100644 --- a/embedded-mysql/pom.xml +++ b/embedded-mysql/pom.xml @@ -35,7 +35,7 @@ org.testcontainers - mysql + testcontainers-mysql org.springframework diff --git a/embedded-mysql/src/main/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfiguration.java b/embedded-mysql/src/main/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfiguration.java index 69df3bee4..42e01ce13 100644 --- a/embedded-mysql/src/main/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfiguration.java +++ b/embedded-mysql/src/main/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.MySQLContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/AutoConfiguredDatasourceDependsOnTest.java b/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/AutoConfiguredDatasourceDependsOnTest.java index a93160d4e..c0cfd9c40 100644 --- a/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/AutoConfiguredDatasourceDependsOnTest.java +++ b/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/AutoConfiguredDatasourceDependsOnTest.java @@ -1,14 +1,19 @@ package com.playtika.testcontainer.mysql; import lombok.extern.slf4j.Slf4j; +import org.apache.tomcat.jdbc.pool.PoolConfiguration; +import org.apache.tomcat.jdbc.pool.PoolProperties; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -22,10 +27,10 @@ AutoConfiguredDatasourceDependsOnTest.TestConfiguration.class }, properties = { - "spring.profiles.active=enabled", "embedded.toxiproxy.proxies.mysql.enabled=true" } ) +@ActiveProfiles("enabled") public class AutoConfiguredDatasourceDependsOnTest { @Autowired @@ -59,5 +64,31 @@ private void hasDependsOn(String beanName) { @EnableAutoConfiguration @Configuration static class TestConfiguration { + + @Value("${spring.datasource.url}") + private String jdbcUrl; + + @Value("${spring.datasource.username}") + private String user; + + @Value("${spring.datasource.password}") + private String password; + + @Bean(name = "dataSource", destroyMethod = "close") + public DataSource dataSource() { + PoolConfiguration poolConfiguration = new PoolProperties(); + poolConfiguration.setUrl(jdbcUrl); + poolConfiguration.setDriverClassName("com.mysql.cj.jdbc.Driver"); + poolConfiguration.setUsername(user); + poolConfiguration.setPassword(password); + poolConfiguration.setTestOnBorrow(true); + poolConfiguration.setTestOnReturn(true); + return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); + } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource dataSource) { + return new JdbcTemplate(dataSource); + } } } diff --git a/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfigurationTest.java b/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfigurationTest.java index 78300b4b2..8b4099a24 100644 --- a/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfigurationTest.java +++ b/embedded-mysql/src/test/java/com/playtika/testcontainer/mysql/EmbeddedMySQLBootstrapConfigurationTest.java @@ -17,6 +17,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import javax.sql.DataSource; @@ -30,10 +31,10 @@ @SpringBootTest( classes = EmbeddedMySQLBootstrapConfigurationTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.mysql.init-script-path=initScript.sql", "embedded.toxiproxy.proxies.mysql.enabled=true" }) +@ActiveProfiles("enabled") public class EmbeddedMySQLBootstrapConfigurationTest { @Autowired @@ -139,5 +140,10 @@ public DataSource customDatasource() { poolConfiguration.setTestOnReturn(true); return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource customDatasource) { + return new JdbcTemplate(customDatasource); + } } } diff --git a/embedded-native-kafka/pom.xml b/embedded-native-kafka/pom.xml index 61aa28357..dcf1458e5 100644 --- a/embedded-native-kafka/pom.xml +++ b/embedded-native-kafka/pom.xml @@ -36,7 +36,7 @@ org.testcontainers - kafka + testcontainers-kafka jakarta.validation diff --git a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurer.java b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurer.java index c58a9d3a4..9a19e19fe 100644 --- a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurer.java +++ b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/NativeKafkaTopicsConfigurer.java @@ -10,7 +10,6 @@ import org.apache.kafka.clients.admin.NewTopic; import org.apache.kafka.clients.producer.ProducerConfig; import org.springframework.beans.factory.InitializingBean; -import org.testcontainers.containers.GenericContainer; import org.testcontainers.kafka.KafkaContainer; import java.util.Collection; @@ -28,7 +27,7 @@ public class NativeKafkaTopicsConfigurer implements InitializingBean { private static final int DEFAULT_PARTITION_COUNT = 1; - private final GenericContainer nativeKafka; + private final KafkaContainer nativeKafka; private final NativeKafkaConfigurationProperties nativeKafkaProperties; @Override @@ -77,4 +76,4 @@ private void createTopicsUsingAdminClient(Collection topicsC throw new RuntimeException("Failed to create topics", e); } } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfiguration.java b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfiguration.java index 5ac8c6fd8..4912693a7 100644 --- a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfiguration.java +++ b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfiguration.java @@ -1,22 +1,193 @@ package com.playtika.testcontainer.nativekafka.configuration; import com.playtika.testcontainer.common.spring.DockerPresenceBootstrapConfiguration; +import com.playtika.testcontainer.nativekafka.NativeKafkaTopicsConfigurer; +import com.playtika.testcontainer.nativekafka.properties.NativeKafkaConfigurationProperties; +import com.playtika.testcontainer.toxiproxy.ToxiproxyClientProxy; +import com.playtika.testcontainer.toxiproxy.ToxiproxyHelper; +import com.playtika.testcontainer.toxiproxy.condition.ConditionalOnToxiProxyEnabled; +import eu.rekawek.toxiproxy.ToxiproxyClient; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; +import org.springframework.test.context.DynamicPropertyRegistrar; +import org.testcontainers.containers.BindMode; +import org.testcontainers.containers.Network; +import org.testcontainers.kafka.KafkaContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; +import org.testcontainers.utility.DockerImageName; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Set; +import java.util.stream.Stream; + +import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; +import static com.playtika.testcontainer.nativekafka.properties.NativeKafkaConfigurationProperties.NATIVE_KAFKA_BEAN_NAME; + +@Slf4j @Configuration @AutoConfigureOrder @ConditionalOnExpression("${embedded.containers.enabled:true}") @AutoConfigureAfter(DockerPresenceBootstrapConfiguration.class) +@ConditionalOnProperty(value = "embedded.kafka.enabled", havingValue = "true", matchIfMissing = true) +@EnableConfigurationProperties(value = {NativeKafkaConfigurationProperties.class}) public class EmbeddedNativeKafkaBootstrapConfiguration { - @Import(value = { - NativeKafkaContainerConfiguration.class, - }) - @Configuration - public static class AllConfigurations { + public static final String NATIVE_KAFKA_HOST_NAME = "kafka-broker.testcontainer.docker"; + + @Bean(destroyMethod = "close") + @ConditionalOnMissingBean(Network.class) + public Network nativeKafkaNetwork() { + Network network = Network.newNetwork(); + log.info("Created docker Network id={}", network.getId()); + return network; + } + + @Bean(name = NATIVE_KAFKA_BEAN_NAME, destroyMethod = "stop") + public KafkaContainer nativeKafka( + NativeKafkaConfigurationProperties nativeKafkaProperties, + Network network) { + + DockerImageName nativeKafkaImageName = DockerImageName.parse(nativeKafkaProperties.getDefaultDockerImage()) + .asCompatibleSubstituteFor("confluentinc/cp-kafka"); + + KafkaContainer nativeKafka = new KafkaContainer(nativeKafkaImageName) + .withNetwork(network) + .withNetworkAliases(NATIVE_KAFKA_HOST_NAME) + .withExtraHost(NATIVE_KAFKA_HOST_NAME, "127.0.0.1"); + + // Configure file system bind if enabled + configureFileSystemBind(nativeKafkaProperties, nativeKafka); + + // Configure and start the container using common utilities + nativeKafka = (KafkaContainer) configureCommonsAndStart(nativeKafka, nativeKafkaProperties, log); + + return nativeKafka; + } + + @Bean + @ConditionalOnMissingBean + public NativeKafkaTopicsConfigurer nativeKafkaTopicsConfigurer( + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, + NativeKafkaConfigurationProperties nativeKafkaProperties) { + return new NativeKafkaTopicsConfigurer(nativeKafka, nativeKafkaProperties); + } + + @Bean + @ConditionalOnToxiProxyEnabled(module = "kafka") + ToxiproxyClientProxy nativeKafkaContainerProxy( + ToxiproxyClient toxiproxyClient, + ToxiproxyContainer toxiproxyContainer, + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, + NativeKafkaConfigurationProperties properties) { + + return ToxiproxyHelper.createProxy( + toxiproxyClient, + toxiproxyContainer, + nativeKafka, + properties.getKafkaPort(), + "native-kafka"); + } + + @Bean + @ConditionalOnToxiProxyEnabled(module = "kafka") + public DynamicPropertyRegistrar nativeKafkaToxiProxyDynamicPropertyRegistrar( + @Qualifier("nativeKafkaContainerProxy") ToxiproxyClientProxy proxy) { + + return registry -> { + String proxyBootstrapServers = String.format("%s:%d", + proxy.getContainerIpAddress(), proxy.getProxyPort()); + + registry.add("embedded.kafka.toxiproxy.bootstrapServers", () -> proxyBootstrapServers); + registry.add("embedded.kafka.toxiproxy.brokerList", () -> proxyBootstrapServers); + registry.add("embedded.kafka.toxiproxy.host", proxy::getContainerIpAddress); + registry.add("embedded.kafka.toxiproxy.port", proxy::getProxyPort); + registry.add("embedded.kafka.toxiproxy.proxyName", proxy::getName); + }; + } + + @Bean + public DynamicPropertyRegistrar nativeKafkaDynamicPropertyRegistrar( + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, + NativeKafkaConfigurationProperties nativeKafkaProperties) { + return registry -> { + String bootstrapServers = nativeKafka.getBootstrapServers(); + String host = nativeKafka.getHost(); + Integer port = nativeKafka.getMappedPort(nativeKafkaProperties.getKafkaPort()); + + registry.add("embedded.kafka.bootstrapServers", () -> bootstrapServers); + registry.add("embedded.kafka.brokerList", () -> bootstrapServers); + registry.add("embedded.kafka.networkAlias", () -> NATIVE_KAFKA_HOST_NAME); + registry.add("embedded.kafka.host", () -> host); + registry.add("embedded.kafka.port", () -> port); + + log.info("Started native kafka broker. Connection details: bootstrapServers={}, host={}, port={}, networkAlias={}", + bootstrapServers, host, port, NATIVE_KAFKA_HOST_NAME); + }; + } + + private void configureFileSystemBind(NativeKafkaConfigurationProperties nativeKafkaProperties, KafkaContainer nativeKafka) { + NativeKafkaConfigurationProperties.FileSystemBind fileSystemBind = nativeKafkaProperties.getFileSystemBind(); + if (fileSystemBind.isEnabled()) { + String currentTimestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH-mm-ss-nnnnnnnnn")); + String dataFolder = fileSystemBind.getDataFolder(); + Path kafkaData = Paths.get(dataFolder, currentTimestamp).toAbsolutePath(); + log.info("Writing native kafka data to: {}", kafkaData); + createPathAndParentOrMakeWritable(kafkaData); + + nativeKafka.addFileSystemBind(kafkaData.toString(), "/tmp/kafka-logs", BindMode.READ_WRITE); + } + } + + private void createPathAndParentOrMakeWritable(Path path) { + Stream.of(path.getParent(), path).forEach(p -> { + if (p != null) { + if (p.toFile().isDirectory()) { + makeWritable(p); + } else { + try { + log.info("Create writable folder: {}", p); + Files.createDirectory(p, PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxrwxrwx"))); + } catch (FileAlreadyExistsException e) { + makeWritable(p); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + }); + } + + private void makeWritable(Path path) { + PosixFileAttributeView fileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class); + if (fileAttributeView == null) { + log.warn("Couldn't get file permissions: {}", path); + return; + } + try { + Set permissions = fileAttributeView.readAttributes().permissions(); + if (permissions.add(PosixFilePermission.OTHERS_WRITE)) { + log.info("Make writable to others: {}", path); + fileAttributeView.setPermissions(permissions); + } + } catch (IOException e) { + throw new RuntimeException(e); + } } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaTestOperationsAutoConfiguration.java b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaTestOperationsAutoConfiguration.java index 1f57ba997..da56c6b2f 100644 --- a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaTestOperationsAutoConfiguration.java +++ b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaTestOperationsAutoConfiguration.java @@ -11,7 +11,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; -import org.testcontainers.containers.GenericContainer; +import org.testcontainers.kafka.KafkaContainer; import static com.playtika.testcontainer.nativekafka.properties.NativeKafkaConfigurationProperties.NATIVE_KAFKA_BEAN_NAME; import static com.playtika.testcontainer.nativekafka.properties.NativeKafkaConfigurationProperties.NATIVE_KAFKA_PACKAGE_PROPERTIES_BEAN_NAME; @@ -30,7 +30,7 @@ public InstallPackageProperties nativeKafkaPackageProperties() { @Bean public PackageInstaller nativeKafkaPackageInstaller(@Qualifier(NATIVE_KAFKA_PACKAGE_PROPERTIES_BEAN_NAME) InstallPackageProperties nativeKafkaPackageProperties, - @Qualifier(NATIVE_KAFKA_BEAN_NAME) GenericContainer nativeKafka) { + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka) { return new YumPackageInstaller(nativeKafkaPackageProperties, nativeKafka); } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java index a786ca0a1..e234945ca 100644 --- a/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java +++ b/embedded-native-kafka/src/main/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfiguration.java @@ -17,10 +17,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.BindMode; -import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.kafka.KafkaContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.DockerImageName; import java.io.IOException; @@ -58,7 +57,7 @@ public Network nativeKafkaNetwork() { } @Bean(name = NATIVE_KAFKA_BEAN_NAME, destroyMethod = "stop") - public GenericContainer nativeKafka( + public KafkaContainer nativeKafka( NativeKafkaConfigurationProperties nativeKafkaProperties, Optional network) { @@ -83,7 +82,7 @@ public GenericContainer nativeKafka( @Bean @ConditionalOnMissingBean public NativeKafkaTopicsConfigurer nativeKafkaTopicsConfigurer( - @Qualifier(NATIVE_KAFKA_BEAN_NAME) GenericContainer nativeKafka, + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, NativeKafkaConfigurationProperties nativeKafkaProperties) { return new NativeKafkaTopicsConfigurer(nativeKafka, nativeKafkaProperties); } @@ -93,7 +92,7 @@ public NativeKafkaTopicsConfigurer nativeKafkaTopicsConfigurer( ToxiproxyClientProxy nativeKafkaContainerProxy( ToxiproxyClient toxiproxyClient, ToxiproxyContainer toxiproxyContainer, - @Qualifier(NATIVE_KAFKA_BEAN_NAME) GenericContainer nativeKafka, + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, NativeKafkaConfigurationProperties properties) { return ToxiproxyHelper.createProxy( @@ -123,10 +122,10 @@ public DynamicPropertyRegistrar nativeKafkaToxiProxyDynamicPropertyRegistrar( @Bean public DynamicPropertyRegistrar nativeKafkaDynamicPropertyRegistrar( - @Qualifier(NATIVE_KAFKA_BEAN_NAME) GenericContainer nativeKafka, + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka, NativeKafkaConfigurationProperties nativeKafkaProperties) { return registry -> { - String bootstrapServers = ((KafkaContainer) nativeKafka).getBootstrapServers(); + String bootstrapServers = nativeKafka.getBootstrapServers(); String host = nativeKafka.getHost(); Integer port = nativeKafka.getMappedPort(nativeKafkaProperties.getKafkaPort()); @@ -190,4 +189,4 @@ private void makeWritable(Path path) { throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/DisableNativeKafkaTest.java b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/DisableNativeKafkaTest.java index eefcb06b6..0985afdaa 100644 --- a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/DisableNativeKafkaTest.java +++ b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/DisableNativeKafkaTest.java @@ -15,7 +15,7 @@ public class DisableNativeKafkaTest { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of( - EmbeddedNativeKafkaBootstrapConfiguration.class, + EmbeddedNativeKafkaBootstrapConfiguration.class, EmbeddedNativeKafkaTestOperationsAutoConfiguration.class)); @Test @@ -29,4 +29,4 @@ public void contextLoads() { .hasNotFailed() .doesNotHaveBean("nativeKafka")); } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.java b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.java index 72c9a37eb..5401a6d52 100644 --- a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.java +++ b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/EmbeddedNativeKafkaWithBindingTest.java @@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.TestPropertySource; import org.testcontainers.DockerClientFactory; -import org.testcontainers.containers.GenericContainer; +import org.testcontainers.kafka.KafkaContainer; import org.testcontainers.utility.PathUtils; import java.net.URI; @@ -30,7 +30,8 @@ public class EmbeddedNativeKafkaWithBindingTest extends EmbeddedNativeKafkaTest { @AfterAll - public static void afterAll(@Autowired NativeKafkaConfigurationProperties nativeKafkaProperties, @Qualifier(NATIVE_KAFKA_BEAN_NAME) GenericContainer nativeKafka) throws Exception { + public static void afterAll(@Autowired NativeKafkaConfigurationProperties nativeKafkaProperties, + @Qualifier(NATIVE_KAFKA_BEAN_NAME) KafkaContainer nativeKafka) throws Exception { Path projectDir = projectDir(); Path nativeKafkaDataFolder = projectDir.resolve(nativeKafkaProperties.getFileSystemBind().getDataFolder()); @@ -53,4 +54,4 @@ protected static Path projectDir() { throw new RuntimeException(e); } } -} \ No newline at end of file +} diff --git a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfigurationTest.java b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfigurationTest.java similarity index 91% rename from embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfigurationTest.java rename to embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfigurationTest.java index e0823172c..a485abfca 100644 --- a/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/NativeKafkaContainerConfigurationTest.java +++ b/embedded-native-kafka/src/test/java/com/playtika/testcontainer/nativekafka/configuration/EmbeddedNativeKafkaBootstrapConfigurationTest.java @@ -18,7 +18,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Optional; import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; import static org.assertj.core.api.Assertions.assertThat; @@ -28,7 +27,7 @@ @ExtendWith(MockitoExtension.class) @DisplayName("NativeKafkaContainerConfiguration Tests") -class NativeKafkaContainerConfigurationTest { +class EmbeddedNativeKafkaBootstrapConfigurationTest { @Mock private NativeKafkaConfigurationProperties properties; @@ -39,17 +38,14 @@ class NativeKafkaContainerConfigurationTest { @Mock private KafkaContainer kafkaContainer; - @Mock - private GenericContainer genericContainer; - @TempDir private Path tempDir; - private NativeKafkaContainerConfiguration configuration; + private EmbeddedNativeKafkaBootstrapConfiguration configuration; @BeforeEach void setUp() { - configuration = new NativeKafkaContainerConfiguration(); + configuration = new EmbeddedNativeKafkaBootstrapConfiguration(); } @Test @@ -73,7 +69,7 @@ void shouldCreateKafkaContainerWithProperConfiguration() { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - GenericContainer result = configuration.nativeKafka(properties, Optional.of(network)); + KafkaContainer result = configuration.nativeKafka(properties, network); assertThat(result).isEqualTo(kafkaContainer); containerUtilsMock.verify(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())); @@ -95,7 +91,7 @@ void shouldConfigureFileSystemBindWhenEnabled() throws IOException { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - GenericContainer result = configuration.nativeKafka(properties, Optional.of(network)); + GenericContainer result = configuration.nativeKafka(properties, (network)); assertThat(result).isEqualTo(kafkaContainer); @@ -119,7 +115,7 @@ void shouldNotConfigureFileSystemBindWhenDisabled() { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - GenericContainer result = configuration.nativeKafka(properties, Optional.of(network)); + GenericContainer result = configuration.nativeKafka(properties, network); assertThat(result).isEqualTo(kafkaContainer); assertThat(Files.exists(tempDir.resolve("embedded-native-kafka-data"))).isFalse(); @@ -138,17 +134,17 @@ void shouldRegisterPropertiesCorrectly() { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - configuration.nativeKafka(properties, Optional.of(network)); + configuration.nativeKafka(properties, network); } } @Test @DisplayName("should create native kafka topics configurer bean") void shouldCreateNativeKafkaTopicsConfigurerBean() { - NativeKafkaTopicsConfigurer result = configuration.nativeKafkaTopicsConfigurer(genericContainer, properties); + NativeKafkaTopicsConfigurer result = configuration.nativeKafkaTopicsConfigurer(kafkaContainer, properties); assertThat(result).isNotNull(); - assertThat(result.getNativeKafka()).isEqualTo(genericContainer); + assertThat(result.getNativeKafka()).isEqualTo(kafkaContainer); assertThat(result.getNativeKafkaProperties()).isEqualTo(properties); } @@ -169,7 +165,7 @@ void shouldHandleDirectoryCreationWithProperPermissions() { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - configuration.nativeKafka(properties, Optional.of(network)); + configuration.nativeKafka(properties, network); assertThat(Files.exists(testPath)).isTrue(); assertThat(Files.isDirectory(testPath)).isTrue(); @@ -195,7 +191,7 @@ void shouldHandleParentDirectoryCreation() throws IOException { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - configuration.nativeKafka(properties, Optional.of(network)); + configuration.nativeKafka(properties, network); assertThat(Files.exists(parentPath)).isTrue(); assertThat(Files.exists(testPath)).isTrue(); @@ -205,7 +201,7 @@ void shouldHandleParentDirectoryCreation() throws IOException { @Test @DisplayName("should verify container host name constant") void shouldVerifyContainerHostNameConstant() { - assertThat(NativeKafkaContainerConfiguration.NATIVE_KAFKA_HOST_NAME) + assertThat(EmbeddedNativeKafkaBootstrapConfiguration.NATIVE_KAFKA_HOST_NAME) .isEqualTo("kafka-broker.testcontainer.docker"); } @@ -227,7 +223,7 @@ void shouldHandleExistingDirectoryScenario() throws IOException { containerUtilsMock.when(() -> configureCommonsAndStart(any(KafkaContainer.class), any(CommonContainerProperties.class), any())) .thenReturn(kafkaContainer); - configuration.nativeKafka(properties, Optional.of(network)); + configuration.nativeKafka(properties, network); assertThat(Files.exists(existingPath)).isTrue(); } diff --git a/embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java b/embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java index 3effd5144..1d6cf433c 100644 --- a/embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java +++ b/embedded-nats/src/main/java/com/playtika/testcontainer/nats/EmbeddedNatsBootstrapConfiguration.java @@ -18,10 +18,10 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.MountableFile; import java.util.Optional; diff --git a/embedded-neo4j/pom.xml b/embedded-neo4j/pom.xml index 8686ce08d..cd7ef3c0e 100644 --- a/embedded-neo4j/pom.xml +++ b/embedded-neo4j/pom.xml @@ -14,7 +14,7 @@ embedded-neo4j - 5.28.9 + 6.0.2 @@ -28,7 +28,7 @@ org.testcontainers - neo4j + testcontainers-neo4j org.springframework.boot diff --git a/embedded-neo4j/src/main/java/com/playtika/testcontainer/neo4j/EmbeddedNeo4jBootstrapConfiguration.java b/embedded-neo4j/src/main/java/com/playtika/testcontainer/neo4j/EmbeddedNeo4jBootstrapConfiguration.java index a35f55d46..44b992261 100644 --- a/embedded-neo4j/src/main/java/com/playtika/testcontainer/neo4j/EmbeddedNeo4jBootstrapConfiguration.java +++ b/embedded-neo4j/src/main/java/com/playtika/testcontainer/neo4j/EmbeddedNeo4jBootstrapConfiguration.java @@ -15,9 +15,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.Neo4jContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.neo4j.Neo4jContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -56,7 +56,7 @@ public DynamicPropertyRegistrar neo4jToxiProxyDynamicPropertyRegistrar(@Qualifie @Bean(name = BEAN_NAME_EMBEDDED_NEO4J, destroyMethod = "stop") public Neo4jContainer neo4j(Neo4jProperties properties, Optional network) { - Neo4jContainer neo4j = new Neo4jContainer<>(ContainerUtils.getDockerImageName(properties)) + Neo4jContainer neo4j = new Neo4jContainer(ContainerUtils.getDockerImageName(properties)) .withAdminPassword(properties.password) .withNetworkAliases(NEO4J_NETWORK_ALIAS); diff --git a/embedded-opensearch/pom.xml b/embedded-opensearch/pom.xml index 891b55f14..ce2ec9a34 100644 --- a/embedded-opensearch/pom.xml +++ b/embedded-opensearch/pom.xml @@ -14,8 +14,9 @@ embedded-opensearch - 1.8.1 - 2.1.3 + 3.0.0 + 4.1.0 + 3.3.0 @@ -36,6 +37,31 @@ org.opensearch.client spring-data-opensearch-starter ${spring-data-opensearch-starter.version} + + + org.springframework.boot + spring-boot-autoconfigure + + + commons-logging + commons-logging + + + + + org.springframework.boot + spring-boot-autoconfigure + + + org.opensearch.client + opensearch-java + ${opensearch-java.version} + + + commons-logging + commons-logging + + org.springframework.boot diff --git a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfiguration.java b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfiguration.java index e9210a378..9fc3464af 100644 --- a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfiguration.java +++ b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfiguration.java @@ -6,7 +6,7 @@ import com.playtika.testcontainer.toxiproxy.condition.ConditionalOnToxiProxyEnabled; import eu.rekawek.toxiproxy.ToxiproxyClient; import lombok.extern.slf4j.Slf4j; -import org.opensearch.testcontainers.OpensearchContainer; +import org.opensearch.testcontainers.OpenSearchContainer; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -18,7 +18,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -39,7 +39,7 @@ public class EmbeddedOpenSearchBootstrapConfiguration { @ConditionalOnToxiProxyEnabled(module = "opensearch") ToxiproxyClientProxy opensearchContainerProxy(ToxiproxyClient toxiproxyClient, ToxiproxyContainer toxiproxyContainer, - @Qualifier(BEAN_NAME_EMBEDDED_OPEN_SEARCH) OpensearchContainer opensearch, + @Qualifier(BEAN_NAME_EMBEDDED_OPEN_SEARCH) OpenSearchContainer opensearch, OpenSearchProperties properties) { return ToxiproxyHelper.createProxy( toxiproxyClient, diff --git a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchRestClientDependenciesAutoConfiguration.java b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchRestClientDependenciesAutoConfiguration.java index 4fe5d9a8e..a5b37a462 100644 --- a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchRestClientDependenciesAutoConfiguration.java +++ b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchRestClientDependenciesAutoConfiguration.java @@ -2,6 +2,7 @@ import com.playtika.testcontainer.common.spring.DependsOnPostProcessor; import org.opensearch.client.RestClient; +import org.opensearch.client.opensearch.OpenSearchClient; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -15,12 +16,18 @@ @AutoConfiguration(afterName = "org.opensearch.spring.boot.autoconfigure.OpenSearchRestClientAutoConfiguration") @AutoConfigureOrder @ConditionalOnExpression("${embedded.containers.enabled:true}") -@ConditionalOnClass(RestClient.class) @ConditionalOnProperty(name = "embedded.opensearch.enabled", matchIfMissing = true) public class EmbeddedOpenSearchRestClientDependenciesAutoConfiguration { @Bean + @ConditionalOnClass(RestClient.class) public static BeanFactoryPostProcessor opensearchRestClientDependencyPostProcessor() { return new DependsOnPostProcessor(RestClient.class, new String[]{BEAN_NAME_EMBEDDED_OPEN_SEARCH}); } + + @Bean + @ConditionalOnClass(OpenSearchClient.class) + public static BeanFactoryPostProcessor opensearchClientDependencyPostProcessor() { + return new DependsOnPostProcessor(OpenSearchClient.class, new String[]{BEAN_NAME_EMBEDDED_OPEN_SEARCH}); + } } diff --git a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/OpenSearchContainerFactory.java b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/OpenSearchContainerFactory.java index 3fd6b5c9b..f915500fe 100644 --- a/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/OpenSearchContainerFactory.java +++ b/embedded-opensearch/src/main/java/com/playtika/testcontainer/opensearch/OpenSearchContainerFactory.java @@ -3,7 +3,7 @@ import com.playtika.testcontainer.common.utils.ContainerUtils; import com.playtika.testcontainer.opensearch.rest.CreateIndex; import com.playtika.testcontainer.opensearch.rest.WaitForGreenStatus; -import org.opensearch.testcontainers.OpensearchContainer; +import org.opensearch.testcontainers.OpenSearchContainer; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; @@ -12,7 +12,7 @@ class OpenSearchContainerFactory { static GenericContainer create(OpenSearchProperties properties) { - OpensearchContainer opensearchContainer = new OpensearchContainer(ContainerUtils.getDockerImageName(properties)); + OpenSearchContainer opensearchContainer = new OpenSearchContainer(ContainerUtils.getDockerImageName(properties)); if (properties.isCredentialsEnabled()) { opensearchContainer.withSecurityEnabled(); } diff --git a/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfigurationTest.java b/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfigurationTest.java index 2d68d8a6e..3835b71f1 100644 --- a/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfigurationTest.java +++ b/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/EmbeddedOpenSearchBootstrapConfigurationTest.java @@ -1,33 +1,35 @@ package com.playtika.testcontainer.opensearch; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.conn.ssl.TrustAllStrategy; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.apache.http.ssl.SSLContextBuilder; -import org.jetbrains.annotations.NotNull; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.ssl.TrustStrategy; import org.junit.jupiter.api.Test; -import org.opensearch.client.RestClientBuilder; -import org.opensearch.spring.boot.autoconfigure.RestClientBuilderCustomizer; +import org.opensearch.data.client.osc.OpenSearchConfiguration; +import org.opensearch.spring.boot.autoconfigure.OpenSearchClientAutoConfiguration; +import org.opensearch.spring.boot.autoconfigure.OpenSearchRestClientAutoConfiguration; +import org.opensearch.spring.boot.autoconfigure.OpenSearchRestHighLevelClientAutoConfiguration; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; +import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; import static org.assertj.core.api.Assertions.assertThat; -@EnableAutoConfiguration(exclude = ElasticsearchDataAutoConfiguration.class) +@EnableAutoConfiguration(exclude = { + OpenSearchClientAutoConfiguration.class, + OpenSearchRestClientAutoConfiguration.class, + OpenSearchRestHighLevelClientAutoConfiguration.class +}) public abstract class EmbeddedOpenSearchBootstrapConfigurationTest { @Autowired @@ -39,55 +41,53 @@ public void propertiesAreAvailable() { assertThat(environment.getProperty("embedded.opensearch.host")).isNotEmpty(); assertThat(environment.getProperty("embedded.opensearch.httpPort")).isNotEmpty(); assertThat(environment.getProperty("embedded.opensearch.transportPort")).isNotEmpty(); + assertThat(environment.getProperty("opensearch.uris")).isNotEmpty(); } @Configuration - @EnableAutoConfiguration - public static class Config { + @EnableAutoConfiguration(exclude = { + OpenSearchClientAutoConfiguration.class, + OpenSearchRestClientAutoConfiguration.class, + OpenSearchRestHighLevelClientAutoConfiguration.class + }) + @EnableElasticsearchRepositories(basePackages = "com.playtika.testcontainer.opensearch.springdata") + public static class Config extends OpenSearchConfiguration { - @Bean - @Profile("credentials") - public RestClientBuilderCustomizer restClientBuilderCustomizer(@NotNull OpenSearchProperties properties) { - return new RestClientBuilderCustomizer() { + @Value("${embedded.opensearch.host}") + private String opensearchHost; - @Override - public void customize(RestClientBuilder builder) { - builder.setHttpClientConfigCallback( - httpClientBuilder -> { - if (properties.isAllowInsecure()) { - httpClientBuilder.setSSLContext(sslcontext()); - } - return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider()); - } - ); - } + @Value("${embedded.opensearch.httpPort}") + private int opensearchPort; - @Override - public void customize(HttpAsyncClientBuilder builder) { - if (properties.isAllowInsecure()) { - builder.setSSLContext(sslcontext()); - } - builder.setDefaultCredentialsProvider(credentialsProvider()); - } + @Autowired + private OpenSearchProperties openSearchProperties; - CredentialsProvider credentialsProvider() { - final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials( - AuthScope.ANY, new UsernamePasswordCredentials(properties.getUsername(), properties.getPassword()) - ); - return credentialsProvider; - } + @Override + public ClientConfiguration clientConfiguration() { + String hostAndPort = opensearchHost + ":" + opensearchPort; - SSLContext sslcontext() { - try { - return SSLContextBuilder.create() - .loadTrustMaterial(null, new TrustAllStrategy()) - .build(); - } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) { - throw new RuntimeException(e); - } + if (openSearchProperties.isCredentialsEnabled()) { + try { + HostnameVerifier allHostsValid = (hostname, session) -> true; + return ClientConfiguration.builder() + .connectedTo(hostAndPort) + .usingSsl(sslcontext(), allHostsValid) + .withBasicAuth(openSearchProperties.getUsername(), openSearchProperties.getPassword()) + .build(); + } catch (Exception e) { + throw new RuntimeException("Failed to create SSL context", e); } - }; + } + + return ClientConfiguration.builder() + .connectedTo(hostAndPort) + .build(); + } + + private SSLContext sslcontext() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException { + return SSLContextBuilder.create() + .loadTrustMaterial(null, (TrustStrategy) (X509Certificate[] chain, String authType) -> true) + .build(); } } } diff --git a/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/springdata/SpringDataTest.java b/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/springdata/SpringDataTest.java index f70dce95d..6b000a2a5 100644 --- a/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/springdata/SpringDataTest.java +++ b/embedded-opensearch/src/test/java/com/playtika/testcontainer/opensearch/springdata/SpringDataTest.java @@ -57,18 +57,15 @@ public void queryShouldWork() { public void shouldSetupDependsOnForNewClient() { String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, RestClient.class); - if (beanNamesForType.length > 0) { - assertThat(beanNamesForType) - .as("New client should be present") - .hasSize(1) - .contains("opensearchRestClient"); - asList(beanNamesForType).forEach(this::hasDependsOn); - } + assertThat(beanNamesForType) + .as("RestClient should be present") + .hasSize(1) + .contains("opensearchRestClient"); + asList(beanNamesForType).forEach(this::hasDependsOn); } private void hasDependsOn(String beanName) { assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) - .isNotNull() .isNotEmpty() .contains(OpenSearchProperties.BEAN_NAME_EMBEDDED_OPEN_SEARCH); } diff --git a/embedded-opensearch/src/test/resources/application-enabled.properties b/embedded-opensearch/src/test/resources/application-enabled.properties index ca07b44c5..1a69b5166 100644 --- a/embedded-opensearch/src/test/resources/application-enabled.properties +++ b/embedded-opensearch/src/test/resources/application-enabled.properties @@ -1 +1 @@ -opensearch.uris=http://${embedded.opensearch.host}:${embedded.opensearch.httpPort} \ No newline at end of file +opensearch.uris=http://${embedded.opensearch.host}:${embedded.opensearch.httpPort} diff --git a/embedded-oracle-xe/pom.xml b/embedded-oracle-xe/pom.xml index 415a62474..acc32cdf8 100644 --- a/embedded-oracle-xe/pom.xml +++ b/embedded-oracle-xe/pom.xml @@ -28,7 +28,7 @@ org.testcontainers - oracle-xe + testcontainers-oracle-xe com.oracle.ojdbc diff --git a/embedded-oracle-xe/src/main/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfiguration.java b/embedded-oracle-xe/src/main/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfiguration.java index 2b17d7ea3..413513b41 100644 --- a/embedded-oracle-xe/src/main/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfiguration.java +++ b/embedded-oracle-xe/src/main/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; import org.testcontainers.containers.OracleContainer; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-oracle-xe/src/test/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfigurationTest.java b/embedded-oracle-xe/src/test/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfigurationTest.java index 7fe116b66..93abb99ef 100644 --- a/embedded-oracle-xe/src/test/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfigurationTest.java +++ b/embedded-oracle-xe/src/test/java/com/playtika/testcontainer/oracle/EmbeddedOracleBootstrapConfigurationTest.java @@ -123,5 +123,10 @@ public DataSource customDatasource() { poolConfiguration.setTestOnReturn(true); return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource customDatasource) { + return new JdbcTemplate(customDatasource); + } } } diff --git a/embedded-postgresql/pom.xml b/embedded-postgresql/pom.xml index e33b25eed..a51bddf0e 100644 --- a/embedded-postgresql/pom.xml +++ b/embedded-postgresql/pom.xml @@ -28,7 +28,7 @@ org.testcontainers - postgresql + testcontainers-postgresql org.postgresql @@ -36,6 +36,11 @@ ${postgresql-driver.version} test + + org.springframework.boot + spring-boot-jdbc + true + org.springframework spring-jdbc diff --git a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfiguration.java b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfiguration.java index 4c8783652..54af93cc5 100644 --- a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfiguration.java +++ b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfiguration.java @@ -17,10 +17,10 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.springframework.util.StringUtils; import org.testcontainers.containers.Network; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.postgresql.PostgreSQLContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -60,7 +60,7 @@ public DynamicPropertyRegistrar postgresqlToxiProxyDynamicPropertyRegistrar(@Qua public PostgreSQLContainer postgresql(PostgreSQLProperties properties, Optional network) { PostgreSQLContainer postgresql = - new PostgreSQLContainer<>(ContainerUtils.getDockerImageName(properties)) + new PostgreSQLContainer(ContainerUtils.getDockerImageName(properties)) .withUsername(properties.getUser()) .withPassword(properties.getPassword()) .withDatabaseName(properties.getDatabase()) diff --git a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLDependenciesAutoConfiguration.java b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLDependenciesAutoConfiguration.java index 248e85d8d..0641f718f 100644 --- a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLDependenciesAutoConfiguration.java +++ b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLDependenciesAutoConfiguration.java @@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @@ -20,8 +21,11 @@ @ConditionalOnProperty(name = "embedded.postgresql.enabled", matchIfMissing = true) public class EmbeddedPostgreSQLDependenciesAutoConfiguration { - @Bean - public static BeanFactoryPostProcessor datasourcePostgreSqlDependencyPostProcessor() { - return new DependsOnPostProcessor(DataSource.class, new String[]{BEAN_NAME_EMBEDDED_POSTGRESQL}); + @Configuration + public static class EmbeddedPostgreSQLDataSourceDependencyContext { + @Bean + public static BeanFactoryPostProcessor datasourcePostgreSqlDependencyPostProcessor() { + return new DependsOnPostProcessor(DataSource.class, new String[]{BEAN_NAME_EMBEDDED_POSTGRESQL}); + } } } diff --git a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/AutoConfiguredDatasourceDependsOnTest.java b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/AutoConfiguredDatasourceDependsOnTest.java index 410821384..622a12973 100644 --- a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/AutoConfiguredDatasourceDependsOnTest.java +++ b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/AutoConfiguredDatasourceDependsOnTest.java @@ -1,13 +1,17 @@ package com.playtika.testcontainer.postgresql; -import com.playtika.testcontainer.postgresql.dummyapp.TestApplication; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration; +import org.springframework.boot.jdbc.autoconfigure.JdbcTemplateAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.TestPropertySource; @@ -21,7 +25,10 @@ class AutoConfiguredDatasourceDependsOnTest { @ActiveProfiles("enabled") - @SpringBootTest(classes = TestApplication.class, + @SpringBootTest( + classes = { + AutoConfiguredDatasourceDependsOnTest.TestConfiguration.class + }, properties = { "embedded.toxiproxy.proxies.postgresql.enabled=true" } @@ -53,7 +60,6 @@ void shouldSetupDependsOnForAllDataSources() { private void hasDependsOn(String beanName) { assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) - .isNotNull() .isNotEmpty() .contains(BEAN_NAME_EMBEDDED_POSTGRESQL); } @@ -66,4 +72,13 @@ private void hasDependsOn(String beanName) { @DisplayName("AutoConfigured Datasource with timescaledb:latest-pg11") class Timescale12Image extends TestDefaults { } + + @EnableAutoConfiguration + @ImportAutoConfiguration({ + DataSourceAutoConfiguration.class, + JdbcTemplateAutoConfiguration.class + }) + @Configuration + static class TestConfiguration { + } } diff --git a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfigurationTest.java b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfigurationTest.java index d35703f46..774647e8b 100644 --- a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfigurationTest.java +++ b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/EmbeddedPostgreSQLBootstrapConfigurationTest.java @@ -153,5 +153,10 @@ public DataSource customDatasource() { poolConfiguration.setTestOnReturn(true); return new org.apache.tomcat.jdbc.pool.DataSource(poolConfiguration); } + + @Bean + public JdbcTemplate jdbcTemplate(DataSource customDatasource) { + return new JdbcTemplate(customDatasource); + } } } diff --git a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/dummyapp/TestApplication.java b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/dummyapp/TestApplication.java index 4365539e7..d969f9611 100644 --- a/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/dummyapp/TestApplication.java +++ b/embedded-postgresql/src/test/java/com/playtika/testcontainer/postgresql/dummyapp/TestApplication.java @@ -1,7 +1,9 @@ package com.playtika.testcontainer.postgresql.dummyapp; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication +@EnableAutoConfiguration public class TestApplication { } diff --git a/embedded-postgresql/src/test/resources/application-test.yml b/embedded-postgresql/src/test/resources/application-test.yml new file mode 100644 index 000000000..b40034248 --- /dev/null +++ b/embedded-postgresql/src/test/resources/application-test.yml @@ -0,0 +1,16 @@ +logging: + level: + com.playtika.testcontainer: info + root: error + pattern: + console: '%d{HH:mm:ss.SSS} |%-5p| %c{1}:%L - %m%n' +spring: + datasource: + driver-class-name: org.postgresql.Driver + password: ${embedded.postgresql.password} + tomcat: + test-on-borrow: true + test-on-connect: true + validation-query: SELECT 1; + url: jdbc:postgresql://${embedded.postgresql.host}:${embedded.postgresql.port}/${embedded.postgresql.schema} + username: ${embedded.postgresql.user} diff --git a/embedded-postgresql/src/test/resources/application.properties b/embedded-postgresql/src/test/resources/application.properties deleted file mode 100644 index 6f3949a29..000000000 --- a/embedded-postgresql/src/test/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -logging.level.com.playtika.testcontainer=info -logging.level.root=error -logging.pattern.console=%d{HH:mm:ss.SSS} |%-5p| %c{1}:%L - %m%n \ No newline at end of file diff --git a/embedded-prometheus/pom.xml b/embedded-prometheus/pom.xml index 2bb0472f6..a51c9bcea 100644 --- a/embedded-prometheus/pom.xml +++ b/embedded-prometheus/pom.xml @@ -45,6 +45,11 @@ + + com.jayway.jsonpath + json-path + test + \ No newline at end of file diff --git a/embedded-prometheus/src/main/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfiguration.java b/embedded-prometheus/src/main/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfiguration.java index 14bc72547..468554766 100644 --- a/embedded-prometheus/src/main/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfiguration.java +++ b/embedded-prometheus/src/main/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfiguration.java @@ -18,9 +18,9 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-prometheus/src/test/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfigurationTest.java b/embedded-prometheus/src/test/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfigurationTest.java index a1810532d..b2bfeccf5 100644 --- a/embedded-prometheus/src/test/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfigurationTest.java +++ b/embedded-prometheus/src/test/java/com/playtika/testcontainer/prometheus/EmbeddedPrometheusBootstrapConfigurationTest.java @@ -1,29 +1,23 @@ package com.playtika.testcontainer.prometheus; +import com.jayway.jsonpath.JsonPath; import org.junit.jupiter.api.Test; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; -import static io.restassured.RestAssured.get; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; class EmbeddedPrometheusBootstrapConfigurationTest extends BaseEmbeddedPrometheusTest { @Test void shouldHaveMetrics() { - UriComponents uriComponents = - UriComponentsBuilder.newInstance() - .scheme("http") - .host(prometheusHost) - .port(prometheusPort) - .path("/api/v1/query?query=up") - .build(); + RestTemplate restTemplate = new RestTemplate(); + String url = "http://" + prometheusHost + ":" + prometheusPort + "/api/v1/query?query=up"; + ResponseEntity response = restTemplate.getForEntity(url, String.class); - get(uriComponents.toUriString()) - .then() - .assertThat() - .body("status", equalTo("success")) - .statusCode(200); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(JsonPath.parse(response.getBody()).read("$.status", String.class)).isEqualTo("success"); } } \ No newline at end of file diff --git a/embedded-pulsar/pom.xml b/embedded-pulsar/pom.xml index 05dec7a30..eda8446b4 100644 --- a/embedded-pulsar/pom.xml +++ b/embedded-pulsar/pom.xml @@ -29,7 +29,7 @@ org.testcontainers - pulsar + testcontainers-pulsar org.apache.pulsar diff --git a/embedded-pulsar/src/main/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfiguration.java b/embedded-pulsar/src/main/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfiguration.java index bdbb4b9d0..5a94f7395 100644 --- a/embedded-pulsar/src/main/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfiguration.java +++ b/embedded-pulsar/src/main/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfiguration.java @@ -15,8 +15,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.PulsarContainer; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.pulsar.PulsarContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfigurationTest.java b/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfigurationTest.java index 87d1aab89..301ab48d9 100644 --- a/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfigurationTest.java +++ b/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarBootstrapConfigurationTest.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.env.ConfigurableEnvironment; -import org.testcontainers.containers.PulsarContainer; +import org.testcontainers.pulsar.PulsarContainer; import static org.assertj.core.api.Assertions.assertThat; diff --git a/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarHttpServiceTest.java b/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarHttpServiceTest.java index d45176df7..e77183f71 100644 --- a/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarHttpServiceTest.java +++ b/embedded-pulsar/src/test/java/com/playtika/testcontainer/pulsar/EmbeddedPulsarHttpServiceTest.java @@ -2,9 +2,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; import java.net.URI; @@ -14,7 +14,7 @@ class EmbeddedPulsarHttpServiceTest extends AbstractEmbeddedPulsarTest { private static final String METRICS_PATH = "/admin/broker-stats/metrics"; - private final TestRestTemplate testRestTemplate = new TestRestTemplate(); + private final RestTemplate restTemplate = new RestTemplate(); @Value("${embedded.pulsar.httpServiceUrl}") private String pulsarServiceUrl; @@ -22,7 +22,7 @@ class EmbeddedPulsarHttpServiceTest extends AbstractEmbeddedPulsarTest { @Test void shouldCommunicateWithPulsarHttpService() { URI pulsarHttpService = URI.create(pulsarServiceUrl + METRICS_PATH); - ResponseEntity response = testRestTemplate.getForEntity(pulsarHttpService, String.class); + ResponseEntity response = restTemplate.getForEntity(pulsarHttpService, String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); } } diff --git a/embedded-rabbitmq/pom.xml b/embedded-rabbitmq/pom.xml index 5dff35a7a..43f505b97 100644 --- a/embedded-rabbitmq/pom.xml +++ b/embedded-rabbitmq/pom.xml @@ -25,7 +25,7 @@ org.testcontainers - rabbitmq + testcontainers-rabbitmq org.springframework.amqp @@ -37,5 +37,16 @@ spring-rabbit-stream test + + org.springframework.boot + spring-boot-starter-amqp + test + + + org.springframework.boot + spring-boot-starter-logging + + + diff --git a/embedded-rabbitmq/src/main/java/com/playtika/testcontainer/rabbitmq/EmbeddedRabbitMQBootstrapConfiguration.java b/embedded-rabbitmq/src/main/java/com/playtika/testcontainer/rabbitmq/EmbeddedRabbitMQBootstrapConfiguration.java index 193a16aa4..048670f2b 100644 --- a/embedded-rabbitmq/src/main/java/com/playtika/testcontainer/rabbitmq/EmbeddedRabbitMQBootstrapConfiguration.java +++ b/embedded-rabbitmq/src/main/java/com/playtika/testcontainer/rabbitmq/EmbeddedRabbitMQBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; import org.testcontainers.containers.RabbitMQContainer; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.LinkedHashMap; import java.util.Map; diff --git a/embedded-redis/README.adoc b/embedded-redis/README.adoc index 7f649ac39..0edd65234 100644 --- a/embedded-redis/README.adoc +++ b/embedded-redis/README.adoc @@ -24,6 +24,21 @@ * `embedded.redis.requirepass` `(true|false, default is true)` * `embedded.toxiproxy.proxies.redis.enabled` Enables both creation of the container with ToxiProxy TCP proxy and a proxy to the `embedded-redis` container. +==== Redis Client Drivers + +The embedded-redis module supports both Jedis and Lettuce Redis client drivers: + +* **Jedis**: Synchronous Redis client (default when Jedis is on classpath) +* **Lettuce**: Asynchronous and reactive Redis client, supports cluster mode and reactive operations + +Both drivers are optional dependencies. Spring Boot will auto-configure the appropriate connection factory based on which drivers are available on the classpath. To explicitly use Lettuce, configure: + +[source,properties] +---- +spring.data.redis.client-type=lettuce +---- + +The module automatically ensures that `LettuceConnectionFactory` and `JedisConnectionFactory` beans depend on the embedded Redis container, ensuring proper startup order. ==== Produces diff --git a/embedded-redis/pom.xml b/embedded-redis/pom.xml index 9e0d9ef53..9ae2a03ad 100644 --- a/embedded-redis/pom.xml +++ b/embedded-redis/pom.xml @@ -38,5 +38,22 @@ ${jedis.version} true + + io.lettuce + lettuce-core + true + + + + org.springframework.boot + spring-boot-starter-data-redis + test + + + org.springframework.boot + spring-boot-starter-logging + + + \ No newline at end of file diff --git a/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisBootstrapConfiguration.java b/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisBootstrapConfiguration.java index 9fac0df9a..1ecaa83bd 100644 --- a/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisBootstrapConfiguration.java +++ b/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisBootstrapConfiguration.java @@ -24,8 +24,8 @@ import org.testcontainers.containers.FixedHostPortGenericContainer; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.utility.MountableFile; import java.io.IOException; diff --git a/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisDependenciesAutoConfiguration.java b/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisDependenciesAutoConfiguration.java index 69b024943..d7ea72eba 100644 --- a/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisDependenciesAutoConfiguration.java +++ b/embedded-redis/src/main/java/com/playtika/testcontainer/redis/EmbeddedRedisDependenciesAutoConfiguration.java @@ -11,6 +11,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import redis.clients.jedis.Jedis; @@ -49,4 +50,13 @@ public static BeanFactoryPostProcessor jedisDependencyPostProcessor() { return new DependsOnPostProcessor(Jedis.class, new String[]{BEAN_NAME_EMBEDDED_REDIS}); } } + + @Configuration + @ConditionalOnClass(LettuceConnectionFactory.class) + public static class LettuceDependencyContext { + @Bean + public static BeanFactoryPostProcessor lettuceConnectionFactoryDependencyPostProcessor() { + return new DependsOnPostProcessor(LettuceConnectionFactory.class, new String[]{BEAN_NAME_EMBEDDED_REDIS}); + } + } } diff --git a/embedded-redis/src/test/java/com/playtika/testcontainer/redis/clustered/ClusteredEmbeddedRedisLettuceTest.java b/embedded-redis/src/test/java/com/playtika/testcontainer/redis/clustered/ClusteredEmbeddedRedisLettuceTest.java new file mode 100644 index 000000000..1ab1b9291 --- /dev/null +++ b/embedded-redis/src/test/java/com/playtika/testcontainer/redis/clustered/ClusteredEmbeddedRedisLettuceTest.java @@ -0,0 +1,80 @@ +package com.playtika.testcontainer.redis.clustered; + +import com.playtika.testcontainer.redis.BaseEmbeddedRedisTest; +import com.playtika.testcontainer.redis.RedisProperties; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisClusterConfiguration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; + +import java.util.Collections; + +import static com.playtika.testcontainer.redis.RedisProperties.BEAN_NAME_EMBEDDED_REDIS; +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +@Slf4j +@SpringBootTest( + classes = ClusteredEmbeddedRedisLettuceTest.TestConfiguration.class, + properties = { + "embedded.redis.clustered=true" + } +) +public class ClusteredEmbeddedRedisLettuceTest extends BaseEmbeddedRedisTest { + + @Test + public void shouldSetupDependsOnForLettuceConnectionFactory() throws Exception { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, RedisConnectionFactory.class); + assertThat(beanNamesForType) + .as("RedisConnectionFactory should be present") + .hasSize(1) + .contains("connectionFactory"); + asList(beanNamesForType).forEach(this::hasDependsOn); + + beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, org.springframework.data.redis.core.RedisTemplate.class); + assertThat(beanNamesForType) + .as("redisTemplates should be present") + .hasSize(2) + .contains("redisTemplate", "stringRedisTemplate"); + asList(beanNamesForType).forEach(this::hasDependsOn); + } + + @Test + public void shouldUseLettuceConnectionFactory() { + RedisConnectionFactory connectionFactory = beanFactory.getBean(RedisConnectionFactory.class); + assertThat(connectionFactory) + .as("Should use LettuceConnectionFactory") + .isInstanceOf(LettuceConnectionFactory.class); + } + + private void hasDependsOn(String beanName) { + assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) + .isNotNull() + .isNotEmpty() + .contains(BEAN_NAME_EMBEDDED_REDIS); + } + + @EnableAutoConfiguration + @Configuration + static class TestConfiguration { + + @Bean + public RedisConnectionFactory connectionFactory(RedisProperties redisProperties) { + log.info(format("Connecting to Redis Cluster node with Lettuce: %s:%s", redisProperties.getHost(), redisProperties.getPort())); + RedisClusterConfiguration redisConfiguration = new RedisClusterConfiguration( + Collections.singletonList(format("%s:%s", redisProperties.getHost(), redisProperties.getPort()))); + if (redisProperties.isRequirepass()) { + redisConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword())); + } + return new LettuceConnectionFactory(redisConfiguration); + } + } +} diff --git a/embedded-redis/src/test/java/com/playtika/testcontainer/redis/standalone/StandaloneEmbeddedRedisLettuceTest.java b/embedded-redis/src/test/java/com/playtika/testcontainer/redis/standalone/StandaloneEmbeddedRedisLettuceTest.java new file mode 100644 index 000000000..6a6522dda --- /dev/null +++ b/embedded-redis/src/test/java/com/playtika/testcontainer/redis/standalone/StandaloneEmbeddedRedisLettuceTest.java @@ -0,0 +1,75 @@ +package com.playtika.testcontainer.redis.standalone; + +import com.playtika.testcontainer.redis.BaseEmbeddedRedisTest; +import com.playtika.testcontainer.redis.RedisProperties; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisPassword; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; + +import static com.playtika.testcontainer.redis.RedisProperties.BEAN_NAME_EMBEDDED_REDIS; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; + +@Slf4j +@SpringBootTest( + classes = StandaloneEmbeddedRedisLettuceTest.TestConfiguration.class +) +public class StandaloneEmbeddedRedisLettuceTest extends BaseEmbeddedRedisTest { + + @Test + public void shouldSetupDependsOnForLettuceConnectionFactory() throws Exception { + String[] beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, RedisConnectionFactory.class); + assertThat(beanNamesForType) + .as("RedisConnectionFactory should be present") + .hasSize(1) + .contains("redisConnectionFactory"); + asList(beanNamesForType).forEach(this::hasDependsOn); + + beanNamesForType = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, RedisTemplate.class); + assertThat(beanNamesForType) + .as("redisTemplates should be present") + .hasSize(2) + .contains("redisTemplate", "stringRedisTemplate"); + asList(beanNamesForType).forEach(this::hasDependsOn); + } + + @Test + public void shouldUseLettuceConnectionFactory() { + RedisConnectionFactory connectionFactory = beanFactory.getBean(RedisConnectionFactory.class); + assertThat(connectionFactory) + .as("Should use LettuceConnectionFactory") + .isInstanceOf(LettuceConnectionFactory.class); + } + + private void hasDependsOn(String beanName) { + assertThat(beanFactory.getBeanDefinition(beanName).getDependsOn()) + .isNotNull() + .isNotEmpty() + .contains(BEAN_NAME_EMBEDDED_REDIS); + } + + @EnableAutoConfiguration + @Configuration + static class TestConfiguration { + + @Bean + public RedisConnectionFactory redisConnectionFactory(RedisProperties redisProperties) { + log.info("Connecting to Redis with Lettuce: {}:{}", redisProperties.getHost(), redisProperties.getPort()); + RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration( + redisProperties.getHost(), redisProperties.getPort()); + if (redisProperties.isRequirepass()) { + redisConfiguration.setPassword(RedisPassword.of(redisProperties.getPassword())); + } + return new LettuceConnectionFactory(redisConfiguration); + } + } +} diff --git a/embedded-redis/src/test/resources/application-lettuce.properties b/embedded-redis/src/test/resources/application-lettuce.properties new file mode 100644 index 000000000..93dbf6216 --- /dev/null +++ b/embedded-redis/src/test/resources/application-lettuce.properties @@ -0,0 +1,5 @@ +spring.data.redis.host=${embedded.redis.host} +spring.data.redis.port=${embedded.redis.port} +spring.data.redis.client-type=lettuce +spring.data.redis.timeout=2500 + diff --git a/embedded-selenium/README.adoc b/embedded-selenium/README.adoc index bb71940ed..45fd9a098 100644 --- a/embedded-selenium/README.adoc +++ b/embedded-selenium/README.adoc @@ -86,7 +86,11 @@ An example test class would look like the following: [source,java] ----------------- -import org.openqa.selenium.WebDriver;@RunWith(SpringRunner.class) +import org.openqa.selenium.MutableCapabilities; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.remote.RemoteWebDriver; +import org.testcontainers.selenium.BrowserWebDriverContainer; +@RunWith(SpringRunner.class) @SpringBootTest( classes = SpringBootWebApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT @@ -103,11 +107,18 @@ public class TestLoginPage { @Autowired private BrowserWebDriverContainer webDriverContainer; + @Autowired + private MutableCapabilities capabilities; + @Test public void test1() { - RemoteWebDriver webDriver = webDriverContainer.getWebDriver(); - webDriver.get("https://" + hostname +":" + port); - assertThat(webDriver.getPageSource()).contains("helloworld"); + RemoteWebDriver webDriver = new RemoteWebDriver(webDriverContainer.getSeleniumAddress(), capabilities); + try { + webDriver.get("https://" + hostname +":" + port); + assertThat(webDriver.getPageSource()).contains("helloworld"); + } finally { + webDriver.quit(); + } } @TestConfiguration diff --git a/embedded-selenium/pom.xml b/embedded-selenium/pom.xml index 68152ff6b..d4ed6d9cf 100644 --- a/embedded-selenium/pom.xml +++ b/embedded-selenium/pom.xml @@ -25,7 +25,7 @@ org.testcontainers - selenium + testcontainers-selenium org.seleniumhq.selenium diff --git a/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java b/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java index 73c5cc12d..d3b7d78c2 100644 --- a/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java +++ b/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/EmbeddedSeleniumBootstrapConfiguration.java @@ -16,7 +16,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.test.context.DynamicPropertyRegistrar; -import org.testcontainers.containers.BrowserWebDriverContainer; import org.testcontainers.containers.Container; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.DefaultRecordingFileFactory; @@ -27,6 +26,7 @@ import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.selenium.BrowserWebDriverContainer; import java.io.File; import java.io.IOException; @@ -85,11 +85,10 @@ public BrowserWebDriverContainer selenium( Optional network) { BrowserWebDriverContainer container = isNotBlank(properties.getDockerImage()) - ? new BrowserWebDriverContainer<>(ContainerUtils.getDockerImageName(properties)) - : new BrowserWebDriverContainer<>(); + ? new BrowserWebDriverContainer(ContainerUtils.getDockerImageName(properties)) + : new BrowserWebDriverContainer(properties.getDefaultDockerImage()); container.waitingFor(getWaitStrategy()); - container.withCapabilities(capabilities); container.withRecordingFileFactory(getRecordingFileFactory()); container.withNetworkAliases(SELENIUM_NETWORK_ALIAS); network.ifPresent(container::withNetwork); @@ -247,4 +246,4 @@ public DynamicPropertyRegistrar seleniumDynamicPropertyRegistrar(@Qualifier(BEAN getHostName(selenium), SELENIUM_NETWORK_ALIAS); }; } -} \ No newline at end of file +} diff --git a/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.java b/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.java index d28ab7be3..95ef367f8 100644 --- a/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.java +++ b/embedded-selenium/src/main/java/com/playtika/testcontainer/selenium/VncRecordingMode.java @@ -1,10 +1,10 @@ package com.playtika.testcontainer.selenium; -import org.testcontainers.containers.BrowserWebDriverContainer; +import org.testcontainers.selenium.BrowserWebDriverContainer; /** - * See {@link org.testcontainers.containers.BrowserWebDriverContainer.VncRecordingMode} + * See {@link org.testcontainers.selenium.BrowserWebDriverContainer.VncRecordingMode} */ public enum VncRecordingMode { SKIP, RECORD_ALL, RECORD_FAILING; @@ -12,4 +12,4 @@ public enum VncRecordingMode { public BrowserWebDriverContainer.VncRecordingMode convert() { return BrowserWebDriverContainer.VncRecordingMode.valueOf(this.name()); } -} \ No newline at end of file +} diff --git a/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/BaseEmbeddedSeleniumTest.java b/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/BaseEmbeddedSeleniumTest.java index a6bb723db..591a09a5a 100644 --- a/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/BaseEmbeddedSeleniumTest.java +++ b/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/BaseEmbeddedSeleniumTest.java @@ -4,12 +4,13 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; +import org.openqa.selenium.MutableCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; -import org.testcontainers.containers.BrowserWebDriverContainer; +import org.testcontainers.selenium.BrowserWebDriverContainer; import static org.assertj.core.api.Assertions.assertThat; @@ -41,6 +42,9 @@ public abstract class BaseEmbeddedSeleniumTest { @Value("${embedded.selenium.vnc.password}") protected String seleniumVncPassword; + @Autowired + protected MutableCapabilities capabilities; + @LocalServerPort private int port; @@ -49,14 +53,14 @@ public abstract class BaseEmbeddedSeleniumTest { @Test public void seleniumShouldWork() { - RemoteWebDriver driver = container.getWebDriver(); + RemoteWebDriver driver = createWebDriver(); getIndexPage(driver); assertThat(driver.getTitle()).isEqualTo("Hello World Page"); } @Test public void seleniumLinkShouldWorkAndPropertiesAreAvailable() { - RemoteWebDriver driver = container.getWebDriver(); + RemoteWebDriver driver = createWebDriver(); getIndexPage(driver); driver.findElement(By.linkText("Test Link")).click(); assertThat(driver.getTitle()).isEqualTo("Test Link Page"); @@ -74,8 +78,17 @@ private void getIndexPage(RemoteWebDriver driver) { driver.get("http://" + dockerHostname + ":" + port + "/index.html"); } + protected RemoteWebDriver createWebDriver() { + return new RemoteWebDriver(container.getSeleniumAddress(), capabilities); + } + public String getBrowserName() { - return (String)container.getWebDriver().getCapabilities().getCapability("browserName"); + RemoteWebDriver driver = createWebDriver(); + try { + return (String) driver.getCapabilities().getCapability("browserName"); + } finally { + driver.quit(); + } } } diff --git a/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/EmbeddedFirefoxSeleniumBeanConfigurationTest.java b/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/EmbeddedFirefoxSeleniumBeanConfigurationTest.java index 71e4f4bd3..edb15e642 100644 --- a/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/EmbeddedFirefoxSeleniumBeanConfigurationTest.java +++ b/embedded-selenium/src/test/java/com/playtika/testcontainer/selenium/drivers/EmbeddedFirefoxSeleniumBeanConfigurationTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.Test; import org.openqa.selenium.firefox.FirefoxOptions; import org.openqa.selenium.remote.CapabilityType; +import org.openqa.selenium.remote.RemoteWebDriver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; @@ -44,8 +45,13 @@ public void testThatTestArgumentIsSet() { @Test public void testThatTestCapabilityIsSet() { // default is true, false is set in localtestconfiguration - boolean acceptUnsecureCertificates = (boolean)container.getWebDriver().getCapabilities().getCapability(CapabilityType.ACCEPT_INSECURE_CERTS); - assertThat(acceptUnsecureCertificates).isFalse(); + RemoteWebDriver driver = createWebDriver(); + try { + boolean acceptUnsecureCertificates = (boolean) driver.getCapabilities().getCapability(CapabilityType.ACCEPT_INSECURE_CERTS); + assertThat(acceptUnsecureCertificates).isFalse(); + } finally { + driver.quit(); + } } @TestConfiguration diff --git a/embedded-solr/README.adoc b/embedded-solr/README.adoc index 77ec05b48..0d4419d13 100644 --- a/embedded-solr/README.adoc +++ b/embedded-solr/README.adoc @@ -16,7 +16,7 @@ * `embedded.solr.enabled` `(true|false, default is true)` * `embedded.solr.reuseContainer` `(true|false, default is false)` -* `embedded.solr.dockerImage` `(default is 'solr:9.9')` +* `embedded.solr.dockerImage` `(default is 'solr:9.10-slim')` ** Image versions on https://hub.docker.com/_/solr/tags[dockerhub] * `embedded.toxiproxy.proxies.solr.enabled` Enables both creation of the container with ToxiProxy TCP proxy and a proxy to the `embedded-solr` container. diff --git a/embedded-solr/pom.xml b/embedded-solr/pom.xml index 96fbd7f07..a9b92c8dc 100644 --- a/embedded-solr/pom.xml +++ b/embedded-solr/pom.xml @@ -28,7 +28,7 @@ org.testcontainers - solr + testcontainers-solr org.apache.solr diff --git a/embedded-solr/src/main/java/com/playtika/testcontainer/solr/EmbeddedSolrBootstrapConfiguration.java b/embedded-solr/src/main/java/com/playtika/testcontainer/solr/EmbeddedSolrBootstrapConfiguration.java index e6940b3f5..f4766aeca 100644 --- a/embedded-solr/src/main/java/com/playtika/testcontainer/solr/EmbeddedSolrBootstrapConfiguration.java +++ b/embedded-solr/src/main/java/com/playtika/testcontainer/solr/EmbeddedSolrBootstrapConfiguration.java @@ -17,8 +17,8 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.SolrContainer; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.solr.SolrContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; @@ -57,7 +57,7 @@ public DynamicPropertyRegistrar solrToxiProxyDynamicPropertyRegistrar(@Qualifier } @Bean(name = BEAN_NAME_EMBEDDED_SOLR, destroyMethod = "stop") - public GenericContainer solrContainer(SolrProperties properties, Optional network) { + public SolrContainer solrContainer(SolrProperties properties, Optional network) { SolrContainer solrContainer = new SolrContainer(ContainerUtils.getDockerImageName(properties)) .withExposedPorts(properties.getPort()) .withNetworkAliases(SOLR_NETWORK_ALIAS); diff --git a/embedded-solr/src/main/java/com/playtika/testcontainer/solr/SolrProperties.java b/embedded-solr/src/main/java/com/playtika/testcontainer/solr/SolrProperties.java index 4659427dd..86ad12942 100644 --- a/embedded-solr/src/main/java/com/playtika/testcontainer/solr/SolrProperties.java +++ b/embedded-solr/src/main/java/com/playtika/testcontainer/solr/SolrProperties.java @@ -17,6 +17,6 @@ public class SolrProperties extends CommonContainerProperties { public String getDefaultDockerImage() { // Please don`t remove this comment. // renovate: datasource=docker - return "solr:9.9"; + return "solr:9.10-slim"; } } diff --git a/embedded-spicedb/src/main/java/com/playtika/testcontainer/spicedb/EmbeddedSpiceDBBootstrapConfiguration.java b/embedded-spicedb/src/main/java/com/playtika/testcontainer/spicedb/EmbeddedSpiceDBBootstrapConfiguration.java index 84f24b365..33154d5a0 100644 --- a/embedded-spicedb/src/main/java/com/playtika/testcontainer/spicedb/EmbeddedSpiceDBBootstrapConfiguration.java +++ b/embedded-spicedb/src/main/java/com/playtika/testcontainer/spicedb/EmbeddedSpiceDBBootstrapConfiguration.java @@ -18,10 +18,10 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitAllStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.java b/embedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.java index 768e01c2c..12ed815aa 100644 --- a/embedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.java +++ b/embedded-temporal/src/test/java/com/playtika/testcontainer/temporal/EmbeddedTemporalBootstrapConfigurationTest.java @@ -23,10 +23,11 @@ import org.springframework.test.web.reactive.server.WebTestClient; import org.testcontainers.containers.Container; +import java.util.List; + import static io.temporal.api.enums.v1.EventType.EVENT_TYPE_WORKFLOW_EXECUTION_STARTED; import static java.util.UUID.randomUUID; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.hasItem; class EmbeddedTemporalBootstrapConfigurationTest { @@ -72,7 +73,10 @@ void workflowExecutionStarts( .expectStatus().isOk() .expectBody() .jsonPath("$.history.events[*].eventType") - .value(hasItem(EVENT_TYPE_WORKFLOW_EXECUTION_STARTED.toString())); + .value(events -> { + List eventTypes = (List) events; + assertThat(eventTypes).contains(EVENT_TYPE_WORKFLOW_EXECUTION_STARTED.toString()); + }); } } diff --git a/embedded-toxiproxy/pom.xml b/embedded-toxiproxy/pom.xml index c7e2271da..38e69e26a 100644 --- a/embedded-toxiproxy/pom.xml +++ b/embedded-toxiproxy/pom.xml @@ -16,7 +16,7 @@ org.testcontainers - toxiproxy + testcontainers-toxiproxy eu.rekawek.toxiproxy diff --git a/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfiguration.java b/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfiguration.java index 14f4892ad..56023468a 100644 --- a/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfiguration.java +++ b/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfiguration.java @@ -14,7 +14,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; @Slf4j @Configuration diff --git a/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/ToxiproxyHelper.java b/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/ToxiproxyHelper.java index 8eb4344e4..327b97452 100644 --- a/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/ToxiproxyHelper.java +++ b/embedded-toxiproxy/src/main/java/com/playtika/testcontainer/toxiproxy/ToxiproxyHelper.java @@ -6,7 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; diff --git a/embedded-toxiproxy/src/test/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfigurationTest.java b/embedded-toxiproxy/src/test/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfigurationTest.java index 3a85b6af4..2ca6c8f03 100644 --- a/embedded-toxiproxy/src/test/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfigurationTest.java +++ b/embedded-toxiproxy/src/test/java/com/playtika/testcontainer/toxiproxy/EmbeddedToxiProxyBootstrapConfigurationTest.java @@ -10,7 +10,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.List; @@ -71,4 +71,4 @@ static class TestConfiguration { } -} \ No newline at end of file +} diff --git a/embedded-vault/pom.xml b/embedded-vault/pom.xml index e50272ceb..c6837469e 100644 --- a/embedded-vault/pom.xml +++ b/embedded-vault/pom.xml @@ -25,7 +25,7 @@ org.testcontainers - vault + testcontainers-vault org.springframework.cloud diff --git a/embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java b/embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java index 4ea8fb0ef..de90d39d5 100644 --- a/embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java +++ b/embedded-vault/src/main/java/com/playtika/testcontainer/vault/EmbeddedVaultBootstrapConfiguration.java @@ -17,7 +17,7 @@ import org.springframework.core.annotation.Order; import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import org.testcontainers.vault.VaultContainer; import java.util.Arrays; diff --git a/embedded-vertica/pom.xml b/embedded-vertica/pom.xml index 3e9cd8419..96c82c955 100644 --- a/embedded-vertica/pom.xml +++ b/embedded-vertica/pom.xml @@ -36,14 +36,15 @@ test - org.springframework - spring-jdbc - test - - - org.apache.tomcat - tomcat-jdbc + org.springframework.boot + spring-boot-starter-jdbc test + + + org.springframework.boot + spring-boot-starter-logging + + diff --git a/embedded-vertica/src/main/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfiguration.java b/embedded-vertica/src/main/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfiguration.java index e3c32a2b1..cf310fb1f 100644 --- a/embedded-vertica/src/main/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfiguration.java +++ b/embedded-vertica/src/main/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfiguration.java @@ -17,8 +17,8 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.time.Duration; import java.util.Optional; diff --git a/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfigurationTest.java b/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfigurationTest.java index 9ea172581..5f33b3b18 100644 --- a/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfigurationTest.java +++ b/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/EmbeddedVerticaBootstrapConfigurationTest.java @@ -3,20 +3,21 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; @Slf4j +@ActiveProfiles("enabled") @SpringBootTest( classes = EmbeddedVerticaBootstrapConfigurationTest.TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.vertica.enabled=true" } ) @@ -27,8 +28,20 @@ class EmbeddedVerticaBootstrapConfigurationTest { @Autowired JdbcTemplate jdbcTemplate; - @Autowired - ConfigurableEnvironment environment; + @Value("${embedded.vertica.port}") + String verticaPort; + + @Value("${embedded.vertica.host}") + String verticaHost; + + @Value("${embedded.vertica.database}") + String verticaDatabase; + + @Value("${embedded.vertica.user}") + String verticaUser; + + @Value("${embedded.vertica.password}") + String verticaPassword; @Test public void shouldConnectToVertica() { @@ -37,11 +50,11 @@ public void shouldConnectToVertica() { @Test public void propertiesAreAvailable() { - assertThat(environment.getProperty("embedded.vertica.port")).isNotEmpty(); - assertThat(environment.getProperty("embedded.vertica.host")).isNotEmpty(); - assertThat(environment.getProperty("embedded.vertica.database")).isNotEmpty(); - assertThat(environment.getProperty("embedded.vertica.user")).isNotEmpty(); - assertThat(environment.getProperty("embedded.vertica.password")).isNotNull(); + assertThat(verticaPort).isNotEmpty(); + assertThat(verticaHost).isNotEmpty(); + assertThat(verticaDatabase).isNotEmpty(); + assertThat(verticaUser).isNotEmpty(); + assertThat(verticaPassword).isNotNull(); } @EnableAutoConfiguration diff --git a/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/NetworkConfigurationTest.java b/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/NetworkConfigurationTest.java index eb46c8f84..d3fdefaa7 100644 --- a/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/NetworkConfigurationTest.java +++ b/embedded-vertica/src/test/java/com/playtika/testcontainer/vertica/NetworkConfigurationTest.java @@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ActiveProfiles; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; @@ -21,10 +22,10 @@ class NetworkConfigurationTest { @Nested + @ActiveProfiles("enabled") @SpringBootTest( classes = TestConfiguration.class, properties = { - "spring.profiles.active=enabled", "embedded.vertica.enabled=true", "embedded.vertica.custom-network=true" } @@ -49,11 +50,9 @@ public void shouldHaveCustomNetworkRegisteredForContainer() { } @Nested + @ActiveProfiles("enabled") @SpringBootTest( - classes = TestConfiguration.class, - properties = { - "spring.profiles.active=enabled", - } + classes = TestConfiguration.class ) class DefaultNetworkConfigurationTest { diff --git a/embedded-victoriametrics/pom.xml b/embedded-victoriametrics/pom.xml index a492f44b5..31a51d9d5 100644 --- a/embedded-victoriametrics/pom.xml +++ b/embedded-victoriametrics/pom.xml @@ -22,17 +22,6 @@ com.playtika.testcontainers embedded-toxiproxy - - io.rest-assured - rest-assured - test - - - commons-logging - commons-logging - - - org.springframework.boot spring-boot-starter-web @@ -44,6 +33,11 @@ + + com.fasterxml.jackson.core + jackson-databind + test + \ No newline at end of file diff --git a/embedded-victoriametrics/src/main/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfiguration.java b/embedded-victoriametrics/src/main/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfiguration.java index 9efc13b13..64ae115c6 100644 --- a/embedded-victoriametrics/src/main/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfiguration.java +++ b/embedded-victoriametrics/src/main/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfiguration.java @@ -19,9 +19,9 @@ import org.springframework.test.context.DynamicPropertyRegistrar; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; -import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.WaitStrategy; +import org.testcontainers.toxiproxy.ToxiproxyContainer; import java.util.Optional; diff --git a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/BaseEmbeddedVictoriaMetricsTest.java b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/BaseEmbeddedVictoriaMetricsTest.java index 556822c39..609e05a4c 100644 --- a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/BaseEmbeddedVictoriaMetricsTest.java +++ b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/BaseEmbeddedVictoriaMetricsTest.java @@ -1,11 +1,20 @@ package com.playtika.testcontainer.victoriametrics; +import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = BaseEmbeddedVictoriaMetricsTest.TestConfiguration.class, @@ -23,8 +32,35 @@ public class BaseEmbeddedVictoriaMetricsTest { @Autowired protected ConfigurableListableBeanFactory beanFactory; + protected final ObjectMapper objectMapper = new ObjectMapper(); + private final HttpClient httpClient = HttpClient.newHttpClient(); + @EnableAutoConfiguration @Configuration static class TestConfiguration { } + + protected VictoriaMetricsHttpResponse queryUp(String host, int port) throws IOException, InterruptedException { + return queryUp(host, port, null); + } + + protected VictoriaMetricsHttpResponse queryUp(String host, int port, Duration timeout) throws IOException, InterruptedException { + URI uri = UriComponentsBuilder.newInstance() + .scheme("http") + .host(host) + .port(port) + .path("/api/v1/query") + .queryParam("query", "up") + .build(true) + .toUri(); + + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(uri).GET(); + if (timeout != null) { + requestBuilder.timeout(timeout); + } + + HttpResponse response = httpClient.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString()); + VictoriaMetricsQueryResponse body = objectMapper.readValue(response.body(), VictoriaMetricsQueryResponse.class); + return new VictoriaMetricsHttpResponse(response.statusCode(), body); + } } diff --git a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfigurationTest.java b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfigurationTest.java index 49f82ddfa..c3f2d1db2 100644 --- a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfigurationTest.java +++ b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/EmbeddedVictoriaMetricsBootstrapConfigurationTest.java @@ -1,29 +1,15 @@ package com.playtika.testcontainer.victoriametrics; import org.junit.jupiter.api.Test; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; -import static io.restassured.RestAssured.get; -import static org.hamcrest.Matchers.equalTo; +import static org.assertj.core.api.Assertions.assertThat; public class EmbeddedVictoriaMetricsBootstrapConfigurationTest extends BaseEmbeddedVictoriaMetricsTest { @Test - void shouldHaveMetrics() { - - UriComponents uriComponents = - UriComponentsBuilder.newInstance() - .scheme("http") - .host(victoriaMetricsHost) - .port(victoriaMetricsPort) - .path("/api/v1/query?query=up") - .build(); - - get(uriComponents.toUriString()) - .then() - .assertThat() - .body("status", equalTo("success")) - .statusCode(200); + void shouldHaveMetrics() throws Exception { + VictoriaMetricsHttpResponse actual = queryUp(victoriaMetricsHost, victoriaMetricsPort); + VictoriaMetricsHttpResponse expected = new VictoriaMetricsHttpResponse(200, new VictoriaMetricsQueryResponse("success")); + assertThat(actual).isEqualTo(expected); } } diff --git a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/ToxiProxyVictoriaMetricsTest.java b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/ToxiProxyVictoriaMetricsTest.java index 6030442c1..f0a8f7306 100644 --- a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/ToxiProxyVictoriaMetricsTest.java +++ b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/ToxiProxyVictoriaMetricsTest.java @@ -2,20 +2,14 @@ import com.playtika.testcontainer.toxiproxy.ToxiproxyClientProxy; import eu.rekawek.toxiproxy.model.ToxicDirection; -import io.restassured.RestAssured; -import io.restassured.config.HttpClientConfig; -import io.restassured.config.RestAssuredConfig; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; -import java.io.IOException; -import java.net.SocketTimeoutException; +import java.net.http.HttpTimeoutException; +import java.time.Duration; -import static io.restassured.RestAssured.given; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hamcrest.Matchers.equalTo; public class ToxiProxyVictoriaMetricsTest extends BaseEmbeddedVictoriaMetricsTest { @@ -23,38 +17,18 @@ public class ToxiProxyVictoriaMetricsTest extends BaseEmbeddedVictoriaMetricsTes private ToxiproxyClientProxy victoriaMetricsContainerProxy; @Test - void shouldAddLatency() throws IOException { - - UriComponents uriComponents = - UriComponentsBuilder.newInstance() - .scheme("http") - .host(victoriaMetricsToxiProxyHost) - .port(victoriaMetricsToxiProxyPort) - .path("/api/v1/query?query=up") - .build(); - + void shouldAddLatency() throws Exception { victoriaMetricsContainerProxy.toxics() .latency("latency", ToxicDirection.DOWNSTREAM, 1_100) .setJitter(100); - RestAssuredConfig config = RestAssured.config() - .httpClient(HttpClientConfig.httpClientConfig() - .setParam("http.socket.timeout", 200)); + assertThatThrownBy(() -> queryUp(victoriaMetricsToxiProxyHost, victoriaMetricsToxiProxyPort, Duration.ofMillis(200))) + .isInstanceOf(HttpTimeoutException.class); - assertThatThrownBy(() -> given() - .config(config) - .get(uriComponents.toUriString())) - .isInstanceOf(SocketTimeoutException.class); + victoriaMetricsContainerProxy.toxics().get("latency").remove(); - victoriaMetricsContainerProxy.toxics() - .get("latency").remove(); - - given() - .config(config) - .get(uriComponents.toUriString()) - .then() - .assertThat() - .body("status", equalTo("success")) - .statusCode(200); + VictoriaMetricsHttpResponse actual = queryUp(victoriaMetricsToxiProxyHost, victoriaMetricsToxiProxyPort); + VictoriaMetricsHttpResponse expected = new VictoriaMetricsHttpResponse(200, new VictoriaMetricsQueryResponse("success")); + assertThat(actual).isEqualTo(expected); } } diff --git a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsHttpResponse.java b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsHttpResponse.java new file mode 100644 index 000000000..e57b00aad --- /dev/null +++ b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsHttpResponse.java @@ -0,0 +1,4 @@ +package com.playtika.testcontainer.victoriametrics; + +public record VictoriaMetricsHttpResponse(int statusCode, VictoriaMetricsQueryResponse body) { +} \ No newline at end of file diff --git a/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsQueryResponse.java b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsQueryResponse.java new file mode 100644 index 000000000..5aab269ed --- /dev/null +++ b/embedded-victoriametrics/src/test/java/com/playtika/testcontainer/victoriametrics/VictoriaMetricsQueryResponse.java @@ -0,0 +1,7 @@ +package com.playtika.testcontainer.victoriametrics; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record VictoriaMetricsQueryResponse(String status) { +} \ No newline at end of file diff --git a/embedded-wiremock/pom.xml b/embedded-wiremock/pom.xml index e697f5e5a..f60bc5f47 100644 --- a/embedded-wiremock/pom.xml +++ b/embedded-wiremock/pom.xml @@ -51,6 +51,10 @@ - + + org.springframework + spring-web + test + diff --git a/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java index 634c7eb3f..dea86a0d7 100644 --- a/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java +++ b/embedded-wiremock/src/test/java/com/playtika/testcontainers/wiremock/EmbeddedWiremockBootstrapConfigurationTest.java @@ -1,7 +1,6 @@ package com.playtika.testcontainers.wiremock; import com.github.tomakehurst.wiremock.client.WireMock; -import io.restassured.RestAssured; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -9,13 +8,14 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.ok; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static io.restassured.RestAssured.given; import static org.assertj.core.api.Assertions.assertThat; -import static org.hamcrest.Matchers.equalTo; @Slf4j @SpringBootTest( @@ -41,7 +41,6 @@ public class EmbeddedWiremockBootstrapConfigurationTest { @BeforeEach void setUp() { WireMock.configureFor(wiremockHost, wiremockPort); - RestAssured.port = wiremockPort; } @Test @@ -49,13 +48,12 @@ void shouldRequestWiremockStub() { stubFor(get("/say-hello") .willReturn(ok("Hello world!"))); - given() - .get("/say-hello") - .then() - .assertThat() - .log().all() - .statusCode(200) - .body(equalTo("Hello world!")); + RestTemplate restTemplate = new RestTemplate(); + String baseUrl = "http://" + wiremockHost + ":" + wiremockPort; + ResponseEntity response = restTemplate.getForEntity(baseUrl + "/say-hello", String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo("Hello world!"); } @Test diff --git a/pom.xml b/pom.xml index 699befbf6..02495f93f 100644 --- a/pom.xml +++ b/pom.xml @@ -38,6 +38,7 @@ testcontainers-spring-boot-bom testcontainers-spring-boot-parent testcontainers-common + embedded-toxiproxy embedded-kafka embedded-native-kafka embedded-keycloak @@ -72,7 +73,6 @@ embedded-db2 embedded-artifactory embedded-azurite - embedded-toxiproxy embedded-mssqlserver embedded-victoriametrics embedded-nats diff --git a/testcontainers-common/pom.xml b/testcontainers-common/pom.xml index 5ce98532b..cb2f679e9 100644 --- a/testcontainers-common/pom.xml +++ b/testcontainers-common/pom.xml @@ -19,6 +19,10 @@ jakarta.validation jakarta.validation-api + + org.slf4j + jcl-over-slf4j + diff --git a/testcontainers-common/src/test/java/com/playtika/testcontainer/common/checks/AbstractCommandWaitStrategyTest.java b/testcontainers-common/src/test/java/com/playtika/testcontainer/common/checks/AbstractCommandWaitStrategyTest.java index d65b210fb..cbd8b2e18 100644 --- a/testcontainers-common/src/test/java/com/playtika/testcontainer/common/checks/AbstractCommandWaitStrategyTest.java +++ b/testcontainers-common/src/test/java/com/playtika/testcontainer/common/checks/AbstractCommandWaitStrategyTest.java @@ -1,6 +1,5 @@ package com.playtika.testcontainer.common.checks; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.GenericContainer; @@ -8,6 +7,8 @@ import java.time.Duration; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + public class AbstractCommandWaitStrategyTest { @Test @@ -17,10 +18,7 @@ public void should_passStartupChecks_andStartContainer() { @Test public void should_failStartupChecks_ifHealthCheckCmdIsFailed() { - Assertions.assertThrows( - ContainerLaunchException.class, - () -> startContainerWithWaitStrategy(new NegativeCommandWaitStrategy()) - ); + assertThatExceptionOfType(ContainerLaunchException.class).isThrownBy(() -> startContainerWithWaitStrategy(new NegativeCommandWaitStrategy())); } private void startContainerWithWaitStrategy(WaitStrategy waitStrategy) { @@ -31,4 +29,4 @@ private void startContainerWithWaitStrategy(WaitStrategy waitStrategy) { .start(); } -} \ No newline at end of file +} diff --git a/testcontainers-common/src/test/java/com/playtika/testcontainer/common/spring/DockerPresenceMarkerTest.java b/testcontainers-common/src/test/java/com/playtika/testcontainer/common/spring/DockerPresenceMarkerTest.java index 0d51aeaf4..beafe2ea4 100644 --- a/testcontainers-common/src/test/java/com/playtika/testcontainer/common/spring/DockerPresenceMarkerTest.java +++ b/testcontainers-common/src/test/java/com/playtika/testcontainer/common/spring/DockerPresenceMarkerTest.java @@ -2,12 +2,12 @@ import org.junit.jupiter.api.Test; -import static org.junit.Assert.assertThrows; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; class DockerPresenceMarkerTest { @Test void markerShouldBlockContextIfDockerIsAbsent() { - assertThrows(DockerNotPresentException.class, () -> new DockerPresenceMarker(false)); + assertThatExceptionOfType(DockerNotPresentException.class).isThrownBy(() -> new DockerPresenceMarker(false)); } -} \ No newline at end of file +} diff --git a/testcontainers-spring-boot-parent/pom.xml b/testcontainers-spring-boot-parent/pom.xml index c0acaa666..73730dfd3 100644 --- a/testcontainers-spring-boot-parent/pom.xml +++ b/testcontainers-spring-boot-parent/pom.xml @@ -15,13 +15,15 @@ Parent pom for all embedded testcontainers - 3.5.7 - 2025.0.0 + 4.0.1 + 2025.1.0 7.4.2 4.3 6.0.2 6.1.0 2.1.11 + 2.0.2 + 5.5.6 @@ -66,6 +68,13 @@ testcontainers-common ${project.version} + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + com.playtika.testcontainers embedded-toxiproxy @@ -81,6 +90,21 @@ toxiproxy-java ${toxiproxy-java.version} + + io.rest-assured + rest-assured + ${rest-assured.version} + + + org.springframework + spring-core + + + commons-logging + commons-logging + + + @@ -135,6 +159,10 @@ org.springframework.boot spring-boot-starter-logging + + commons-logging + commons-logging +