Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88b64e7116 | ||
|
|
8e9c80dbd8 | ||
|
|
92e4b67ea2 | ||
|
|
39c32ffa12 | ||
|
|
d52a3f4648 | ||
|
|
df42a6bd91 | ||
|
|
d5aece1287 | ||
|
|
5cddef012d | ||
|
|
0f1d9d11f2 | ||
|
|
27925d6b3c | ||
|
|
987e720dad | ||
|
|
0f351a0e13 | ||
|
|
0b57648740 | ||
|
|
a68912407c | ||
|
|
522958f887 | ||
|
|
e587904b31 | ||
|
|
5993136356 | ||
|
|
59a9b2fef0 | ||
|
|
d4d84c6ac2 | ||
|
|
fc9a014395 | ||
|
|
e30ea19f15 | ||
|
|
287f6bf324 | ||
|
|
de66c15fd2 | ||
|
|
da78ff097a | ||
|
|
978323c0c7 | ||
|
|
4b61642734 | ||
|
|
95d09f3003 | ||
|
|
fc17fca498 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -40,3 +40,4 @@ gradle/
|
|||||||
|
|
||||||
**/.gradle
|
**/.gradle
|
||||||
**/build
|
**/build
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@ -18,4 +18,5 @@ deploy:
|
|||||||
rules:
|
rules:
|
||||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
- if: $CI_COMMIT_BRANCH =~ /^release/
|
- if: $CI_COMMIT_BRANCH =~ /^release/
|
||||||
|
- if: $CI_COMMIT_BRANCH =~ /^feature/
|
||||||
- if: $CI_COMMIT_TAG
|
- if: $CI_COMMIT_TAG
|
||||||
@ -1,7 +1,6 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
`maven-publish`
|
`maven-publish`
|
||||||
`kotlin-dsl`
|
|
||||||
pmd
|
pmd
|
||||||
checkstyle
|
checkstyle
|
||||||
jacoco
|
jacoco
|
||||||
@ -11,9 +10,6 @@ plugins {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
maven {
|
|
||||||
url = uri("https://pdftron.com/maven/release")
|
|
||||||
}
|
|
||||||
maven {
|
maven {
|
||||||
url = uri("https://nexus.knecon.com/repository/gindev/");
|
url = uri("https://nexus.knecon.com/repository/gindev/");
|
||||||
credentials {
|
credentials {
|
||||||
@ -28,10 +24,11 @@ repositories {
|
|||||||
val springBootVersion = "3.1.5"
|
val springBootVersion = "3.1.5"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("com.knecon.fforesight:tenant-commons:0.23.0")
|
api("com.knecon.fforesight:tenant-commons:0.31.0")
|
||||||
api("org.liquibase:liquibase-core:4.20.0")
|
api("org.liquibase:liquibase-core:4.29.2")
|
||||||
api("org.liquibase.ext:liquibase-mongodb:4.20.0")
|
api("org.liquibase.ext:liquibase-mongodb:4.29.2")
|
||||||
api("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}")
|
api("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}")
|
||||||
|
api("org.springframework.boot:spring-boot-starter-validation:${springBootVersion}")
|
||||||
api("org.springframework.boot:spring-boot-configuration-processor:${springBootVersion}")
|
api("org.springframework.boot:spring-boot-configuration-processor:${springBootVersion}")
|
||||||
api("org.projectlombok:lombok:1.18.28")
|
api("org.projectlombok:lombok:1.18.28")
|
||||||
runtimeOnly("org.springframework.boot:spring-boot-devtools:${springBootVersion}")
|
runtimeOnly("org.springframework.boot:spring-boot-devtools:${springBootVersion}")
|
||||||
@ -86,7 +83,7 @@ tasks.named<Test>("test") {
|
|||||||
|
|
||||||
sonarqube {
|
sonarqube {
|
||||||
properties {
|
properties {
|
||||||
property("sonar.login", providers.gradleProperty("sonarToken").getOrNull())
|
providers.gradleProperty("sonarToken").getOrNull()?.let { property("sonar.login", it) }
|
||||||
property("sonar.host.url", "https://sonarqube.knecon.com")
|
property("sonar.host.url", "https://sonarqube.knecon.com")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,4 +103,4 @@ tasks.jacocoTestReport {
|
|||||||
|
|
||||||
java {
|
java {
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
version = 0.2-SNAPSHOT
|
version = 0.3-SNAPSHOT
|
||||||
@ -1,59 +0,0 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons;
|
|
||||||
|
|
||||||
import org.springframework.amqp.core.Binding;
|
|
||||||
import org.springframework.amqp.core.BindingBuilder;
|
|
||||||
import org.springframework.amqp.core.Queue;
|
|
||||||
import org.springframework.amqp.core.QueueBuilder;
|
|
||||||
import org.springframework.amqp.core.TopicExchange;
|
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import com.knecon.fforesight.mongo.database.commons.liquibase.EnableMongoLiquibaseCondition;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Conditional(EnableMongoLiquibaseCondition.class)
|
|
||||||
public class MongoTenantMessagingConfiguration {
|
|
||||||
|
|
||||||
@Value("${fforesight.mongo.multitenancy.tenant-created-queue:tenant-created}")
|
|
||||||
private String tenantCreatedEventQueue;
|
|
||||||
|
|
||||||
@Value("${fforesight.mongo.multitenancy.tenant-created-dlq:tenant-created-dlq}")
|
|
||||||
private String tenantCreatedDLQ;
|
|
||||||
|
|
||||||
|
|
||||||
@Bean(name = "mongoTenantExchange")
|
|
||||||
TopicExchange mongoTenantExchange(@Value("${fforesight.tenant-exchange.name}") String tenantExchangeName) {
|
|
||||||
|
|
||||||
return new TopicExchange(tenantExchangeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Bean("persistenceServiceMongoTenantCreatedQueue")
|
|
||||||
public Queue persistenceServiceMongoTenantCreatedQueue() {
|
|
||||||
|
|
||||||
return QueueBuilder.durable(tenantCreatedEventQueue)
|
|
||||||
.withArgument("x-dead-letter-exchange", "").withArgument("x-dead-letter-routing-key", tenantCreatedDLQ).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Queue persistenceServiceMongoTenantDLQ() {
|
|
||||||
|
|
||||||
return QueueBuilder.durable(tenantCreatedDLQ).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Binding tenantExchangeBinding(@Qualifier("persistenceServiceMongoTenantCreatedQueue") Queue persistenceServiceTenantCreatedQueue,
|
|
||||||
@Qualifier("mongoTenantExchange") TopicExchange tenantExchange) {
|
|
||||||
|
|
||||||
return BindingBuilder.bind(persistenceServiceTenantCreatedQueue).to(tenantExchange).with("tenant.created");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,15 +1,20 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.config;
|
package com.knecon.fforesight.mongo.database.commons.config;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import org.bson.Document;
|
import org.bson.Document;
|
||||||
|
import org.bson.codecs.configuration.CodecRegistry;
|
||||||
import org.bson.conversions.Bson;
|
import org.bson.conversions.Bson;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
|
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
|
||||||
|
|
||||||
import com.knecon.fforesight.mongo.database.commons.service.MongoDataSources;
|
import com.knecon.fforesight.mongo.database.commons.service.MongoDataSources;
|
||||||
import com.mongodb.ClientSessionOptions;
|
import com.mongodb.ClientSessionOptions;
|
||||||
|
import com.mongodb.ReadConcern;
|
||||||
|
import com.mongodb.ReadPreference;
|
||||||
|
import com.mongodb.WriteConcern;
|
||||||
import com.mongodb.client.ChangeStreamIterable;
|
import com.mongodb.client.ChangeStreamIterable;
|
||||||
import com.mongodb.client.ClientSession;
|
import com.mongodb.client.ClientSession;
|
||||||
import com.mongodb.client.ListDatabasesIterable;
|
import com.mongodb.client.ListDatabasesIterable;
|
||||||
@ -26,7 +31,21 @@ public class MultiTenantMongoDBFactory extends SimpleMongoClientDatabaseFactory
|
|||||||
|
|
||||||
public MultiTenantMongoDBFactory(MongoDataSources mongoDataSources) {
|
public MultiTenantMongoDBFactory(MongoDataSources mongoDataSources) {
|
||||||
|
|
||||||
super(new MongoClient() {
|
super(getBootstrapMongoClient(), "BOOTSTRAP");
|
||||||
|
this.mongoDataSources = mongoDataSources;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull MongoDatabase doGetMongoDatabase(@NotNull String dbName) {
|
||||||
|
|
||||||
|
return mongoDataSources.mongoDatabaseCurrentTenantResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static MongoClient getBootstrapMongoClient() {
|
||||||
|
return new MongoClient() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MongoDatabase getDatabase(String s) {
|
public MongoDatabase getDatabase(String s) {
|
||||||
|
|
||||||
@ -157,15 +176,7 @@ public class MultiTenantMongoDBFactory extends SimpleMongoClientDatabaseFactory
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}, "BOOTSTRAP");
|
};
|
||||||
this.mongoDataSources = mongoDataSources;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected @NotNull MongoDatabase doGetMongoDatabase(@NotNull String dbName) {
|
|
||||||
|
|
||||||
return mongoDataSources.mongoDatabaseCurrentTenantResolver();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,11 +2,12 @@ package com.knecon.fforesight.mongo.database.commons.liquibase;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.context.annotation.Condition;
|
import org.springframework.context.annotation.Condition;
|
||||||
import org.springframework.context.annotation.ConditionContext;
|
import org.springframework.context.annotation.ConditionContext;
|
||||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
public class EnableMongoLiquibaseCondition implements Condition {
|
public class EnableMongoLiquibaseCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public class MongoLiquibaseConfig {
|
|||||||
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public TenantMongoLiquibaseExecutor tenantLiquibase(EncryptionDecryptionService encryptionService,
|
public TenantMongoLiquibaseExecutor tenantMongoLiquibaseExecutor(EncryptionDecryptionService encryptionService,
|
||||||
TenantProvider tenantProvider,
|
TenantProvider tenantProvider,
|
||||||
@Qualifier("tenantMongoLiquibaseProperties") LiquibaseProperties mongoLiquibaseProperties) {
|
@Qualifier("tenantMongoLiquibaseProperties") LiquibaseProperties mongoLiquibaseProperties) {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,104 @@
|
|||||||
|
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import liquibase.Contexts;
|
||||||
|
import liquibase.GlobalConfiguration;
|
||||||
|
import liquibase.LabelExpression;
|
||||||
|
import liquibase.Liquibase;
|
||||||
|
import liquibase.Scope;
|
||||||
|
import liquibase.configuration.ConfiguredValue;
|
||||||
|
import liquibase.database.Database;
|
||||||
|
import liquibase.exception.LiquibaseException;
|
||||||
|
import liquibase.integration.commandline.LiquibaseCommandLineConfiguration;
|
||||||
|
import liquibase.integration.spring.SpringLiquibase;
|
||||||
|
import liquibase.integration.spring.SpringResourceAccessor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MongoSpringLiquibase extends SpringLiquibase {
|
||||||
|
|
||||||
|
protected Database database;
|
||||||
|
|
||||||
|
|
||||||
|
public MongoSpringLiquibase() {
|
||||||
|
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executed automatically when the bean is initialized.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws LiquibaseException {
|
||||||
|
|
||||||
|
final ConfiguredValue<Boolean> shouldRunProperty = LiquibaseCommandLineConfiguration.SHOULD_RUN.getCurrentConfiguredValue();
|
||||||
|
|
||||||
|
if (!(Boolean) shouldRunProperty.getValue()) {
|
||||||
|
Scope.getCurrentScope().getLog(getClass()).info("Liquibase did not run because " + shouldRunProperty.getProvidedValue().describe() + " was set to false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!shouldRun) {
|
||||||
|
Scope.getCurrentScope()
|
||||||
|
.getLog(getClass())
|
||||||
|
.info("Liquibase did not run because 'shouldRun' " + "property was set " + "to false on " + getBeanName() + " Liquibase Spring bean.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Liquibase liquibase = createLiquibase(getDatabase())) {
|
||||||
|
generateRollbackFile(liquibase);
|
||||||
|
performUpdate(liquibase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void generateRollbackFile(Liquibase liquibase) throws LiquibaseException {
|
||||||
|
|
||||||
|
if (rollbackFile != null) {
|
||||||
|
|
||||||
|
try (OutputStream outputStream = Files.newOutputStream(rollbackFile.toPath()); Writer output = new OutputStreamWriter(outputStream,
|
||||||
|
GlobalConfiguration.OUTPUT_FILE_ENCODING.getCurrentValue())) {
|
||||||
|
|
||||||
|
if (tag != null) {
|
||||||
|
liquibase.futureRollbackSQL(tag, new Contexts(getContexts()), new LabelExpression(getLabelFilter()), output);
|
||||||
|
} else {
|
||||||
|
liquibase.futureRollbackSQL(new Contexts(getContexts()), new LabelExpression(getLabelFilter()), output);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new LiquibaseException("Unable to generate rollback file.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("squid:S2095")
|
||||||
|
@SneakyThrows
|
||||||
|
protected Liquibase createLiquibase(Database db) {
|
||||||
|
|
||||||
|
Liquibase liquibase;
|
||||||
|
try (SpringResourceAccessor resourceAccessor = createResourceOpener()) {
|
||||||
|
liquibase = new Liquibase(getChangeLog(), resourceAccessor, db);
|
||||||
|
if (parameters != null) {
|
||||||
|
for (Map.Entry<String, String> entry : parameters.entrySet()) {
|
||||||
|
liquibase.setChangeLogParameter(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDropFirst()) {
|
||||||
|
liquibase.dropAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return liquibase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@AllArgsConstructor
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class MongoTenantCreatedEvent {
|
|
||||||
|
|
||||||
private String tenantId;
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
|
||||||
|
|
||||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Conditional;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Conditional(EnableMongoLiquibaseCondition.class)
|
|
||||||
public class MongoTenantCreatedListener {
|
|
||||||
|
|
||||||
private final TenantMongoLiquibaseExecutor tenantMongoLiquibaseExecutor;
|
|
||||||
|
|
||||||
@Value("${fforesight.multitenancy.mongo.tenant-created-queue:mongo-tenant-created}")
|
|
||||||
private String tenantCreatedQueue;
|
|
||||||
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void postConstruct() {
|
|
||||||
|
|
||||||
log.info("Listener for tenant-created started for queue: {}", tenantCreatedQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
@RabbitListener(queues = "${fforesight.multitenancy.mongo.tenant-created-queue:mongo-tenant-created}")
|
|
||||||
public void createTenant(MongoTenantCreatedEvent tenantRequest) {
|
|
||||||
|
|
||||||
tenantMongoLiquibaseExecutor.initializeTenant(tenantRequest.getTenantId());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Conditional;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.knecon.fforesight.tenantcommons.listener.ITenantEventHandler;
|
||||||
|
import com.knecon.fforesight.tenantcommons.model.TenantCreatedEvent;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Conditional(EnableMongoLiquibaseCondition.class)
|
||||||
|
public class TenantCreatedMongoEventHandler implements ITenantEventHandler<TenantCreatedEvent> {
|
||||||
|
|
||||||
|
private final TenantMongoLiquibaseExecutor tenantMongoLiquibaseExecutor;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(TenantCreatedEvent tenantCreatedEvent) {
|
||||||
|
|
||||||
|
tenantMongoLiquibaseExecutor.initializeTenant(tenantCreatedEvent.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<TenantCreatedEvent> getEventClass() {
|
||||||
|
|
||||||
|
return TenantCreatedEvent.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,23 +1,24 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
package com.knecon.fforesight.mongo.database.commons.liquibase;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||||
import org.springframework.context.ResourceLoaderAware;
|
import org.springframework.context.ResourceLoaderAware;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
import com.knecon.fforesight.mongo.database.commons.utils.MongoUtils;
|
|
||||||
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
import com.knecon.fforesight.tenantcommons.EncryptionDecryptionService;
|
||||||
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
import com.knecon.fforesight.tenantcommons.TenantProvider;
|
||||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||||
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
import com.knecon.fforesight.tenantcommons.model.TenantResponse;
|
||||||
|
import com.knecon.fforesight.tenantcommons.utils.MongoConnectionStringHelper;
|
||||||
|
|
||||||
import feign.RetryableException;
|
import feign.RetryableException;
|
||||||
import liquibase.Contexts;
|
import liquibase.database.Database;
|
||||||
import liquibase.Liquibase;
|
|
||||||
import liquibase.changelog.ChangeSet;
|
|
||||||
import liquibase.database.DatabaseFactory;
|
import liquibase.database.DatabaseFactory;
|
||||||
|
import liquibase.exception.LiquibaseException;
|
||||||
import liquibase.ext.mongodb.database.MongoLiquibaseDatabase;
|
import liquibase.ext.mongodb.database.MongoLiquibaseDatabase;
|
||||||
import liquibase.integration.spring.SpringResourceAccessor;
|
import liquibase.integration.spring.SpringResourceAccessor;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -54,41 +55,56 @@ public class TenantMongoLiquibaseExecutor implements InitializingBean, ResourceL
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
protected void runOnAllTenants(List<TenantResponse> tenants) {
|
protected void runOnAllTenants(List<TenantResponse> tenants) {
|
||||||
|
|
||||||
tenants.forEach(this::runLiquibase);
|
tenants.forEach(this::runMongoLiquibase);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void runLiquibase(TenantResponse tenant) {
|
|
||||||
|
|
||||||
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
|
||||||
var mongoUrl = MongoUtils.buildMongoUrl(mongoDBConnection);
|
|
||||||
log.info("Initializing MongoDB liquibase for tenant {} / {}", tenant.getTenantId(), mongoUrl);
|
|
||||||
|
|
||||||
try (SpringResourceAccessor resourceAccessor = new SpringResourceAccessor(resourceLoader)) {
|
|
||||||
|
|
||||||
try (MongoLiquibaseDatabase database = (MongoLiquibaseDatabase) DatabaseFactory.getInstance()
|
|
||||||
.openDatabase(mongoUrl, mongoDBConnection.getUsername(), encryptionService.decrypt(mongoDBConnection.getPassword()), null, resourceAccessor)) {
|
|
||||||
database.setSupportsValidator(false);
|
|
||||||
try (Liquibase liquibase = new Liquibase(tenantMongoLiquibaseProperties.getChangeLog(), resourceAccessor, database)) {
|
|
||||||
Contexts contexts = new Contexts(tenantMongoLiquibaseProperties.getContexts());
|
|
||||||
List<ChangeSet> changeSetsList = liquibase.listUnrunChangeSets(contexts, null);
|
|
||||||
if (!changeSetsList.isEmpty()) {
|
|
||||||
liquibase.update(contexts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Failed to run liquibase migration on MongoDB for tenant: {}", tenant.getTenantId(), e);
|
|
||||||
}
|
|
||||||
log.info("Liquibase ran on MongoDB for tenant " + tenant.getTenantId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void initializeTenant(String tenantId) {
|
public void initializeTenant(String tenantId) {
|
||||||
|
|
||||||
runLiquibase(tenantProvider.getTenant(tenantId));
|
runMongoLiquibase(tenantProvider.getTenant(tenantId));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void runMongoLiquibase(TenantResponse tenant) {
|
||||||
|
|
||||||
|
log.info("Initializing MongoDB liquibase for tenant {}", tenant.getTenantId());
|
||||||
|
|
||||||
|
try (SpringResourceAccessor resourceAccessor = new SpringResourceAccessor(resourceLoader)) {
|
||||||
|
|
||||||
|
MongoDBConnection mongoDBConnection = tenant.getMongoDBConnection();
|
||||||
|
try (MongoLiquibaseDatabase database = (MongoLiquibaseDatabase) DatabaseFactory.getInstance()
|
||||||
|
.openDatabase(MongoConnectionStringHelper.buildGenericMongoUrl(mongoDBConnection),
|
||||||
|
mongoDBConnection.getUsername(),
|
||||||
|
encryptionService.decrypt( mongoDBConnection.getPassword()),
|
||||||
|
null,
|
||||||
|
resourceAccessor)) {
|
||||||
|
database.setSupportsValidator(false);
|
||||||
|
|
||||||
|
executeMongoSpringLiquibase(database);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to run liquibase migration on MongoDB for tenant: {}", tenant.getTenantId(), e);
|
||||||
|
} log.info("Liquibase ran on MongoDB for tenant " + tenant.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void executeMongoSpringLiquibase(Database database) throws LiquibaseException {
|
||||||
|
|
||||||
|
MongoSpringLiquibase liquibase = new MongoSpringLiquibase();
|
||||||
|
liquibase.setResourceLoader(resourceLoader);
|
||||||
|
liquibase.setDatabase(database);
|
||||||
|
liquibase.setChangeLog(tenantMongoLiquibaseProperties.getChangeLog());
|
||||||
|
liquibase.setContexts(tenantMongoLiquibaseProperties.getContexts());
|
||||||
|
liquibase.setClearCheckSums(tenantMongoLiquibaseProperties.isClearChecksums());
|
||||||
|
|
||||||
|
String databaseName = database.getConnection().getCatalog(); // or getDatabaseName() depending on your implementation
|
||||||
|
Map<String, String> changeLogParameters = new HashMap<>();
|
||||||
|
changeLogParameters.put("databaseName", databaseName);
|
||||||
|
liquibase.setChangeLogParameters(changeLogParameters);
|
||||||
|
|
||||||
|
liquibase.afterPropertiesSet();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.service;
|
package com.knecon.fforesight.mongo.database.commons.service;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@ -12,13 +10,12 @@ import com.google.common.cache.CacheLoader;
|
|||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.knecon.fforesight.mongo.database.commons.model.MongoClientConnection;
|
import com.knecon.fforesight.mongo.database.commons.model.MongoClientConnection;
|
||||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
||||||
import com.mongodb.MongoClientSettings;
|
import com.knecon.fforesight.tenantcommons.utils.MongoConnectionStringHelper;
|
||||||
import com.mongodb.MongoCredential;
|
|
||||||
import com.mongodb.ServerAddress;
|
|
||||||
import com.mongodb.client.MongoClient;
|
import com.mongodb.client.MongoClient;
|
||||||
import com.mongodb.client.MongoClients;
|
import com.mongodb.client.MongoClients;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
@ -56,14 +53,7 @@ public class MongoClientCache {
|
|||||||
|
|
||||||
private MongoClient buildMongoClient(MongoDBConnection mongoDBConnection) {
|
private MongoClient buildMongoClient(MongoDBConnection mongoDBConnection) {
|
||||||
|
|
||||||
MongoCredential credential = MongoCredential.createCredential(mongoDBConnection.getUsername(),
|
return MongoClients.create(MongoConnectionStringHelper.buildGenericMongoConnectionString(mongoDBConnection));
|
||||||
mongoDBConnection.getDatabase(),
|
|
||||||
mongoDBConnection.getPassword().toCharArray());
|
|
||||||
return MongoClients.create(MongoClientSettings.builder()
|
|
||||||
.applyToClusterSettings(builder -> builder.hosts(Collections.singletonList(new ServerAddress(mongoDBConnection.getHost(),
|
|
||||||
Integer.parseInt(mongoDBConnection.getPort())))))
|
|
||||||
.credential(credential)
|
|
||||||
.build());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -80,4 +70,4 @@ public class MongoClientCache {
|
|||||||
return clients.get(tenantId);
|
return clients.get(tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,55 +0,0 @@
|
|||||||
package com.knecon.fforesight.mongo.database.commons.utils;
|
|
||||||
|
|
||||||
import com.knecon.fforesight.tenantcommons.model.MongoDBConnection;
|
|
||||||
|
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
|
|
||||||
@UtilityClass
|
|
||||||
public class MongoUtils {
|
|
||||||
|
|
||||||
|
|
||||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String database) {
|
|
||||||
|
|
||||||
return new StringBuilder("mongodb://").append(host).append(':').append(port).append('/').append(database);
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String username, String password, String database) {
|
|
||||||
|
|
||||||
return createMongoConnectionStringBuilder(host, port, username, password).append('/').append(database);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private StringBuilder createMongoConnectionStringBuilder(String host, String port, String username, String password) {
|
|
||||||
|
|
||||||
return new StringBuilder("mongodb://").append(username).append(':').append(password).append("@").append(host).append(':').append(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String buildMongoUrl(MongoDBConnection mongoDBConnection) {
|
|
||||||
|
|
||||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
|
||||||
mongoDBConnection.getPort(),
|
|
||||||
mongoDBConnection.getDatabase()).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String buildMongoUrlWithAuth(MongoDBConnection mongoDBConnection) {
|
|
||||||
|
|
||||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
|
||||||
mongoDBConnection.getPort(),
|
|
||||||
mongoDBConnection.getUsername(),
|
|
||||||
mongoDBConnection.getPassword()).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String buildMongoUrlWithAuthForDatabase(MongoDBConnection mongoDBConnection) {
|
|
||||||
|
|
||||||
return createMongoConnectionStringBuilder(mongoDBConnection.getHost(),
|
|
||||||
mongoDBConnection.getPort(),
|
|
||||||
mongoDBConnection.getUsername(),
|
|
||||||
mongoDBConnection.getPassword(),
|
|
||||||
mongoDBConnection.getDatabase()).toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user