diff --git a/multiapps-controller-database-migration/pom.xml b/multiapps-controller-database-migration/pom.xml index a8bcdc7209..8eefa4a28b 100644 --- a/multiapps-controller-database-migration/pom.xml +++ b/multiapps-controller-database-migration/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 multiapps-controller-database-migration @@ -45,6 +45,10 @@ org.cloudfoundry.multiapps multiapps-controller-persistence + + org.cloudfoundry.multiapps + multiapps-common + io.pivotal.cfenv java-cfenv diff --git a/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/DatabaseMigration.java b/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/DatabaseMigration.java index 61c002e65b..59d98da2cb 100644 --- a/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/DatabaseMigration.java +++ b/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/DatabaseMigration.java @@ -1,33 +1,38 @@ package org.cloudfoundry.multiapps.controller.database.migration; +import java.io.IOException; +import java.io.InputStream; +import javax.sql.DataSource; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.ConfigurationSource; +import org.cloudfoundry.multiapps.common.util.JsonUtil; import org.cloudfoundry.multiapps.controller.database.migration.executor.DatabaseSequenceMigrationExecutor; import org.cloudfoundry.multiapps.controller.database.migration.executor.DatabaseTableMigrationExecutor; import org.cloudfoundry.multiapps.controller.database.migration.executor.ImmutableDatabaseSequenceMigrationExecutor; import org.cloudfoundry.multiapps.controller.database.migration.executor.ImmutableDatabaseTableMigrationExecutor; import org.cloudfoundry.multiapps.controller.database.migration.extractor.DataSourceEnvironmentExtractor; - -import java.io.IOException; -import java.io.InputStream; -import javax.sql.DataSource; +import org.cloudfoundry.multiapps.controller.persistence.dto.DatabaseServiceKey; public class DatabaseMigration { private static final Logger LOGGER = (Logger) LogManager.getLogger(DatabaseMigration.class); + private static final String DATABASE_TARGET_SERVICE_KEY = "DATABASE_TARGET_SERVICE_KEY"; public static void main(String[] args) { configureLogger(); - LOGGER.info("Starting database migration..."); + DatabaseServiceKey databaseServiceKey = getServiceKeyFromEnvironment(); DataSourceEnvironmentExtractor environmentExtractor = new DataSourceEnvironmentExtractor(); - DataSource sourceDataSource = environmentExtractor.extractDataSource("deploy-service-database-source"); DataSource targetDataSource = environmentExtractor.extractDataSource("deploy-service-database"); + DataSource sourceDataSource = environmentExtractor.extractDataSource(databaseServiceKey); DatabaseSequenceMigrationExecutor sequenceMigrationExecutor = ImmutableDatabaseSequenceMigrationExecutor.builder() - .sourceDataSource(sourceDataSource) - .targetDataSource(targetDataSource) + .sourceDataSource( + sourceDataSource) + .targetDataSource( + targetDataSource) .build(); DatabaseTableMigrationExecutor tableMigrationExecutor = ImmutableDatabaseTableMigrationExecutor.builder() @@ -36,13 +41,17 @@ public static void main(String[] args) { .build(); sequenceMigrationExecutor.executeMigration("configuration_entry_sequence"); sequenceMigrationExecutor.executeMigration("configuration_subscription_sequence"); - tableMigrationExecutor.executeMigration("configuration_registry"); tableMigrationExecutor.executeMigration("configuration_subscription"); LOGGER.info("Database migration completed."); } + private static DatabaseServiceKey getServiceKeyFromEnvironment() { + String databaseTargetServiceKey = System.getenv(DATABASE_TARGET_SERVICE_KEY); + return new DatabaseServiceKey(JsonUtil.convertJsonToMap(databaseTargetServiceKey)); + } + private static void configureLogger() { ClassLoader classLoader = DatabaseMigration.class.getClassLoader(); if (classLoader != null) { diff --git a/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/extractor/DataSourceEnvironmentExtractor.java b/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/extractor/DataSourceEnvironmentExtractor.java index 362f323ae1..dde76b68a0 100644 --- a/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/extractor/DataSourceEnvironmentExtractor.java +++ b/multiapps-controller-database-migration/src/main/java/org/cloudfoundry/multiapps/controller/database/migration/extractor/DataSourceEnvironmentExtractor.java @@ -2,13 +2,13 @@ import javax.sql.DataSource; +import io.pivotal.cfenv.jdbc.CfJdbcService; +import org.cloudfoundry.multiapps.controller.persistence.dto.DatabaseServiceKey; import org.cloudfoundry.multiapps.controller.persistence.util.DataSourceFactory; import org.cloudfoundry.multiapps.controller.persistence.util.EnvironmentServicesFinder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.pivotal.cfenv.jdbc.CfJdbcService; - public class DataSourceEnvironmentExtractor { private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceEnvironmentExtractor.class); @@ -19,6 +19,10 @@ public DataSource extractDataSource(String serviceName) { return createDataSource(service); } + public DataSource extractDataSource(DatabaseServiceKey databaseServiceKey) { + return createDataSource(databaseServiceKey); + } + private CfJdbcService findService(String serviceName) { return new EnvironmentServicesFinder().findJdbcService(serviceName); } @@ -27,4 +31,7 @@ private DataSource createDataSource(CfJdbcService service) { return new DataSourceFactory().createDataSource(service); } + private DataSource createDataSource(DatabaseServiceKey databaseServiceKey) { + return new DataSourceFactory().createDataSource(databaseServiceKey); + } } diff --git a/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/dto/DatabaseServiceKey.java b/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/dto/DatabaseServiceKey.java new file mode 100644 index 0000000000..f1f8d910b1 --- /dev/null +++ b/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/dto/DatabaseServiceKey.java @@ -0,0 +1,47 @@ +package org.cloudfoundry.multiapps.controller.persistence.dto; + +import java.text.MessageFormat; +import java.util.Map; + +public class DatabaseServiceKey { + + private final Map credentials; + private static final String JDBC_URI_TEMPLATE = "jdbc:postgresql://{0}:{1}/{2}?user={3}&password={4}"; + + public DatabaseServiceKey(Map credentials) { + this.credentials = credentials; + } + + public String getUsername() { + return getValueFromCredentials("username"); + } + + public String getPassword() { + return getValueFromCredentials("password"); + } + + public String getJdbcUri() { + return MessageFormat.format(JDBC_URI_TEMPLATE, getHostname(), getPort(), getDbName(), getUsername(), getPassword()); + } + + private String getHostname() { + return getValueFromCredentials("hostname"); + } + + private String getPort() { + return getValueFromCredentials("port"); + } + + private String getDbName() { + return getValueFromCredentials("dbname"); + } + + private String getValueFromCredentials(String key) { + return getCredentialsObject().get(key) + .toString(); + } + + private Map getCredentialsObject() { + return (Map) credentials.get("credentials"); + } +} diff --git a/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/util/DataSourceFactory.java b/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/util/DataSourceFactory.java index 9fe58012a7..40225be2d1 100644 --- a/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/util/DataSourceFactory.java +++ b/multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/util/DataSourceFactory.java @@ -1,41 +1,51 @@ package org.cloudfoundry.multiapps.controller.persistence.util; import java.nio.file.Path; - import javax.sql.DataSource; -import org.cloudfoundry.multiapps.controller.persistence.Constants; - import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; - import io.pivotal.cfenv.jdbc.CfJdbcService; import jakarta.inject.Named; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Logger; +import org.cloudfoundry.multiapps.controller.persistence.Constants; +import org.cloudfoundry.multiapps.controller.persistence.dto.DatabaseServiceKey; @Named public class DataSourceFactory { + private static final Logger LOGGER = (Logger) LogManager.getLogger(DataSourceFactory.class); + public DataSource createDataSource(CfJdbcService service) { return createDataSource(service, null, null); } + public DataSource createDataSource(DatabaseServiceKey databaseServiceKey) { + DatabaseConfig databaseConfig = createDatabaseConfigFromDatabaseServiceKey(databaseServiceKey); + return new HikariDataSource(createHikariConfig(databaseConfig, null, "null")); + } + public DataSource createDataSource(CfJdbcService service, Integer maximumPoolSize, String appInstanceTemplate) { - return new HikariDataSource(createHikariConfig(service, maximumPoolSize, appInstanceTemplate)); + DatabaseConfig databaseConfig = createDatabaseConfigFromCfJdbcService(service); + return new HikariDataSource(createHikariConfig(databaseConfig, maximumPoolSize, appInstanceTemplate)); } - private HikariConfig createHikariConfig(CfJdbcService service, Integer maximumPoolSize, String appInstanceTemplate) { + private HikariConfig createHikariConfig(DatabaseConfig databaseConfig, Integer maximumPoolSize, String appInstanceTemplate) { HikariConfig hikariConfig = new HikariConfig(); - hikariConfig.setUsername(service.getUsername()); - hikariConfig.setPassword(service.getPassword()); - hikariConfig.setJdbcUrl(service.getJdbcUrl()); + hikariConfig.setUsername(databaseConfig.username); + hikariConfig.setPassword(databaseConfig.password); + hikariConfig.setJdbcUrl(databaseConfig.jdbcUrl); hikariConfig.setConnectionTimeout(60000); hikariConfig.setIdleTimeout(60000); hikariConfig.setMinimumIdle(10); hikariConfig.addDataSourceProperty("tcpKeepAlive", true); - hikariConfig.addDataSourceProperty("ApplicationName", appInstanceTemplate); - configureSSLClientKeyIfExists(service, hikariConfig); + configureSSLClientKeyIfExists(databaseConfig, hikariConfig); + if (appInstanceTemplate != null) { + hikariConfig.addDataSourceProperty("ApplicationName", appInstanceTemplate); + } if (maximumPoolSize != null) { hikariConfig.setMaximumPoolSize(maximumPoolSize); } @@ -43,12 +53,9 @@ private HikariConfig createHikariConfig(CfJdbcService service, Integer maximumPo return hikariConfig; } - private void configureSSLClientKeyIfExists(CfJdbcService service, HikariConfig hikariConfig) { - String clientKey = (String) service.getCredentials() - .getMap() - .get("sslkey"); - if (clientKey != null) { - configureClientCertificate(clientKey, hikariConfig); + private void configureSSLClientKeyIfExists(DatabaseConfig service, HikariConfig hikariConfig) { + if (service.sslKey != null) { + configureClientCertificate(service.sslKey, hikariConfig); } } @@ -58,4 +65,19 @@ private void configureClientCertificate(String clientKey, HikariConfig hikariCon hikariConfig.addDataSourceProperty("sslkey", encodedKeyPath.toAbsolutePath()); } + private DatabaseConfig createDatabaseConfigFromCfJdbcService(CfJdbcService service) { + String clientKey = (String) service.getCredentials() + .getMap() + .get("sslkey"); + return new DatabaseConfig(service.getUsername(), service.getPassword(), service.getJdbcUrl(), clientKey); + } + + private DatabaseConfig createDatabaseConfigFromDatabaseServiceKey(DatabaseServiceKey databaseServiceKey) { + return new DatabaseConfig(databaseServiceKey.getUsername(), databaseServiceKey.getPassword(), databaseServiceKey.getJdbcUri(), + null); + } + + private record DatabaseConfig(String username, String password, String jdbcUrl, String sslKey) { + } + }