Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce DockerOpenPaasExtension #1535

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
6 changes: 6 additions & 0 deletions tmail-backend/tmail-third-party/openpaas/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@
<artifactId>wiremock-standalone</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
<scope>test</scope>
<version>5.3.1</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.linagora.tmail;

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.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.extension.ParameterResolver;

public class DockerOpenPaasExtension implements ParameterResolver, BeforeAllCallback,
AfterAllCallback{

private static final DockerOpenPaasSetup DOCKER_OPEN_PAAS_SINGLETON = new DockerOpenPaasSetup();
private static final int OPEN_PASS_TEST_USERS_COUNT = 20;

private DockerOpenPaasPopulateService dockerOpenPaasPopulateService = new DockerOpenPaasPopulateService();

public static DockerOpenPaasSetup getDockerOpenPaasSingleton() {
return DOCKER_OPEN_PAAS_SINGLETON;
}

@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws
ParameterResolutionException {
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
return (parameterContext.getParameter().getType() == DockerOpenPaasSetup.class);
}

@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
return DOCKER_OPEN_PAAS_SINGLETON;
}

@Override
public void beforeAll(ExtensionContext context) {
DOCKER_OPEN_PAAS_SINGLETON.start();
}

@Override
public void afterAll(ExtensionContext context) {
DOCKER_OPEN_PAAS_SINGLETON.stop();
}

public DockerOpenPaasSetup getDockerOpenPaasSetup() {
return DOCKER_OPEN_PAAS_SINGLETON;
}

