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: