DatabaseSpec.java
package com.cloudforge.core.interfaces;
import java.util.List;
import java.util.Map;
/**
* Database specification interface for applications requiring external databases.
*
* <p>Applications implementing this interface can request managed RDS databases
* instead of using embedded file-based databases.</p>
*
* <p><b>Supported Engines:</b></p>
* <ul>
* <li>PostgreSQL (postgres)</li>
* <li>MySQL (mysql)</li>
* <li>MariaDB (mariadb)</li>
* <li>Aurora PostgreSQL (aurora-postgresql)</li>
* <li>Aurora MySQL (aurora-mysql)</li>
* </ul>
*
* <p><b>Example Usage:</b></p>
* <pre>{@code
* public class MetabaseApplicationSpec implements ApplicationSpec, DatabaseSpec {
* @Override
* public DatabaseRequirement databaseRequirement() {
* return DatabaseRequirement.optional("postgres", "15");
* }
*
* @Override
* public Map<String, String> containerEnvironmentVariables(
* String fqdn, boolean sslEnabled, String authMode, DatabaseConnection dbConn) {
* if (dbConn != null) {
* return Map.of(
* "MB_DB_TYPE", "postgres",
* "MB_DB_HOST", dbConn.endpoint(),
* "MB_DB_PORT", String.valueOf(dbConn.port()),
* "MB_DB_DBNAME", dbConn.databaseName(),
* "MB_DB_USER", dbConn.username(),
* "MB_DB_PASS", dbConn.passwordSecretArn()
* );
* } else {
* // Fallback to H2 embedded
* return Map.of("MB_DB_TYPE", "h2");
* }
* }
* }
* }</pre>
*
* @since 3.0.0
*/
public interface DatabaseSpec {
/**
* Database requirement for this application.
*
* @return database requirement (required, optional, or none)
*/
DatabaseRequirement databaseRequirement();
/**
* Database initialization SQL scripts to run after creation.
*
* @return list of SQL scripts, or empty list
*/
default List<String> databaseInitScripts() {
return List.of();
}
/**
* Database configuration overrides for specific engines.
*
* <p>Example PostgreSQL parameters:</p>
* <ul>
* <li>max_connections - 200</li>
* <li>shared_buffers - {DBInstanceClassMemory/4096}</li>
* <li>work_mem - 16MB</li>
* <li>log_statement - all</li>
* </ul>
*
* @return map of parameter group settings
*/
default Map<String, String> databaseParameters() {
return Map.of();
}
/**
* Database backup retention requirements.
*
* @return backup retention days (1-35), default 7
*/
default int backupRetentionDays() {
return 7; // Minimum for production
}
/**
* Whether this application requires read replicas for scaling.
*
* @return true if read replicas should be created
*/
default boolean requiresReadReplicas() {
return false;
}
/**
* Number of read replicas for production.
*
* @return read replica count (0-5), default 0
*/
default int readReplicaCount() {
return 0;
}
/**
* Database requirement specification.
*
* @param type the requirement type (REQUIRED, OPTIONAL, or NONE)
* @param engine the database engine (e.g., "postgres", "mysql")
* @param version the database engine version
* @param instanceClass the RDS instance class (e.g., "db.t3.micro")
* @param allocatedStorageGB the allocated storage in GB
* @param databaseName the name of the database to create
* @param publiclyAccessible whether the database should be publicly accessible
*/
record DatabaseRequirement(
RequirementType type,
String engine,
String version,
String instanceClass,
int allocatedStorageGB,
String databaseName,
boolean publiclyAccessible
) {
public enum RequirementType {
/** Application MUST have external database (GitLab, Mattermost) */
REQUIRED,
/** Application CAN use external database or embedded (Metabase, Grafana) */
OPTIONAL,
/** Application does not support external database (simple apps) */
NONE
}
public static DatabaseRequirement required(String engine, String version) {
return new DatabaseRequirement(
RequirementType.REQUIRED,
engine,
version,
"db.t3.micro", // Default instance class
20, // Default 20GB storage
"applicationdb", // Default database name
false // Never publicly accessible
);
}
public static DatabaseRequirement optional(String engine, String version) {
return new DatabaseRequirement(
RequirementType.OPTIONAL,
engine,
version,
"db.t3.micro",
20,
"applicationdb",
false
);
}
public static DatabaseRequirement none() {
return new DatabaseRequirement(
RequirementType.NONE,
null, null, null, 0, null, false
);
}
public DatabaseRequirement withInstanceClass(String instanceClass) {
return new DatabaseRequirement(type, engine, version, instanceClass,
allocatedStorageGB, databaseName, publiclyAccessible);
}
public DatabaseRequirement withStorage(int allocatedStorageGB) {
return new DatabaseRequirement(type, engine, version, instanceClass,
allocatedStorageGB, databaseName, publiclyAccessible);
}
public DatabaseRequirement withDatabaseName(String databaseName) {
return new DatabaseRequirement(type, engine, version, instanceClass,
allocatedStorageGB, databaseName, publiclyAccessible);
}
}
/**
* Database connection information provided to applications.
*
* @param endpoint the database endpoint hostname
* @param port the database port number
* @param databaseName the name of the database
* @param username the database username
* @param passwordSecretArn the ARN of the secret containing the database password
* @param engine the database engine type
* @param version the database engine version
* @param readReplicaEndpoints list of read replica endpoints (if any)
*/
record DatabaseConnection(
String endpoint,
int port,
String databaseName,
String username,
String passwordSecretArn,
String engine,
String version,
List<String> readReplicaEndpoints
) {
public boolean hasReadReplicas() {
return readReplicaEndpoints != null && !readReplicaEndpoints.isEmpty();
}
}
}