From 69e432fe5cbf2644d110a8e6fb29cea83324c1e9 Mon Sep 17 00:00:00 2001 From: antonioT90 <34568575+antonioT90@users.noreply.github.com> Date: Tue, 31 Oct 2023 17:38:52 +0100 Subject: [PATCH 1/2] IDP-2102 configuring a single mongodb instance for all tests (#222) --- .github/CODEOWNERS | 2 +- .../admissibility/BaseIntegrationTest.java | 6 +- ...eratorOpsRepositoryImplTestIntegrated.java | 7 +- .../kafka/KafkaTestUtilitiesService.java | 2 + .../mongo/EmbeddedMongodbTestClient.java | 5 + .../common/mongo/MongoTestIntegrated.java | 13 +- .../AutoConfigureSingleInstanceMongodb.java | 16 ++ ...ingleEmbeddedMongodbAutoConfiguration.java | 149 ++++++++++++++++++ .../SingleInstanceMongodWrapper.java | 56 +++++++ ...eactiveMongoRepositoryIntegrationTest.java | 7 +- ...ReactiveMongoRepositoryTestIntegrated.java | 7 +- .../EmbeddedMongodbTestReactiveClient.java | 50 ++++++ ...questRateTooLargeRetryIntegrationTest.java | 18 +-- .../EmbeddedRedisTestConfiguration.java | 2 + ...ot.autoconfigure.AutoConfiguration.imports | 1 + ....data.mongo.AutoConfigureDataMongo.imports | 1 + .../mongodbEmbeddedDisabled.properties | 1 - 17 files changed, 312 insertions(+), 31 deletions(-) create mode 100644 src/test/java/it/gov/pagopa/common/mongo/EmbeddedMongodbTestClient.java create mode 100644 src/test/java/it/gov/pagopa/common/mongo/singleinstance/AutoConfigureSingleInstanceMongodb.java create mode 100644 src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleEmbeddedMongodbAutoConfiguration.java create mode 100644 src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleInstanceMongodWrapper.java create mode 100644 src/test/java/it/gov/pagopa/common/reactive/mongo/EmbeddedMongodbTestReactiveClient.java create mode 100644 src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 src/test/resources/META-INF/spring/org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo.imports delete mode 100644 src/test/resources/mongodbEmbeddedDisabled.properties diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 19597baf..3ddc5356 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # see https://help.github.com/en/articles/about-code-owners#example-of-a-codeowners-file -* @pagopa/idpay-app-maintainer-team @dariopelliccioli @antonioT90 @GiovanaSolorzano @pelliccm +* @pagopa/idpay-app-maintainer-team @dariopelliccioli @antonioT90 @frtrinca @Benedetta-fabbri @FrancescoGraziano @stedelia \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/admissibility/BaseIntegrationTest.java b/src/test/java/it/gov/pagopa/admissibility/BaseIntegrationTest.java index 3ca1e67d..c9eebca8 100644 --- a/src/test/java/it/gov/pagopa/admissibility/BaseIntegrationTest.java +++ b/src/test/java/it/gov/pagopa/admissibility/BaseIntegrationTest.java @@ -8,6 +8,7 @@ import it.gov.pagopa.admissibility.model.IseeTypologyEnum; import it.gov.pagopa.common.kafka.KafkaTestUtilitiesService; import it.gov.pagopa.common.mongo.MongoTestUtilitiesService; +import it.gov.pagopa.common.mongo.singleinstance.AutoConfigureSingleInstanceMongodb; import it.gov.pagopa.common.rest.utils.WireMockUtils; import it.gov.pagopa.common.stream.StreamsHealthIndicator; import it.gov.pagopa.common.utils.JUnitExtensionContextHolder; @@ -27,7 +28,6 @@ import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.Status; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContextInitializer; @@ -95,7 +95,7 @@ //region mongodb "logging.level.org.mongodb.driver=WARN", "logging.level.de.flapdoodle.embed.mongo.spring.autoconfigure=WARN", - "de.flapdoodle.mongodb.embedded.version=4.0.21", + "de.flapdoodle.mongodb.embedded.version=4.2.24", //endregion //region pdv @@ -103,7 +103,7 @@ "app.pdv.retry.max-attempts=3", //endregion }) -@AutoConfigureDataMongo +@AutoConfigureSingleInstanceMongodb @AutoConfigureWebTestClient @ContextConfiguration(initializers = {BaseIntegrationTest.WireMockInitializer.class}) public abstract class BaseIntegrationTest { diff --git a/src/test/java/it/gov/pagopa/admissibility/connector/repository/CustomSequenceGeneratorOpsRepositoryImplTestIntegrated.java b/src/test/java/it/gov/pagopa/admissibility/connector/repository/CustomSequenceGeneratorOpsRepositoryImplTestIntegrated.java index 78877aac..bfbccc01 100644 --- a/src/test/java/it/gov/pagopa/admissibility/connector/repository/CustomSequenceGeneratorOpsRepositoryImplTestIntegrated.java +++ b/src/test/java/it/gov/pagopa/admissibility/connector/repository/CustomSequenceGeneratorOpsRepositoryImplTestIntegrated.java @@ -1,14 +1,11 @@ package it.gov.pagopa.admissibility.connector.repository; -import org.springframework.test.context.TestPropertySource; +import it.gov.pagopa.common.mongo.MongoTestIntegrated; /** * See confluence page: Secrets for UnitTests */ @SuppressWarnings({"squid:S3577", "NewClassNamingConvention"}) // suppressing class name not match alert: we are not using the Test suffix in order to let not execute this test by default maven configuration because it depends on properties not pushable. See -@TestPropertySource(locations = { - "classpath:/mongodbEmbeddedDisabled.properties", - "classpath:/secrets/mongodbConnectionString.properties" -}) +@MongoTestIntegrated public class CustomSequenceGeneratorOpsRepositoryImplTestIntegrated extends CustomSequenceGeneratorOpsRepositoryImplTest{ } \ No newline at end of file diff --git a/src/test/java/it/gov/pagopa/common/kafka/KafkaTestUtilitiesService.java b/src/test/java/it/gov/pagopa/common/kafka/KafkaTestUtilitiesService.java index 4742fe7b..4c2c6c6d 100644 --- a/src/test/java/it/gov/pagopa/common/kafka/KafkaTestUtilitiesService.java +++ b/src/test/java/it/gov/pagopa/common/kafka/KafkaTestUtilitiesService.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import it.gov.pagopa.common.kafka.utils.KafkaConstants; +import it.gov.pagopa.common.mongo.singleinstance.AutoConfigureSingleInstanceMongodb; import it.gov.pagopa.common.reactive.kafka.consumer.BaseKafkaConsumer; import it.gov.pagopa.common.utils.MemoryAppender; import it.gov.pagopa.common.utils.TestUtils; @@ -69,6 +70,7 @@ public class KafkaTestUtilitiesService { private ObjectMapper objectMapper; @TestConfiguration + @AutoConfigureSingleInstanceMongodb static class TestKafkaConfiguration { @Bean public KafkaTemplate testPublisher(ProducerFactory producerFactory) { diff --git a/src/test/java/it/gov/pagopa/common/mongo/EmbeddedMongodbTestClient.java b/src/test/java/it/gov/pagopa/common/mongo/EmbeddedMongodbTestClient.java new file mode 100644 index 00000000..42604372 --- /dev/null +++ b/src/test/java/it/gov/pagopa/common/mongo/EmbeddedMongodbTestClient.java @@ -0,0 +1,5 @@ +package it.gov.pagopa.common.mongo; + +public interface EmbeddedMongodbTestClient { + void dropDatabase(); +} diff --git a/src/test/java/it/gov/pagopa/common/mongo/MongoTestIntegrated.java b/src/test/java/it/gov/pagopa/common/mongo/MongoTestIntegrated.java index 1854f530..d4da6ea6 100644 --- a/src/test/java/it/gov/pagopa/common/mongo/MongoTestIntegrated.java +++ b/src/test/java/it/gov/pagopa/common/mongo/MongoTestIntegrated.java @@ -12,9 +12,14 @@ */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) -@TestPropertySource(locations = { - "classpath:/mongodbEmbeddedDisabled.properties", - "classpath:/secrets/mongodbConnectionString.properties" -}) +@TestPropertySource( + properties = { + "spring.autoconfigure.exclude=" + + " de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration," + + " it.gov.pagopa.common.mongo.singleinstance.SingleEmbeddedMongodbAutoConfiguration" + }, + locations = { + "classpath:/secrets/mongodbConnectionString.properties" + }) public @interface MongoTestIntegrated { } diff --git a/src/test/java/it/gov/pagopa/common/mongo/singleinstance/AutoConfigureSingleInstanceMongodb.java b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/AutoConfigureSingleInstanceMongodb.java new file mode 100644 index 00000000..f0d55ae7 --- /dev/null +++ b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/AutoConfigureSingleInstanceMongodb.java @@ -0,0 +1,16 @@ +package it.gov.pagopa.common.mongo.singleinstance; + +import de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo; + +import java.lang.annotation.*; + +/** It will enable the usage of a single instance of {@link EmbeddedMongoAutoConfiguration}, dropping the database at each new Spring Context */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@AutoConfigureDataMongo +@ImportAutoConfiguration(exclude = EmbeddedMongoAutoConfiguration.class) +public @interface AutoConfigureSingleInstanceMongodb { +} diff --git a/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleEmbeddedMongodbAutoConfiguration.java b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleEmbeddedMongodbAutoConfiguration.java new file mode 100644 index 00000000..0253f50f --- /dev/null +++ b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleEmbeddedMongodbAutoConfiguration.java @@ -0,0 +1,149 @@ +package it.gov.pagopa.common.mongo.singleinstance; + +import de.flapdoodle.embed.mongo.commands.MongodArguments; +import de.flapdoodle.embed.mongo.config.Net; +import de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion; +import de.flapdoodle.embed.mongo.spring.autoconfigure.*; +import de.flapdoodle.embed.mongo.transitions.Mongod; +import it.gov.pagopa.common.mongo.EmbeddedMongodbTestClient; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; +import org.springframework.boot.autoconfigure.mongo.MongoProperties; +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.test.context.event.annotation.AfterTestClass; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import java.util.Objects; + +/** + * Used to start just once Mongodb instance for the entire duration of the test, dropping the database at each new Spring Context + */ +@AutoConfiguration( + before = {MongoAutoConfiguration.class, MongoReactiveAutoConfiguration.class, EmbeddedMongoAutoConfiguration.class} +) +public class SingleEmbeddedMongodbAutoConfiguration extends EmbeddedMongoAutoConfiguration { + + private static MongodWrapper singleMongodWrapperInstance; + + private final EmbeddedMongodbTestClient embeddedMongodbTestClient; + + public SingleEmbeddedMongodbAutoConfiguration(EmbeddedMongodbTestClient embeddedMongodbTestClient) { + this.embeddedMongodbTestClient = embeddedMongodbTestClient; + } + + @Bean + @Override + public Net net(ConfigurableApplicationContext context) throws IOException { + if(SingleInstanceMongodWrapper.singleMongodNet!=null){ + ConfigurableEnvironment env = context.getEnvironment(); + env.getPropertySources().addFirst(new MapPropertySource("embeddedMongoReusedProperties", + Map.of("spring.data.mongodb.port", SingleInstanceMongodWrapper.singleMongodNet.getPort()))); + super.net(context); + + return SingleInstanceMongodWrapper.singleMongodNet; + }else { + return SingleInstanceMongodWrapper.singleMongodNet = super.net(context); + } + } + + @AfterTestClass + void clearData(){ + embeddedMongodbTestClient.dropDatabase(); + } + + @ConditionalOnClass(name = { + "com.mongodb.reactivestreams.client.MongoClient", + "org.springframework.data.mongodb.core.ReactiveMongoClientFactoryBean" + }) + static class ReactiveClientServerWrapperConfig { + + private final Constructor unprotectedReactiveClientServerFactoryConstructor; + + ReactiveClientServerWrapperConfig() { + try { + unprotectedReactiveClientServerFactoryConstructor = ReactiveClientServerFactory.class.getDeclaredConstructor(MongoProperties.class); + unprotectedReactiveClientServerFactoryConstructor.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Cannot unprotect AbstractServerFactory constructor", e); + } + } + + @Bean( + initMethod = "start", + destroyMethod = "stop" + ) + @ConditionalOnMissingBean + public MongodWrapper reactiveClientServerWrapper(IFeatureAwareVersion version, MongoProperties properties, Mongod mongod, MongodArguments mongodArguments) { + return Objects.requireNonNullElseGet( + singleMongodWrapperInstance, + () -> createMongodWrapper(unprotectedReactiveClientServerFactoryConstructor, version, properties, mongod, mongodArguments)); + } + + @Bean + @ConditionalOnMissingBean + public EmbeddedMongodbTestClient embeddedMongodbTestClient(Environment env) { + return createEmbeddedMongodbTestClient("it.gov.pagopa.common.reactive.mongo.EmbeddedMongodbTestReactiveClient", env); + } + } + + @ConditionalOnClass(name = { + "com.mongodb.client.MongoClient", + "org.springframework.data.mongodb.core.MongoClientFactoryBean" + }) + static class SyncClientServerWrapperConfig { + + private final Constructor unprotectedSyncClientServerFactoryConstructor; + + SyncClientServerWrapperConfig() { + try { + unprotectedSyncClientServerFactoryConstructor = SyncClientServerFactory.class.getDeclaredConstructor(MongoProperties.class); + unprotectedSyncClientServerFactoryConstructor.setAccessible(true); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Cannot unprotect AbstractServerFactory constructor", e); + } + } + + @Bean( + initMethod = "start", + destroyMethod = "stop" + ) + @ConditionalOnMissingBean + public MongodWrapper syncClientServerWrapper(IFeatureAwareVersion version, MongoProperties properties, Mongod mongod, MongodArguments mongodArguments) { + return Objects.requireNonNullElseGet( + singleMongodWrapperInstance, + () -> createMongodWrapper(unprotectedSyncClientServerFactoryConstructor, version, properties, mongod, mongodArguments)); + } + + @Bean + @ConditionalOnMissingBean + public EmbeddedMongodbTestClient embeddedMongodbTestClient(Environment env) { + return createEmbeddedMongodbTestClient("it.gov.pagopa.common.mongo.EmbeddedMongodbTestSyncClient", env); + } + } + + private static MongodWrapper createMongodWrapper(Constructor> unprotectedSyncClientServerFactoryConstructor, IFeatureAwareVersion version, MongoProperties properties, Mongod mongod, MongodArguments mongodArguments) { + try { + return singleMongodWrapperInstance = new SingleInstanceMongodWrapper(unprotectedSyncClientServerFactoryConstructor.newInstance(properties).createWrapper(version, mongod, mongodArguments)); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Cannot call protected constructor", e); + } + } + + private static EmbeddedMongodbTestClient createEmbeddedMongodbTestClient(String embeddedMongodbTestClientClassName, Environment env) { + try { + return (EmbeddedMongodbTestClient) Class.forName(embeddedMongodbTestClientClassName).getConstructor(Environment.class).newInstance(env); + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | InvocationTargetException | NoSuchMethodException e) { + throw new IllegalStateException("Cannot create EmbeddedMongodbTestClient", e); + } + } +} diff --git a/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleInstanceMongodWrapper.java b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleInstanceMongodWrapper.java new file mode 100644 index 00000000..55c2ed0d --- /dev/null +++ b/src/test/java/it/gov/pagopa/common/mongo/singleinstance/SingleInstanceMongodWrapper.java @@ -0,0 +1,56 @@ +package it.gov.pagopa.common.mongo.singleinstance; + +import de.flapdoodle.embed.mongo.config.Net; +import de.flapdoodle.embed.mongo.spring.autoconfigure.MongodWrapper; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +public class SingleInstanceMongodWrapper extends MongodWrapper { + + private final Runnable unprotectedStart; + private final Runnable unprotectedStop; + + private final AtomicInteger counter = new AtomicInteger(0); + public static Net singleMongodNet; + + public SingleInstanceMongodWrapper(MongodWrapper mongodWrapper) { + super(null); + + unprotectedStart = unprotectMongodWrapperMethod("start", mongodWrapper); + unprotectedStop = unprotectMongodWrapperMethod("stop", mongodWrapper); + } + + private Runnable unprotectMongodWrapperMethod(String methodName, MongodWrapper mongodWrapper) { + try { + Method method = MongodWrapper.class.getDeclaredMethod(methodName); + method.setAccessible(true); + return () -> { + try { + method.invoke(mongodWrapper); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Cannot invoke protected %s mongodWrapper method".formatted(methodName), e); + } + }; + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Cannot unprotect mongodWrapper methods", e); + } + } + + @SuppressWarnings("unused") // called by Spring + private void start() { + synchronized (counter) { + if (counter.getAndIncrement() == 0) { + unprotectedStart.run(); + } + } + } + + @SuppressWarnings("unused") // called by Spring + private void stop() { + if (counter.decrementAndGet() == 0) { + unprotectedStop.run(); + } + } +} diff --git a/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryIntegrationTest.java b/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryIntegrationTest.java index 49f68059..f85adc2a 100644 --- a/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryIntegrationTest.java +++ b/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryIntegrationTest.java @@ -6,6 +6,7 @@ import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import it.gov.pagopa.common.mongo.MongoTestUtilitiesService; import it.gov.pagopa.common.mongo.config.MongoConfig; +import it.gov.pagopa.common.mongo.singleinstance.AutoConfigureSingleInstanceMongodb; import it.gov.pagopa.common.reactive.mongo.config.ReactiveMongoConfig; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -15,7 +16,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.mongo.MongoClientSettingsBuilderCustomizer; -import org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; @@ -25,7 +25,7 @@ import java.util.Map; @TestPropertySource(properties = { - "de.flapdoodle.mongodb.embedded.version=4.0.21", + "de.flapdoodle.mongodb.embedded.version=4.2.24", "spring.data.mongodb.database=idpay", "spring.data.mongodb.config.connectionPool.maxSize: 100", @@ -36,7 +36,7 @@ "spring.data.mongodb.config.connectionPool.maxConnecting: 2", }) @ExtendWith(SpringExtension.class) -@AutoConfigureDataMongo +@AutoConfigureSingleInstanceMongodb @ContextConfiguration(classes = {BaseReactiveMongoRepositoryIntegrationTest.TestMongoRepositoryConfig.class, ReactiveMongoConfig.class, MongoTestUtilitiesService.TestMongoConfiguration.class, SimpleMeterRegistry.class}) class BaseReactiveMongoRepositoryIntegrationTest { @@ -45,6 +45,7 @@ class BaseReactiveMongoRepositoryIntegrationTest { } @TestConfiguration + @AutoConfigureSingleInstanceMongodb static class TestMongoRepositoryConfig extends MongoConfig { @Autowired private MongoMetricsCommandListener mongoMetricsCommandListener; diff --git a/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryTestIntegrated.java b/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryTestIntegrated.java index 81186cb4..1fb48701 100644 --- a/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryTestIntegrated.java +++ b/src/test/java/it/gov/pagopa/common/reactive/mongo/BaseReactiveMongoRepositoryTestIntegrated.java @@ -1,19 +1,16 @@ package it.gov.pagopa.common.reactive.mongo; +import it.gov.pagopa.common.mongo.MongoTestIntegrated; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.ReactiveMongoTemplate; -import org.springframework.test.context.TestPropertySource; /** * See confluence page: Secrets for UnitTests */ @SuppressWarnings({"squid:S3577", "NewClassNamingConvention"}) // suppressing class name not match alert: we are not using the Test suffix in order to let not execute this test by default maven configuration because it depends on properties not pushable. See -@TestPropertySource(locations = { - "classpath:/mongodbEmbeddedDisabled.properties", - "classpath:/secrets/mongodbConnectionString.properties" -}) +@MongoTestIntegrated class BaseReactiveMongoRepositoryTestIntegrated extends BaseReactiveMongoRepositoryIntegrationTest { @Autowired diff --git a/src/test/java/it/gov/pagopa/common/reactive/mongo/EmbeddedMongodbTestReactiveClient.java b/src/test/java/it/gov/pagopa/common/reactive/mongo/EmbeddedMongodbTestReactiveClient.java new file mode 100644 index 00000000..d2bc1c9a --- /dev/null +++ b/src/test/java/it/gov/pagopa/common/reactive/mongo/EmbeddedMongodbTestReactiveClient.java @@ -0,0 +1,50 @@ +package it.gov.pagopa.common.reactive.mongo; + +import com.mongodb.reactivestreams.client.MongoClient; +import com.mongodb.reactivestreams.client.MongoClients; +import it.gov.pagopa.common.mongo.EmbeddedMongodbTestClient; +import it.gov.pagopa.common.mongo.singleinstance.SingleInstanceMongodWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; +import reactor.core.publisher.BaseSubscriber; + +import java.util.Objects; + +@Slf4j +@Service +public class EmbeddedMongodbTestReactiveClient implements EmbeddedMongodbTestClient { + + private final String dbName; + + public EmbeddedMongodbTestReactiveClient(Environment env) { + this.dbName = Objects.requireNonNull(env.getProperty("spring.data.mongodb.database")); + } + + @Override + public void dropDatabase() { + String mongodbUrl = getEmbeddedMongdbUrl(); + + try(MongoClient mongoClient = MongoClients.create(mongodbUrl)){ + mongoClient.getDatabase(dbName).drop().subscribe(new BaseSubscriber<>() { + @Override + protected void hookOnComplete() { + log.info("Database {} dropped", dbName); + synchronized (mongoClient){ + mongoClient.notify(); + } + } + }); + synchronized (mongoClient){ + mongoClient.wait(1000); + } + } catch (InterruptedException e) { + throw new IllegalStateException("Cannot drop database", e); + } + } + + private static String getEmbeddedMongdbUrl() { + int dbPort = Objects.requireNonNull(SingleInstanceMongodWrapper.singleMongodNet).getPort(); + return "mongodb://localhost:" + dbPort; + } +} diff --git a/src/test/java/it/gov/pagopa/common/reactive/mongo/retry/MongoRequestRateTooLargeRetryIntegrationTest.java b/src/test/java/it/gov/pagopa/common/reactive/mongo/retry/MongoRequestRateTooLargeRetryIntegrationTest.java index c294ba09..9b55b8e8 100644 --- a/src/test/java/it/gov/pagopa/common/reactive/mongo/retry/MongoRequestRateTooLargeRetryIntegrationTest.java +++ b/src/test/java/it/gov/pagopa/common/reactive/mongo/retry/MongoRequestRateTooLargeRetryIntegrationTest.java @@ -1,6 +1,7 @@ package it.gov.pagopa.common.reactive.mongo.retry; import it.gov.pagopa.common.mongo.config.MongoConfig; +import it.gov.pagopa.common.mongo.singleinstance.AutoConfigureSingleInstanceMongodb; import it.gov.pagopa.common.reactive.mongo.DummySpringRepository; import it.gov.pagopa.common.reactive.mongo.config.ReactiveMongoConfig; import it.gov.pagopa.common.reactive.mongo.retry.exception.MongoRequestRateTooLargeRetryExpiredException; @@ -12,19 +13,15 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mockito; 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.autoconfigure.data.mongo.AutoConfigureDataMongo; import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -36,9 +33,14 @@ @TestPropertySource( properties = { - "de.flapdoodle.mongodb.embedded.version=4.0.21", + "mongo.request-rate-too-large.api.enabled: false", + "mongo.request-rate-too-large.batch.enabled: true", + "mongo.request-rate-too-large.batch.max-retry: 3", + "mongo.request-rate-too-large.batch.max-millis-elapsed: 0", - "spring.data.mongodb.database=idpay", + "de.flapdoodle.mongodb.embedded.version: 4.2.24", + + "spring.data.mongodb.database: idpay", "spring.data.mongodb.config.connectionPool.maxSize: 100", "spring.data.mongodb.config.connectionPool.minSize: 0", "spring.data.mongodb.config.connectionPool.maxWaitTimeMS: 120000", @@ -46,7 +48,6 @@ "spring.data.mongodb.config.connectionPool.maxConnectionIdleTimeMS: 120000", "spring.data.mongodb.config.connectionPool.maxConnecting: 2", }) -@ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { ReactiveRequestContextFilter.class, MongoRequestRateTooLargeAutomaticRetryAspect.class, @@ -58,9 +59,8 @@ MongoRequestRateTooLargeRetryIntegrationTest.TestController.class, MongoRequestRateTooLargeRetryIntegrationTest.TestRepository.class }) +@AutoConfigureSingleInstanceMongodb @WebFluxTest -@AutoConfigureDataMongo -@EnableAutoConfiguration class MongoRequestRateTooLargeRetryIntegrationTest { @Value("${mongo.request-rate-too-large.batch.max-retry:3}") diff --git a/src/test/java/it/gov/pagopa/common/redis/config/EmbeddedRedisTestConfiguration.java b/src/test/java/it/gov/pagopa/common/redis/config/EmbeddedRedisTestConfiguration.java index fe0738ff..65a3e848 100644 --- a/src/test/java/it/gov/pagopa/common/redis/config/EmbeddedRedisTestConfiguration.java +++ b/src/test/java/it/gov/pagopa/common/redis/config/EmbeddedRedisTestConfiguration.java @@ -1,5 +1,6 @@ package it.gov.pagopa.common.redis.config; +import it.gov.pagopa.common.mongo.singleinstance.AutoConfigureSingleInstanceMongodb; import it.gov.pagopa.common.utils.TestUtils; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; @@ -8,6 +9,7 @@ import redis.embedded.RedisServer; @TestConfiguration +@AutoConfigureSingleInstanceMongodb public class EmbeddedRedisTestConfiguration { private final RedisServer redisServer; diff --git a/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000..5757108f --- /dev/null +++ b/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +it.gov.pagopa.common.mongo.singleinstance.SingleEmbeddedMongodbAutoConfiguration \ No newline at end of file diff --git a/src/test/resources/META-INF/spring/org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo.imports b/src/test/resources/META-INF/spring/org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo.imports new file mode 100644 index 00000000..5757108f --- /dev/null +++ b/src/test/resources/META-INF/spring/org.springframework.boot.test.autoconfigure.data.mongo.AutoConfigureDataMongo.imports @@ -0,0 +1 @@ +it.gov.pagopa.common.mongo.singleinstance.SingleEmbeddedMongodbAutoConfiguration \ No newline at end of file diff --git a/src/test/resources/mongodbEmbeddedDisabled.properties b/src/test/resources/mongodbEmbeddedDisabled.properties deleted file mode 100644 index 47a498e1..00000000 --- a/src/test/resources/mongodbEmbeddedDisabled.properties +++ /dev/null @@ -1 +0,0 @@ -spring.autoconfigure.exclude=de.flapdoodle.embed.mongo.spring.autoconfigure.EmbeddedMongoAutoConfiguration \ No newline at end of file From b7837890d12609b22f469752d7362ee641cd9407 Mon Sep 17 00:00:00 2001 From: antonioT90 <34568575+antonioT90@users.noreply.github.com> Date: Tue, 7 Nov 2023 12:02:32 +0100 Subject: [PATCH 2/2] chore: IDP-2115 fix CVE-2023-44487 on application-insight (#223) --- Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index ff038b9a..da26a300 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # # Build # -FROM maven:3.9.5-amazoncorretto-17-al2023@sha256:b7f94a5f1b6582a045692e31c2c97ef6f0ed867961669a0adbc2d5f0bbf8bc85 AS buildtime +FROM maven:3.9.5-amazoncorretto-17-al2023@sha256:eeaa7ab572d931f7273fc5cf31429923f172091ae388969e11f42ec6dd817d74 AS buildtime WORKDIR /build COPY . . @@ -13,7 +13,7 @@ RUN mvn clean package -DskipTests # FROM amazoncorretto:17.0.9-alpine3.18@sha256:df48bf2e183230040890460ddb4359a10aa6c7aad24bd88899482c52053c7e17 AS runtime -RUN apk add shadow +RUN apk --no-cache add shadow RUN useradd --uid 10000 runner VOLUME /tmp @@ -21,7 +21,7 @@ WORKDIR /app COPY --from=buildtime /build/target/*.jar /app/app.jar # The agent is enabled at runtime via JAVA_TOOL_OPTIONS. -ADD https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.4.17/applicationinsights-agent-3.4.17.jar /app/applicationinsights-agent.jar +ADD https://github.com/microsoft/ApplicationInsights-Java/releases/download/3.4.18/applicationinsights-agent-3.4.18.jar /app/applicationinsights-agent.jar RUN chown -R runner:runner /app