diff --git a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/BootstrapperConfig.java b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/BootstrapperConfig.java index a72c56828..9962cdd01 100644 --- a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/BootstrapperConfig.java +++ b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/BootstrapperConfig.java @@ -23,6 +23,9 @@ public class BootstrapperConfig { public final String KAFKA_APPLICATION_ID; public final String[] DGRAPH_ALPHA_HOSTS; public final int[] DGRAPH_ALPHA_PORTS; + public final String API_CONFIG_REFERENCE_FILENAME; + public final String API_FIELDS_CONFIG_FILENAME; + public final String SYSTEM_CONFIG_DIR; public BootstrapperConfig(final Config parsedConfig) { POSTGRESQL_IP = parsedConfig.getString("POSTGRESQL_IP"); @@ -40,6 +43,9 @@ public BootstrapperConfig(final Config parsedConfig) { KAFKA_BOOTSTRAP_SERVERS = parsedConfig.getString("KAFKA_BOOTSTRAP_SERVERS"); KAFKA_APPLICATION_ID = parsedConfig.getString("KAFKA_APPLICATION_ID"); DGRAPH_ALPHA_HOSTS = parsedConfig.getString("DGRAPH_HOSTS").split(","); + API_CONFIG_REFERENCE_FILENAME = parsedConfig.getString("API_CONFIG_REFERENCE_FILENAME"); + API_FIELDS_CONFIG_FILENAME = parsedConfig.getString("API_FIELDS_CONFIG_FILENAME"); + SYSTEM_CONFIG_DIR = parsedConfig.getString("SYSTEM_CONFIG_DIR"); DGRAPH_ALPHA_PORTS = Arrays.stream(parsedConfig.getString("DGRAPH_PORTS").split(",")).mapToInt(s -> { try { return Integer.parseInt(s); diff --git a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/data/sql/postgres/PostgresDataBootstrapper.java b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/data/sql/postgres/PostgresDataBootstrapper.java index 18481888c..4d1ac9d0f 100644 --- a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/data/sql/postgres/PostgresDataBootstrapper.java +++ b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/java/org/jembi/jempi/bootstrapper/data/sql/postgres/PostgresDataBootstrapper.java @@ -2,6 +2,7 @@ import org.jembi.jempi.bootstrapper.data.DataBootstrapper; import org.jembi.jempi.bootstrapper.data.utils.DataBootstraperConsts; +import org.jembi.jempi.shared.models.GlobalConstants; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -150,7 +151,7 @@ public Boolean insertConfigurationData() throws SQLException, IOException { } private String[][] getConfigFiles(final String configurationTable) { - String configDir = Optional.of(Paths.get("/app/conf_system")) + String configDir = Optional.of(Paths.get(this.loadedConfig.SYSTEM_CONFIG_DIR)) .filter(Files::exists) .map(Path::toString) .orElseGet(() -> System.getenv("SYSTEM_CSV_DIR")); @@ -159,11 +160,11 @@ private String[][] getConfigFiles(final String configurationTable) { LOGGER.info("configDir " + configDir); // Define an array of config file paths and their corresponding keys String[][] configFiles = { - {configDir + "/config.json", "config"}, - {configDir + "/config-api.json", "config-api"}, - // Add more configuration files as needed - }; - return configFiles; + {configDir + "/" + this.loadedConfig.API_CONFIG_REFERENCE_FILENAME, GlobalConstants.CONFIGURATION_CONFIG_KEY}, + {configDir + "/" + this.loadedConfig.API_FIELDS_CONFIG_FILENAME, GlobalConstants.CONFIGURATION_CONFIG_API_KEY}, + // Add more configuration files as needed + }; + return configFiles; } private String readJsonFile(final String filePath) throws IOException { diff --git a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/resources/data/postgres/configuration-schema.sql b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/resources/data/postgres/configuration-schema.sql index 42f8941eb..a72ec57b8 100644 --- a/JeMPI_Apps/JeMPI_Bootstrapper/src/main/resources/data/postgres/configuration-schema.sql +++ b/JeMPI_Apps/JeMPI_Bootstrapper/src/main/resources/data/postgres/configuration-schema.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS configuration ( id SERIAL PRIMARY KEY, - key VARCHAR(255) NOT NULL, + key VARCHAR(255) NOT NULL UNIQUE, json JSON NOT NULL, dateCreated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, dateUpdated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP diff --git a/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/BackEnd.java b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/BackEnd.java index 6d4842120..25c8736dd 100644 --- a/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/BackEnd.java +++ b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/BackEnd.java @@ -4,7 +4,6 @@ import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.*; import akka.http.javadsl.server.directives.FileInfo; -import com.fasterxml.jackson.databind.ObjectMapper; import io.vavr.control.Either; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -24,17 +23,19 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.sql.SQLException; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.*; + public final class BackEnd extends AbstractBehavior { private static final Logger LOGGER = LogManager.getLogger(BackEnd.class); + private final PsqlClient psqlClient; private final String pgIP; + private final int pgPort; private final String pgUser; private final String pgPassword; private final String pgNotificationsDb; @@ -50,6 +51,8 @@ public final class BackEnd extends AbstractBehavior { private String[] dgraphHosts = null; private int[] dgraphPorts = null; + private final PostgresClientDao postgresClientDao; + private BackEnd( final Level debugLevel, final ActorContext context, @@ -74,7 +77,7 @@ private BackEnd( this.dgraphHosts = dgraphHosts; this.dgraphPorts = dgraphPorts; this.pgIP = sqlIP; - Integer pgPort = sqlPort; + this.pgPort = sqlPort; this.pgUser = sqlUser; this.pgPassword = sqlPassword; this.pgNotificationsDb = sqlNotificationsDb; @@ -87,6 +90,8 @@ private BackEnd( psqlNotifications = new PsqlNotifications(sqlIP, sqlPort, sqlNotificationsDb, sqlUser, sqlPassword); psqlAuditTrail = new PsqlAuditTrail(sqlIP, sqlPort, sqlAuditDb, sqlUser, sqlPassword); openMPI(kafkaBootstrapServers, kafkaClientId, debugLevel); + psqlClient = new PsqlClient(sqlIP, sqlPort, sqlConfigurationDb, sqlUser, sqlPassword); + this.postgresClientDao = PostgresClientDaoImpl.create(sqlIP, sqlPort, sqlConfigurationDb, sqlUser, sqlPassword); } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw e; @@ -499,76 +504,32 @@ private Behavior getSqlDashboardDataHandler(final SQLDashboardDataRequest } private Behavior getConfigurationHandler(final GetConfigurationRequest request) { - Path configMasterJsonFilePath = Paths.get(systemConfigDirectory, configMasterFileName); - Path configReferenceJsonFilePath = Paths.get(systemConfigDirectory, configReferenceFileName); - - Path configFilePath = configMasterJsonFilePath; - if (!Files.exists(configFilePath)) { - configFilePath = configReferenceJsonFilePath; - } - try { - String configFileContent = new String(Files.readAllBytes(configFilePath), StandardCharsets.UTF_8); - ObjectMapper mapper = new ObjectMapper(); - Configuration configuration = mapper.readValue(configFileContent, Configuration.class); + Configuration configuration = postgresClientDao.getConfiguration(GlobalConstants.CONFIGURATION_CONFIG_KEY); request.replyTo.tell(new GetConfigurationResponse(configuration)); - } catch (Exception exception) { - LOGGER.error("getConfigurationHandler failed with error: {}", exception.getMessage()); + } catch (Exception e) { + LOGGER.error("getConfigurationHandler failed with error: {}", e.getMessage()); } - return Behaviors.same(); } private Behavior getFieldsConfigurationHandler(final GetFieldsConfigurationRequest request) { - final var separator = FileSystems.getDefault().getSeparator(); - final String configDir = System.getenv("SYSTEM_CONFIG_DIRS"); - Path filePath = Paths.get(""); // Start with an empty path - // Create ubuntuFilePath - Path ubuntuFilePath = new File(String.format("%sapp%sconf_system%s%s", separator, separator, separator, fieldsConfigurationFileName)).toPath(); - // Check if ubuntuFilePath exists - if (Files.exists(ubuntuFilePath)) { - filePath = ubuntuFilePath; - } else { - // If ubuntuFilePath does not exist, assign the alternative path - filePath = Paths.get(configDir, "config-api.json"); - } try { - String configFileContent = new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8); - FieldsConfiguration fieldsConfiguration = AppUtils.OBJECT_MAPPER.readValue(configFileContent, FieldsConfiguration.class); - ArrayList fields = new ArrayList<>(); - fields.addAll(fieldsConfiguration.systemFields()); - fields.addAll(fieldsConfiguration.fields()); + List fields = postgresClientDao.getFieldsConfiguration(GlobalConstants.CONFIGURATION_CONFIG_API_KEY); request.replyTo.tell(new GetFieldsConfigurationResponse(fields)); - } catch (Exception exception) { - LOGGER.error("getFieldsConfigurationHandler failed with error: {}", exception.getLocalizedMessage()); + } catch (Exception e) { + LOGGER.error("getFieldsConfigurationHandler failed with error: {}", e.getMessage()); } - return Behaviors.same(); } private Behavior postConfigurationHandler(final PostConfigurationRequest request) { - Path configMasterJsonFilePath = Paths.get(systemConfigDirectory, configMasterFileName); - ObjectMapper objectMapper = new ObjectMapper(); - Configuration configJson = request.configuration; - - if (configJson == null) { - request.replyTo.tell(new PostConfigurationResponse("error: configuration is missing")); - LOGGER.error("postConfigurationHandler failed: configuration is missing in the request"); - return Behaviors.same(); - } - try { - String jsonConfig = objectMapper.writeValueAsString(configJson); - Files.write(configMasterJsonFilePath, - jsonConfig.getBytes(StandardCharsets.UTF_8), - StandardOpenOption.CREATE, - StandardOpenOption.TRUNCATE_EXISTING); + postgresClientDao.saveConfiguration(request.configuration, GlobalConstants.CONFIGURATION_CONFIG_KEY); request.replyTo.tell(new PostConfigurationResponse("ok")); - } catch (Exception exception) { - LOGGER.error("postConfigurationHandler failed with error: {}", exception.getMessage()); - request.replyTo.tell(new PostConfigurationResponse("error: " + exception.getMessage())); + } catch (Exception e) { + LOGGER.error("postConfigurationHandler failed with error: {}", e.getMessage()); } - return Behaviors.same(); } diff --git a/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDao.java b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDao.java new file mode 100644 index 000000000..c78aa504b --- /dev/null +++ b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDao.java @@ -0,0 +1,13 @@ +package org.jembi.jempi.libapi; + +import org.jembi.jempi.shared.models.ConfigurationModel.Configuration; +import org.jembi.jempi.shared.models.FieldsConfiguration; +import java.util.List; + +public interface PostgresClientDao { + void connect(); + void disconnect(); + Configuration getConfiguration(String configKey); + List getFieldsConfiguration(String configKey); + void saveConfiguration(Configuration configuration, String configKey); +} diff --git a/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDaoImpl.java b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDaoImpl.java new file mode 100644 index 000000000..3529e06e4 --- /dev/null +++ b/JeMPI_Apps/JeMPI_LibAPI/src/main/java/org/jembi/jempi/libapi/PostgresClientDaoImpl.java @@ -0,0 +1,178 @@ +package org.jembi.jempi.libapi; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jembi.jempi.shared.models.ConfigurationModel.Configuration; +import org.jembi.jempi.shared.models.FieldsConfiguration; +import org.jembi.jempi.shared.utils.AppUtils; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of PostgresClientDao interface for interacting with a PostgreSQL database. + * This class can be extended to provide custom behavior for database operations. + */ +public final class PostgresClientDaoImpl implements PostgresClientDao { + private static final Logger LOGGER = LogManager.getLogger(PostgresClientDaoImpl.class); + private final PsqlClient psqlClient; + + /** + * Constructs a new PostgresClientDaoImpl with the given database connection parameters. + * + * @param pgIP The IP address of the PostgreSQL server + * @param pgPort The port number of the PostgreSQL server + * @param pgDatabase The name of the database to connect to + * @param pgUser The username for database authentication + * @param pgPassword The password for database authentication + */ + private PostgresClientDaoImpl( + final String pgIP, + final int pgPort, + final String pgDatabase, + final String pgUser, + final String pgPassword) { + this.psqlClient = new PsqlClient(pgIP, pgPort, pgDatabase, pgUser, pgPassword); + } + + /** + * Creates a new instance of PostgresClientDaoImpl with the given database connection parameters. + * + * @param ip The IP address of the PostgreSQL server + * @param port The port number of the PostgreSQL server + * @param db The name of the database to connect to + * @param user The username for database authentication + * @param password The password for database authentication + */ + public static PostgresClientDaoImpl create( + final String ip, + final int port, + final String db, + final String user, + final String password) { + return new PostgresClientDaoImpl( + ip, + port, + db, + user, + password); + } + + /** + * Establishes a connection to the PostgreSQL database. + * This method can be overridden to provide custom connection logic. + * + * @throws SQLException if a database access error occurs + */ + @Override + public void connect() { + LOGGER.info("Connecting to PostgreSQL database"); + psqlClient.connect(); + LOGGER.info("Successfully connected to PostgreSQL database"); + } + + /** + * Closes the connection to the PostgreSQL database. + * This method can be overridden to provide custom disconnection logic. + * + * @throws SQLException if a database access error occurs + */ + @Override + public void disconnect() { + LOGGER.info("Disconnecting from PostgreSQL database"); + psqlClient.disconnect(); + LOGGER.info("Successfully disconnected from PostgreSQL database"); + } + + /** + * Retrieves the current configuration from the database. + * This method can be overridden to provide custom configuration retrieval logic. + * + * @return The Configuration object, or null if no configuration is found + * @throws SQLException if a database access error occurs or the retrieved JSON is invalid + */ + @Override + public Configuration getConfiguration(final String configKey) { + this.connect(); + LOGGER.info("Retrieving configuration from database"); + String sql = String.format("SELECT json FROM CONFIGURATION WHERE key = '%s' ORDER BY id DESC LIMIT 1", configKey); + try (PreparedStatement preparedStatement = psqlClient.prepareStatement(sql); + ResultSet rs = preparedStatement.executeQuery()) { + + if (rs.next()) { + String configFileContent = rs.getString("json"); + ObjectMapper mapper = new ObjectMapper(); + Configuration config = mapper.readValue(configFileContent, Configuration.class); + LOGGER.info("Successfully retrieved configuration from database"); + return config; + } else { + LOGGER.info("No configuration found in the database"); + return null; + } + } catch (Exception e) { + LOGGER.error(e); + } + this.disconnect(); + return null; + } + + /** + * Retrieves the fields configuration from the database. + * This method can be overridden to provide custom fields configuration retrieval logic. + * + * @return A List of FieldsConfiguration.Field objects, or null if no configuration is found + * @throws SQLException if a database access error occurs or the retrieved JSON is invalid + */ + @Override + public List getFieldsConfiguration(final String configKey) { + this.connect(); + LOGGER.info("Retrieving fields configuration from database"); + String sql = String.format("SELECT json FROM CONFIGURATION WHERE key = '%s' ORDER BY id DESC LIMIT 1", configKey); + try (PreparedStatement preparedStatement = psqlClient.prepareStatement(sql); + ResultSet rs = preparedStatement.executeQuery()) { + if (rs.next()) { + String configFileContent = rs.getString("json"); + FieldsConfiguration fieldsConfiguration = AppUtils.OBJECT_MAPPER.readValue(configFileContent, FieldsConfiguration.class); + ArrayList fields = new ArrayList<>(); + if (fieldsConfiguration != null && fieldsConfiguration.systemFields() != null && fieldsConfiguration.fields() != null) { + fields.addAll(fieldsConfiguration.systemFields()); + fields.addAll(fieldsConfiguration.fields()); + } + LOGGER.info("Successfully retrieved fields configuration from database"); + return fields; + } else { + LOGGER.info("No fields configuration found in the database"); + return null; + } + } catch (Exception e) { + LOGGER.error(e); + } + this.disconnect(); + return null; + } + + /** + * Saves the given configuration to the database. + * This method can be overridden to provide custom configuration saving logic. + * + * @param configuration The Configuration object to be saved + * @throws SQLException if a database access error occurs or the configuration cannot be converted to JSON + */ + @Override + public void saveConfiguration(final Configuration configuration, final String configKey) { + LOGGER.info("Saving configuration to database"); + this.connect(); + String sql = "UPDATE CONFIGURATION SET json = ?::jsonb WHERE key = ?"; + try (PreparedStatement preparedStatement = psqlClient.prepareStatement(sql)) { + String jsonConfig = AppUtils.OBJECT_MAPPER.writeValueAsString(configuration); + preparedStatement.setString(1, jsonConfig); + preparedStatement.setString(2, configKey); + int rowsAffected = preparedStatement.executeUpdate(); + LOGGER.info("Successfully saved configuration to database. Rows affected: {}", rowsAffected); + } catch (Exception e) { + LOGGER.error(e); + } + this.disconnect(); + } +} diff --git a/JeMPI_Apps/JeMPI_LibShared/src/main/java/org/jembi/jempi/shared/models/GlobalConstants.java b/JeMPI_Apps/JeMPI_LibShared/src/main/java/org/jembi/jempi/shared/models/GlobalConstants.java index cc21f9e30..e68aed962 100644 --- a/JeMPI_Apps/JeMPI_LibShared/src/main/java/org/jembi/jempi/shared/models/GlobalConstants.java +++ b/JeMPI_Apps/JeMPI_LibShared/src/main/java/org/jembi/jempi/shared/models/GlobalConstants.java @@ -71,6 +71,10 @@ public final class GlobalConstants { public static final int TIMEOUT_GENERAL_SECS = 60; public static final int TIMEOUT_TEA_TIME_SECS = 30; + //Configuration Key + public static final String CONFIGURATION_CONFIG_KEY = "config"; + public static final String CONFIGURATION_CONFIG_API_KEY = "config-api"; + private GlobalConstants() { } diff --git a/devops/linux/docker/conf/postgres/config-configuration.sql b/devops/linux/docker/conf/postgres/config-configuration.sql index 48fc4e6ae..3f7627f3b 100644 --- a/devops/linux/docker/conf/postgres/config-configuration.sql +++ b/devops/linux/docker/conf/postgres/config-configuration.sql @@ -1,6 +1,6 @@ CREATE TABLE IF NOT EXISTS configuration ( id SERIAL PRIMARY KEY, - key VARCHAR(255) NOT NULL, + key VARCHAR(255) NOT NULL UNIQUE, json JSON NOT NULL, dateCreated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, dateUpdated TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP diff --git a/devops/linux/docker/conf/stack/docker-stack-high-0.yml b/devops/linux/docker/conf/stack/docker-stack-high-0.yml index 4eb43621c..8ee793413 100644 --- a/devops/linux/docker/conf/stack/docker-stack-high-0.yml +++ b/devops/linux/docker/conf/stack/docker-stack-high-0.yml @@ -836,6 +836,9 @@ services: KAFKA_APPLICATION_ID: app-id-bootstrapper DGRAPH_HOSTS: ${DGRAPH_HOSTS} DGRAPH_PORTS: ${DGRAPH_PORTS} + API_CONFIG_REFERENCE_FILENAME: ${API_CONFIG_REFERENCE_FILENAME} + API_FIELDS_CONFIG_FILENAME: ${API_FIELDS_CONFIG_FILENAME} + SYSTEM_CONFIG_DIR: /app/conf_system deploy: mode: global diff --git a/devops/linux/docker/conf/stack/docker-stack-high-1.yml b/devops/linux/docker/conf/stack/docker-stack-high-1.yml index 24bf927d0..e261f1bdd 100644 --- a/devops/linux/docker/conf/stack/docker-stack-high-1.yml +++ b/devops/linux/docker/conf/stack/docker-stack-high-1.yml @@ -836,6 +836,9 @@ services: KAFKA_APPLICATION_ID: app-id-bootstrapper DGRAPH_HOSTS: ${DGRAPH_HOSTS} DGRAPH_PORTS: ${DGRAPH_PORTS} + API_CONFIG_REFERENCE_FILENAME: ${API_CONFIG_REFERENCE_FILENAME} + API_FIELDS_CONFIG_FILENAME: ${API_FIELDS_CONFIG_FILENAME} + SYSTEM_CONFIG_DIR: /app/conf_system deploy: mode: global diff --git a/devops/linux/docker/conf/stack/docker-stack-low-0.yml b/devops/linux/docker/conf/stack/docker-stack-low-0.yml index c33550f3b..a9096fc2b 100644 --- a/devops/linux/docker/conf/stack/docker-stack-low-0.yml +++ b/devops/linux/docker/conf/stack/docker-stack-low-0.yml @@ -625,6 +625,9 @@ services: KAFKA_APPLICATION_ID: app-id-bootstrapper DGRAPH_HOSTS: ${DGRAPH_HOSTS} DGRAPH_PORTS: ${DGRAPH_PORTS} + API_CONFIG_REFERENCE_FILENAME: ${API_CONFIG_REFERENCE_FILENAME} + API_FIELDS_CONFIG_FILENAME: ${API_FIELDS_CONFIG_FILENAME} + SYSTEM_CONFIG_DIR: /app/conf_system deploy: mode: global diff --git a/devops/linux/docker/conf/stack/docker-stack-low-1.yml b/devops/linux/docker/conf/stack/docker-stack-low-1.yml index 7f5563d18..de3a7c898 100644 --- a/devops/linux/docker/conf/stack/docker-stack-low-1.yml +++ b/devops/linux/docker/conf/stack/docker-stack-low-1.yml @@ -609,7 +609,7 @@ services: - type: bind source: $DATA_SYSTEM_CONFIG_DIR target: /app/conf_system - read_only: true + read_only: true environment: POSTGRESQL_IP: postgresql POSTGRESQL_PORT: 5432 @@ -625,6 +625,9 @@ services: KAFKA_APPLICATION_ID: app-id-bootstrapper DGRAPH_HOSTS: ${DGRAPH_HOSTS} DGRAPH_PORTS: ${DGRAPH_PORTS} + API_CONFIG_REFERENCE_FILENAME: ${API_CONFIG_REFERENCE_FILENAME} + API_FIELDS_CONFIG_FILENAME: ${API_FIELDS_CONFIG_FILENAME} + SYSTEM_CONFIG_DIR: /app/conf_system deploy: mode: global