diff --git a/README.md b/README.md index 559538a..2b6c80f 100644 --- a/README.md +++ b/README.md @@ -102,11 +102,23 @@ connection: # Represents password, which will be used to decode operations. password: "test123" -# Represents section used for ObjectStorage API Server temporate storage configuration. -temporate-storage: - # Represents format used for content to be saved. - format: "zip" +# Represents section used for ObjectStorage API Server internal database configuration. +internal-storage: + # Represents provider selected for ObjectStorage internal database. Supported providers are "sqlite3" and "postgres" only. + provider: "sqlite3" + + # Represents host for the previously selected ObjectStorage internal database provider, works only for "postgres". + # host: "localhost:5432" + + # Represents username for the previously selected ObjectStorage internal database provider. + username: "objectstorage_user" + + # Represents password for the previously selected ObjectStorage internal database provider. + password: "objectstorage_password" +# Represents section used for ObjectStorage API Server temporate storage configuration. Same compression will be +# used to upload files to the configured cloud providers. +temporate-storage: # Represents frequency of scheduled operations processing. frequency: "*/5 * * * * ?" @@ -118,10 +130,13 @@ backup: # Represents frequency of backup operation for selected provider. frequency: "0 */5 * * * ?" + # Represents the highest amount of downloaded backup content versions per each workspace. + max-versions: 5 + # Represents section used for ObjectStorage API Server diagnostics configuration. diagnostics: # Enables diagnostics functionality. - enabled: false + enabled: true # Represents section used for ObjectStorage diagnostics metrics configuration. metrics: @@ -144,6 +159,9 @@ diagnostics: port: 8121 ``` +In the **~/.objectstorage/internal/database** directory there will be located internal database data, if **sqlite3** +option is selected as target database. + ### Diagnostics dashboard For **ObjectStorage API Server** configuration the following section should be modified: \ No newline at end of file diff --git a/api-server/pom.xml b/api-server/pom.xml index 6a79f68..2f99a8e 100644 --- a/api-server/pom.xml +++ b/api-server/pom.xml @@ -100,6 +100,10 @@ io.quarkiverse.jdbc quarkus-jdbc-sqlite + + io.quarkus + quarkus-jdbc-postgresql + io.quarkus quarkus-smallrye-jwt diff --git a/api-server/src/main/java/com/objectstorage/entity/common/ConfigEntity.java b/api-server/src/main/java/com/objectstorage/entity/common/ConfigEntity.java index 361f673..347d4f3 100644 --- a/api-server/src/main/java/com/objectstorage/entity/common/ConfigEntity.java +++ b/api-server/src/main/java/com/objectstorage/entity/common/ConfigEntity.java @@ -51,6 +51,55 @@ public static class Security { @JsonProperty("connection") public Connection connection; + /** + * Represents ObjectStorage internal storage configuration used for internal database setup. + */ + @Getter + public static class InternalStorage { + /** + * Represents all supported providers, which can be used by ObjectStorage internal storage. + */ + @Getter + public enum Provider { + @JsonProperty("sqlite3") + SQLITE3("sqlite3"), + + @JsonProperty("postgres") + POSTGRES("postgres"); + + private final String value; + + Provider(String value) { + this.value = value; + } + + public String toString() { + return value; + } + } + + @Valid + @NotNull + @JsonProperty("provider") + public Provider provider; + + @JsonProperty("host") + public String host; + + @NotNull + @JsonProperty("username") + public String username; + + @NotNull + @JsonProperty("password") + public String password; + } + + @Valid + @NotNull + @JsonProperty("internal-storage") + public InternalStorage internalStorage; + /** * Represents ObjectStorage API Server configuration used for temporate storage setup. */ diff --git a/api-server/src/main/java/com/objectstorage/entity/common/PropertiesEntity.java b/api-server/src/main/java/com/objectstorage/entity/common/PropertiesEntity.java index ec3e7a9..cbc7502 100644 --- a/api-server/src/main/java/com/objectstorage/entity/common/PropertiesEntity.java +++ b/api-server/src/main/java/com/objectstorage/entity/common/PropertiesEntity.java @@ -20,6 +20,15 @@ public class PropertiesEntity { @ConfigProperty(name = "quarkus.http.port") Integer applicationPort; + @ConfigProperty(name = "database.name") + String databaseName; + + @ConfigProperty(name = "liquibase.sqlite3.config") + String liquibaseSqlite3Config; + + @ConfigProperty(name = "liquibase.postgres.config") + String liquibasePostgresConfig; + @ConfigProperty(name = "content.root.notation") String contentRootNotation; diff --git a/api-server/src/main/java/com/objectstorage/exception/ConfigDatabasePropertiesMissingException.java b/api-server/src/main/java/com/objectstorage/exception/ConfigDatabasePropertiesMissingException.java new file mode 100644 index 0000000..76007d9 --- /dev/null +++ b/api-server/src/main/java/com/objectstorage/exception/ConfigDatabasePropertiesMissingException.java @@ -0,0 +1,21 @@ +package com.objectstorage.exception; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Formatter; + +/** + * Represents exception used when configuration file database properties are missing. + */ +public class ConfigDatabasePropertiesMissingException extends IOException { + public ConfigDatabasePropertiesMissingException() { + this(""); + } + + public ConfigDatabasePropertiesMissingException(Object... message) { + super( + new Formatter() + .format("Config file database properties are missing: %s", Arrays.stream(message).toArray()) + .toString()); + } +} diff --git a/api-server/src/main/java/com/objectstorage/repository/ConfigRepository.java b/api-server/src/main/java/com/objectstorage/repository/ConfigRepository.java deleted file mode 100644 index cce2352..0000000 --- a/api-server/src/main/java/com/objectstorage/repository/ConfigRepository.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.objectstorage.repository; - -import com.objectstorage.entity.common.PropertiesEntity; -import com.objectstorage.entity.repository.ConfigEntity; -import com.objectstorage.exception.QueryEmptyResultException; -import com.objectstorage.exception.QueryExecutionFailureException; -import com.objectstorage.exception.RepositoryOperationFailureException; -import com.objectstorage.repository.executor.RepositoryExecutor; -import io.quarkus.runtime.annotations.RegisterForReflection; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -/** - * Represents repository implementation to handle config table. - */ -@ApplicationScoped -@RegisterForReflection -public class ConfigRepository { - @Inject - PropertiesEntity properties; - - @Inject - RepositoryExecutor repositoryExecutor; - - /** - * Inserts given values into the config table. - * - * @param provider given provider. - * @param secret given secret. - * @param hash given configuration file hash. - * @throws RepositoryOperationFailureException if operation execution fails. - */ - public void insert(Integer provider, Integer secret, String hash) throws RepositoryOperationFailureException { - try { - repositoryExecutor.performQuery( - String.format( - "INSERT INTO %s (provider, secret, hash) VALUES (%d, %d, '%s')", - properties.getDatabaseConfigTableName(), - provider, - secret, - hash)); - - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } - } - - /** - * Retrieves all the persisted temporate entities with the given provider and secret. - * - * @return retrieved temporate entities. - * @throws RepositoryOperationFailureException if repository operation fails. - */ - public List findByProviderAndSecret(Integer provider, Integer secret) throws - RepositoryOperationFailureException { - ResultSet resultSet; - - try { - resultSet = - repositoryExecutor.performQueryWithResult( - String.format( - "SELECT t.id, t.hash FROM %s as t WHERE t.provider = %d AND t.secret = %d", - properties.getDatabaseConfigTableName(), - provider, - secret)); - - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } - - List result = new ArrayList<>(); - - Integer id; - String hash; - - try { - while (resultSet.next()) { - id = resultSet.getInt("id"); - hash = resultSet.getString("hash"); - - result.add(ConfigEntity.of(id, provider, secret, hash)); - } - } catch (SQLException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } - - try { - resultSet.close(); - } catch (SQLException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } - - return result; - } - - /** - * Deletes all entities with the given provider and secret from config table. - * - * @param provider given provider. - * @param secret given secret. - * @throws RepositoryOperationFailureException if operation execution fails. - */ - public void deleteByProviderAndSecret(Integer provider, Integer secret) throws RepositoryOperationFailureException { - try { - repositoryExecutor.performQuery( - String.format( - "DELETE FROM %s as t WHERE t.provider = %d AND t.secret = %d", - properties.getDatabaseConfigTableName(), - provider, - secret)); - - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } - } -} diff --git a/api-server/src/main/java/com/objectstorage/repository/ContentRepository.java b/api-server/src/main/java/com/objectstorage/repository/ContentRepository.java index 32412d8..dab78ca 100644 --- a/api-server/src/main/java/com/objectstorage/repository/ContentRepository.java +++ b/api-server/src/main/java/com/objectstorage/repository/ContentRepository.java @@ -49,7 +49,7 @@ public void insert(Integer provider, Integer secret, String root) throws Reposit try { repositoryExecutor.performQuery(query); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } @@ -77,12 +77,29 @@ public ContentEntity findByProviderAndSecret(Integer provider, Integer secret) t throw new RepositoryOperationFailureException(e.getMessage()); } - Integer id; - String root; - try { - id = resultSet.getInt("id"); - root = resultSet.getString("root"); + if (resultSet.next()) { + try { + Integer id = resultSet.getInt("id"); + String root = resultSet.getString("root"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return ContentEntity.of(id, provider, secret, root); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -99,7 +116,7 @@ public ContentEntity findByProviderAndSecret(Integer provider, Integer secret) t throw new RepositoryOperationFailureException(e.getMessage()); } - return ContentEntity.of(id, provider, secret, root); + return null; } /** @@ -167,7 +184,7 @@ public void deleteByProviderAndSecret(Integer provider, Integer secret) throws R provider, secret)); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } diff --git a/api-server/src/main/java/com/objectstorage/repository/ProviderRepository.java b/api-server/src/main/java/com/objectstorage/repository/ProviderRepository.java index 6e8ad7c..566bea4 100644 --- a/api-server/src/main/java/com/objectstorage/repository/ProviderRepository.java +++ b/api-server/src/main/java/com/objectstorage/repository/ProviderRepository.java @@ -49,10 +49,28 @@ public ProviderEntity findByName(String name) throws RepositoryOperationFailureE throw new RepositoryOperationFailureException(e.getMessage()); } - Integer id; - try { - id = resultSet.getInt("id"); + if (resultSet.next()) { + try { + Integer id = resultSet.getInt("id"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return ProviderEntity.of(id, name); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -69,7 +87,7 @@ public ProviderEntity findByName(String name) throws RepositoryOperationFailureE throw new RepositoryOperationFailureException(e.getMessage()); } - return ProviderEntity.of(id, name); + return null; } /** @@ -94,10 +112,28 @@ public ProviderEntity findById(Integer id) throws RepositoryOperationFailureExce throw new RepositoryOperationFailureException(e.getMessage()); } - String name; - try { - name = resultSet.getString("name"); + if (resultSet.next()) { + try { + String name = resultSet.getString("name"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return ProviderEntity.of(id, name); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -114,6 +150,6 @@ public ProviderEntity findById(Integer id) throws RepositoryOperationFailureExce throw new RepositoryOperationFailureException(e.getMessage()); } - return ProviderEntity.of(id, name); + return null; } } diff --git a/api-server/src/main/java/com/objectstorage/repository/SecretRepository.java b/api-server/src/main/java/com/objectstorage/repository/SecretRepository.java index 0e0508b..af076da 100644 --- a/api-server/src/main/java/com/objectstorage/repository/SecretRepository.java +++ b/api-server/src/main/java/com/objectstorage/repository/SecretRepository.java @@ -45,7 +45,7 @@ public void insert(Integer session, String credentials) throws RepositoryOperati try { repositoryExecutor.performQuery(query); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } @@ -107,10 +107,28 @@ public SecretEntity findBySessionAndCredentials(Integer session, String credenti throw new RepositoryOperationFailureException(e.getMessage()); } - Integer id; - try { - id = resultSet.getInt("id"); + if (resultSet.next()) { + try { + Integer id = resultSet.getInt("id"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return SecretEntity.of(id, session, credentials); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -127,7 +145,7 @@ public SecretEntity findBySessionAndCredentials(Integer session, String credenti throw new RepositoryOperationFailureException(e.getMessage()); } - return SecretEntity.of(id, session, credentials); + return null; } /** @@ -150,18 +168,19 @@ public SecretEntity findById(Integer id) throws RepositoryOperationFailureExcept throw new RepositoryOperationFailureException(e.getMessage()); } - Integer session; - try { - session = resultSet.getInt("session"); - } catch (SQLException e) { - throw new RepositoryOperationFailureException(e.getMessage()); - } + if (resultSet.next()) { + Integer session = resultSet.getInt("session"); + String credentials = resultSet.getString("credentials"); - String credentials; + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } - try { - credentials = resultSet.getString("credentials"); + return SecretEntity.of(id, session, credentials); + } } catch (SQLException e1) { try { resultSet.close(); @@ -178,7 +197,7 @@ public SecretEntity findById(Integer id) throws RepositoryOperationFailureExcept throw new RepositoryOperationFailureException(e.getMessage()); } - return SecretEntity.of(id, session, credentials); + return null; } /** @@ -195,7 +214,7 @@ public void deleteById(Integer id) throws RepositoryOperationFailureException { properties.getDatabaseSecretTableName(), id)); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } diff --git a/api-server/src/main/java/com/objectstorage/repository/TemporateRepository.java b/api-server/src/main/java/com/objectstorage/repository/TemporateRepository.java index 5069417..1a7a5a3 100644 --- a/api-server/src/main/java/com/objectstorage/repository/TemporateRepository.java +++ b/api-server/src/main/java/com/objectstorage/repository/TemporateRepository.java @@ -7,6 +7,7 @@ import com.objectstorage.exception.QueryExecutionFailureException; import com.objectstorage.exception.RepositoryOperationFailureException; import com.objectstorage.repository.executor.RepositoryExecutor; +import com.objectstorage.service.config.ConfigService; import io.quarkus.runtime.annotations.RegisterForReflection; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -27,6 +28,9 @@ public class TemporateRepository { @Inject PropertiesEntity properties; + @Inject + ConfigService configService; + @Inject RepositoryExecutor repositoryExecutor; @@ -54,7 +58,7 @@ public void insert(Integer provider, Integer secret, String location, String has try { repositoryExecutor.performQuery(query); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } @@ -71,16 +75,45 @@ public Integer count() throws RepositoryOperationFailureException { try { resultSet = repositoryExecutor.performQueryWithResult( - String.format("SELECT COUNT(1) as 'result' FROM %s", properties.getDatabaseTemporateTableName())); + String.format("SELECT COUNT(1) as result FROM %s", properties.getDatabaseTemporateTableName())); } catch (QueryExecutionFailureException | QueryEmptyResultException e) { throw new RepositoryOperationFailureException(e.getMessage()); } - Integer count; + Integer count = 0; try { - count = resultSet.getInt("result"); + if (resultSet.next()) { + switch (configService.getConfig().getInternalStorage().getProvider()) { + case SQLITE3 -> { + try { + count = resultSet.getInt("result"); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } + case POSTGRES -> { + try { + count = (int) resultSet.getLong("result"); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -120,20 +153,33 @@ public TemporateEntity findEarliest() throws RepositoryOperationFailureException throw new RepositoryOperationFailureException(e.getMessage()); } - Integer id; - Integer provider; - Integer secret; - String location; - String hash; - Long createdAt; - try { - id = resultSet.getInt("id"); - provider = resultSet.getInt("provider"); - secret = resultSet.getInt("secret"); - location = resultSet.getString("location"); - hash = resultSet.getString("hash"); - createdAt = resultSet.getLong("created_at"); + if (resultSet.next()) { + try { + Integer id = resultSet.getInt("id"); + Integer provider = resultSet.getInt("provider"); + Integer secret = resultSet.getInt("secret"); + String location = resultSet.getString("location"); + String hash = resultSet.getString("hash"); + Long createdAt = resultSet.getLong("created_at"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return TemporateEntity.of(id, provider, secret, location, hash, createdAt); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -150,7 +196,7 @@ public TemporateEntity findEarliest() throws RepositoryOperationFailureException throw new RepositoryOperationFailureException(e.getMessage()); } - return TemporateEntity.of(id, provider, secret, location, hash, createdAt); + return null; } /** @@ -240,15 +286,30 @@ public TemporateEntity findEarliestByLocationProviderAndSecret( throw new RepositoryOperationFailureException(e.getMessage()); } - Integer id; - String hash; - Long createdAt; - try { - id = resultSet.getInt("id"); - hash = resultSet.getString("hash"); - createdAt = resultSet.getLong("created_at"); - + if (resultSet.next()) { + try { + Integer id = resultSet.getInt("id"); + String hash = resultSet.getString("hash"); + Long createdAt = resultSet.getLong("created_at"); + + try { + resultSet.close(); + } catch (SQLException e) { + throw new RepositoryOperationFailureException(e.getMessage()); + } + + return TemporateEntity.of(id, provider, secret, location, hash, createdAt); + } catch (SQLException e1) { + try { + resultSet.close(); + } catch (SQLException e2) { + throw new RepositoryOperationFailureException(e2.getMessage()); + } + + throw new RepositoryOperationFailureException(e1.getMessage()); + } + } } catch (SQLException e1) { try { resultSet.close(); @@ -265,7 +326,7 @@ public TemporateEntity findEarliestByLocationProviderAndSecret( throw new RepositoryOperationFailureException(e.getMessage()); } - return TemporateEntity.of(id, provider, secret, location, hash, createdAt); + return null; } /** @@ -347,7 +408,7 @@ public void deleteByLocationProviderAndSecret(String location, Integer provider, provider, secret)); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } @@ -366,7 +427,7 @@ public void deleteByHash(String hash) throws RepositoryOperationFailureException properties.getDatabaseTemporateTableName(), hash)); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } @@ -387,7 +448,7 @@ public void deleteByProviderAndSecret(Integer provider, Integer secret) throws R provider, secret)); - } catch (QueryExecutionFailureException | QueryEmptyResultException e) { + } catch (QueryExecutionFailureException e) { throw new RepositoryOperationFailureException(e.getMessage()); } } diff --git a/api-server/src/main/java/com/objectstorage/repository/executor/RepositoryExecutor.java b/api-server/src/main/java/com/objectstorage/repository/executor/RepositoryExecutor.java index 18ab7ee..7848137 100644 --- a/api-server/src/main/java/com/objectstorage/repository/executor/RepositoryExecutor.java +++ b/api-server/src/main/java/com/objectstorage/repository/executor/RepositoryExecutor.java @@ -1,8 +1,10 @@ package com.objectstorage.repository.executor; +import com.objectstorage.entity.common.ConfigEntity; import com.objectstorage.entity.common.PropertiesEntity; import com.objectstorage.exception.*; import com.objectstorage.repository.common.RepositoryConfigurationHelper; +import com.objectstorage.service.config.ConfigService; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import jakarta.enterprise.context.ApplicationScoped; @@ -29,16 +31,16 @@ public class RepositoryExecutor { PropertiesEntity properties; @Inject - DataSource dataSource; + ConfigService configService; @Inject - RepositoryConfigurationHelper repositoryConfigurationHelper; + DataSource dataSource; private Connection connection; - private final List statements = new ArrayList<>(); + private final static List statements = new ArrayList<>(); - private final ScheduledExecutorService scheduledExecutorService = + private final static ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); /** @@ -56,36 +58,48 @@ private void configure() throws QueryExecutionFailureException { } /** - * Performs given SQL query without result. + * Performs given SQL query via given connection without result. * + * @param connection given SQL connection. * @param query given SQL query to be executed. + * @param databaseStatementCloseDelay given database statement close delay. * @throws QueryExecutionFailureException if query execution is interrupted by failure. - * @throws QueryEmptyResultException if result is empty. */ - public void performQuery(String query) throws QueryExecutionFailureException, QueryEmptyResultException { + public static void performQuery(Connection connection, String query, Integer databaseStatementCloseDelay) + throws QueryExecutionFailureException { Statement statement; try { - statement = this.connection.createStatement(); + statement = connection.createStatement(); } catch (SQLException e) { throw new QueryExecutionFailureException(e.getMessage()); } + statements.add(statement); + try { statement.executeUpdate(query); } catch (SQLException e) { throw new QueryExecutionFailureException(e.getMessage()); } - statements.add(statement); - scheduledExecutorService.schedule(() -> { try { statement.close(); } catch (SQLException e) { logger.fatal(new QueryExecutionFailureException(e.getMessage()).getMessage()); } - }, properties.getDatabaseStatementCloseDelay(), TimeUnit.MILLISECONDS); + }, databaseStatementCloseDelay, TimeUnit.MILLISECONDS); + } + + /** + * Performs given SQL query without result. + * + * @param query given SQL query to be executed. + * @throws QueryExecutionFailureException if query execution is interrupted by failure. + */ + public void performQuery(String query) throws QueryExecutionFailureException { + performQuery(this.connection, query, properties.getDatabaseStatementCloseDelay()); } /** @@ -105,6 +119,8 @@ public ResultSet performQueryWithResult(String query) throws QueryExecutionFailu throw new QueryExecutionFailureException(e.getMessage()); } + statements.add(statement); + ResultSet resultSet; try { @@ -113,8 +129,6 @@ public ResultSet performQueryWithResult(String query) throws QueryExecutionFailu throw new QueryExecutionFailureException(e.getMessage()); } - statements.add(statement); - scheduledExecutorService.schedule(() -> { try { statement.close(); diff --git a/api-server/src/main/java/com/objectstorage/service/integration/backup/BackupService.java b/api-server/src/main/java/com/objectstorage/service/integration/backup/BackupService.java index 453fc2a..1eb6e40 100644 --- a/api-server/src/main/java/com/objectstorage/service/integration/backup/BackupService.java +++ b/api-server/src/main/java/com/objectstorage/service/integration/backup/BackupService.java @@ -85,8 +85,6 @@ public void process() throws BackupPeriodRetrievalFailureException { } catch (ContentApplicationRetrievalFailureException e) { StateService.getBackupProcessorGuard().unlock(); - logger.error(e.getMessage()); - return; } diff --git a/api-server/src/main/java/com/objectstorage/service/integration/diagnostics/DiagnosticsConfigService.java b/api-server/src/main/java/com/objectstorage/service/integration/diagnostics/DiagnosticsConfigService.java index 662f996..61c5f33 100644 --- a/api-server/src/main/java/com/objectstorage/service/integration/diagnostics/DiagnosticsConfigService.java +++ b/api-server/src/main/java/com/objectstorage/service/integration/diagnostics/DiagnosticsConfigService.java @@ -159,22 +159,12 @@ private void process() throws configService.getConfig().getDiagnostics().getNodeExporter().getPort(), properties.getDiagnosticsCommonDockerNetworkName()); - CommandExecutorOutputDto nodeExporterDeployCommandOutput; - try { - nodeExporterDeployCommandOutput = - commandExecutorService.executeCommand(nodeExporterDeployCommandService); + commandExecutorService.executeCommand(nodeExporterDeployCommandService); } catch (CommandExecutorException e) { throw new NodeExporterDeploymentFailureException(e.getMessage()); } - String nodeExporterDeployCommandErrorOutput = nodeExporterDeployCommandOutput.getErrorOutput(); - - if (Objects.nonNull(nodeExporterDeployCommandErrorOutput) && - !nodeExporterDeployCommandErrorOutput.isEmpty()) { - throw new NodeExporterDeploymentFailureException(nodeExporterDeployCommandErrorOutput); - } - PrometheusDeployCommandService prometheusDeployCommandService = new PrometheusDeployCommandService( properties.getDiagnosticsPrometheusDockerName(), @@ -184,22 +174,12 @@ private void process() throws properties.getDiagnosticsPrometheusConfigLocation(), properties.getDiagnosticsPrometheusInternalLocation()); - CommandExecutorOutputDto prometheusDeployCommandOutput; - try { - prometheusDeployCommandOutput = - commandExecutorService.executeCommand(prometheusDeployCommandService); + commandExecutorService.executeCommand(prometheusDeployCommandService); } catch (CommandExecutorException e) { throw new PrometheusDeploymentFailureException(e.getMessage()); } - String prometheusDeployCommandErrorOutput = prometheusDeployCommandOutput.getErrorOutput(); - - if (Objects.nonNull(prometheusDeployCommandErrorOutput) && - !prometheusDeployCommandErrorOutput.isEmpty()) { - throw new PrometheusDeploymentFailureException(prometheusDeployCommandErrorOutput); - } - GrafanaDeployCommandService grafanaDeployCommandService = new GrafanaDeployCommandService( properties.getDiagnosticsGrafanaDockerName(), @@ -209,21 +189,11 @@ private void process() throws properties.getDiagnosticsGrafanaConfigLocation(), properties.getDiagnosticsGrafanaInternalLocation()); - CommandExecutorOutputDto grafanaDeployCommandOutput; - try { - grafanaDeployCommandOutput = - commandExecutorService.executeCommand(grafanaDeployCommandService); + commandExecutorService.executeCommand(grafanaDeployCommandService); } catch (CommandExecutorException e) { throw new GrafanaDeploymentFailureException(e.getMessage()); } - - String grafanaDeployCommandErrorOutput = grafanaDeployCommandOutput.getErrorOutput(); - - if (Objects.nonNull(grafanaDeployCommandErrorOutput) && - !grafanaDeployCommandErrorOutput.isEmpty()) { - throw new GrafanaDeploymentFailureException(grafanaDeployCommandErrorOutput); - } } } diff --git a/api-server/src/main/java/com/objectstorage/service/integration/properties/database/DatabasePropertiesConfigService.java b/api-server/src/main/java/com/objectstorage/service/integration/properties/database/DatabasePropertiesConfigService.java new file mode 100644 index 0000000..2154704 --- /dev/null +++ b/api-server/src/main/java/com/objectstorage/service/integration/properties/database/DatabasePropertiesConfigService.java @@ -0,0 +1,130 @@ +package com.objectstorage.service.integration.properties.database; + +import com.objectstorage.exception.ConfigDatabasePropertiesMissingException; +import com.objectstorage.exception.QueryExecutionFailureException; +import com.objectstorage.repository.executor.RepositoryExecutor; +import com.objectstorage.service.config.common.ConfigConfigurationHelper; +import io.quarkus.runtime.annotations.StaticInitSafe; +import io.smallrye.config.ConfigSourceContext; +import io.smallrye.config.ConfigSourceFactory; +import io.smallrye.config.ConfigValue; +import io.smallrye.config.PropertiesConfigSource; +import lombok.SneakyThrows; +import org.eclipse.microprofile.config.spi.ConfigSource; +import com.objectstorage.entity.common.ConfigEntity; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.Collections; +import java.util.Objects; +import java.util.OptionalInt; +import java.util.Properties; + +/** + * Service used to perform security properties configuration operations. + */ +@StaticInitSafe +public class DatabasePropertiesConfigService implements ConfigSourceFactory { + @Override + @SneakyThrows + public Iterable getConfigSources(final ConfigSourceContext context) { + final ConfigValue configLocation = context.getValue("config.location"); + + if (Objects.isNull(configLocation) || Objects.isNull(configLocation.getValue())) { + return Collections.emptyList(); + } + + final ConfigValue databaseName = context.getValue("database.name"); + if (Objects.isNull(databaseName) || Objects.isNull(databaseName.getValue())) { + return Collections.emptyList(); + } + + final ConfigValue liquibaseSqlite3Config = context.getValue("liquibase.sqlite3.config"); + if (Objects.isNull(liquibaseSqlite3Config) || Objects.isNull(liquibaseSqlite3Config.getValue())) { + return Collections.emptyList(); + } + + final ConfigValue liquibasePostgresConfig = context.getValue("liquibase.postgres.config"); + if (Objects.isNull(liquibasePostgresConfig) || Objects.isNull(liquibasePostgresConfig.getValue())) { + return Collections.emptyList(); + } + + final ConfigValue databaseStatementCloseDelay = context.getValue("database.statement.close-delay"); + if (Objects.isNull(databaseStatementCloseDelay) || Objects.isNull(databaseStatementCloseDelay.getValue())) { + return Collections.emptyList(); + } + + Properties properties = new Properties(); + + ConfigEntity config = ConfigConfigurationHelper.readConfig(configLocation.getValue(), false); + if (Objects.isNull(config)) { + return Collections.emptyList(); + } + + if (Objects.isNull(config.getInternalStorage()) || + Objects.isNull(config.getInternalStorage().getProvider()) || + Objects.isNull(config.getInternalStorage().getUsername()) || + Objects.isNull(config.getInternalStorage().getPassword())) { + throw new ConfigDatabasePropertiesMissingException(); + } + + if (config.getInternalStorage().getProvider() == ConfigEntity.InternalStorage.Provider.POSTGRES && + Objects.isNull(config.getInternalStorage().getHost())) { + throw new ConfigDatabasePropertiesMissingException(); + } + + switch (config.getInternalStorage().getProvider()) { + case SQLITE3 -> { + properties.put("quarkus.liquibase.change-log", liquibaseSqlite3Config.getValue()); + + properties.put("quarkus.datasource.jdbc.driver", "org.sqlite.JDBC"); + properties.put("quarkus.datasource.db-kind", "other"); + properties.put( + "quarkus.datasource.jdbc.url", + String.format( + "jdbc:sqlite:%s/.%s/internal/database/data.db", + System.getProperty("user.home"), + databaseName.getValue())); + } + case POSTGRES -> { + properties.put("quarkus.liquibase.change-log", liquibasePostgresConfig.getValue()); + + properties.put("quarkus.datasource.db-kind", "postgresql"); + properties.put( + "quarkus.datasource.jdbc.url", + String.format("jdbc:postgresql://%s/%s", + config.getInternalStorage().getHost(), + databaseName.getValue())); + + Connection connection = DriverManager.getConnection( + String.format("jdbc:postgresql://%s/postgres", config.getInternalStorage().getHost()), + config.getInternalStorage().getUsername(), + config.getInternalStorage().getPassword()); + + try { + RepositoryExecutor.performQuery( + connection, + String.format("CREATE DATABASE %s", databaseName.getValue()), + Integer.valueOf(databaseStatementCloseDelay.getValue())); + } catch (QueryExecutionFailureException ignore) { + } + + connection.close(); + } + } + + properties.put("quarkus.datasource.username", config.getInternalStorage().getUsername()); + properties.put("quarkus.datasource.password", config.getInternalStorage().getPassword()); + + return Collections.singletonList( + new PropertiesConfigSource( + properties, + com.objectstorage.service.integration.properties.security.SecurityPropertiesConfigService.class.getSimpleName(), + 290)); + } + + @Override + public OptionalInt getPriority() { + return OptionalInt.of(290); + } +} \ No newline at end of file diff --git a/api-server/src/main/java/com/objectstorage/service/integration/properties/security/SecurityPropertiesConfigService.java b/api-server/src/main/java/com/objectstorage/service/integration/properties/security/SecurityPropertiesConfigService.java index ad66940..b7084c2 100644 --- a/api-server/src/main/java/com/objectstorage/service/integration/properties/security/SecurityPropertiesConfigService.java +++ b/api-server/src/main/java/com/objectstorage/service/integration/properties/security/SecurityPropertiesConfigService.java @@ -24,14 +24,14 @@ public class SecurityPropertiesConfigService implements ConfigSourceFactory { @Override @SneakyThrows public Iterable getConfigSources(final ConfigSourceContext context) { - final ConfigValue value = context.getValue("config.location"); - if (value == null || value.getValue() == null) { + final ConfigValue configLocation = context.getValue("config.location"); + if (Objects.isNull(configLocation) || Objects.isNull(configLocation.getValue())) { return Collections.emptyList(); } Properties properties = new Properties(); - ConfigEntity config = ConfigConfigurationHelper.readConfig(value.getValue(), false); + ConfigEntity config = ConfigConfigurationHelper.readConfig(configLocation.getValue(), false); if (Objects.isNull(config)) { return Collections.emptyList(); } diff --git a/api-server/src/main/java/com/objectstorage/service/state/watcher/WatcherService.java b/api-server/src/main/java/com/objectstorage/service/state/watcher/WatcherService.java index bf3a21e..0d215c3 100644 --- a/api-server/src/main/java/com/objectstorage/service/state/watcher/WatcherService.java +++ b/api-server/src/main/java/com/objectstorage/service/state/watcher/WatcherService.java @@ -1,7 +1,5 @@ package com.objectstorage.service.state.watcher; -import org.apache.commons.io.FileUtils; - /** * Service used to track state metrics for the current session in the application. */ @@ -39,7 +37,10 @@ public void increaseUploadedFilesSize(Integer value) { */ public Double getAverageFileSize() { if (filesUploadCounter > 0) { - return Double.valueOf(uploadedFilesSize) / Double.valueOf(filesUploadCounter) / 1024 / 1024; + return (Double.valueOf(uploadedFilesSize) / + Double.valueOf(filesUploadCounter)) / + (double) 1024 / + (double) 1024; } return (double) 0; diff --git a/api-server/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory b/api-server/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory index 282b490..f12dc8a 100644 --- a/api-server/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory +++ b/api-server/src/main/resources/META-INF/services/io.smallrye.config.ConfigSourceFactory @@ -1 +1,2 @@ -com.objectstorage.service.integration.properties.security.SecurityPropertiesConfigService \ No newline at end of file +com.objectstorage.service.integration.properties.database.DatabasePropertiesConfigService +com.objectstorage.service.integration.properties.security.SecurityPropertiesConfigService diff --git a/api-server/src/main/resources/application.properties b/api-server/src/main/resources/application.properties index d9213f4..0eb7d0c 100644 --- a/api-server/src/main/resources/application.properties +++ b/api-server/src/main/resources/application.properties @@ -6,18 +6,15 @@ quarkus.swagger-ui.always-include=true quarkus.native.builder-image=graalvm quarkus.banner.path=banner.txt +# Describes database Quarkus configuration. +database.name=objectstorage + # Describes security Quarkus configuration. quarkus.rest-client.alpn=false -# Describes database Quarkus configuration. -quarkus.datasource.jdbc.driver=org.sqlite.JDBC -quarkus.datasource.db-kind=other -quarkus.datasource.jdbc.url=jdbc:sqlite:${user.home}/.objectstorage/internal/database/data.db -quarkus.datasource.username=objectstorage_user -quarkus.datasource.password=objectstorage_password - # Describes LiquiBase Quarkus configuration. -quarkus.liquibase.change-log=liquibase/config.yaml +liquibase.sqlite3.config=liquibase/sqlite3/config.yaml +liquibase.postgres.config=liquibase/postgres/config.yaml quarkus.liquibase.migrate-at-start=true # Describes internal healthcheck client configuration. diff --git a/api-server/src/main/resources/liquibase/postgres/config.yaml b/api-server/src/main/resources/liquibase/postgres/config.yaml new file mode 100644 index 0000000..affff68 --- /dev/null +++ b/api-server/src/main/resources/liquibase/postgres/config.yaml @@ -0,0 +1,134 @@ +databaseChangeLog: + - changeSet: + id: 1 + author: YarikRevich + changes: + - createTable: + tableName: secret + columns: + - column: + name: id + type: INT + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: session + type: INT + constraints: + nullable: false + - column: + name: credentials + type: TEXT + constraints: + nullable: true + - createTable: + tableName: provider + columns: + - column: + name: id + type: INT + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: name + type: TEXT + constraints: + unique: true + nullable: false + - createTable: + tableName: content + columns: + - column: + name: id + type: INT + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: provider + type: INT + constraints: + foreignKeyName: provider_fk + references: provider(id) + nullable: false + deleteCascade: true + - column: + name: secret + type: INT + constraints: + foreignKeyName: secret_fk + references: secret(id) + nullable: false + unique: true + deleteCascade: true + - column: + name: root + type: TEXT + constraints: + nullable: false + - createTable: + tableName: temporate + columns: + - column: + name: id + type: INT + autoIncrement: true + constraints: + primaryKey: true + nullable: false + - column: + name: provider + type: INT + constraints: + foreignKeyName: provider_fk + references: provider(id) + nullable: false + deleteCascade: true + - column: + name: secret + type: INT + constraints: + foreignKeyName: secret_fk + references: secret(id) + nullable: false + deleteCascade: true + - column: + name: location + type: TEXT + constraints: + nullable: false + - column: + name: hash + type: TEXT + constraints: + nullable: false + unique: true + - column: + name: created_at + type: BIGINT + constraints: + nullable: false + - createIndex: + columns: + - column: + name: name + indexName: idx_provider_name + tableName: provider + - loadData: + tableName: provider + usePreparedStatements: false + separator: ; + relativeToChangelogFile: true + file: data/data.csv + encoding: UTF-8 + quotchar: '''' + columns: + - column: + header: Name + name: name + type: STRING \ No newline at end of file diff --git a/api-server/src/main/resources/liquibase/data/data.csv b/api-server/src/main/resources/liquibase/postgres/data/data.csv similarity index 100% rename from api-server/src/main/resources/liquibase/data/data.csv rename to api-server/src/main/resources/liquibase/postgres/data/data.csv diff --git a/api-server/src/main/resources/liquibase/config.yaml b/api-server/src/main/resources/liquibase/sqlite3/config.yaml similarity index 80% rename from api-server/src/main/resources/liquibase/config.yaml rename to api-server/src/main/resources/liquibase/sqlite3/config.yaml index 75f23cd..2443eb8 100644 --- a/api-server/src/main/resources/liquibase/config.yaml +++ b/api-server/src/main/resources/liquibase/sqlite3/config.yaml @@ -3,37 +3,6 @@ databaseChangeLog: id: 1 author: YarikRevich changes: - - createTable: - tableName: config - columns: - - column: - name: id - type: INT - autoIncrement: true - constraints: - primaryKey: true - nullable: false - - column: - name: provider - type: INT - constraints: - foreignKeyName: provider_fk - references: provider(id) - nullable: false - deleteCascade: true - - column: - name: secret - type: INT - constraints: - foreignKeyName: secret_fk - references: secret(id) - nullable: false - deleteCascade: true - - column: - name: hash - type: VARCHAR - constraints: - nullable: false - createTable: tableName: secret columns: diff --git a/api-server/src/main/resources/liquibase/sqlite3/data/data.csv b/api-server/src/main/resources/liquibase/sqlite3/data/data.csv new file mode 100644 index 0000000..49f7e28 --- /dev/null +++ b/api-server/src/main/resources/liquibase/sqlite3/data/data.csv @@ -0,0 +1,3 @@ +Name +s3 +gcs \ No newline at end of file diff --git a/config/grafana/dashboards/diagnostics.tmpl b/config/grafana/dashboards/diagnostics.tmpl index a9e7da5..c7ebb33 100644 --- a/config/grafana/dashboards/diagnostics.tmpl +++ b/config/grafana/dashboards/diagnostics.tmpl @@ -18,8 +18,8 @@ "description": "ObjectStorage API Server: ${(info.version)}", "editable": true, "fiscalYearStartMonth": 0, - "gnetId": 179, "graphTooltip": 1, + "id": 1, "links": [], "panels": [ { @@ -52,6 +52,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -115,6 +116,7 @@ "sort": "none" } }, + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -153,6 +155,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -216,6 +219,7 @@ "sort": "none" } }, + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -254,6 +258,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -317,6 +322,7 @@ "sort": "none" } }, + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -355,6 +361,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -419,6 +426,7 @@ "sort": "none" } }, + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -457,6 +465,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -497,7 +506,7 @@ } ] }, - "unit": "decmbytes" + "unit": "none" }, "overrides": [] }, @@ -521,6 +530,7 @@ "sort": "none" } }, + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -578,6 +588,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "auto", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -589,7 +600,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.2", + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -649,6 +660,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "auto", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -660,7 +672,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.2", + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -747,6 +759,7 @@ "graphMode": "none", "justifyMode": "auto", "orientation": "horizontal", + "percentChangeColorMode": "standard", "reduceOptions": { "calcs": [ "lastNotNull" @@ -758,7 +771,7 @@ "textMode": "auto", "wideLayout": true }, - "pluginVersion": "10.4.2", + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -842,7 +855,7 @@ "showThresholdMarkers": true, "sizing": "auto" }, - "pluginVersion": "10.4.2", + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -928,7 +941,7 @@ "showThresholdMarkers": true, "sizing": "auto" }, - "pluginVersion": "10.4.2", + "pluginVersion": "11.3.1", "targets": [ { "datasource": { @@ -947,8 +960,9 @@ "type": "gauge" } ], - "refresh": "", - "schemaVersion": 39, + "preload": false, + "refresh": "auto", + "schemaVersion": 40, "tags": [ "docker", "prometheus, ", @@ -962,11 +976,9 @@ "auto_count": 30, "auto_min": "10s", "current": { - "selected": false, "text": "1h", "value": "1h" }, - "hide": 0, "label": "interval", "name": "interval", "options": [ @@ -1022,27 +1034,19 @@ } ], "query": "1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", - "queryValue": "", "refresh": 2, - "skipUrlSync": false, "type": "interval" }, { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": "All", + "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "P21B111CBFE6E8FCA" }, "definition": "label_values(node_exporter_build_info{name=~'$name'},instance)", - "hide": 0, "includeAll": true, "label": "IP", "multi": true, @@ -1051,29 +1055,19 @@ "query": "label_values(node_exporter_build_info{name=~'$name'},instance)", "refresh": 2, "regex": "", - "skipUrlSync": false, "sort": 1, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" }, { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": "All", + "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "P21B111CBFE6E8FCA" }, "definition": "label_values(node_exporter_build_info,env)", - "hide": 0, "includeAll": true, "label": "Env", "multi": true, @@ -1082,29 +1076,18 @@ "query": "label_values(node_exporter_build_info,env)", "refresh": 2, "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" }, { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "text": "All", + "value": "$__all" }, "datasource": { "type": "prometheus", "uid": "P21B111CBFE6E8FCA" }, "definition": "label_values(node_exporter_build_info{env=~'$env'},name)", - "hide": 0, "includeAll": true, "label": "CPU Name", "multi": true, @@ -1113,47 +1096,18 @@ "query": "label_values(node_exporter_build_info{env=~'$env'},name)", "refresh": 2, "regex": "", - "skipUrlSync": false, - "sort": 0, - "tagValuesQuery": "", - "tagsQuery": "", - "type": "query", - "useTags": false + "type": "query" } ] }, "time": { - "from": "2024-11-29T14:23:10.911Z", - "to": "2024-11-29T14:25:03.115Z" - }, - "timepicker": { - "refresh_intervals": [ - "5s", - "10s", - "30s", - "1m", - "5m", - "15m", - "30m", - "1h", - "2h", - "1d" - ], - "time_options": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] + "from": "now-5m", + "to": "now" }, + "timepicker": {}, "timezone": "browser", "title": "ObjectStorage Diagnostics", "uid": "64nrElFmk", - "version": 10, + "version": 2, "weekStart": "" } \ No newline at end of file diff --git a/docs/internal-database-design.md b/docs/internal-database-design.md index 09c31c2..03568f5 100644 --- a/docs/internal-database-design.md +++ b/docs/internal-database-design.md @@ -7,14 +7,6 @@ Internal database design of "ObjectStorage" end title -entity "config" { - *id : number <> - *provider : number <> # provider(id) - *secret: number <> # secret(id) - -- - hash : varchar -} - entity "secret" { *id : number <> -- @@ -44,9 +36,8 @@ entity "temporate" { hash : varchar } -config ||...|| secret #magenta : attached to content ||...|| secret #magenta : attached to content }|...|| provider #magenta : configures -temporate ||...|| secret #magenta : created with -temporate }|...|| provider #magenta : created with +temporate }|...|| secret #magenta : created with +temporate }|...|| provider #magenta : created for ``` \ No newline at end of file diff --git a/docs/internal-database-design.png b/docs/internal-database-design.png index 79e56b1..c733a54 100644 Binary files a/docs/internal-database-design.png and b/docs/internal-database-design.png differ diff --git a/docs/internal-storage-design.md b/docs/internal-storage-design.md index 7f92d4a..14bfd7c 100644 --- a/docs/internal-storage-design.md +++ b/docs/internal-storage-design.md @@ -7,7 +7,9 @@ Internal storage design of "ObjectStorage" end title * Workspace unit -** Temporate Storage +** Objects +*** N-files +** Backups *** N-files @endwbs ``` \ No newline at end of file diff --git a/docs/internal-storage-design.png b/docs/internal-storage-design.png index bb6bb4a..d01cecd 100644 Binary files a/docs/internal-storage-design.png and b/docs/internal-storage-design.png differ diff --git a/pom.xml b/pom.xml index 18ebd18..bb5e9de 100644 --- a/pom.xml +++ b/pom.xml @@ -243,6 +243,11 @@ quarkus-jdbc-sqlite 3.0.11 + + io.quarkus + quarkus-jdbc-postgresql + 3.17.2 + io.quarkus quarkus-smallrye-jwt diff --git a/samples/config/api-server/api-server.yaml b/samples/config/api-server/api-server.yaml index 4022b0a..1bf5e43 100644 --- a/samples/config/api-server/api-server.yaml +++ b/samples/config/api-server/api-server.yaml @@ -14,6 +14,20 @@ connection: # Represents password, which will be used to decode operations. password: "test123" +# Represents section used for ObjectStorage API Server internal database configuration. +internal-storage: + # Represents provider selected for ObjectStorage internal database. Supported providers are "sqlite3" and "postgres" only. + provider: "sqlite3" + + # Represents host for the previously selected ObjectStorage internal database provider, works only for "postgres". + # host: "localhost:5432" + + # Represents username for the previously selected ObjectStorage internal database provider. + username: "objectstorage_user" + + # Represents password for the previously selected ObjectStorage internal database provider. + password: "objectstorage_password" + # Represents section used for ObjectStorage API Server temporate storage configuration. Same compression will be # used to upload files to the configured cloud providers. temporate-storage: