diff --git a/embedded-artifactory/README.adoc b/embedded-artifactory/README.adoc index 82199d363..78effeab6 100644 --- a/embedded-artifactory/README.adoc +++ b/embedded-artifactory/README.adoc @@ -16,13 +16,32 @@ * `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.98.9')` ** 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.toxiproxy.proxies.artifactory.enabled` Enables both creation of the container with ToxiProxy TCP proxy and a proxy to the `embedded-artifactory` container. +==== PostgreSQL backing store + +Artifactory uses PostgreSQL as its backing database, provided by the `embedded-postgresql` module. +Configure the database via `embedded.postgresql.*` properties: + +* `embedded.postgresql.user` `(default is 'postgresql')` +* `embedded.postgresql.password` `(default is 'letmein')` +* `embedded.postgresql.database` `(default is 'test_db')` +* `embedded.postgresql.networkAlias` `(default is 'postgresql.testcontainer.docker')` +* `embedded.postgresql.dockerImage` `(default is 'postgres:18-alpine')` + +Example override in `bootstrap.properties`: +[source,properties] +---- +embedded.postgresql.user=artifactory +embedded.postgresql.password=artifactory +embedded.postgresql.database=artifactory +---- + ==== Produces * `embedded.artifactory.host` diff --git a/embedded-artifactory/pom.xml b/embedded-artifactory/pom.xml index 34832c79c..70468786d 100644 --- a/embedded-artifactory/pom.xml +++ b/embedded-artifactory/pom.xml @@ -23,6 +23,10 @@ com.playtika.testcontainers embedded-toxiproxy + + com.playtika.testcontainers + embedded-postgresql + io.rest-assured @@ -41,4 +45,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..b750bc02d 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 @@ -20,13 +20,13 @@ public class ArtifactoryProperties extends CommonContainerProperties { int generalPort = 8082; 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.98.9"; } } 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 bf93fa58c..b61ab4fca 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,11 +2,14 @@ import com.playtika.testcontainer.common.spring.DockerPresenceBootstrapConfiguration; import com.playtika.testcontainer.common.utils.ContainerUtils; +import com.playtika.testcontainer.postgresql.EmbeddedPostgreSQLBootstrapConfiguration; +import com.playtika.testcontainer.postgresql.PostgreSQLProperties; 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.jspecify.annotations.NonNull; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; @@ -21,24 +24,35 @@ import org.testcontainers.containers.Network; 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.nio.charset.StandardCharsets; import java.util.LinkedHashMap; -import java.util.Optional; import static com.playtika.testcontainer.artifactory.ArtifactoryProperties.ARTIFACTORY_BEAN_NAME; import static com.playtika.testcontainer.common.utils.ContainerUtils.configureCommonsAndStart; +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"; + @Bean + @ConditionalOnMissingBean(Network.class) + Network artifactoryNetwork() { + Network network = Network.newNetwork(); + log.info("Created docker Network with id={}", network.getId()); + return network; + } + @Bean @ConditionalOnMissingBean(name = "artifactoryWaitStrategy") public WaitStrategy artifactoryWaitStrategy(ArtifactoryProperties properties) { @@ -70,17 +84,23 @@ ToxiproxyClientProxy artifactoryContainerProxy(ToxiproxyClient toxiproxyClient, @Bean(name = ARTIFACTORY_BEAN_NAME, destroyMethod = "stop") public GenericContainer artifactory(ConfigurableEnvironment environment, ArtifactoryProperties properties, + PostgreSQLContainer postgreSQLContainer, + PostgreSQLProperties postgresqlProperties, WaitStrategy artifactoryWaitStrategy, - Optional network) { + Network network) { + + String systemYaml = getSystemYaml(postgresqlProperties, postgreSQLContainer); 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") .waitingFor(artifactoryWaitStrategy); - network.ifPresent(container::withNetwork); configureCommonsAndStart(container, properties, log); registerEnvironment(container, environment, properties); @@ -88,6 +108,22 @@ public GenericContainer artifactory(ConfigurableEnvironment environment, return container; } + static @NonNull String getSystemYaml(PostgreSQLProperties postgresqlProperties, + PostgreSQLContainer postgreSQLContainer) { + String jdbcUrl = "jdbc:postgresql://%s:%d/%s" + .formatted(postgresqlProperties.getNetworkAlias(), POSTGRESQL_PORT, postgresqlProperties.getDatabase()); + + return """ + shared: + database: + type: "postgresql" + driver: "org.postgresql.Driver" + url: "%s" + username: "%s" + password: "%s" + """.formatted(jdbcUrl, postgreSQLContainer.getUsername(), postgreSQLContainer.getPassword()); + } + private void registerEnvironment(GenericContainer artifactory, ConfigurableEnvironment environment, ArtifactoryProperties properties) { diff --git a/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationSystemYamlTest.java b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationSystemYamlTest.java new file mode 100644 index 000000000..3a2ae6ac1 --- /dev/null +++ b/embedded-artifactory/src/test/java/com/playtika/testcontainer/artifactory/EmbeddedArtifactoryBootstrapConfigurationSystemYamlTest.java @@ -0,0 +1,31 @@ +package com.playtika.testcontainer.artifactory; + +import com.playtika.testcontainer.postgresql.PostgreSQLProperties; +import org.junit.jupiter.api.Test; +import org.testcontainers.postgresql.PostgreSQLContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +class EmbeddedArtifactoryBootstrapConfigurationSystemYamlTest { + + @Test + void shouldUseConfiguredPostgresqlNetworkAliasInSystemYaml() { + PostgreSQLProperties postgresqlProperties = new PostgreSQLProperties(); + postgresqlProperties.setDatabase("artifactory"); + postgresqlProperties.setNetworkAlias("postgresql.internal"); + + PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:18-alpine") + .withNetworkAliases("postgresql.internal") + .withUsername("artifactory") + .withPassword("secret"); + + String systemYaml = EmbeddedArtifactoryBootstrapConfiguration.getSystemYaml( + postgresqlProperties, + postgreSQLContainer); + + assertThat(systemYaml) + .contains("url: \"jdbc:postgresql://postgresql.internal:5432/artifactory\"") + .contains("username: \"artifactory\"") + .contains("password: \"secret\""); + } +} diff --git a/embedded-artifactory/src/test/resources/bootstrap.properties b/embedded-artifactory/src/test/resources/bootstrap.properties new file mode 100644 index 000000000..3f07a7265 --- /dev/null +++ b/embedded-artifactory/src/test/resources/bootstrap.properties @@ -0,0 +1,3 @@ +embedded.postgresql.user=artifactory +embedded.postgresql.password=artifactory +embedded.postgresql.database=artifactory diff --git a/embedded-postgresql/README.adoc b/embedded-postgresql/README.adoc index 35b9ccf6c..1d5f19d88 100644 --- a/embedded-postgresql/README.adoc +++ b/embedded-postgresql/README.adoc @@ -22,6 +22,7 @@ * `embedded.postgresql.database` * `embedded.postgresql.user` * `embedded.postgresql.password` +* `embedded.postgresql.networkAlias` `(default is 'postgresql.testcontainer.docker')` * `embedded.postgresql.initScriptPath` `(default is null)` * `embedded.postgresql.startupLogCheckRegex` `(default is null)` * `embedded.postgresql.mountVolumes` `(default is empty list)` 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 c54728895..5b9d7eef5 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 @@ -18,9 +18,9 @@ import org.springframework.core.env.MapPropertySource; import org.springframework.util.StringUtils; import org.testcontainers.containers.Network; -import org.testcontainers.containers.PostgreSQLContainer; 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.LinkedHashMap; @@ -37,8 +37,6 @@ @EnableConfigurationProperties(PostgreSQLProperties.class) public class EmbeddedPostgreSQLBootstrapConfiguration { - private static final String POSTGRESQL_NETWORK_ALIAS = "postgresql.testcontainer.docker"; - @Bean @ConditionalOnToxiProxyEnabled(module = "postgresql") ToxiproxyClientProxy postgresqlContainerProxy(ToxiproxyClient toxiproxyClient, @@ -63,12 +61,12 @@ public PostgreSQLContainer postgresql(ConfigurableEnvironment environment, Optional network) { PostgreSQLContainer postgresql = - new PostgreSQLContainer<>(ContainerUtils.getDockerImageName(properties)) + new PostgreSQLContainer(ContainerUtils.getDockerImageName(properties)) .withUsername(properties.getUser()) .withPassword(properties.getPassword()) .withDatabaseName(properties.getDatabase()) .withInitScript(properties.initScriptPath) - .withNetworkAliases(POSTGRESQL_NETWORK_ALIAS); + .withNetworkAliases(properties.getNetworkAlias()); network.ifPresent(postgresql::withNetwork); @@ -96,7 +94,7 @@ private void registerPostgresqlEnvironment(PostgreSQLContainer postgresql, map.put("embedded.postgresql.schema", properties.getDatabase()); map.put("embedded.postgresql.user", properties.getUser()); map.put("embedded.postgresql.password", properties.getPassword()); - map.put("embedded.postgresql.networkAlias", POSTGRESQL_NETWORK_ALIAS); + map.put("embedded.postgresql.networkAlias", properties.getNetworkAlias()); map.put("embedded.postgresql.internalPort", PostgreSQLContainer.POSTGRESQL_PORT); String jdbcURL = "jdbc:postgresql://{}:{}/{}"; diff --git a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/PostgreSQLProperties.java b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/PostgreSQLProperties.java index 951bfcc06..e6436b75f 100644 --- a/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/PostgreSQLProperties.java +++ b/embedded-postgresql/src/main/java/com/playtika/testcontainer/postgresql/PostgreSQLProperties.java @@ -10,10 +10,12 @@ @ConfigurationProperties("embedded.postgresql") public class PostgreSQLProperties extends CommonContainerProperties { static final String BEAN_NAME_EMBEDDED_POSTGRESQL = "embeddedPostgreSql"; + static final String DEFAULT_NETWORK_ALIAS = "postgresql.testcontainer.docker"; String user = "postgresql"; String password = "letmein"; String database = "test_db"; + String networkAlias = DEFAULT_NETWORK_ALIAS; String startupLogCheckRegex; /** * The SQL file path to execute after the container starts to initialize the database. diff --git a/embedded-postgresql/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/embedded-postgresql/src/main/resources/META-INF/additional-spring-configuration-metadata.json index dd067aaad..bfe1af239 100644 --- a/embedded-postgresql/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/embedded-postgresql/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -17,6 +17,11 @@ "type": "java.lang.String", "defaultValue": "null", "description": "The SQL file path to execute after the container starts to initialize the database." + }, + { + "name": "embedded.postgresql.network-alias", + "type": "java.lang.String", + "defaultValue": "postgresql.testcontainer.docker" } ], "hints": [ diff --git a/testcontainers-spring-boot-parent/pom.xml b/testcontainers-spring-boot-parent/pom.xml index a622ab945..14181b76e 100644 --- a/testcontainers-spring-boot-parent/pom.xml +++ b/testcontainers-spring-boot-parent/pom.xml @@ -80,6 +80,11 @@ embedded-toxiproxy ${project.version} + + com.playtika.testcontainers + embedded-postgresql + ${project.version} + com.playtika.testcontainers embedded-aerospike