public OpenPaasUser newTestUser() {
return dockerOpenPaasPopulateService.createUser()
.map(OpenPaasUser::fromDocument)
.block();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.linagora.tmail;
chibenwa marked this conversation as resolved.
Show resolved Hide resolved

import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.testcontainers.containers.ContainerState;

public class DockerOpenPaasExtensionTest {

@RegisterExtension
static DockerOpenPaasExtension dockerOpenPaasExtension = new DockerOpenPaasExtension();

@Test
void allServersShouldStartSuccessfully() {
assertTrue(dockerOpenPaasExtension.getDockerOpenPaasSetup().getAllContainers()
.stream().allMatch(this::checkContainerStarted));
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
void newTestUserShouldSucceed() {
OpenPaasUser user = dockerOpenPaasExtension.newTestUser();
assertAll(
() -> assertThat("User id should not be null", user.id() != null),
() -> assertThat("User firstname should not be null", user.firstname() != null),
() -> assertThat("User lastname should not be null", user.lastname() != null),
() -> assertThat("User email should not be null", user.email() != null),
() -> assertThat("User password should not be null", user.password() != null)
);
}

boolean checkContainerStarted(ContainerState containerState) {
return containerState.isRunning();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.linagora.tmail;

import static com.mongodb.client.model.Filters.eq;
import static com.mongodb.client.model.Updates.push;

import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;

import org.bson.Document;

import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import com.mongodb.reactivestreams.client.MongoCollection;
import com.mongodb.reactivestreams.client.MongoDatabase;

import reactor.core.publisher.Mono;

public class DockerOpenPaasPopulateService {
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved

private static final Logger LOGGER = Logger.getLogger(DockerOpenPaasPopulateService.class.getName());

private final MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
private final MongoDatabase database = mongoClient.getDatabase("esn_docker");
private final MongoCollection<Document> usersCollection = database.getCollection("users");
private final MongoCollection<Document> domainsCollection = database.getCollection("domains");
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved

private Document getOpenPaasDomain() {
return Mono.from(domainsCollection.find()
.filter(new Document("name", "open-paas.org"))
.first()).block();
}

private Mono<Document> joinDomain(Document user, Document domain) {
return Mono.from(usersCollection
.findOneAndUpdate(
eq("_id", user.get("_id")),
push("domains", new Document("domain_id", domain.get("_id")))));
}

public Mono<Document> createUser() {
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
UUID randomUUID = UUID.randomUUID();
Document userToSave = new Document()
.append("firstname", "User_" + randomUUID)
.append("lastname", "User_" + randomUUID)
.append("password", "secret")
.append("accounts", List.of(new Document()
.append("type", "email")
.append("emails", List.of("user_" + randomUUID + "@open-paas.org"))));

return Mono.from(usersCollection.insertOne(userToSave))
.then(joinDomain(userToSave, getOpenPaasDomain()));
}
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.linagora.tmail;

import java.io.File;
import java.net.URISyntaxException;
import java.time.Duration;
import java.util.List;

import static com.google.common.io.Resources.getResource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.ComposeContainer;
import org.testcontainers.containers.ContainerState;
import org.testcontainers.containers.wait.strategy.Wait;

public class DockerOpenPaasSetup {
private static final Logger LOGGER = LoggerFactory.getLogger(DockerOpenPaasSetup.class);

private final ComposeContainer environment;

{
try {
environment = new ComposeContainer(
new File(DockerOpenPaasSetup.class.getResource("/docker-openpaas-setup.yml").toURI()))
.waitingFor("openpaas", Wait.forLogMessage(".*Users currently connected.*", 1)
.withStartupTimeout(Duration.ofMinutes(3)));
}
catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}

public void start() {
environment.start();
}

public void stop() {
environment.stop();
}

public ContainerState getOpenPaasContainer() {
return environment.getContainerByServiceName("openpaas").orElseThrow();
}

public ContainerState getRabbitMqContainer() {
return environment.getContainerByServiceName("rabbitmq").orElseThrow();
}

public ContainerState getSabreDavContainer() {
return environment.getContainerByServiceName("sabre_dav").orElseThrow();
}

public ContainerState getMongoDDContainer() {
return environment.getContainerByServiceName("mongo").orElseThrow();
}

public ContainerState getElasticsearchContainer() {
return environment.getContainerByServiceName("elasticsearch").orElseThrow();
}

public ContainerState getRedisContainer() {
return environment.getContainerByServiceName("redis").orElseThrow();
}

public List<ContainerState> getAllContainers() {
return List.of(
getOpenPaasContainer(),
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
getRabbitMqContainer(),
getSabreDavContainer(),
getMongoDDContainer(),
getElasticsearchContainer(),
getRedisContainer());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.linagora.tmail;

import org.bson.Document;

public record OpenPaasUser(String id, String firstname, String lastname, String email, String password) {

public static OpenPaasUser fromDocument(Document document) {
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
return new OpenPaasUser(
document.getObjectId("_id").toString(),
document.getString("firstname"),
document.getString("lastname"),
document.getList("accounts", Document.class)
.getFirst().getList("emails", String.class).getFirst(),
document.getString("password"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
version: "2"

networks:
emaily:
driver: bridge

services:
openpaas:
hostname: esn
image: linagora/esn:branch-1.11
ports:
- "8080:8080"
HoussemNasri marked this conversation as resolved.
Show resolved Hide resolved
environment:
- SABRE_ENV=dev
- PROVISION=true
- MONGO_HOST=mongo
- MONGO_PORT=27017
- MONGO_DBNAME=esn_docker
- MONGO_TIMEOUT=100000
- REDIS_HOST=redis
- REDIS_PORT=6379
- AMQP_HOST=rabbitmq
- AMQP_PORT=5672
- AMQP_PROTOCOL=amqp
- AMQP_USERNAME=guest
- AMQP_PASSWORD=guest
- ELASTICSEARCH_HOST=elasticsearch
- ELASTICSEARCH_PORT=9200
- WEB_PORT=8080
- DAV_SERVER_HOST=esn_sabre
- DAV_SERVER_PORT=80
depends_on:
- mongo
- redis
- rabbitmq
- elasticsearch
- sabre_dav
networks:
- emaily

redis:
image: redis:latest
ports:
- "6379:6379"
networks:
- emaily

rabbitmq:
image: rabbitmq:3.13.3-management
hostname: esn-rabbit
ports:
- 5672:5672
- 15672:15672
networks:
- emaily

mongo:
image: mongo
ports:
- "27017:27017"
networks:
- emaily

elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.3.2
ports:
- "9200:9200"
environment:
- discovery.type=single-node
networks:
- emaily

sabre_dav:
hostname: esn_sabre
image: linagora/sabre:lng-12-02-2025
ports:
- "8001:80"
environment:
- SABRE_ENV=dev
- SABRE_MONGO_HOST=mongo
- SABRE_MONGO_PORT=27017
- ESN_MONGO_HOST=mongo
- ESN_MONGO_PORT=27017
- ESN_MONGO_DBNAME=esn_docker
- MONGO_TIMEOUT=100000
- ESN_HOST=esn
- ESN_PORT=8080
- REDIS_HOST=redis
- REDIS_PORT=6379
- AMQP_HOST=rabbitmq
- AMQP_PORT=5672
- SABRE_ADMIN_LOGIN=admin
- SABRE_ADMIN_PASSWORD=secret123
- OPENPASS_BASIC_AUTH=YWRtaW5Ab3Blbi1wYWFzLm9yZzpzZWNyZXQ=
networks:
- emaily