mirror of
https://github.com/valitydev/testcontainers-annotations.git
synced 2024-11-06 08:55:19 +00:00
add @CephTestcontainer (#8)
This commit is contained in:
parent
52005f6c32
commit
84f5ed2789
4
pom.xml
4
pom.xml
@ -12,7 +12,7 @@
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<artifactId>testcontainers-annotations</artifactId>
|
||||
<version>1.0.4</version>
|
||||
<version>1.0.5</version>
|
||||
<url>https://github.com/rbkmoney/testcontainers-annotations</url>
|
||||
|
||||
<licenses>
|
||||
@ -36,7 +36,7 @@
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<kafka-common-lib.version>0.1.8</kafka-common-lib.version>
|
||||
<kafka-common-lib.version>0.1.9</kafka-common-lib.version>
|
||||
<woody.version>[1.1.22,)</woody.version>
|
||||
<spring-boot.version>2.5.0</spring-boot.version>
|
||||
<lombok.version>1.18.16</lombok.version>
|
||||
|
@ -0,0 +1,28 @@
|
||||
package com.rbkmoney.testcontainers.annotations.ceph;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExtendWith(CephTestcontainerExtension.class)
|
||||
public @interface CephTestcontainer {
|
||||
|
||||
/**
|
||||
* properties = {"postgresql.make.happy=true",...}
|
||||
*/
|
||||
String[] properties() default {};
|
||||
|
||||
String signingRegion() default "RU";
|
||||
|
||||
String clientProtocol() default "HTTP";
|
||||
|
||||
String clientMaxErrorRetry() default "10";
|
||||
|
||||
String bucketName() default "TEST";
|
||||
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package com.rbkmoney.testcontainers.annotations.ceph;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.var;
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
|
||||
import org.junit.platform.commons.support.AnnotationSupport;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.ContextCustomizerFactory;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.rbkmoney.testcontainers.annotations.ceph.CephTestcontainerFactory.ACCESS_KEY;
|
||||
import static com.rbkmoney.testcontainers.annotations.ceph.CephTestcontainerFactory.SECRET_KEY;
|
||||
import static com.rbkmoney.testcontainers.annotations.util.GenericContainerUtil.startContainer;
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadDefaultLibraryProperty;
|
||||
|
||||
@Slf4j
|
||||
public class CephTestcontainerExtension
|
||||
implements TestInstancePostProcessor, BeforeAllCallback, AfterAllCallback {
|
||||
|
||||
private static final ThreadLocal<GenericContainer<?>> THREAD_CONTAINER = new ThreadLocal<>();
|
||||
|
||||
@Override
|
||||
public void postProcessTestInstance(Object testInstance, ExtensionContext context) {
|
||||
var annotation = findCephTestcontainerSingletonAnnotation(context);
|
||||
if (!annotation.isPresent()) {
|
||||
return;
|
||||
}
|
||||
var container = CephTestcontainerFactory.singletonContainer();
|
||||
if (!container.isRunning()) {
|
||||
startContainer(container);
|
||||
}
|
||||
THREAD_CONTAINER.set(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
var annotation = findCephTestcontainerAnnotation(context);
|
||||
if (!annotation.isPresent()) {
|
||||
return;
|
||||
}
|
||||
var container = CephTestcontainerFactory.container();
|
||||
if (!container.isRunning()) {
|
||||
startContainer(container);
|
||||
}
|
||||
THREAD_CONTAINER.set(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) {
|
||||
if (findCephTestcontainerAnnotation(context).isPresent()) {
|
||||
var container = THREAD_CONTAINER.get();
|
||||
if (container != null && container.isRunning()) {
|
||||
container.stop();
|
||||
}
|
||||
THREAD_CONTAINER.remove();
|
||||
} else if (findCephTestcontainerSingletonAnnotation(context).isPresent()) {
|
||||
THREAD_CONTAINER.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<CephTestcontainer> findCephTestcontainerAnnotation(ExtensionContext context) {
|
||||
return AnnotationSupport.findAnnotation(context.getElement(), CephTestcontainer.class);
|
||||
}
|
||||
|
||||
private static Optional<CephTestcontainer> findCephTestcontainerAnnotation(Class<?> testClass) {
|
||||
return AnnotationSupport.findAnnotation(testClass, CephTestcontainer.class);
|
||||
}
|
||||
|
||||
private static Optional<CephTestcontainerSingleton> findCephTestcontainerSingletonAnnotation(
|
||||
ExtensionContext context) {
|
||||
return AnnotationSupport.findAnnotation(context.getElement(), CephTestcontainerSingleton.class);
|
||||
}
|
||||
|
||||
private static Optional<CephTestcontainerSingleton> findCephTestcontainerSingletonAnnotation(
|
||||
Class<?> testClass) {
|
||||
return AnnotationSupport.findAnnotation(testClass, CephTestcontainerSingleton.class);
|
||||
}
|
||||
|
||||
public static class CephTestcontainerContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
@Override
|
||||
public ContextCustomizer createContextCustomizer(
|
||||
Class<?> testClass,
|
||||
List<ContextConfigurationAttributes> configAttributes) {
|
||||
return (context, mergedConfig) -> {
|
||||
var cephTestcontainerAnnotation = findCephTestcontainerAnnotation(testClass);
|
||||
if (cephTestcontainerAnnotation.isPresent()) {
|
||||
var annotation = cephTestcontainerAnnotation.get();
|
||||
init(
|
||||
context,
|
||||
annotation.signingRegion(),
|
||||
annotation.clientProtocol(),
|
||||
annotation.clientMaxErrorRetry(),
|
||||
annotation.bucketName(),
|
||||
annotation.properties());
|
||||
} else {
|
||||
findCephTestcontainerSingletonAnnotation(testClass).ifPresent(
|
||||
annotation -> init(
|
||||
context,
|
||||
annotation.signingRegion(),
|
||||
annotation.clientProtocol(),
|
||||
annotation.clientMaxErrorRetry(),
|
||||
annotation.bucketName(),
|
||||
annotation.properties()));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void init(
|
||||
ConfigurableApplicationContext context,
|
||||
String signingRegion,
|
||||
String clientProtocol,
|
||||
String clientMaxErrorRetry,
|
||||
String bucketName,
|
||||
String[] properties) {
|
||||
var container = THREAD_CONTAINER.get();
|
||||
TestPropertyValues.of(
|
||||
"storage.endpoint=" + container.getContainerIpAddress() + ":"
|
||||
+ container.getMappedPort(8080),
|
||||
"storage.signingRegion=" + signingRegion,
|
||||
"storage.accessKey=" + loadDefaultLibraryProperty(ACCESS_KEY),
|
||||
"storage.secretKey=" + loadDefaultLibraryProperty(SECRET_KEY),
|
||||
"storage.clientProtocol=" + clientProtocol,
|
||||
"storage.clientMaxErrorRetry=" + clientMaxErrorRetry,
|
||||
"storage.bucketName=" + bucketName)
|
||||
.and(properties)
|
||||
.applyTo(context);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package com.rbkmoney.testcontainers.annotations.ceph;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Synchronized;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
|
||||
import org.testcontainers.containers.wait.strategy.WaitStrategy;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadDefaultLibraryProperty;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class CephTestcontainerFactory {
|
||||
|
||||
public static final String ACCESS_KEY = "testcontainers.ceph.accessKey";
|
||||
public static final String SECRET_KEY = "testcontainers.ceph.secretKey";
|
||||
private static final String CEPH_DAEMON_IMAGE_NAME = "ceph/daemon";
|
||||
private static final String TAG_PROPERTY = "testcontainers.ceph.tag";
|
||||
|
||||
private GenericContainer<?> cephDaemonContainer;
|
||||
|
||||
public static GenericContainer<?> container() {
|
||||
return instance().create();
|
||||
}
|
||||
|
||||
public static GenericContainer<?> singletonContainer() {
|
||||
return instance().getOrCreateSingletonContainer();
|
||||
}
|
||||
|
||||
private static CephTestcontainerFactory instance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private GenericContainer<?> getOrCreateSingletonContainer() {
|
||||
if (cephDaemonContainer != null) {
|
||||
return cephDaemonContainer;
|
||||
}
|
||||
cephDaemonContainer = create();
|
||||
return cephDaemonContainer;
|
||||
}
|
||||
|
||||
private GenericContainer<?> create() {
|
||||
try (GenericContainer<?> container = new GenericContainer<>(
|
||||
DockerImageName
|
||||
.parse(CEPH_DAEMON_IMAGE_NAME)
|
||||
.withTag(loadDefaultLibraryProperty(TAG_PROPERTY)))
|
||||
.withNetworkAliases("ceph-daemon")
|
||||
.withEnv("RGW_NAME", "localhost")
|
||||
.withEnv("NETWORK_AUTO_DETECT", "4")
|
||||
.withEnv("CEPH_DAEMON", "demo")
|
||||
.withEnv("CEPH_DEMO_UID", "ceph-test")
|
||||
.withEnv("CEPH_DEMO_ACCESS_KEY", loadDefaultLibraryProperty(ACCESS_KEY))
|
||||
.withEnv("CEPH_DEMO_SECRET_KEY", loadDefaultLibraryProperty(SECRET_KEY))
|
||||
.withEnv("CEPH_DEMO_BUCKET", "TEST")
|
||||
.waitingFor(cephHealthCheck())) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
private WaitStrategy cephHealthCheck() {
|
||||
return getWaitStrategy("/api/v0.1/health", 200, 5000, Duration.ofMinutes(1));
|
||||
}
|
||||
|
||||
private static WaitStrategy getWaitStrategy(String path, Integer statusCode, Integer port, Duration duration) {
|
||||
return new HttpWaitStrategy()
|
||||
.forPath(path)
|
||||
.forPort(port)
|
||||
.forStatusCode(statusCode)
|
||||
.withStartupTimeout(duration);
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
|
||||
private static final CephTestcontainerFactory INSTANCE = new CephTestcontainerFactory();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.rbkmoney.testcontainers.annotations.ceph;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ExtendWith(CephTestcontainerExtension.class)
|
||||
@Transactional
|
||||
public @interface CephTestcontainerSingleton {
|
||||
|
||||
/**
|
||||
* properties = {"postgresql.make.happy=true",...}
|
||||
*/
|
||||
String[] properties() default {};
|
||||
|
||||
String signingRegion() default "RU";
|
||||
|
||||
String clientProtocol() default "HTTP";
|
||||
|
||||
String clientMaxErrorRetry() default "10";
|
||||
|
||||
String bucketName() default "TEST";
|
||||
|
||||
}
|
@ -7,7 +7,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.testcontainers.containers.ClickHouseContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadTagFromSpringApplicationPropertiesFile;
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadDefaultLibraryProperty;
|
||||
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@ -43,7 +43,8 @@ public class ClickhouseTestcontainerFactory {
|
||||
try (ClickHouseContainer container = new ClickHouseContainer(
|
||||
DockerImageName
|
||||
.parse(CLICKHOUSE_IMAGE_NAME)
|
||||
.withTag(loadTagFromSpringApplicationPropertiesFile(TAG_PROPERTY)))) {
|
||||
.withTag(loadDefaultLibraryProperty(TAG_PROPERTY)))) {
|
||||
container.withNetworkAliases("clickhouse-server");
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.testcontainers.containers.KafkaContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadTagFromSpringApplicationPropertiesFile;
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadDefaultLibraryProperty;
|
||||
|
||||
@Slf4j
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@ -43,8 +43,9 @@ public class KafkaTestcontainerFactory {
|
||||
try (KafkaContainer container = new KafkaContainer(
|
||||
DockerImageName
|
||||
.parse(KAFKA_IMAGE_NAME)
|
||||
.withTag(loadTagFromSpringApplicationPropertiesFile(TAG_PROPERTY)))
|
||||
.withTag(loadDefaultLibraryProperty(TAG_PROPERTY)))
|
||||
.withEmbeddedZookeeper()) {
|
||||
container.withNetworkAliases("cp-kafka");
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import lombok.Synchronized;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadTagFromSpringApplicationPropertiesFile;
|
||||
import static com.rbkmoney.testcontainers.annotations.util.SpringApplicationPropertiesLoader.loadDefaultLibraryProperty;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class PostgresqlTestcontainerFactory {
|
||||
@ -41,7 +41,8 @@ public class PostgresqlTestcontainerFactory {
|
||||
try (PostgreSQLContainer<?> container = new PostgreSQLContainer<>(
|
||||
DockerImageName
|
||||
.parse(POSTGRESQL_IMAGE_NAME)
|
||||
.withTag(loadTagFromSpringApplicationPropertiesFile(TAG_PROPERTY)))) {
|
||||
.withTag(loadDefaultLibraryProperty(TAG_PROPERTY)))) {
|
||||
container.withNetworkAliases("postgres");
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +23,14 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class SpringApplicationPropertiesLoader {
|
||||
|
||||
public static String loadTagFromSpringApplicationPropertiesFile(String keyTag) {
|
||||
var tag = loadPropertiesByFile().get(keyTag);
|
||||
public static String loadDefaultLibraryProperty(String key) {
|
||||
var tag = loadPropertiesByFile().get(key);
|
||||
if (tag == null) {
|
||||
tag = getSource(PropertiesFileParameters.builder()
|
||||
.propertySourceLoader(YamlPropertySourceLoader::new)
|
||||
.name("testcontainers-annotations.yml")
|
||||
.build())
|
||||
.get(keyTag);
|
||||
.get(key);
|
||||
}
|
||||
return String.valueOf(tag);
|
||||
}
|
||||
|
@ -2,4 +2,5 @@
|
||||
org.springframework.test.context.ContextCustomizerFactory=\
|
||||
com.rbkmoney.testcontainers.annotations.postgresql.PostgresqlTestcontainerExtension.PostgresqlTestcontainerContextCustomizerFactory,\
|
||||
com.rbkmoney.testcontainers.annotations.kafka.KafkaTestcontainerExtension.KafkaTestcontainerContextCustomizerFactory,\
|
||||
com.rbkmoney.testcontainers.annotations.clickhouse.ClickhouseTestcontainerExtension.ClickhouseTestcontainerContextCustomizerFactory
|
||||
com.rbkmoney.testcontainers.annotations.clickhouse.ClickhouseTestcontainerExtension.ClickhouseTestcontainerContextCustomizerFactory,\
|
||||
com.rbkmoney.testcontainers.annotations.ceph.CephTestcontainerExtension.CephTestcontainerContextCustomizerFactory
|
||||
|
@ -5,3 +5,7 @@ testcontainers:
|
||||
tag: '6.2.0'
|
||||
clickhouse:
|
||||
tag: 'latest-alpine'
|
||||
ceph:
|
||||
tag: 'v3.0.5-stable-3.0-luminous-centos-7'
|
||||
accessKey: 'test'
|
||||
secretKey: 'test'
|
||||
|
Loading…
Reference in New Issue
Block a user